There's something I've been wondering. Is there some protocol in place for accessing global variables of another task in OS4 PPC code? Looking at examples code just accesses variables regardless.
In the 68K days we had things like geta4() type functions. Or just taking care of it yourself with a bit of ASM. But what about OS4?
I tend to be pedantic about these things and if I need pass data or modify it I tend to keep it inside an object that I send to another task. For example, in an interrupt, I would make use of the user data field to pass an object.
That's a rather low level example, but what about in general code? Say, a parent task having variables read by a child task? Or even, a library function that needs to run code, which belongs to a library master task?
This timer interrupt example below does pass a data pointer as user data. But it doesn't access it as a parameter. Nor does it use IExec as a parameter. But rather, it accesses each directly. Unless I'm missing something I didn't know this was a special feature of interrupt routines.
That's the right way to handle it :)
I usually implement a protocol similar to what Workbench does. I create the child with CreateNewProc. As first action the child WaitPort()s on its pr_MsgPort. The creator then sends an initialisation message to the child's pr_MsgPort.
Now it depends on what the child is used for. If the child is a server of some kind which should process additional messages, the creator waits on a reply for the intitial message and the child replies to the message once it has done its initialization.
If the child should do some asynchronous processing and then quit, the creator proceeds without waiting, the child does its work and replies to the message when it's done and quits. The parent knows that the child's work is done when it receives the reply.
If the shared memory block should be updated by multiple processes, I also include a struct SignalSemaphore and each task does an ObtainSemaphore before it accesses the data and ReleaseSemaphore afterwards.
Sharing interface pointers and library bases is another story. Normally this works by just referencing the global symbol. Often it is not possible to do it otherwise in C without a lot of programming efforts. However, it does not work with bsdsocket.library and other libraries which create a new base for each OpenLibrary call.
Thanks for your reply.
I'm on the right track then. :-)
That makes sense.
Looks organised that way.
I wonder if that could be reduced to signals. Perhaps not since both would need to know what signal was used.
I do that myself. Usually when writing library code that could be called from multiple processes. I semaphore lock an object that only my library function knows about.
I'm currently looking at 68K library code I intend to port to PPC. The different ABI and places for parameters looks like the hardest to manage.
Though it's a known about, the different bsdsocket.library bases does cause grief for some people. Amiga E does that in the library mode. Which has caused me trouble with code that doesn't expect it. In Amiga terms dynamic library bases are not thread safe. :-)
Normally you would want to get a result from the task. For example if you want to decode picture files asynchronously, you'd create the task, send it a file name and when it is finished you'd receive a pointer to a bitmap.
There isn't too much info on this floating about. Unless it's hidden in the SDK. But apparently the default on OS4 is to compile for a large data model. So we don't need to worry about global pointers and can access them whenever we like. Unless we are using small data model.