pcooper@LUKE.EECS.WSU.EDU (Phil Cooper - CS495) (11/24/90)
Fellow Amigans: I would like some advice/examples on how to set up several functions in a source code file as independent processes (using ports and messages for inter-process communications.) My problem can be described as follows: main() { /* brilliant code inserted here...*/ } func_1() { } func_2() { } I would like to set up func_1 and func_2 to run as completely independent processes. Also, After they are set up, is anything needed to get them to actually start executing? I have a project now where the tasks are being set up correctly (even show up with TaskX), but they seem to never actually execute. Any suggestions? Phil
markv@kuhub.cc.ukans.edu (11/27/90)
> Fellow Amigans: > > I would like some advice/examples on how to set up several functions > in a source code file as independent processes (using ports and messages > for inter-process communications.) My problem can be described as follows: >... I've done exactly this thing with *tasks*. Using functions as *tasks* is easy. Using functions as processes is tricky. If you are a task the only restriction is you can't call DOS or do anything that calls DOS. This isn't too hard actually, as you can have the parent process do such things for you. Some things to keep in mind... Exec/DOS maintain NO parent-child information. It is up to the program to make sure the children are removed before the parent exits (ie: the tasks are delete with from the system b/4 parent exits so Exex doesn't try to execute non-existant code). Two, there is no guarenteed synchronization. The children need some way of signalling the parent they are ready, and the parent needs some way of signaling the children to die. (Plus any other inter-task communication). You can use Signals, semaphores, messages, and in the case of functions as tasks, shared global variables (if using base relative the children must fetch the global base either with geta4() or __saveds). Try this crude example (I may be off in parameter order on some functions, but it should be obvious which parameter is what). I use CreateTask() out of amiga.lib. /* ** handy macro... */ #define BIT(x) (1L << x) /* ** Child to parent signals. */ BYTE C1Sig, C2Sig; BYTE DieFlag; TASK *C1, *C2, *Main; main() { ULONG WaitRet; /* CreateTask() takes the start address of the code, the stack size, ** the name, and the priority. */ C1Sig = AllocSignal(-1); C2Sig = AllocSignal(-1); Main = FindTask(NULL); C1 = CreateTask(func_1, "TASK 1", 4000, 1); C2 = CreateTask(func_2, "TASK 2", 4000, 1); /* ** Wait for both children to signal they are ready. */ WaitRet = 0; while(WaitRet != ((BIT(C1Sig) | BIT(C2Sig)) WaitRet = WaitRet | Wait(BIT(C1Sig) | BIT(C2Sig)); while (not time to quit) { /* ** brilliant inter-task communication code event loop... */ } /* ** Time to kill children... */ DieFlag = TRUE; /* ** Wait for both children to signal they are ready to die. */ while(WaitRet != ((BIT(C1Sig) | BIT(C2Sig)) WaitRet = WaitRet | Wait(BIT(C1Sig) | BIT(C2Sig)); DeleteTask(C1); DeleteTask(C2); exit(0); } func_1() { /* ** Ensure addressability of global data... */ geta4(); /* ..brilliant initialization code, then Signal we are ready */ Signal(Main, BIT(C1)); for (;;) { /* ** brilliant inter-task communication code event loop... */ if (DieFlag) { Signal(Main, BIT(C1)); Wait(0L); /* Wait() forever */ } } func_2() { /* same as func_1 except use C2 */ } This code does NOT check error returns from things like AllocSignal(), etc which it should do. For this particular example to be completely safe, the children should be running at a higher priority than the parent. The children do a Wait(0L) to put them in a "safe" state to remove them. DeleteTask() calls RemoveTask() which isn't always safe depending on the state that removed task is in, Wait(0L); is a safe state. Oh, obviously the parent and children should do any cleanup before they wait or exit (FreeSignal() comes to mind). Note that most allocation calls can be done by either side, but certain things, like AllocSignal() are "context dependant" and should be allocated by the owning/receiving end. > I would like to set up func_1 and func_2 to run as completely independent > processes. Also, After they are set up, is anything needed to get them to > actually start executing? I have a project now where the tasks are being > set up correctly (even show up with TaskX), but they seem to never actually > execute. Any suggestions? When something is AddTask()ed (which is called by create task), it will began executing as soon as it normally would, which is dependant on its priority. With multitasking programs its important to avoid deadlock conditions (where task A is waiting on task B for something at the same time task B is waiting on task A, so both tasks stop forever). You can use WaitMask = SetSignal(0, 0); as a safe way to check and clear signals without blocking if the signals aren't there (such as break checking). > Phil Obviously all this code assumes tasks. Processes are much trickier as you have to create file handles, get around the SegList problem, etc. -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Mark Gooderum /\ \ | / H a p p y Academic Computing Services / v\ -- * -- H o l i d a y s ! :-) University of Kansas /v v\ / | \ /// /__v___\ Only /// /| __ _ Bitnet: MARKV@UKANVAX || \\\ /// /__| |\/| | | _ /_\ makes it Internet: markv@kuhub.cc.ukans.edu \/\/ / | | | | |__| / \ possible ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rick@rsami.UUCP (Rick Schaeffer) (12/04/90)
>In article <9011241137.AA24447@luke.eecs.wsu.edu> pcooper@LUKE.EECS.WSU.EDU (Phil Cooper - CS495) writes: >Fellow Amigans: > > I would like some advice/examples on how to set up several functions >in a source code file as independent processes (using ports and messages >for inter-process communications.) My problem can be described as follows: > > Phil You might take a look at the popen example I posted to alt.sources.amiga a while back. The 2.0 version of it uses the new CreateNewProc() function which can optionally create an entire process out of a function within the current process. I use that feature to start the background part of the pipe. If you don't yet have access to Dos2.0, there was an example of exactly what you want posted a long time ago. It was called "proc.c" and illustrated how to create a process out of a function by using the old CreateProc() function. This function takes a pointer to a "seglist"...well a seglist simply consists of a pointer to the next segment followed by the actual code to be executed. What he did was to stuff a "jmp" instruction into a dummy seglist structure, set the address of the jump to the function address, and then call CreateProc() passing a pointer to this dummy seglist. Hopefully, this is enough to get you going. If not, I can probably dig up the source code and email it to you. If you decide to email to me, be sure to use the address in my .signature. My news site is my amiga and it isn't a registered site! -- Rick Schaeffer UUCP: uunet!isc-br.isc-br.com!ricks E. 13611 26th Ave. ricks@isc-br.isc-br.com Spokane, Wa. 99216 Phone: (509)928-3533