From: Todd_Lewis@unc.edu (Todd M. Lewis)
Subject: Re: task communication and forbid()
Organization: UNC Office of Information Technology
Date: Tue, 22 Dec 1992 21:06:06 GMT

In article <1992Dec18.204844.1796@samba.oit.unc.edu> Todd_Lewis@unc.edu (Todd  
M. Lewis) writes:
>Ugh.  That's not good.  You will waste half of your cycles busy-waiting.
>You want to do a for-real Wait().  Some notes on the code that follows.
>  1)  This is off the top of my head--I don't have an Amiga here to
>      test it with, so it may not compile, much less work.

Well, I took it home and fixed a few things.  This example compiles
and runs under Manx 5.2a.  Porting to "other platforms" should
be simple.  If you kept the previous post for reference, replace it
with this one.  Nothing major, but it might save you a few minutes.

================== coordinate.c =============================
/********
Some notes on the code that follows.
  1)  This works under Manx 5.2a.  Other C compilers should be easy too.
  2)  The signal SIGF_SINGLE is pre-allocated for every task so if
      you are just waiting on one thing you can use this "well-known signal".
      Always clear it before waiting on it.  That's what simple_wait() is for.
  3)  When you call CreateTask(), you have no way to know if the subtask has
      gotten to run at all by time the call returns, so coordination between
      parent and child tasks is really tricky.
  4)  carefully study the Forbid()/Permit() pairs around the state variable
      examination/change/simple_wait() groups.  Follow both threads of
      execution and at every line in the program ask yourself "What happens
      if a task switch occurs here?"  I think I've considered all the pitfalls.
  5)  This is just an example.  You should make sure a ^C doesn't kill
      the main() task while child() is running.
*********************/

#include <exec/tasks.h>
#ifdef AZTEC_C
  #include <functions.h>
#endif

#define STARTRUNNING 1
#define RUNNING      2
#define DROPDEAD     3
#define DEAD         4

struct Task *mamma_ptr;
struct Task *child_ptr;

int             state      = 0;
ULONG           counter    = 0;

void simple_wait( void )
  {
    SetSignal( 0L, SIGF_SINGLE );  /* Clear the signal.    */
    Wait( SIGF_SINGLE );           /* Wait for the signal. */
  }

void child( void )
  {
#ifdef AZTEC_C
    geta4();
#endif
    Forbid();
      while ( state < STARTRUNNING )
        simple_wait();
    Permit();

    Forbid();
      state = RUNNING;
      Signal( mamma_ptr, SIGF_SINGLE);
    Permit();

    while( state == RUNNING )  /* Do something wonderful.   */
       counter++;

    Forbid();                  /* state should be DROPDEAD. */
      state = DEAD;
      Signal( mamma_ptr, SIGF_SINGLE );
    /* Hanging Forbid() ensures child exits before main() resumes. */
  }

int main( int argc, char *argv[] )
  {
    mamma_ptr = FindTask(0);
    child_ptr = CreateTask("the kid", 0, child, 2048 );

    if ( child_ptr )
       {
         printf("Child task created.\n");

         state = STARTRUNNING; /* Tell child to run some more. */
         Signal( child_ptr, SIGF_SINGLE );

         Forbid();             /* Wait for child to start running. */
           while ( state < RUNNING )
             simple_wait();
         Permit();             /* Child is running.       */

         printf("Child task is running.\n");

         Delay( 250L );        /* Sleep for 5 seconds.    */
                               /* Do something wonderful. */
         printf("Child has counted to %d.\n", counter );

         Forbid();
           state = DROPDEAD;   /* Tell child to die.      */
           simple_wait();      /* Wait for child to die.  */
         Permit();
                     /* child (and state) should be DEAD. */
         printf("Child task completed.\n");
         printf("Child has counted to %d.\n", counter );
       }
    return 0;
  }

--
 _/_/_/  _/     Todd_Lewis@unc.edu          You can lead a horse to 
  _/    _/     utoddl@guitar.oit.unc.edu   Mohammad, but you can't make
 _/    _/_/_/                             a mountain drink a mole hill.