home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / c / kernel.arc / K1.C next >
Text File  |  1986-11-25  |  28KB  |  750 lines

  1. /*
  2. Listing 1      Scheduling Algorithm
  3. (C) Copyright 1986 Ken Berry.
  4. All rights reserved.
  5. Copies may be made for non-commercial, private use only.
  6. */
  7.  
  8. #define _F 0         /* false */
  9. #define _T 1         /* true */
  10. #define _E -1         /* error */
  11.  
  12. #define _NULL 0      /* null pointer */
  13.  
  14. typedef char pointer;     /* pointer type */
  15. typedef char logical;     /* logical type */
  16. typedef unsigned selector; /* 8086 selector type */
  17.  
  18. struct sys_parm      /* register storage block for 8086 interface */
  19. {
  20.   union {unsigned sys_rax; struct {char sys_ral, sys_rah;} sys_byt;} sys_ra;
  21.   union {unsigned sys_rbx; struct {char sys_rbl, sys_rbh;} sys_byt;} sys_rb;
  22.   union {unsigned sys_rcx; struct {char sys_rcl, sys_rch;} sys_byt;} sys_rc;
  23.   union {unsigned sys_rdx; struct {char sys_rdl, sys_rdh;} sys_byt;} sys_rd;
  24. #define sys_ax sys_ra.sys_rax
  25. #define sys_al sys_ra.sys_byt.sys_ral
  26. #define sys_ah sys_ra.sys_byt.sys_rah
  27. #define sys_bx sys_rb.sys_rbx
  28. #define sys_bl sys_rb.sys_byt.sys_rbl
  29. #define sys_bh sys_rb.sys_byt.sys_rbh
  30. #define sys_cx sys_rc.sys_rcx
  31. #define sys_cl sys_rc.sys_byt.sys_rcl
  32. #define sys_ch sys_rc.sys_byt.sys_rch
  33. #define sys_dx sys_rd.sys_rdx
  34. #define sys_dl sys_rd.sys_byt.sys_rdl
  35. #define sys_dh sys_rd.sys_byt.sys_rdh
  36.   unsigned sys_bp;     /* base pointer */
  37.   unsigned sys_si;     /* source index */
  38.   unsigned sys_di;     /* destination index */
  39.   unsigned sys_sp;     /* stack pointer */
  40.   unsigned sys_cs;     /* code segment */
  41.   unsigned sys_ds;     /* data segment */
  42.   unsigned sys_ss;     /* stack segment */
  43.   unsigned sys_es;     /* extra segment */
  44.   unsigned sys_pf;     /* 80286 processor flags */
  45. #define SYS_OF 0x0800          /* overflow flag- 1: lost significance */
  46. #define SYS_DF 0x0400          /* direction flag- 1: strings auto-decrement */
  47. #define SYS_IF 0x0200          /* interrupt flag- 1: enable interrupts */
  48. #define SYS_TF 0x0100          /* trap flag- 1: interrupt every instruction */
  49. #define SYS_SF 0x0080          /* sign flag- 1: result negative */
  50. #define SYS_ZF 0x0040          /* zero flag- 1: result 0 */
  51. #define SYS_AF 0x0010          /* auxiliary carry flag- 1: carry from bit 3 */
  52. #define SYS_PF 0x0004          /* parity flag- 1: even number of 1's */
  53. #define SYS_CF 0x0001          /* carry flag- 1: carry from bit 8 or 16 */
  54.   unsigned sys_sw;     /* status word */
  55. #define SYS_TS 0x0008          /* task switch */
  56. #define SYS_EM 0x0004          /* processor extension emulation */
  57. #define SYS_MP 0x0002          /* monitor processor extension */
  58. #define SYS_PE 0x0001          /* protection enable */
  59.   unsigned sys_ip;     /* instruction pointer */
  60.   unsigned sys_res;     /* unused */
  61. };
  62.  
  63. struct t_xstck
  64. {
  65.   unsigned t_xbase;     /* application stack base (overflow detection) */
  66.   unsigned t_xes;     /* es */
  67.   unsigned t_xbp;     /* bp */
  68.   unsigned t_xdi;     /* di */
  69.   unsigned t_xsi;     /* si */
  70.   unsigned t_xdx;     /* dx */
  71.   unsigned t_xcx;     /* cx */
  72.   unsigned t_xbx;     /* bx */
  73.   unsigned t_xax;     /* ax */
  74.   unsigned t_xds;     /* ds */
  75.   unsigned t_xip;     /* ip */
  76.   unsigned t_xcs;     /* cs */
  77.   unsigned t_xpf;     /* pf */
  78.   unsigned t_retip;     /* return address */
  79. };
  80.  
  81. struct t_task
  82. {
  83.   char t_type;         /* task type */
  84. #define T_X 0x80     /* execute queue */
  85. #define T_W 0x40     /* wait queue */
  86. #define T_P 0x20     /* priority queue */
  87. #define T_SW 0x10     /* secondary wait queue */
  88. #define T_ATASK 0x01     /* abreviated task */
  89.   unsigned t_wttk;     /* wait tick count */
  90.   unsigned t_cls;     /* priority queue index */
  91.   struct t_task *t_pqtsk,*t_nqtsk; /* queue linkage */
  92.   struct t_task *t_ratsk,*t_pstsk,*t_nstsk,*t_fdtsk,*t_ldtsk; /* family */
  93.   struct sys_parm t_ps;  /* processor status */
  94.   unsigned t_xtm0;     /* execution time accumulator */
  95.   unsigned t_xtm1;
  96.   unsigned t_xtm2;
  97.   pointer *t_axstk;     /* execution stack pointer */
  98. };
  99.  
  100. extern pointer *sys_task; /* current task control table pointer */
  101. #define _tsk ( ( struct t_task * ) sys_task ) /* task control table ref */
  102.  
  103. #define T_SCLS 4     /* number of scheduling classes */
  104.  
  105. struct t_scls         /* scheduling class queue */
  106. {
  107.   unsigned t_sfrq;     /* scheduling frequency */
  108.   int t_sct;         /* queue length */
  109.   struct t_task *t_fqtsk,*t_lqtsk; /* queue header */
  110. };
  111.  
  112. struct t_schd         /* scheduling control table */
  113. {
  114.   int t_xct;         /* execution queue length */
  115.   struct t_task *t_fxtsk, *t_lxtsk; /* execution queue header */
  116.   int t_wct;         /* wait queue length */
  117.   struct t_task *t_fwtsk, *t_lwtsk; /* wait queue header */
  118.   int t_swct;         /* secondary wait queue length */
  119.   struct t_task *t_fswtsk, *t_lswtsk; /* secondary wait queue header */
  120.   int t_sclsl;         /* scheduling class index limit */
  121.   struct t_scls **t_sclsp; /* scheduling class array pointer */
  122. };
  123.  
  124. extern pointer *sys_tsch; /* task scheduling control table pointer */
  125. #define _tschd ( ( struct t_schd * ) sys_tsch ) /* quick pointer */
  126.  
  127. /*
  128. t__krnl          * security kernel *
  129. */
  130. t__krnl()
  131. /*
  132. This is the security kernel.  It never returns, being the most trusted
  133. software in the system. The current contents in t__crtss and t__crtsp
  134. are used to set the stack for when the current task is resumed. */
  135. {
  136.   extern logical t_astrm; /* tick termination flag */
  137.   extern selector t__crtss; /* current task ss storage */
  138.   extern pointer *t__crtsp; /* current task sp storage */
  139.   extern unsigned tmr_tkct; /* tick clock */
  140.   int xtskct;         /* task queue count (at entry) */
  141.   int ttc;         /* task termination code */
  142.   _tsk -> t_ps.sys_ss = t__crtss; /* set current task stack */
  143.   _tsk -> t_ps.sys_sp = t__crtsp;
  144.   while(_T)         /* find executable task */
  145.   {
  146.     xtskct = _tschd -> t_xct; /* save task count */
  147.     if ( t_astrm ) t__wtst( tmr_tkct ); /* process wait tasks */
  148.     if ( xtskct == 0 ) t__sch(); /* schedule application tasks if necessary */
  149.     sys_task = _tschd -> t_fxtsk; /* set next task address */
  150.     if ( sys_task != _NULL )  /* test for executable task available */
  151.     {
  152.       _tschd -> t_xct--; /* decrement executing task count */
  153.       _tschd -> t_fxtsk = _tsk -> t_nqtsk; /* delink task */
  154.       if ( _tschd -> t_fxtsk == _NULL )
  155.     _tschd -> t_lxtsk = _NULL;
  156.       else _tschd -> t_fxtsk -> t_pqtsk = _NULL;
  157.       _tsk -> t_type &= ~T_X; /* indicate task not in execution queue */
  158.       ttc = t__xtsk( sys_task ); /* execute application task */
  159.       if ( !sys_task ) continue; /* test for task terminated */
  160.       if ( ttc < 0 ) t__inxq(); /* insert task into execution queue */
  161.       else if ( ttc == 0 ) t__inpq(); /* insert task into priority queue */
  162.       else t__inwq( ttc ); /* insert into wait queue */
  163.     }
  164.   }
  165. }
  166.  
  167. /*
  168. t__wtst          test waiting tasks
  169. */
  170. t__wtst( tc)
  171. unsigned tc;
  172. /*
  173. The wait queue is traversed.  All tasks with a wait value of tc are executed.
  174. _F is always returned. */
  175. {
  176.   while(_T)         /* traverse wait queue */
  177.   {
  178.     sys_task = _tschd -> t_fwtsk; /* set current task pointer */
  179.     if ( !sys_task ) break; /* test for no waiting tasks */
  180.     _tsk -> t_type &= ~T_W; /* remove task from wait queue */
  181.     _tsk -> t_type |= T_X; /* indicate task in execution queue */
  182.     if ( _tsk -> t_wttk > tc ) break; /* test for effective end of list */
  183.     --_tschd -> t_wct;     /* decrement waiting task  count */
  184.     _tschd -> t_fwtsk = _tsk -> t_nqtsk; /* delink from wait queue */
  185.     if ( _tsk -> t_nqtsk == _NULL )
  186.       _tschd -> t_lwtsk = _NULL;
  187.     else _tsk -> t_nqtsk -> t_pqtsk = _NULL;
  188.     _tsk -> t_pqtsk = _NULL; /* insert at top of execution queue */
  189.     _tsk -> t_nqtsk = _tschd -> t_fxtsk;
  190.     _tschd -> t_fxtsk = sys_task;
  191.     ++_tschd -> t_xct;     /* increment executable task count */
  192.     if ( _tschd -> t_lxtsk == _NULL )
  193.       _tschd -> t_lxtsk = sys_task;
  194.     else _tsk -> t_nqtsk -> t_pqtsk = sys_task;
  195.   }
  196.   return _F;         /* return */
  197. }
  198.  
  199. /*
  200. t__sch             schedule task
  201. */
  202. t__sch()
  203. /*
  204. This function searches the priority queues and links tasks ready for execution
  205. into the execution queue. The return is always _F. */
  206. {
  207.   struct t_scls **a;     /* priority queue pointer array pointer */
  208.   struct t_scls *q;     /* priority queue pointer */
  209.   int i,j;         /* iteration variables */
  210.   a = _tschd -> t_sclsp; /* set pointer array address */
  211. /*  while(_T)            * nonterminating task *
  212.   { */
  213.     for ( i = 0; i < _tschd -> t_sclsl; ++i ) /* traverse queues */
  214.     {
  215.       q = a[i];      /* set priority queue pointer */
  216.       for ( j = 0; j++<q -> t_sfrq; ) /* schedule tasks from priority queue */
  217.       {
  218.     if ( q -> t_fqtsk == _NULL ) break; /* test for queue empty */
  219.     if ( _tschd -> t_lxtsk ) /* link to end of execution queue */
  220.       _tschd -> t_lxtsk -> t_nqtsk = q -> t_fqtsk;
  221.     else _tschd -> t_fxtsk = q -> t_fqtsk;
  222.     q -> t_fqtsk -> t_type &= ~T_P; /* indicate not in priority queue */
  223.     q -> t_fqtsk -> t_pqtsk = _tschd -> t_lxtsk;
  224.     _tschd -> t_lxtsk = q -> t_fqtsk;
  225.     q -> t_fqtsk = q -> t_fqtsk -> t_nqtsk; /* update queue header */
  226.     _tschd -> t_lxtsk -> t_nqtsk = _NULL;
  227.     if ( q -> t_fqtsk == _NULL )
  228.       q -> t_lqtsk = _NULL;
  229.     else q -> t_fqtsk -> t_pqtsk = _NULL;
  230.     q -> t_sct --;     /* decrement queue count */
  231.     ++ _tschd -> t_xct; /* increment execution queue length */
  232.     _tschd -> t_lxtsk -> t_type |= T_X; /* ind. task in execution queue */
  233.       }
  234.     }
  235. /*    t_rels();         * return to bottom of execution queue *
  236.   }*/
  237.   return _F;         /* return */
  238. }
  239.  
  240. /*
  241. t__inxq          insert task into execution queue
  242. */
  243. t__inxq()
  244. /*
  245. The current task is inserted into the execution queue. _F is always returned.
  246. */
  247. {
  248.   _tsk -> t_wttk = 0;     /* indicate not waiting for system tick */
  249.   if ( _tschd -> t_lxtsk == _NULL ) /* test for execution queue empty */
  250.   {
  251.     _tschd -> t_fxtsk = sys_task; /* insert in empty queue */
  252.     _tsk -> t_pqtsk = _NULL;
  253.   }
  254.   else             /* execution queue not empty */
  255.   {
  256.     _tschd -> t_lxtsk -> t_nqtsk = sys_task; /* insert at end of queue */
  257.     _tsk -> t_pqtsk = _tschd -> t_lxtsk;
  258.   }
  259.   _tsk -> t_nqtsk = _NULL; /* new task at end of list */
  260.   _tschd -> t_lxtsk = sys_task;
  261.   _tschd -> t_xct++;     /* increment executable task count */
  262.   _tschd -> t_lxtsk -> t_type |= T_X; /* indicate task in execution queue */
  263.   return _F;         /* return */
  264. }
  265.  
  266. /*
  267. t__secw          process secondary wait queue
  268. */
  269. t__secw()
  270. /*
  271. This program executes every 64K system ticks. It moves the secondary
  272. wait queue to the primary wait queue and changes the type of the waiting
  273. tasks. */
  274. {
  275.   struct t_task *tsk;     /* task control table pointer */
  276.   char swtflg;         /* system state flag */
  277.   extern int tmr_tkct;     /* tick clock     */
  278.   while(_T)         /* nonterminating task */
  279.   {
  280.     t__syntr( &swtflg ); /* enter system state */
  281.     for ( tsk = _tschd -> t_fwtsk; tsk; tsk = tsk -> t_nqtsk ) /* traverse */
  282.     {
  283.       tsk -> t_type &= ~T_SW;
  284.       tsk -> t_type |= T_W; /* change task type */
  285.     }
  286.     _tschd -> t_wct = _tschd -> t_swct; /* append secondary wait queue */
  287.     _tschd -> t_fwtsk = _tschd -> t_fswtsk;
  288.     _tschd -> t_lwtsk = _tschd -> t_lswtsk;
  289.     _tschd -> t_fswtsk = _tschd -> t_lswtsk = _NULL; /* empty sec. queue */
  290.     _tschd -> t_swct = 0;
  291.     t__inwq( 0xFFFF - tmr_tkct ); /* insert self into wait queue at end */
  292.     sys_task = _NULL;     /* remove task from kernel control */
  293.     t_term();         /* suspend execution */
  294.   }
  295. }
  296.  
  297. /*
  298. t__inwq          insert task into wait queue
  299. */
  300. t__inwq(tc)
  301. unsigned tc;
  302. /*
  303. The  current task is inserted into the wait queue.  tc is the number of system
  304. ticks that the task is to wait. _F is always returned. */
  305. {
  306.   extern unsigned tmr_tkct; /* tick clock */
  307.   unsigned crtk;     /* current tick */
  308.   crtk = tmr_tkct;     /* set current system tick */
  309.   _tsk -> t_wttk = tc + crtk; /* compute reactivation time */
  310.   if ( _tsk -> t_wttk >= crtk ) /* test for task in wait queue */
  311.   { t__inwt( &_tschd -> t_wct ); /* insert in wait queue */
  312.     _tsk -> t_type |= T_W;
  313.   }else          /* task in secondary wait queue */
  314.   { t__inwt( &_tschd -> t_swct ); /* insert in secondary wait queue */
  315.     _tsk -> t_type |= T_SW;
  316.   }return _F;         /* indicate task inserted */
  317. }
  318.  
  319. /*
  320. t__inwt          insert into wait or secondary wait queue
  321. */
  322. struct t_wtq
  323. {
  324.   int wct;         /* wait queue length */
  325.   struct t_task *frs,*lst; /* queue header */
  326. };
  327. t__inwt( w )
  328. struct t_wtq *w;
  329. /*
  330. The t_wtq structure is implicitly contained in the scheduling control table
  331. (t_schd structure).  The current task is inserted into the queue. _F is always
  332. returned. */
  333. {
  334.   struct t_task *p;     /* task pointer */
  335.   unsigned tc;         /* reactivation time */
  336.   tc = _tsk -> t_wttk;     /* set reactivation time */
  337.   ++w -> wct;         /* increment queue length */
  338.   for ( p = w -> frs; p; p = p -> t_nqtsk ) /* traverse queue */
  339.   {
  340.     if ( tc < p -> t_wttk ) /* test for task earlier */
  341.     {
  342.       _tsk -> t_nqtsk = p; /* insert within queue */
  343.       _tsk -> t_pqtsk = p -> t_pqtsk;
  344.       p -> t_pqtsk = sys_task;
  345.       if ( ( p = _tsk -> t_pqtsk ) ) p -> t_nqtsk = sys_task;
  346.       else w -> frs = sys_task;
  347.       return _F;     /* indicate task inserted */
  348.     }
  349.   }
  350.   if ( ( p = w -> lst ) ) /* test for wait queue not empty */
  351.   {
  352.     p -> t_nqtsk = w -> lst = sys_task; /* insert at end of queue */
  353.     _tsk -> t_pqtsk = p;
  354.     _tsk -> t_nqtsk = _NULL;
  355.   }
  356.   else             /* wait queue empty */
  357.   {
  358.     w -> frs = w -> lst = sys_task; /* initialize wait queue */
  359.     _tsk -> t_nqtsk = _tsk -> t_pqtsk = _NULL;
  360.   }
  361.   return _F;         /* indicate task inserted */
  362. }
  363.  
  364. /*
  365. t__inpq          insert into priority queue
  366. */
  367. t__inpq()
  368. /*
  369. The current task is inserted into its priority queue. _F is always returned.
  370. */
  371. {
  372.   struct t_scls *q;     /* priority queue pointer */
  373.   _tsk -> t_wttk = 0;     /* indicate not waiting for tick */
  374.   q = _tschd -> t_sclsp[ _tsk -> t_cls ]; /* set priority queue address */
  375.   _tsk -> t_pqtsk = q -> t_lqtsk; /* link task into priority queue */
  376.   _tsk -> t_nqtsk = _NULL;
  377.   if ( q -> t_lqtsk == _NULL ) q -> t_fqtsk = sys_task;
  378.   else q -> t_lqtsk -> t_nqtsk = sys_task;
  379.   q -> t_lqtsk = sys_task;
  380.   ++q -> t_sct;      /* increment queue length */
  381.   _tsk -> t_type |= T_P; /* indicate task in priority queue */
  382.   return _F;         /* return */
  383. }
  384.  
  385. /*
  386. t__xtsk          execute task
  387. */
  388. t__xtsk( t )
  389. struct t_task *t;
  390. /*
  391. Task t is executed. The returned value is the termination code.
  392. */
  393. {
  394.   extern unsigned t_mnxtm; /* minimum execution time */
  395.   extern unsigned t_syxtm[]; /* system pseudo time accumulator */
  396.   extern logical t_astrm; /* application termination flag */
  397.   extern int t__crtss;    /* current task ss storage    */
  398.   extern int t__crtsp;    /* current task sp storage    */
  399.   int ttc;         /* return value storage */
  400.   unsigned atm;      /* accumulated time */
  401.   unsigned rtm;      /* reference time */
  402.   int xtm;         /* execution time */
  403.   atm = 0;         /* initialize accumulated execution time */
  404.   while(_T)         /* execute task */
  405.   {
  406.     rtm = t -> t_xtm0;     /* set reference time */
  407.     t_rtmark( &t -> t_xtm0 ); /* accumulate pseudo time */
  408.     ttc = t__dspap( t -> t_ps.sys_ss, t -> t_ps.sys_sp ); /* execute task */
  409.     t -> t_ps.sys_ss = t__crtss; /* store ss */
  410.     t -> t_ps.sys_sp = t__crtsp; /* store sp */
  411.     t_rtmark( &t_syxtm ); /* accumulate pseudo time */
  412.     if ( ( ttc != 0 ) || !t_astrm ) break; /* test for not tick termination */
  413.     xtm = t -> t_xtm0 - rtm; /* compute execution time */
  414.     if ( xtm < rtm ) xtm = -xtm;
  415.     atm += xtm;      /* accumulate execution time */
  416.     if ( atm >= t_mnxtm ) break; /* test for minimum time satisfied */
  417.   }
  418.   return ttc;         /* return */
  419. }
  420. /*
  421. t__init          initialize task system
  422. */
  423. t__init()
  424. /*
  425. This function initializes the task system. _F is the normal return. _E is
  426. returned if the system cannot be initialized. */
  427. {
  428. #define WSTK 252     /* t_wqupd stack size */
  429.   extern struct sys_parm sys_stat; /* initial processor status */
  430.   extern struct t_task *t_wqupd; /* secondary wait queue update task */
  431.   extern selector sys_dgrp; /* data segment selector storage */
  432.   extern char *sys_ssbs; /* system stack pointer */
  433.   extern unsigned sys_sssz; /* system stack length */
  434.   extern char tmr_ilck;  /* tick service interlock */
  435.   int t__secw();     /* wait queue update function */
  436.   struct t_scls *cls;     /* priority queue pointer */
  437.   struct t_scls **ary;     /* priority queue pointer array pointer */
  438.   int i;         /* iteration variable */
  439.   char *s;         /* pointer */
  440.   tmr__int();         /* initialize system tick clock */
  441.   sys_task = sys_ssbs + sys_sssz; /* set main task control table pointer */
  442.   _tsk -> t_xtm0 =     /* initialize execution time */
  443.   _tsk -> t_xtm1 =
  444.   _tsk -> t_xtm2 = 0;
  445.   if( ( sys_tsch = mm_aloc( sizeof( struct t_schd ) ) ) == _NULL )goto err1;
  446.   if( ( ary = mm_aloc( T_SCLS*( sizeof( struct t_scls )+2 ) ) )
  447.      == _NULL )goto err2;
  448.   _tsk -> t_pqtsk =     /* NULL linkage */
  449.   _tsk -> t_nqtsk =
  450.   _tsk -> t_ratsk =
  451.   _tsk -> t_pstsk =
  452.   _tsk -> t_nstsk =
  453.   _tsk -> t_fdtsk =
  454.   _tsk -> t_ldtsk = _NULL;
  455.   _tsk -> t_cls = 0;     /* set priority class 0 */
  456.   _tsk -> t_wttk = 0;     /* indicate not waiting */
  457.   for( i = 0, s = &_tsk -> t_ps;
  458.     i++<sizeof( struct sys_parm ); )*s = 0; /* clear t_ps */
  459.   _tsk -> t_ps.sys_cs = sys_stat.sys_cs; /* set selectors */
  460.   _tsk -> t_ps.sys_ds =
  461.   _tsk -> t_ps.sys_es =
  462.   _tsk -> t_ps.sys_ss = sys_dgrp;
  463.   _tsk -> t_axstk = _NULL; /* NULL execution stack pointer */
  464.   _tschd -> t_xct = 1;     /* set execution task count */
  465.   _tschd -> t_fxtsk =     /* set execution queue */
  466.   _tschd -> t_lxtsk = sys_task;
  467.   _tschd -> t_wct = 0;     /* indicate idle wait queue */
  468.   _tschd -> t_fwtsk =     /* set wait queue */
  469.   _tschd -> t_lwtsk = _NULL;
  470.   _tschd -> t_swct = 0;  /* indicate empty secondary wait queue */
  471.   _tschd -> t_fswtsk =     /* NULL secondary wait queue */
  472.   _tschd -> t_lswtsk = _NULL;
  473.   _tschd -> t_sclsl = T_SCLS; /* set priority queue count */
  474.   _tschd -> t_sclsp = ary; /* set priority queue pointer array address */
  475.   cls = &ary[ T_SCLS ];  /* set first t_scls pointer */
  476.   for( i = 0; i<T_SCLS; ++i, ++cls ) /* initialize priority queues */
  477.   {
  478.     ary[i] = cls;     /* set priority queue pointer */
  479.     cls -> t_sfrq = 1;     /* set default frequency */
  480.     cls -> t_sct = 0;     /* indicate empty queue */
  481.     cls -> t_fqtsk =     /* NULL queue linkage */
  482.     cls -> t_lqtsk = _NULL;
  483.   }
  484.   t_wqupd =         /* create task to update wait queue */
  485.     t_crt( t__secw, 0, 0, WSTK, 0, 0, 0 );
  486.   if( t_wqupd == _NULL )goto err3;
  487.   t_wqupd -> t_wttk = 0xFFFF; /* update wait queue at wraparound time */
  488.   t__dspsy();         /* dispatch system */
  489.   tmr_ilck = 0x00;     /* enable tick service */
  490.   return _F;         /* indicate task system initialized */
  491. err3: mm_free( ary );     /* error nest */
  492. err2: mm_free( sys_tsch );
  493. err1: return _E;
  494. }
  495.  
  496. /*
  497. t__term
  498. */
  499. t__term()
  500. /*
  501. The task system is terminated. All tasks and storage allocated by t__init are
  502. released. The return is always _F. */
  503. {
  504.   extern char *sys_ssbs; /* system stack base */
  505.   extern unsigned sys_sssz; /* system stack size */
  506.   struct t_task *t;     /* t_task pointer */
  507.   char trmflg;         /* system state flag storage */
  508.   tmr__rst();         /* reset system tick clock */
  509.   t__syntr( &trmflg );     /* enter system state */
  510.   sys_task = sys_ssbs + sys_sssz; /* set original task address */
  511.   while( ( t = _tsk -> t_fdtsk ) ) /* delete all created tasks */
  512.     t_del( t, _F );
  513.   mm_free( _tschd -> t_sclsp );
  514.   mm_free( sys_tsch );
  515.   return _F;         /* normal return */
  516. }
  517.  
  518. /*
  519. t_crt             create task
  520. */
  521. t_crt( xadr, pcnt, padr, ssiz, dsiz, sadr, prty )
  522. pointer *xadr;
  523. unsigned pcnt;
  524. unsigned *padr;
  525. unsigned ssiz, dsiz;
  526. pointer *sadr;
  527. unsigned prty;
  528. /*
  529. A  new task is created with execution priority prty.  Execution will begin  at
  530. xadr.  pcnt parameters will be passed (on the new task stack).    The parameters
  531. are  in  an array addressed by padr.  The new task will have a stack  of  ssiz
  532. bytes  and a dynamic memory area of dsiz bytes.  dsiz may be zero to  indicate
  533. that no dynamic memory is required.  sadr will recieve a termination code when
  534. the  task  terminates. If sadr is _NULL, an abreviated task is created. _F  is
  535. returned if insufficient memory  is  available.  Otherwise the address of the
  536. t_ftask table is returned. */
  537. {
  538.   extern int t__halt();  /* return address */
  539.   struct t_task *tsk;     /* task control table pointer (t_task) */
  540.   struct t_scls *pq;     /* priority queue pointer */
  541.   struct t_xstck *sp;     /* execution stack pointer */
  542.   pointer *ss;         /* stack start */
  543.   unsigned *pr;      /* parameter pointer */
  544.   unsigned ln;         /* task control table length */
  545.   int i;         /* iteration variable */
  546.   char *s;         /* pointer */
  547.   char *sptr;         /* execution stack pointer */
  548.   logical crtflg;     /* system state flag storage */
  549.   t__syntr( &crtflg );     /* enter system state */
  550.   ln = sizeof( struct t_task );  /* allocate task control table */
  551.   if( ( tsk = mm_aloc( ln ) ) == _NULL ) goto err1;
  552.   ssiz += sizeof( struct t_xstck ); /* allocate stack */
  553.   if( ( ss = tsk -> t_axstk = mm_aloc( ssiz ) ) == _NULL )goto err2;
  554.   tsk -> t_type = T_ATASK; /* indicate abreviated task control table */
  555.   tsk -> t_wttk = 0;     /* indicate not waiting */
  556.   tsk -> t_ratsk = sys_task; /* task family linkage */
  557.   tsk -> t_pstsk = _tsk -> t_ldtsk;
  558.   tsk -> t_nstsk =
  559.   tsk -> t_fdtsk =
  560.   tsk -> t_ldtsk = _NULL;
  561.   _tsk -> t_ldtsk = tsk;
  562.   if( tsk -> t_pstsk == _NULL )_tsk -> t_fdtsk = tsk;
  563.   else tsk -> t_pstsk -> t_nstsk = tsk;
  564.   if( prty > _tschd -> t_sclsl ) /* adjust priority */
  565.     prty = _tschd -> t_sclsl-1;
  566.   tsk -> t_cls = prty;     /* set priority */
  567.   pq = _tschd -> t_sclsp[ prty ]; /* set scheduling array pointer */
  568.   ++pq -> t_sct;     /* scheduling linkage */
  569.   tsk -> t_pqtsk = pq -> t_lqtsk;
  570.   tsk -> t_nqtsk = _NULL;
  571.   if( tsk -> t_pqtsk == _NULL )pq -> t_fqtsk = tsk;
  572.   else tsk -> t_pqtsk -> t_nqtsk = tsk;
  573.   pq -> t_lqtsk = tsk;
  574.   tsk -> t_xtm0 =     /* no execution time yet */
  575.   tsk -> t_xtm1 =
  576.   tsk -> t_xtm2 = 0;
  577.   pr = sptr = ss+ssiz-2*pcnt; /* initialize execution stack & t_ps */
  578.   tsk -> t_ps.sys_sp =
  579.   sp = sptr - sizeof( struct t_xstck );
  580.   sp -> t_xbp = ss + ssiz;
  581.   sp -> t_xbase = ss;
  582.   while( pcnt-- )*pr++ = *padr++;
  583.   for( i = 0, s = &tsk -> t_ps; i++ < sizeof( struct sys_parm ); )*s = 0;
  584.   tsk -> t_ps.sys_ds =
  585.   tsk -> t_ps.sys_es =
  586.   tsk -> t_ps.sys_ss =
  587.   sp -> t_xds =
  588.   sp -> t_xes =  _tsk -> t_ps.sys_ds;
  589.   sp -> t_xdi =
  590.   sp -> t_xsi =
  591.   sp -> t_xdx =
  592.   sp -> t_xcx =
  593.   sp -> t_xbx =
  594.   sp -> t_xax = _NULL;
  595.   sp -> t_xip = xadr;
  596.   tsk -> t_ps.sys_cs =
  597.   sp -> t_xcs =
  598.   _tsk -> t_ps.sys_cs;
  599.   tsk -> t_ps.sys_pf =
  600.   sp -> t_xpf = SYS_IF;
  601.   tsk -> t_ps.sys_ip =
  602.   sp -> t_retip = &t__halt;
  603.   t__syxit( &crtflg );     /* exit system state */
  604.   return tsk;         /* return */
  605. err3: mm_free( tsk -> t_ps.sys_ss );
  606. err2: mm_free( tsk );
  607. err1: t__syxit( &crtflg );
  608.   return _NULL;
  609. }
  610.  
  611. /*
  612. t__halt          terminate task
  613. */
  614. t__halt()
  615. /*
  616. If  a subtask returns into its orginal stack,  control will pass  to  t__halt.
  617. This  function    deletes the subtask and then clears the sys_task pointer  just
  618. before returning on the system stack (to reenter the security kernel). */
  619. {
  620.   logical haltflg;     /* system state flag storage */
  621.   t__syntr( &haltflg );  /* enter system state */
  622.   t_rtmark( &_tsk -> t_ratsk -> t_xtm0 ); /* accumulate pseudo time */
  623.   t_del( sys_task, _F ); /* delete current task */
  624.   sys_task = _NULL;     /* indicate task terminated */
  625.   while(_T)t_term();     /* return to security kernel */
  626. }
  627.  
  628. /*
  629. t_del             delete task
  630. */
  631. t_del( tsk, st )
  632. struct t_task *tsk;
  633. int st;
  634. /*
  635. Task tsk is killed. st is the status returned to the calling program.
  636. */
  637. {
  638. #define tskf ( ( struct t_ftask * )tsk ) /** (t_ftask) */
  639.   struct t_task *t;     /* task control table pointer */
  640.   logical delflg;     /* system state flag storage */
  641.   t__syntr( &delflg );     /* enter system state */
  642.   while( ( t = tsk -> t_fdtsk ) )t_del( t, st ); /* delete subtasks first */
  643.   if( tsk -> t_pstsk )     /* family linkage */
  644.     tsk -> t_pstsk -> t_nstsk = tsk -> t_nstsk;
  645.   else tsk -> t_ratsk -> t_ldtsk = tsk -> t_nstsk;
  646.   if( tsk -> t_nstsk )
  647.     tsk -> t_nstsk -> t_pstsk = tsk -> t_pstsk;
  648.   else tsk -> t_ratsk -> t_fdtsk = tsk -> t_pstsk;
  649.   if( tsk -> t_pqtsk )     /* queue linkage */
  650.     tsk -> t_pqtsk -> t_nqtsk = tsk -> t_nqtsk;
  651.   else if( ( tsk -> t_type&T_P )
  652.        && ( _tschd -> t_sclsp[ tsk -> t_cls ] -> t_fqtsk == tsk ) )
  653.      _tschd -> t_sclsp[ tsk -> t_cls ] -> t_fqtsk = tsk -> t_nqtsk;
  654.   else if( ( tsk -> t_type&T_W ) && ( _tschd -> t_fwtsk == tsk ) )
  655.     _tschd -> t_fwtsk = tsk -> t_nqtsk;
  656.   else if( ( tsk -> t_type&T_SW ) && ( _tschd -> t_fswtsk == tsk ) )
  657.     _tschd -> t_fswtsk = tsk -> t_nqtsk;
  658.   else if( ( tsk -> t_type&T_X ) && ( _tschd -> t_fxtsk == tsk ) )
  659.     _tschd -> t_fxtsk = tsk -> t_nqtsk;
  660.   if( tsk -> t_nqtsk )tsk -> t_nqtsk -> t_pqtsk = tsk -> t_pqtsk;
  661.   else if( ( tsk -> t_type&T_P )
  662.        && ( _tschd -> t_sclsp[ tsk -> t_cls ] -> t_lqtsk == tsk ) )
  663.      _tschd -> t_sclsp[tsk -> t_cls] -> t_lqtsk = tsk -> t_pqtsk;
  664.   else if( ( tsk -> t_type&T_W ) && ( _tschd -> t_fwtsk == tsk ) )
  665.     _tschd -> t_lwtsk = tsk -> t_pqtsk;
  666.   else if( ( tsk -> t_type&T_SW ) && ( _tschd -> t_fswtsk == tsk ) )
  667.     _tschd -> t_lswtsk = tsk -> t_pqtsk;
  668.   else if( ( tsk -> t_type&T_X ) && ( _tschd -> t_fxtsk == tsk ) )
  669.    _tschd -> t_lxtsk = tsk -> t_pqtsk;
  670.   t = sys_task;      /* save current t_task pointer */
  671.   sys_task = tsk -> t_ratsk; /* set ancestor task */
  672.   mm_free( tsk -> t_ps.sys_ss ); /* free stack */
  673.   mm_free( tsk );     /* free t_task table */
  674.   sys_task = t;      /* restore current task pointer */
  675.   t__syxit( &delflg );     /* exit system state */
  676.   return _F;         /* return */
  677. }
  678.  
  679. /*
  680. mm_aloc          memory allocation
  681. */
  682. mm_aloc(ln)
  683. unsigned ln;
  684. /*
  685. ln bytes are allocated from the heap. The address of the first byte is
  686. returned. If there is not enough available memory to satisfy the request,
  687. _NULL is returned. */
  688. {
  689.   return malloc(ln);     /* allocate storage */
  690. }
  691.  
  692. /*
  693. mm_free          memory deallocation
  694. */
  695. mm_free(st)
  696. char *st;
  697. /*
  698. st is the address returned by a previous call to function mm_free. The storage
  699. previously allocated is made available for future use. The normal return is
  700. _F. _E is returned if st does not point to an area previously allocated by
  701. mm_aloc. */
  702. {
  703.   return free(st);     /* deallocate storage */
  704. }
  705.  
  706. /*
  707. main             test program
  708. */
  709. main()
  710. /*
  711. This function serves to test the task scheduler. Two tasks are created, each
  712. of which increments a variable. The original task continually displays the
  713. counts, as well as its own iteration number. Depressing any key will cause a
  714. return to MS-DOS. */
  715. {
  716.   int ctr1, ctr2, ctr3;  /* counters */
  717.   int count();         /* counting subroutine */
  718.   int param[ 2 ];     /* parameter array */
  719.   printf("tasktest (C) 1986 Ken Berry- All Rights Reserved\n");
  720.   printf("Tele task scheduler: 1986 September 2 version (DDJ mod)\n\n");
  721.   t__init();         /* initialize task scheduler */
  722.   ctr1 = ctr2 = ctr3 = 0; /* initialize counters */
  723.   param[ 0 ] = &ctr1;     /* create first task */
  724.   param[ 1 ] = 1;
  725.   t_crt( count, 2, ¶m, 256, 0, 0, 0);
  726.   param[ 0 ] = &ctr2;     /* create second task */
  727.   param[ 1 ] = 2;
  728.   t_crt( count, 2, ¶m, 256, 0, 0, 0);
  729.   while( !kbhit() )     /* loop until key depressed */
  730.   {
  731.     ++ctr3;         /* increment main loop count */
  732.     printf("main = %d, task 1 = %d, task 2 = %d\n", ctr3, ctr1, ctr2 );
  733.   }
  734.   getch();         /* discard termination character */
  735.   t__term();         /* terminate task scheduler */
  736.   return _F;         /* return to MSvDOS */
  737. }
  738.  
  739. count(ctr,inc)
  740. int *ctr,inc;
  741. {
  742.   while(_T)         /* infinite loop */
  743.   {
  744.     *ctr += inc;     /* update counter */
  745.   }
  746. }
  747.  
  748.  
  749.  
  750.