Man Page task.3




NAME

     task - coroutines in the C++ task library


SYNOPSIS

     #include <task.h>
     typedef int (*PFIO)(int,object*);
     typedef void (*PFV)();

     class object {
     public:
           // exported constants and types
          enum objtype { OBJECT, TIMER, TASK, QHEAD, QTAIL, INTHANDLER };
          // exported constructor
          object();
           // exported data members
          object*   o_next;
          static    PFIO error_fct;
          // exported virtual functions
          virtual   objtype   o_type();
          virtual   int  pending();
          virtual   void print(int, int=0);
          // print flags, used as arguments to print function
          #define CHAIN       1
          #define VERBOSE     2
          #define STACK       4
          // exported misc functions
          void alert();
          void forget(task*);
          void remember(task*);
          // exported static member functions
          static    int task_error(int, object*);
          static    task* this_task();
     };

     class sched: public object {
     public:
          // exported constants and types
          enum statetype { IDLE=1, RUNNING=2, TERMINATED=4 };
     protected:
          // protected constructor
          sched();
     public:
          // exported data members
          static    task*     clock_task;
          static    PFV  exit_fct;
          // exported virtual functions
          virtual   int  pending();
          virtual   void print(int, int =0);
          virtual   void setwho(object*);
          // exported misc functions
          void cancel(int);
          int  dont_wait();
          sched*    get_priority_sched();
          int  keep_waiting();
          statetype rdstate();
          long rdtime();
          int  result();
          // exported static member functions
          static    long get_clock();
          static    sched*    get_run_chain();
          static    int  get_exit_status();
          static    void set_exit_status(int i);
          static    void setclock(long);
     };

     class task: public sched {
     public:
          // exported constants and types
          typedef unsigned char _Uchar;
          enum modetype { DEDICATED=1, SHARED=2 };
          #define DEFAULT_MODE DEDICATED
          #define SIZE 3000
     protected:
          // protected constructor
          task(char* = 0, modetype = DEFAULT_MODE, int = SIZE);
     public:
          // exported data members
          task*     t_next;
          _Uchar*   t_name;
          // exported virtual functions
          virtual   objtype   o_type();
          virtual   void print(int, int =0);
          virtual   void setwho(object*);
          // exported misc functions
          void cancel(int);
          void delay(int);
          int  preempt();
          void resultis(int);
          void sleep(object* =0);
          void wait(object*);
          int  waitlist(object* ...);
          int  waitvec(object**);
          object*   who_alerted_me();
          // exported static member function
          static    task*     get_task_chain();
     };

     class timer: public sched {
     public:
          // exported constructor
          timer(int);
          // exported virtual functions
          virtual   objtype   o_type();
          virtual   void print(int, int =0);
          virtual   void setwho(object*);
          // exported misc functions
          void reset(int);
     };


DESCRIPTION

     A task is an object with a control thread running its  asso-
     ciated program.  More specifically, a user task is an object
     of a type derived from class task.  The constructor of  that
     object  is  the main program of the task.  The task does not
     survive the completion of the constructor.

     The task system works in terms of operations  which  may  be
     performed  immediately or which must wait, and objects which
     are ready or pending.  If a task requests  a  service  which
     may be performed immediately, or waits on an object which is
     ready, the task continues execution.  If the service  cannot
     be performed immediately or if the object being waited on is
     not ready, the task is blocked.   When  a  running  task  is
     blocked,  the scheduler selects the next task which is ready
     to run and gives it control.  A task is never preempted, but
     may  be  blocked, thus allowing other tasks to run.  Control
     proceeds in a round-robin sequence.  (It is possible  for  a
     task  to be given priority and moved to the head of the list
     of tasks to be  run.)   Whenever  an  object  becomes  newly
     ready, any tasks which were waiting for it are notified, and
     those tasks become ready to run.

     A task may be in one of three states:

     RUNNING
          Running now or ready to be run.

     IDLE Not ready to run; waiting for some object.

     TERMINATED
          The task has  finished  and  cannot  be  resumed.   The
          task's return value may be retrieved.

     The task system is rooted in class object.  Anything derived
     from this class may be put on a queue or waited on.  Virtual
     member function pending() returns non-zero if the object  is
     not  ready.  Each type of object may have its own version of
     this function, and thus its  own  criteria  for  determining
     whether  it  is  ready or pending, but there may be only one
     such function.

     Each object has a list of objects which are waiting  on  it,
     the remember chain.  When a task waits on an object which is
     not ready, the task is suspended (IDLE)  and  added  to  the
     object's remember chain.  When the object next becomes ready
     (not pending), each waiting  task  is  notified  via  member
     function  object::alert().   This function changes the state
     of these tasks to RUNNING and puts them back on the list  of
     ready tasks, the scheduler's run chain.

     Class sched, derived from object, provides the functionality
     common  to  task-like objects.  The scheduling functions are
     provided  here.   Rather  than  a  separate  scheduler,  the
     scheduling  operations  are  part  of class sched, and tasks
     cooperatively provide scheduling  by  means  of  its  member
     functions.   This  class may not be instantiated, but may be
     used only as the base class of tasks and timers.

     Class sched also provides the facilities for  the  simulated
     passage  of time.  Units of simulated time need have nothing
     to do with real time.  The simulated system  clock  is  ini-
     tialized   to  zero,  and  can  be  set  at  most  once  via
     sched::setclock().  Thereafter, the clock advances  only  by
     calls  to  task::delay(),  whose  parameter is the number of
     simulated time units to delay.  When that  amount  of  simu-
     lated  time  has  elapsed,  delay()  returns.   The  call to
     delay() causes the clock to advance to the  earlier  of  the
     amount  of  delay and the next simulated time at which some-
     thing is scheduled to happen.   The  current  value  of  the
     clock may be read via function sched::getclock().

     Class timer is a stripped-down task which simply delays  the
     specified  amount  of  simulated  time,  then terminates.  A
     timer may be waited on, and when its time  has  elapsed  any
     waiting tasks are alerted.  A timer can be either RUNNING or
     TERMINATED, but never IDLE.

     Class task is derived from  sched  and  provides  the  basic
     functionality  of user tasks.  No object of type task may be
     instantiated.  All user tasks must be derived directly  from
     class  task; that is, you may not further derive from a user
     task type.  Examples:
          task mytask;        //  ERROR:  cannot  create  a  task
     object
          class consumer : public task { ... }    // OK
          class glutton : public consumer { ... } // ERROR:  can-
     not derive again
     The first error is diagnosed by the compiler, since the task
     constructor  is protected.  The error in the third line can-
     not be diagnosed, but the program will not work.

     A task may not terminate by simply exiting the  constructor,
     nor  may  the  function return mechanism be used to return a
     value from a task.  A task must instead set its return value
     by  calling either task::resultis() or task::cancel().  This
     puts the task in the  TERMINATED  state.   Other  tasks  may
     retrieve  the  result value by calling task::result(), which
     will suspend the calling task until  the  queried  task  has
     terminated.  Even if a task does not need to return a value,
     it must call resultis() or cancel() to ensure  the  task  is
     properly terminated before it is destroyed.

     The task constructor takes three optional arguments: a name,
     a mode, and a stack size.

     The name should be a character string  allocated  statically
     or  on  the  heap, not a character array local to some func-
     tion.  The name appears only in printouts, and has no effect
     on the task operation.

     The mode specifies what sort of stack  the  task  will  use.
     The  mode may be DEDICATED (the default) or SHARED.  Usually
     you want a dedicated stack, meaning the task has a  reserved
     area  of memory for its own stack.  Shared stacks are expen-
     sive, because tasks  may  need  to  swap  their  own  stacks
     between  the  shared  area  and  a  save area as they become
     active and inactive.  If you have hundreds of  small  tasks,
     it makes sense for them to share stack space.

     The stack size argument  specifies  the  maximum  amount  of
     stack  space  the  task may use.  The default is 3000 bytes.
     There is no foolproof test for overflowing the stack  space,
     and  the  stack  cannot  be dynamically expanded.  The stack
     size is checked when a task is swapped in, and overflow is a
     fatal error.  If the stack overflows during execution due to
     depth of function call nesting and amount of local  variable
     storage, this may cause bizarre program behavior or a crash.

     When you derive a class from task, its constructor becomes a
     new  task  which  runs  along  with others which may already
     exist.  Function main() becomes a task with the creation  of
     the  first task in the system.  If several tasks are started
     sequentially in main(), the second task  cannot  be  created
     until  the  first becomes blocked and main() regains control
     to create a new task, and so on for additional tasks.   This
     also  means  that  main() must invoke resultis() or cancel()
     after starting all its tasks, so that it  doesn't  exit  and
     terminate the entire program while tasks are running.

     Any task constructor may itself create new tasks.

  Class object
     Class object has only one constructor, which takes no  argu-
     ments.

     object o;
          Constructs an object o (which  is  illegal,  since  the
          constructor is protected), which is not on any list.

     object *p = o.o_next;
          An object may be on at most one list (run chain, queue,
          etc)  at  at  time.   The  next  object  on the list is
          pointed to by public data member o_next.   This  member
          will  be  zero if there is no next object, and, in par-
          ticular, if the current object is not on any list.

     objtype t = p->o_type();
          This virtual function returns the enumeration  constant
          of  type  objtype  corresponding  to the type of object
          which p points to.

     int i = p->pending();
          Returns non-zero (true) if the object pointed to  by  p
          is  not  ready.  Derived classes must define a suitable
          version of this virtual function  if  they  are  to  be
          waited  on.  The default version in class object always
          returns true (not ready).  The other predefined classes
          have their own versions of this function.

     o.print(how);
          Prints basic information about the object pointed to by
          p  on  stdout  (not cout).  If the first int parameter,
          how, has bit VERBOSE set, prints information about  all
          the  tasks  on the object's remember chain.  The second
          argument is for internal  use  and  defaults  to  zero.
          This virtual function is normally called by the print()
          functions from derived classes.

     o.alert()
          Scans the remember chain of task o, changes  each  task
          from IDLE to RUNNING mode and puts it on the run chain.
          When a pending object is waited on, the waiting task is
          made  IDLE,  taken  off  the  run chain, and put on the
          object's remember chain.  When the  object  becomes  no
          longer  pending,  this function is called automatically
          by the predefined classes to wake up  all  the  waiting
          tasks.

     o.forget(p)
          Removes all instances of the task pointed to by p  from
          the remember chain of task o.

     o.remember(p)
          Adds the task pointed to by p to the remember chain  of
          task o.

     int user_err_func(int, object*);
     object::error_fct = user_err_func;
          Allows  the  user  a  measure  of  control  over  error
          recovery.  If a user error function is defined, it must
          take an int parameter which is one of the error numbers
          in  the  DIAGNOSTICS section below, and a pointer to an
          object.  The latter will be  the  object  which  called
          function  object::task_error(),  or  which is otherwise
          responsible for the error, as explained below.   Static
          data  member  object::error_fct  may be set to point to
          such a user error function.  If it is set, task_error()
          will  call  the  user  function.   If the user function
          returns zero, task_error() will return, and the  opera-
          tion  which  resulted  in  an  error will presumably be
          retried.   If  the  user  function  returns   non-zero,
          task_error() will call exit().

     int i = o.task_error(err, p);
     int i = object::task_error(err, p);
          This static member function is called  by  task  system
          functions  when a run-time error occurs.  The first int
          parameter is one of the error codes listed in the DIAG-
          NOSTICS   section   below.   The  second  parameter  is
          intended to be the object which called the function, or
          may  be zero if there is no identifiable object respon-
          sible.   If  static  data  member  error_fct  is  zero,
          task_error()  prints a message on stderr (not cerr) and
          calls exit(err).  If error_fct is  non-zero,  the  user
          function  is  called with parameters err and p.  If the
          user function returns 0, then so  does  task_error()  .
          Otherwise,  it calls exit(err) as above.  If this func-
          tion returns 0, its caller is  intended  to  retry  the
          operation which failed.

     task *tp = o.this_task();
     task *tp = object::this_task();
          This static member function returns a  pointer  to  the
          task which is currently running.

  Class Sched
     Class sched provides the  basic  scheduling  functions,  and
     classes  task and timer are each derived from it.  No object
     of this class may be created;  it  serves  only  as  a  base
     class.

     sched s;
          Constructs an object s of type sched (which is illegal,
          since  the  constructor is protected).  The constructor
          has no arguments.  The object is initialized to be IDLE
          and have no delay.

     task* tp = ...;
     sched::clock_task = tp;
          If static data member  sched::clock_task  is  non-zero,
          the  task  it  points  to  will be scheduled before any
          other task each time  the  clock  advances.   When  the
          current  task, if any, is blocked, this clock task will
          be resumed.  The clock task must be  IDLE  when  it  is
          resumed,  and may place itself in that state by calling
          task::sleep().

     void user_exit_func(void);
     sched::exit_fct = user_exit_func;
          You may declare a function  taking  no  parameters  and
          returning  void  and  assign  it  to static data member
          sched::exit_fct.  This function  will  then  be  called
          just before final exit from the task system.

     int i = s.pending();
          The version of this function for  class  sched  returns
          non-zero (true) if the object (a task or timer) is TER-
          MINATED, and zero (false) otherwise.

     s.print(how);
          Prints data about the sched portion of  the  object  on
          stdout  (not  cout).   The first int parameter, how, is
          passed to object::print().  The second argument is  for
          internal  use and defaults to zero.  This virtual func-
          tion is normally called by the print()  functions  from
          derived classes.

     tp->setwho(objp)
          This virtual function is provided for classes task  and
          timer.   See  the  writeup for those classes.  It is an
          error to call this version.

     s.cancel(val);
          Puts task or timer s in the TERMINATED state, and  uses
          int   value   val   as   its  returned  value.   Unlike
          resultis(), cancel() does not suspend the caller.  This
          enables  one  task to terminate another while retaining
          control.

     int i = s.dont_wait();
          Returns the difference  between  the  number  of  times
          keep_waiting() and the number of times dont_wait() have
          been called, not counting this call.  The count is then
          decremented.   This count is kept in a static variable,
          so it represents the system-wide difference.  The count
          is  supposed  to  represent the number of objects which
          are waiting for external  events.   See  keep_waiting()
          below.

     sched *tp = s.get_priority_sched();
          A  special  system  task,  the  interrupt  alerter,  is
          priority-scheduled when a signal has occurred which was
          being waited for.  This function returns a  pointer  to
          that  task  if  it  has been scheduled, zero otherwise.
          See also interrupt(3CC4).

     int i = s.keep_waiting();
          Returns the difference  between  the  number  of  times
          keep_waiting() and the number of times dont_wait() have
          been called, including this call.  That is,  the  count
          is  first  incremented.  This count is kept in a static
          variable, so it represents the system-wide  difference.
          The  count  is  supposed  to  represent  the  number of
          objects which are waiting for external events.  In par-
          ticular,  the  constructor  for class Interrupt_handler
          calls   keep_waiting()   and   the   destructor   calls
          dont_wait().   The  scheduler  uses this information so
          the task system doesn't exit  when  interrupt  handlers
          are active.

     statetype t = s.rdstate();
          Returns the state of task or timer s:   RUNNING,  IDLE,
          or TERMINATED.

     long l = s.rdtime();
          Returns the simulated time at which task or timer s  is
          scheduled to run.

     int i = s.result();
          Returns the ``result'' of  task  s,  which  is  set  by
          sched::cancel(),  task::cancel(),  or task::resultis().
          If task s has not terminated, the calling task will  be
          suspended  until it does terminate.  It is an error for
          a task to call result() on itself.

     long l = s.getclock();
     long l = sched::getclock();
          Returns the value of the current simulated time.

     sched* p = s.get_run_chain();
     sched* p = sched::get_run_chain();
          Returns a pointer to the run chain,  the  list  of  all
          tasks and timers which are ready to run.  These objects
          are linked through the o_next field.

     int i = s.get_exit_status();
     int i = sched::get_exit_status();
          When the task system exits normally (not because  of  a
          call   to   task_error()),  the  value  last  given  to
          set_exit_status() is passed to the system  exit()  rou-
          tine.   This  is  by  default  zero,  the  indicator of
          succesful   completion.    Function   get_exit_status()
          returns  the  value  currently  slated  to be passed to
          exit().

     s.set_exit_status(i);
     sched::set_exit_status(i);
          The int value i is saved, and will  be  passed  to  the
          system  function  exit()  if the task system terminates
          normally (not because of a call to  task_error()).   If
          set_exit_status()  is  never called, that value will be
          zero, the indicator of  succesful  completion.   Other-
          wise,  the  last value passed to set_exit_status() will
          be used.

     s.setclock(l);
     sched::setclock(l);
          Sets the simulated clock to long value l.  System  time
          starts at zero by default.  It is an error to call this
          function more than once.

  Class Task
     task t(name, mode, size);
          Constructs a task.  The parameters are described above.
          As  also noted above, the constructor is protected, and
          thus task may serve only  as  a  base  class  for  user
          tasks.

     task *tp = t.t_next;
          The next task on the master list  of  all  tasks.   See
          get_task_chain() below.

     unsigned char* p = t.t_name;
          A pointer to the name of the task as  assigned  by  the
          task constructor.

     objtype o = t.o_type();
          This virtual function defined  in  object  returns  the
          kind of object.  For a task, the object kind is TASK.

     t.print(how);
          Prints data about task t on  stdout  (not  cout).   The
          first  int  parameter, how, may have any combination of
          the VERBOSE and CHAIN bits set.   If  VERBOSE  is  set,
          addtional  information  is  printed.   If CHAIN is set,
          information on every task in  the  system  is  printed.
          This parameter is passed to sched::print().  The second
          argument is for internal use and defaults to zero.

     t.setwho(objptr);
          This virtual function remembers the object  pointed  to
          by  objptr  as  the  object  which alerted task t.  The
          intent is that task t was waiting  on  object  *objptr,
          and  when  it  went  from  pending to ready, the object
          alerted this task and changed its state  from  IDLE  to
          RUNNING.   The  object  which  was  remembered  may  be
          retrieved with who_alerted_me().

     t.cancel(val);
          Puts task t in the TERMINATED state, and uses int value
          val as its returned value.  Unlike resultis(), cancel()
          does not suspend the caller.  This enables one task  to
          terminate  another  while  retaining control.  See also
          resultis().

     t.delay(n);
          Suspends task t for n simulated time units, leaving  it
          RUNNING.   The  RUNNING  task with the least delay left
          gets control, and the simulated clock  is  advanced  to
          its  continuation time.  When the clock has advanced by
          n units, task t will continue execution.   The  use  of
          delay() is the only way to advance the clock.

     int i = t.preempt();
          Suspends RUNNING task t, making it  IDLE.   It  returns
          the number of time units left before t was scheduled to
          continue execution.  It is an error to  call  preempt()
          for an IDLE or TERMINATED task.

     t.resultis(val);
          Puts task t in the TERMINATED state, and uses int value
          val  as its returned value.  This value may be examined
          by calling t.result().  Any  tasks  which  have  called
          result() on task t and are thus waiting for the task to
          terminate will be alerted.  A task  may  not  return  a
          value  via  the ordinary function return mechanism, but
          must call either resultis() or cancel()  to  terminate.
          Every task is pending until it is terminated.

     t.sleep(objptr);
          Unconditionally suspends task t, making it  IDLE.   The
          optional   argument  points  to  an  object  that  will
          ``remember'' task  t  and  alert  it  when  the  object
          becomes  ready.   Unlike wait(), sleep() does not first
          check the object to see whether it is pending; the task
          is always suspended.

     t.wait(objptr);
          Suspends task t (makes it IDLE) if the  object  pointed
          to  by  objptr  is  pending.   In  this case, t will be
          alerted by the object (made RUNNING and put back on the
          run  chain)  when  the  object  becomes  ready.  If the
          object is not pending, task t  is  not  suspended,  but
          retains control.

     int which = t.waitlist(op1, op2, ... , NULL);
          This function takes a list of pointers to objects, ter-
          minated  by  a  null  pointer.   If  all of the objects
          pointed to are pending, task t is suspended  until  one
          of  them becomes ready.  Waitlist returns when at least
          one of the tasks is ready, returning the index  (start-
          ing  from  0)  in  the  list of objects that caused the
          return.  Other objects in the list might also be  ready
          at  this  point.  If none of the objects are pending as
          of the call to waitlist(), task t is not suspended  and
          waitlist() returns immediately.

     int which = t.waitvec(objarray);
          This works in  exactly  the  same  way  as  waitlist(),
          except that this function takes an an array of pointers
          to objects instead  of  a  variable-length  list.   The
          array is terminated by a null pointer.

     task *tp = t.get_task_chain();
     task *tp = task::get_task_chain();
          This static member function returns  the  head  of  the
          list  of all tasks.  Every task in the system, RUNNING,
          IDLE, and TERMINATED, is on this list, linked  via  the
          t_next data member.

  Class Timer
     timer tm(d);
          Constructs a timer which will  expire  in  d  simulated
          time units.  The timer is placed on the run chain.

     objtype o = tm.o_type();
          This virtual function defined  in  object  returns  the
          kind of object.  For a timer, the object kind is TIMER.

     tm.print(how);
          Prints data about timer tm on stdout (not  cout).   The
          first  int parameter, how, is passed to sched::print().
          The second argument is for internal use and defaults to
          zero.

     tm.setwho(objptr);
          This virtual function has no effect for  timers,  since
          they cannot be alerted.

     tm.reset(d);
          Resets the delay of timer tm to d simulated time units.
          A  timer  may  be reset even if it has been terminated.
          This means that a timer may be reused; they need not be
          continually created and destroyed.


DIAGNOSTICS

     When the task system detects a  run  time  error,  it  calls
     object::task_error()  as  described  above.   The  following
     table lists the possible error values, associated  messages,
     and meanings.




     ____________________________________________________________
      Error Name    Message                   Explanation
     ____________________________________________________________
      E_ERROR       (no message)              Undefined error.
     ____________________________________________________________
      E_OLINK       object::delete():         Attempt to des-
                    has chain                 troy an object
                                              which
                                              ``remembers''
                                              one or more
                                              objects.
     ____________________________________________________________
      E_ONEXT       object::delete(): on      Attempt to des-
                    chain                     troy an object
                                              which is on a
                                              list.
     ____________________________________________________________
      E_GETEMPTY    qhead::get(): empty       Attempt to get
                                              from an empty
                                              queue.
     ____________________________________________________________
      E_PUTOBJ      qtail::put(): object      Attempt to put
                    on other queue            an object on a
                                              queue which is
                                              already on a
                                              queue.
     ____________________________________________________________
      E_PUTFULL     qtail::put(): full        Attempt to put
                                              an object on a
                                              full queue.
     ____________________________________________________________
      E_BACKOBJ     qhead::putback():         Attempt to put
                    object on other           back onto a
                    queue                     queue an object
                                              which is already
                                              on a queue.
     ____________________________________________________________
      E_BACKFULL    qhead::putback():         Attempt to put
                    full                      back an object
                                              to a full queue.
     ____________________________________________________________
      E_SETCLOCK    sched::setclock():        Attempt to set
                    clock!=0                  the clock twice.
     ____________________________________________________________
      E_CLOCKIDLE   sched::schedule():        The clock task
                    clock_task not idle       was not IDLE
                                              when it was
                                              scheduled to be
                                              run.



     ____________________________________________________________
    | E_RESTERM   | sched::insert():        | Attempt to        |
    |             | cannot schedule ter-    | resume a TER-     |
    |             | minated sched           | MINATED task.     |
    |_____________|_________________________|___________________|
    | E_RESRUN    | sched::schedule():      | Attempt to        |
    |             | running                 | resume a RUNNING  |
    |             |                         | task.             |
    |_____________|_________________________|___________________|
    | E_NEGTIME   | sched::schedule():      | Attempt to set    |
    |             | clock<0                 | the clock to a    |
    |             |                         | negative value    |
    |             |                         | or use a nega-    |
    |             |                         | tive delay.       |
    |_____________|_________________________|___________________|
    | E_RESOBJ    | sched::schedule():      | Attempt to        |
    |             | task or timer on        | resume task       |
    |             | other queue             | already on a      |
    |             |                         | queue.            |
    |_____________|_________________________|___________________|
    | E_HISTO     | histogram::histogram(): | Inconsistent or   |
    |             | bad arguments           | illegal argu-     |
    |             |                         | ments to histo-   |
    |             |                         | gram construc-    |
    |             |                         | tor.              |
    |_____________|_________________________|___________________|
    | E_STACK     | task::task() or         | The run time      |
    |             | task::resume():         | task stack has    |
    |             | stack overflow          | overflowed.       |
    |_____________|_________________________|___________________|
    | E_STORE     | new: free store         | No more free      |
    |             | exhausted               | store available   |
    |             |                         | for task book-    |
    |             |                         | keeping.          |
    |_____________|_________________________|___________________|
     continued...
















     ______________________________________________________________
      Error Name    Message                      Explanation
     ______________________________________________________________
      E_TASKMODE    task::task(): bad            Illegal mode
                    mode                         arguments for
                                                 the task con-
                                                 structor.
     ______________________________________________________________
      E_TASKDEL     task::~task(): not           Attempt to des-
                    terminated                   troy a non-
                                                 TERMINATED task.
     ______________________________________________________________
      E_TASKPRE     task::preempt(): not         Attempt to
                    running                      preempt a non-
                                                 RUNNING task.
     ______________________________________________________________
      E_TIMERDEL    timer::~timer(): not         Attempt to des-
                    terminated                   troy a non-
                                                 TERMINATED
                                                 timer.
     ______________________________________________________________
      E_SCHTIME     sched::schedule():           Run chain cor-
                    runchain corrupted:          rupted, not in
                    bad time                     time order.
     ______________________________________________________________
      E_SCHOBJ      sched object used            Attempt to use a
                    directly (not as             sched object
                    base)                        rather than a
                                                 derived task or
                                                 timer.
     ______________________________________________________________
      E_QDEL        queue::~queue(): not         Attempt to des-
                    empty                        troy a non-empty
                                                 queue.
     ______________________________________________________________
      E_RESULT      task::result():              A task attempted
                    thistask->result()           to call result()
                                                 on itself.
     ______________________________________________________________
      E_WAIT        task::wait(): wait           A task attempted
                    for self                     to wait on
                                                 itself.
     ______________________________________________________________
      E_FUNCS       FrameLayout::FrameLayout():  (not used)
                    function start
     ______________________________________________________________
      E_FRAMES      FrameLayout::FrameLayout():  (not used)
                    frame size
     ______________________________________________________________
      E_REGMASK     task::fudge_return():
                    unexpected register
                    mask
                                                 (not used)



















































     ______________________________________________________________
    | E_FUDGE_SIZE| task::fudge_return():      | (not used)       |
    |             | frame too big              |                  |
    |_____________|____________________________|__________________|
    | E_NO_HNDLR  | signal_handler - no        | A signal         |
    |             | handler for signal         | occurred but no  |
    |             |                            | handler was      |
    |             |                            | registered.      |
    |_____________|____________________________|__________________|
    | E_BADSIG    | illegal signal             | Attempt to       |
    |             | number                     | register an      |
    |             |                            | illegal signal   |
    |             |                            | number.          |
    |_____________|____________________________|__________________|
    | E_LOSTHNDLR | Interrupt_handler::        | Internal error:  |
    |             | ~Interrupt_handler():      | a signal handler |
    |             | signal handler not         | was lost.        |
    |             | on chain                   |                  |
    |_____________|____________________________|__________________|
    | E_RUNCHAIN  | sched::sched(): run        | All tasks have   |
    |             | chain empty                | terminated and   |
    |             |                            | there are no     |
    |             |                            | interrupt        |
    |             |                            | handlers.        |
    |_____________|____________________________|__________________|


NOTE

     As of the date of this release, the coroutine  library  will
     not be supported beyond the current version.


SEE ALSO

     task.intro(3CC4), interrupt(3CC4), queue(3CC4),
     tasksim(3CC4), exit(3C).