I want to launch a subprocess with CreateNewProc(). This subprocess will need to communicate with the main one. For this purpose I want to create message ports in both of them and then exchange messages. Now the problem arises: either main proces should somehow learn about subprocess port address, or subprocess should get main process port address. Is there any recommended solution for this? On AmigaOS 3.x I've just used a global variable. With OS 4.x having more and more memory protection it is not a good idea I guess?
Well, i'm pretty sure that even if OS4.5 introduced seperate memory spaces, that if you include the "NP_Child" tag, your subprocess will share its memory space with its parent.
For compatibility with OS3 and above, you can just stick the port pointer in NP_ExitData. In the child, just read it from child_proc->pr_ExitData.
For OS4, you should set the NP_Child tag if the child process is going to be running in the parents loaded code space, this automatically prevents the parent exiting before the child does first.
NP_Child also allows the child to share the "newlib" context of the parent, without it, a child calling a newlib function will crash, unless it explicitly opens the library itself.
For OS3, the new tag is ignored, and you will have to arbitrate this yourself, I guess you could also use the childs pr_ExitData field as a flag to indicate when the child exits, (by having the child clear it on exit) and put the parent in a Delay() wait loop until it does, otherwise it will crash if the child is still running when the parent exits and unloads the seglist.
My code is compiled for AmigaOS 3.x, AmigaOS 4 and MorphOS, so it is explicitly designed in a way that main process cannot exit before the subprocess. Also I do not use any standard library at all (linking with -nostdilb -nostartfiles).
I see there is NP_NotifyOnDeathMessage tag in CreateNewProc() of AmigaOS 4. I'm going to use it for synchronization when the main process exits (it sends internal "Quit" command to the subprocess, then it can wait for this death message). MorphOS has similar NP_StartupMessage, but it is extended in a way that I can peek into this message from a subprocess using NewGetTaskAttrs(), so I can pass some initial parameters there as well as obtain main task port address looking at msg->mn_ReplyPort. AmigaOS 4 autodocs do not say I can look at DeathMessage from the subprocess. Anyway I can pass the ports via global vars after using NP_Child.
Another question - what is the recommended way to obtain the SysBase in a subprocess? Just old-style reading $00000004? Or it is passed as an argument to NP_Entry function? Or maybe when I use NP_Child for a subprocess I can share SysBase with main process? What about ExecIFace then? Can it be shared too?
Another question - what is the recommended way to obtain the SysBase in a subprocess? Just old-style reading $00000004? Or it is passed as an argument to NP_Entry function? Or maybe when I use NP_Child for a subprocess I can share SysBase with main process? What about ExecIFace then? Can it be shared too?
It's passed as third parameter to the entry function.
Allow me to rephrase my last reply.... I was in a hurry to go out for dinner at the time.
As the previous reply from Salass00 indicated, you get a free ExecBase pointer when you enter the child entry() function of the code pointed to by NP_Entry.
See the include file; dos/startup.h The child process starts up like all other processes in DOS do, just remember to declare the child process entry() just like that shown in startup.h. Just don't call the child entry function _start(), that symbol name is reserved for the initial entry point of the main executable.
If you wish to pass additional parameters to the child, you can use any of the "Spare" process fields of the child process, as long as they can be initialised in the call to CreateNewProc() via tags. For example; NP_EntryData, NP_ExitData, NP_FinalData, NP_UserData..... These are all available for your general usage, you can even pass pointers in these fields, such as a custom parameter structure or such like.
NB: The NP_EntryData and NP_ExitData tag values can be obtained by calling IDOS->GetEntryData() or IDOS->GetExitData() from within the child process. The other fields do not have accessor functions and would require that you call; struct Process *child = IExec->FindTask(0); from the child process to to get the child process pointer and to then access those other fields.
When the child is running in the shared code space of the parent, all globals are accessible, but remember that you have to take care with data that is shared by the two processes and employ some sort of arbitration when modifying any global values as the child is running independantly of the parent.
Now, as far as NP_Child tag goes, it causes DOS to put the parent process to sleep for a while if the child is still running when the parent attempts to exit. Once the child leaves, the parent is then allowed to exit fully and unload the program code. This tag should be specified when a child is depending on any resources of the parent process.
Just remember that NP_Child is only for non-persistent child processes, as the parent will not be able to terminate until the child does so first.
I've used NP_UserData for passing some startup parameters. In the subprocess I get them just via FindTask(NULL)->tc_UserData.
Semaphore protection of shared, non read-only data is obvious to me. I'm an Amiga programmer for 12 years, just new to OS 4.
I have another question. Does subprocess entry point function need some compiler flag like '__saveds' on 68k? I get some near-zero read hits when accessing globals.
I have another question. Does subprocess entry point function need some compiler flag like '__saveds' on 68k? I get some near-zero read hits when accessing globals.
There are no such compiler flags, if you build your program with -msdata you have to copy r13 from the parent to the child yourself (r2 if you use -mbaserel).