/* 2Tasks.C James M Synge, May 18, 1987 */ /* Include files */ #include "exec/types.h" #include "exec/nodes.h" #include "exec/lists.h" #include "exec/tasks.h" #include "exec/libraries.h" #include "exec/ports.h" /* Other declarations */ struct Library *TaskBase, /* Library Base Pointer. */ *OpenLibrary(); struct MsgPort *CreatePort(), *FindPort(); struct Message *WaitPort(), *GetMsg(); #define TASK_LIBRARY "task.library" #define TASK_VERSION 1L #define CHILD_PORT "2Tasks.Child.Port" #define CHILD_TASK "2Tasks.Child.Name" main() { struct Message message, *msg; struct MsgPort *ParentPort, *ChildPort; struct Task *ChildTask, *CreateTask(); void ChildMain(); int seconds; /* First things first: Open the task library: */ printf("Openning %s\n", TASK_LIBRARY); TaskBase = OpenLibrary(TASK_LIBRARY, TASK_VERSION); if (TaskBase == 0L) { printf("Unable to open %s\n", TASK_LIBRARY); exit(10); } /* Create a nameless MsgPort where we can receive * the reply to a message. */ if ((ParentPort = CreatePort( 0L, 0L )) == 0L) { printf("Unable to create a MsgPort!\n"); CloseLibrary( TaskBase ); exit(10); } /* Now create the child task. */ printf("Creating the child task.\n"); ChildTask = CreateTask( CHILD_TASK, /* Name of the task. */ 1L, /* Higher priority. */ ChildMain, /* Its main routine. */ 4096L); /* Stack Size. */ if (ChildTask == 0L) { printf("Unable to create child task!\n"); DeletePort( ParentPort ); CloseLibrary( TaskBase ); exit(10); } /* Find the child's message port. */ for(seconds = 0; seconds < 60; seconds++) { printf("Find the child's MsgPort\n"); if (ChildPort = FindPort( CHILD_PORT )) break; Delay(50); /* Wait a second! */ } if (ChildPort == 0L) { printf("Unable to find child MsgPort!\n"); DeleteTask( ChildTask ); DeletePort( ParentPort ); CloseLibrary( TaskBase ); exit(10); } /* Send the child a message. */ message.mn_Node.ln_Type = NT_MESSAGE; message.mn_ReplyPort = ParentPort; message.mn_Length = 0; printf("Sending the message.\n"); PutMsg( ChildPort, &message ); /* Wait for the child to respond. */ WaitPort( ParentPort ); /* Get the message. */ msg = GetMsg( ParentPort ); printf("Got the reply. All done.\n"); /* And now delete the MsgPort we used. */ DeletePort( ParentPort ); /* Finally, close the library. */ CloseLibrary( TaskBase ); exit(0); } /* Notice that the child doesn't open any libraries, * including exec.library and Task.Library whose * routines it uses. It does this because it will * operate solely during the life of the parent, when we * know the libraries will be open. This is not kosher in * general, but Commodore has produced examples doing this, * and I know there aren't any problems in this case. * * It's also particularly difficult to close a library * after using DeleteTask() on yourself! */ void ChildMain() { struct Message *msg; struct MsgPort *ChildPort; /* To allow this to be a small code/small data model * task, we must make sure register A4 contains the * correct value. We do so by calling the Aztec C * routine geta4() which computes the value. */ geta4(); /* Create a MsgPort where we can receive a message * from the parent task. */ if ((ChildPort = CreatePort( CHILD_PORT, 0L )) == 0) DeleteTask( FindTask( 0L )); /* Now wait for the message. */ WaitPort( ChildPort ); /* Fetch it from the port... */ msg = GetMsg( ChildPort ); /* ... and reply to it. Do so inside a Forbid() / * Permit() pair so there'll be time to delete the * message port. Note that the Permit() call is * not included because it will never be called; * instead, DeleteTask() is called so that we * delete the current task: ourselves! */ Forbid(); ReplyMsg( msg ); DeletePort( ChildPort ); /* Now take the leap of death. */ DeleteTask( FindTask( 0L )); /* That's all she wrote! */ }