my current focus is on the so called AmigaDOS handlers and the related packets interface.
I couldn' t find any good documentation about it. Anyway I was able to put together a bit of info looking at some (rather old) sources:
1) A handler process is started for each invocation (code must be re-entrant?).
2) Just one handler process is started for multiple invocations.
I really would like to better understand 1) and 2).
Any help is more than welcome as usual :)
If you have the latest SDK installed you can find documentation on DOS packets in:
Thanks for the DOS packets reference, they are the communication layer, correct me if I am wrong.
But before that I would need a bit of theory to understand what a handler is and how it really works.
If I understand well a handler is basically a process which is possible to "call" through normal AmigaDOS file I/O functions such as Open(), Read() and Write().
Don' t we have a skeleton code or such?
It feels like AmigaDOS handlers are certainly a very powerful OS feature but also rather obscure for developers.
My (basic) questions:
Is a new handler process started for each (DOS) invocation?
Or just one handler process is started to serve multiple and concurrent invocations?
Reentrancy / concurrency have to be taken into account?
Only if the handler/filesystem doesn't set the dn_Port field of the DeviceNode (dp_Arg3 of the startup packet).
Only if it's meant to be made resident or used as a kickstart module.
Thanks for the precious info.
Then I guess if the dn_Port field of the DeviceNode is properly set, the handler should also manage multiple and concurrent calls by means a semaphore.
Unless you're doing a vector port filesystem (there's no vector port API equivalent for handlers) you just deal with packets in the order you receive them at your message port.
If you are doing a vector port filesystem (which it doesn't sound to me like you are) you should use fsvptool to generate a fileystem skeleton. I used it for my updated XADFileSystem and it was very useful.
Yes, I actually have a DOS handler in mind, rather than a vector port filesystem.
Thanks for your clear responses, it feels like I got the answers to my questions.
You are right, a semaphore or similar mechanism doesn' t make sense because multiple and concurrent calls to the handler don' t share any memory.
Thus the handler manages a packet at a time with the work flow being like
1) get a packet GetMsg()
2) process packet
3) return packet PutMsg()
and it doesn' t get a new packet 1) until the current one is returned 3).
Please correct me if I have misunderstood something.
Sorry for all my questions, I would like to understand all details.
I found comments in rather old source codes stating that in case of dn_Port set to NULL, multiple calls to the handler (= multiple handler processes started) share the same global data segment.
Is this true?
That might be true come to think of it.
In that case you can't have any non-const global variables which also means that you can't really use newlib. You will have to use clib2 and of course you should stick to only simple clib functions like those from string.h, ctype.h for instance that do not require any special setup code. Also you should set up some kind of global data structure (either allocated from the stack or using AllocVecTags()) that you can then pass around to all your functions and will be used store all the global data for the current handler instance.
If you're using handler process' pr_MsgPort to receive packets you can use WaitPkt() and SendPkt()/ReplyPkt() functions from dos.library instead.
Well after our focus on topic, I see that not all handlers examined by me so far cover the mentioned aspects, thus there is a risk that they may not work as expected under the mentioned circumstances.
Is there some reason why you need a new handler instance to be created for each Open() call? What kind of handler are you intending to write exactly?
Thanks for your interest.
The handler concept I have in mind is a sort of "server" managing multiple requests from different "clients" (client-server model).
I am now evaluating how to handle a flow of requests for each client:
1) by a new handler instance for each client
2) by a unique handler instance for all clients
The handler needs to instantiate a timer for each client.
The client work flow should be like this:
- Send request 1, Write()
- Send request 2, Write()
- Send request N, Write()
Surely 2) requires a bigger programming effort.
I hope it is clear enough, what do you think about it?
You could do you're own multi-threading by spawning subprocesses for each file handle and then just sending on the packets to them from your main handler process.
I want to keep it as simple as possible, thus at the moment I am more oriented to create a new handler instance (automatically done by DOS) for each request / file handle.
Now it is also more defined that in a normal case the handler itself should manage at most just a few requests.
For those interested, I finalized this thread to a real project, have a look at Watchdog-Handler available from OS4 Depot.
You may wanna use GetUpTime() instead of GetSysTime() in case someone plays with his systemtime ...
Interesting and cool alternative and idea thanks ;)