home *** CD-ROM | disk | FTP | other *** search
- /*
- Listing 1 Scheduling Algorithm
- (C) Copyright 1986 Ken Berry.
- All rights reserved.
- Copies may be made for non-commercial, private use only.
- */
-
- #define _F 0 /* false */
- #define _T 1 /* true */
- #define _E -1 /* error */
-
- #define _NULL 0 /* null pointer */
-
- typedef char pointer; /* pointer type */
- typedef char logical; /* logical type */
- typedef unsigned selector; /* 8086 selector type */
-
- struct sys_parm /* register storage block for 8086 interface */
- {
- union {unsigned sys_rax; struct {char sys_ral, sys_rah;} sys_byt;} sys_ra;
- union {unsigned sys_rbx; struct {char sys_rbl, sys_rbh;} sys_byt;} sys_rb;
- union {unsigned sys_rcx; struct {char sys_rcl, sys_rch;} sys_byt;} sys_rc;
- union {unsigned sys_rdx; struct {char sys_rdl, sys_rdh;} sys_byt;} sys_rd;
- #define sys_ax sys_ra.sys_rax
- #define sys_al sys_ra.sys_byt.sys_ral
- #define sys_ah sys_ra.sys_byt.sys_rah
- #define sys_bx sys_rb.sys_rbx
- #define sys_bl sys_rb.sys_byt.sys_rbl
- #define sys_bh sys_rb.sys_byt.sys_rbh
- #define sys_cx sys_rc.sys_rcx
- #define sys_cl sys_rc.sys_byt.sys_rcl
- #define sys_ch sys_rc.sys_byt.sys_rch
- #define sys_dx sys_rd.sys_rdx
- #define sys_dl sys_rd.sys_byt.sys_rdl
- #define sys_dh sys_rd.sys_byt.sys_rdh
- unsigned sys_bp; /* base pointer */
- unsigned sys_si; /* source index */
- unsigned sys_di; /* destination index */
- unsigned sys_sp; /* stack pointer */
- unsigned sys_cs; /* code segment */
- unsigned sys_ds; /* data segment */
- unsigned sys_ss; /* stack segment */
- unsigned sys_es; /* extra segment */
- unsigned sys_pf; /* 80286 processor flags */
- #define SYS_OF 0x0800 /* overflow flag- 1: lost significance */
- #define SYS_DF 0x0400 /* direction flag- 1: strings auto-decrement */
- #define SYS_IF 0x0200 /* interrupt flag- 1: enable interrupts */
- #define SYS_TF 0x0100 /* trap flag- 1: interrupt every instruction */
- #define SYS_SF 0x0080 /* sign flag- 1: result negative */
- #define SYS_ZF 0x0040 /* zero flag- 1: result 0 */
- #define SYS_AF 0x0010 /* auxiliary carry flag- 1: carry from bit 3 */
- #define SYS_PF 0x0004 /* parity flag- 1: even number of 1's */
- #define SYS_CF 0x0001 /* carry flag- 1: carry from bit 8 or 16 */
- unsigned sys_sw; /* status word */
- #define SYS_TS 0x0008 /* task switch */
- #define SYS_EM 0x0004 /* processor extension emulation */
- #define SYS_MP 0x0002 /* monitor processor extension */
- #define SYS_PE 0x0001 /* protection enable */
- unsigned sys_ip; /* instruction pointer */
- unsigned sys_res; /* unused */
- };
-
- struct t_xstck
- {
- unsigned t_xbase; /* application stack base (overflow detection) */
- unsigned t_xes; /* es */
- unsigned t_xbp; /* bp */
- unsigned t_xdi; /* di */
- unsigned t_xsi; /* si */
- unsigned t_xdx; /* dx */
- unsigned t_xcx; /* cx */
- unsigned t_xbx; /* bx */
- unsigned t_xax; /* ax */
- unsigned t_xds; /* ds */
- unsigned t_xip; /* ip */
- unsigned t_xcs; /* cs */
- unsigned t_xpf; /* pf */
- unsigned t_retip; /* return address */
- };
-
- struct t_task
- {
- char t_type; /* task type */
- #define T_X 0x80 /* execute queue */
- #define T_W 0x40 /* wait queue */
- #define T_P 0x20 /* priority queue */
- #define T_SW 0x10 /* secondary wait queue */
- #define T_ATASK 0x01 /* abreviated task */
- unsigned t_wttk; /* wait tick count */
- unsigned t_cls; /* priority queue index */
- struct t_task *t_pqtsk,*t_nqtsk; /* queue linkage */
- struct t_task *t_ratsk,*t_pstsk,*t_nstsk,*t_fdtsk,*t_ldtsk; /* family */
- struct sys_parm t_ps; /* processor status */
- unsigned t_xtm0; /* execution time accumulator */
- unsigned t_xtm1;
- unsigned t_xtm2;
- pointer *t_axstk; /* execution stack pointer */
- };
-
- extern pointer *sys_task; /* current task control table pointer */
- #define _tsk ( ( struct t_task * ) sys_task ) /* task control table ref */
-
- #define T_SCLS 4 /* number of scheduling classes */
-
- struct t_scls /* scheduling class queue */
- {
- unsigned t_sfrq; /* scheduling frequency */
- int t_sct; /* queue length */
- struct t_task *t_fqtsk,*t_lqtsk; /* queue header */
- };
-
- struct t_schd /* scheduling control table */
- {
- int t_xct; /* execution queue length */
- struct t_task *t_fxtsk, *t_lxtsk; /* execution queue header */
- int t_wct; /* wait queue length */
- struct t_task *t_fwtsk, *t_lwtsk; /* wait queue header */
- int t_swct; /* secondary wait queue length */
- struct t_task *t_fswtsk, *t_lswtsk; /* secondary wait queue header */
- int t_sclsl; /* scheduling class index limit */
- struct t_scls **t_sclsp; /* scheduling class array pointer */
- };
-
- extern pointer *sys_tsch; /* task scheduling control table pointer */
- #define _tschd ( ( struct t_schd * ) sys_tsch ) /* quick pointer */
-
- /*
- t__krnl * security kernel *
- */
- t__krnl()
- /*
- This is the security kernel. It never returns, being the most trusted
- software in the system. The current contents in t__crtss and t__crtsp
- are used to set the stack for when the current task is resumed. */
- {
- extern logical t_astrm; /* tick termination flag */
- extern selector t__crtss; /* current task ss storage */
- extern pointer *t__crtsp; /* current task sp storage */
- extern unsigned tmr_tkct; /* tick clock */
- int xtskct; /* task queue count (at entry) */
- int ttc; /* task termination code */
- _tsk -> t_ps.sys_ss = t__crtss; /* set current task stack */
- _tsk -> t_ps.sys_sp = t__crtsp;
- while(_T) /* find executable task */
- {
- xtskct = _tschd -> t_xct; /* save task count */
- if ( t_astrm ) t__wtst( tmr_tkct ); /* process wait tasks */
- if ( xtskct == 0 ) t__sch(); /* schedule application tasks if necessary */
- sys_task = _tschd -> t_fxtsk; /* set next task address */
- if ( sys_task != _NULL ) /* test for executable task available */
- {
- _tschd -> t_xct--; /* decrement executing task count */
- _tschd -> t_fxtsk = _tsk -> t_nqtsk; /* delink task */
- if ( _tschd -> t_fxtsk == _NULL )
- _tschd -> t_lxtsk = _NULL;
- else _tschd -> t_fxtsk -> t_pqtsk = _NULL;
- _tsk -> t_type &= ~T_X; /* indicate task not in execution queue */
- ttc = t__xtsk( sys_task ); /* execute application task */
- if ( !sys_task ) continue; /* test for task terminated */
- if ( ttc < 0 ) t__inxq(); /* insert task into execution queue */
- else if ( ttc == 0 ) t__inpq(); /* insert task into priority queue */
- else t__inwq( ttc ); /* insert into wait queue */
- }
- }
- }
-
- /*
- t__wtst test waiting tasks
- */
- t__wtst( tc)
- unsigned tc;
- /*
- The wait queue is traversed. All tasks with a wait value of tc are executed.
- _F is always returned. */
- {
- while(_T) /* traverse wait queue */
- {
- sys_task = _tschd -> t_fwtsk; /* set current task pointer */
- if ( !sys_task ) break; /* test for no waiting tasks */
- _tsk -> t_type &= ~T_W; /* remove task from wait queue */
- _tsk -> t_type |= T_X; /* indicate task in execution queue */
- if ( _tsk -> t_wttk > tc ) break; /* test for effective end of list */
- --_tschd -> t_wct; /* decrement waiting task count */
- _tschd -> t_fwtsk = _tsk -> t_nqtsk; /* delink from wait queue */
- if ( _tsk -> t_nqtsk == _NULL )
- _tschd -> t_lwtsk = _NULL;
- else _tsk -> t_nqtsk -> t_pqtsk = _NULL;
- _tsk -> t_pqtsk = _NULL; /* insert at top of execution queue */
- _tsk -> t_nqtsk = _tschd -> t_fxtsk;
- _tschd -> t_fxtsk = sys_task;
- ++_tschd -> t_xct; /* increment executable task count */
- if ( _tschd -> t_lxtsk == _NULL )
- _tschd -> t_lxtsk = sys_task;
- else _tsk -> t_nqtsk -> t_pqtsk = sys_task;
- }
- return _F; /* return */
- }
-
- /*
- t__sch schedule task
- */
- t__sch()
- /*
- This function searches the priority queues and links tasks ready for execution
- into the execution queue. The return is always _F. */
- {
- struct t_scls **a; /* priority queue pointer array pointer */
- struct t_scls *q; /* priority queue pointer */
- int i,j; /* iteration variables */
- a = _tschd -> t_sclsp; /* set pointer array address */
- /* while(_T) * nonterminating task *
- { */
- for ( i = 0; i < _tschd -> t_sclsl; ++i ) /* traverse queues */
- {
- q = a[i]; /* set priority queue pointer */
- for ( j = 0; j++<q -> t_sfrq; ) /* schedule tasks from priority queue */
- {
- if ( q -> t_fqtsk == _NULL ) break; /* test for queue empty */
- if ( _tschd -> t_lxtsk ) /* link to end of execution queue */
- _tschd -> t_lxtsk -> t_nqtsk = q -> t_fqtsk;
- else _tschd -> t_fxtsk = q -> t_fqtsk;
- q -> t_fqtsk -> t_type &= ~T_P; /* indicate not in priority queue */
- q -> t_fqtsk -> t_pqtsk = _tschd -> t_lxtsk;
- _tschd -> t_lxtsk = q -> t_fqtsk;
- q -> t_fqtsk = q -> t_fqtsk -> t_nqtsk; /* update queue header */
- _tschd -> t_lxtsk -> t_nqtsk = _NULL;
- if ( q -> t_fqtsk == _NULL )
- q -> t_lqtsk = _NULL;
- else q -> t_fqtsk -> t_pqtsk = _NULL;
- q -> t_sct --; /* decrement queue count */
- ++ _tschd -> t_xct; /* increment execution queue length */
- _tschd -> t_lxtsk -> t_type |= T_X; /* ind. task in execution queue */
- }
- }
- /* t_rels(); * return to bottom of execution queue *
- }*/
- return _F; /* return */
- }
-
- /*
- t__inxq insert task into execution queue
- */
- t__inxq()
- /*
- The current task is inserted into the execution queue. _F is always returned.
- */
- {
- _tsk -> t_wttk = 0; /* indicate not waiting for system tick */
- if ( _tschd -> t_lxtsk == _NULL ) /* test for execution queue empty */
- {
- _tschd -> t_fxtsk = sys_task; /* insert in empty queue */
- _tsk -> t_pqtsk = _NULL;
- }
- else /* execution queue not empty */
- {
- _tschd -> t_lxtsk -> t_nqtsk = sys_task; /* insert at end of queue */
- _tsk -> t_pqtsk = _tschd -> t_lxtsk;
- }
- _tsk -> t_nqtsk = _NULL; /* new task at end of list */
- _tschd -> t_lxtsk = sys_task;
- _tschd -> t_xct++; /* increment executable task count */
- _tschd -> t_lxtsk -> t_type |= T_X; /* indicate task in execution queue */
- return _F; /* return */
- }
-
- /*
- t__secw process secondary wait queue
- */
- t__secw()
- /*
- This program executes every 64K system ticks. It moves the secondary
- wait queue to the primary wait queue and changes the type of the waiting
- tasks. */
- {
- struct t_task *tsk; /* task control table pointer */
- char swtflg; /* system state flag */
- extern int tmr_tkct; /* tick clock */
- while(_T) /* nonterminating task */
- {
- t__syntr( &swtflg ); /* enter system state */
- for ( tsk = _tschd -> t_fwtsk; tsk; tsk = tsk -> t_nqtsk ) /* traverse */
- {
- tsk -> t_type &= ~T_SW;
- tsk -> t_type |= T_W; /* change task type */
- }
- _tschd -> t_wct = _tschd -> t_swct; /* append secondary wait queue */
- _tschd -> t_fwtsk = _tschd -> t_fswtsk;
- _tschd -> t_lwtsk = _tschd -> t_lswtsk;
- _tschd -> t_fswtsk = _tschd -> t_lswtsk = _NULL; /* empty sec. queue */
- _tschd -> t_swct = 0;
- t__inwq( 0xFFFF - tmr_tkct ); /* insert self into wait queue at end */
- sys_task = _NULL; /* remove task from kernel control */
- t_term(); /* suspend execution */
- }
- }
-
- /*
- t__inwq insert task into wait queue
- */
- t__inwq(tc)
- unsigned tc;
- /*
- The current task is inserted into the wait queue. tc is the number of system
- ticks that the task is to wait. _F is always returned. */
- {
- extern unsigned tmr_tkct; /* tick clock */
- unsigned crtk; /* current tick */
- crtk = tmr_tkct; /* set current system tick */
- _tsk -> t_wttk = tc + crtk; /* compute reactivation time */
- if ( _tsk -> t_wttk >= crtk ) /* test for task in wait queue */
- { t__inwt( &_tschd -> t_wct ); /* insert in wait queue */
- _tsk -> t_type |= T_W;
- }else /* task in secondary wait queue */
- { t__inwt( &_tschd -> t_swct ); /* insert in secondary wait queue */
- _tsk -> t_type |= T_SW;
- }return _F; /* indicate task inserted */
- }
-
- /*
- t__inwt insert into wait or secondary wait queue
- */
- struct t_wtq
- {
- int wct; /* wait queue length */
- struct t_task *frs,*lst; /* queue header */
- };
- t__inwt( w )
- struct t_wtq *w;
- /*
- The t_wtq structure is implicitly contained in the scheduling control table
- (t_schd structure). The current task is inserted into the queue. _F is always
- returned. */
- {
- struct t_task *p; /* task pointer */
- unsigned tc; /* reactivation time */
- tc = _tsk -> t_wttk; /* set reactivation time */
- ++w -> wct; /* increment queue length */
- for ( p = w -> frs; p; p = p -> t_nqtsk ) /* traverse queue */
- {
- if ( tc < p -> t_wttk ) /* test for task earlier */
- {
- _tsk -> t_nqtsk = p; /* insert within queue */
- _tsk -> t_pqtsk = p -> t_pqtsk;
- p -> t_pqtsk = sys_task;
- if ( ( p = _tsk -> t_pqtsk ) ) p -> t_nqtsk = sys_task;
- else w -> frs = sys_task;
- return _F; /* indicate task inserted */
- }
- }
- if ( ( p = w -> lst ) ) /* test for wait queue not empty */
- {
- p -> t_nqtsk = w -> lst = sys_task; /* insert at end of queue */
- _tsk -> t_pqtsk = p;
- _tsk -> t_nqtsk = _NULL;
- }
- else /* wait queue empty */
- {
- w -> frs = w -> lst = sys_task; /* initialize wait queue */
- _tsk -> t_nqtsk = _tsk -> t_pqtsk = _NULL;
- }
- return _F; /* indicate task inserted */
- }
-
- /*
- t__inpq insert into priority queue
- */
- t__inpq()
- /*
- The current task is inserted into its priority queue. _F is always returned.
- */
- {
- struct t_scls *q; /* priority queue pointer */
- _tsk -> t_wttk = 0; /* indicate not waiting for tick */
- q = _tschd -> t_sclsp[ _tsk -> t_cls ]; /* set priority queue address */
- _tsk -> t_pqtsk = q -> t_lqtsk; /* link task into priority queue */
- _tsk -> t_nqtsk = _NULL;
- if ( q -> t_lqtsk == _NULL ) q -> t_fqtsk = sys_task;
- else q -> t_lqtsk -> t_nqtsk = sys_task;
- q -> t_lqtsk = sys_task;
- ++q -> t_sct; /* increment queue length */
- _tsk -> t_type |= T_P; /* indicate task in priority queue */
- return _F; /* return */
- }
-
- /*
- t__xtsk execute task
- */
- t__xtsk( t )
- struct t_task *t;
- /*
- Task t is executed. The returned value is the termination code.
- */
- {
- extern unsigned t_mnxtm; /* minimum execution time */
- extern unsigned t_syxtm[]; /* system pseudo time accumulator */
- extern logical t_astrm; /* application termination flag */
- extern int t__crtss; /* current task ss storage */
- extern int t__crtsp; /* current task sp storage */
- int ttc; /* return value storage */
- unsigned atm; /* accumulated time */
- unsigned rtm; /* reference time */
- int xtm; /* execution time */
- atm = 0; /* initialize accumulated execution time */
- while(_T) /* execute task */
- {
- rtm = t -> t_xtm0; /* set reference time */
- t_rtmark( &t -> t_xtm0 ); /* accumulate pseudo time */
- ttc = t__dspap( t -> t_ps.sys_ss, t -> t_ps.sys_sp ); /* execute task */
- t -> t_ps.sys_ss = t__crtss; /* store ss */
- t -> t_ps.sys_sp = t__crtsp; /* store sp */
- t_rtmark( &t_syxtm ); /* accumulate pseudo time */
- if ( ( ttc != 0 ) || !t_astrm ) break; /* test for not tick termination */
- xtm = t -> t_xtm0 - rtm; /* compute execution time */
- if ( xtm < rtm ) xtm = -xtm;
- atm += xtm; /* accumulate execution time */
- if ( atm >= t_mnxtm ) break; /* test for minimum time satisfied */
- }
- return ttc; /* return */
- }
- /*
- t__init initialize task system
- */
- t__init()
- /*
- This function initializes the task system. _F is the normal return. _E is
- returned if the system cannot be initialized. */
- {
- #define WSTK 252 /* t_wqupd stack size */
- extern struct sys_parm sys_stat; /* initial processor status */
- extern struct t_task *t_wqupd; /* secondary wait queue update task */
- extern selector sys_dgrp; /* data segment selector storage */
- extern char *sys_ssbs; /* system stack pointer */
- extern unsigned sys_sssz; /* system stack length */
- extern char tmr_ilck; /* tick service interlock */
- int t__secw(); /* wait queue update function */
- struct t_scls *cls; /* priority queue pointer */
- struct t_scls **ary; /* priority queue pointer array pointer */
- int i; /* iteration variable */
- char *s; /* pointer */
- tmr__int(); /* initialize system tick clock */
- sys_task = sys_ssbs + sys_sssz; /* set main task control table pointer */
- _tsk -> t_xtm0 = /* initialize execution time */
- _tsk -> t_xtm1 =
- _tsk -> t_xtm2 = 0;
- if( ( sys_tsch = mm_aloc( sizeof( struct t_schd ) ) ) == _NULL )goto err1;
- if( ( ary = mm_aloc( T_SCLS*( sizeof( struct t_scls )+2 ) ) )
- == _NULL )goto err2;
- _tsk -> t_pqtsk = /* NULL linkage */
- _tsk -> t_nqtsk =
- _tsk -> t_ratsk =
- _tsk -> t_pstsk =
- _tsk -> t_nstsk =
- _tsk -> t_fdtsk =
- _tsk -> t_ldtsk = _NULL;
- _tsk -> t_cls = 0; /* set priority class 0 */
- _tsk -> t_wttk = 0; /* indicate not waiting */
- for( i = 0, s = &_tsk -> t_ps;
- i++<sizeof( struct sys_parm ); )*s = 0; /* clear t_ps */
- _tsk -> t_ps.sys_cs = sys_stat.sys_cs; /* set selectors */
- _tsk -> t_ps.sys_ds =
- _tsk -> t_ps.sys_es =
- _tsk -> t_ps.sys_ss = sys_dgrp;
- _tsk -> t_axstk = _NULL; /* NULL execution stack pointer */
- _tschd -> t_xct = 1; /* set execution task count */
- _tschd -> t_fxtsk = /* set execution queue */
- _tschd -> t_lxtsk = sys_task;
- _tschd -> t_wct = 0; /* indicate idle wait queue */
- _tschd -> t_fwtsk = /* set wait queue */
- _tschd -> t_lwtsk = _NULL;
- _tschd -> t_swct = 0; /* indicate empty secondary wait queue */
- _tschd -> t_fswtsk = /* NULL secondary wait queue */
- _tschd -> t_lswtsk = _NULL;
- _tschd -> t_sclsl = T_SCLS; /* set priority queue count */
- _tschd -> t_sclsp = ary; /* set priority queue pointer array address */
- cls = &ary[ T_SCLS ]; /* set first t_scls pointer */
- for( i = 0; i<T_SCLS; ++i, ++cls ) /* initialize priority queues */
- {
- ary[i] = cls; /* set priority queue pointer */
- cls -> t_sfrq = 1; /* set default frequency */
- cls -> t_sct = 0; /* indicate empty queue */
- cls -> t_fqtsk = /* NULL queue linkage */
- cls -> t_lqtsk = _NULL;
- }
- t_wqupd = /* create task to update wait queue */
- t_crt( t__secw, 0, 0, WSTK, 0, 0, 0 );
- if( t_wqupd == _NULL )goto err3;
- t_wqupd -> t_wttk = 0xFFFF; /* update wait queue at wraparound time */
- t__dspsy(); /* dispatch system */
- tmr_ilck = 0x00; /* enable tick service */
- return _F; /* indicate task system initialized */
- err3: mm_free( ary ); /* error nest */
- err2: mm_free( sys_tsch );
- err1: return _E;
- }
-
- /*
- t__term
- */
- t__term()
- /*
- The task system is terminated. All tasks and storage allocated by t__init are
- released. The return is always _F. */
- {
- extern char *sys_ssbs; /* system stack base */
- extern unsigned sys_sssz; /* system stack size */
- struct t_task *t; /* t_task pointer */
- char trmflg; /* system state flag storage */
- tmr__rst(); /* reset system tick clock */
- t__syntr( &trmflg ); /* enter system state */
- sys_task = sys_ssbs + sys_sssz; /* set original task address */
- while( ( t = _tsk -> t_fdtsk ) ) /* delete all created tasks */
- t_del( t, _F );
- mm_free( _tschd -> t_sclsp );
- mm_free( sys_tsch );
- return _F; /* normal return */
- }
-
- /*
- t_crt create task
- */
- t_crt( xadr, pcnt, padr, ssiz, dsiz, sadr, prty )
- pointer *xadr;
- unsigned pcnt;
- unsigned *padr;
- unsigned ssiz, dsiz;
- pointer *sadr;
- unsigned prty;
- /*
- A new task is created with execution priority prty. Execution will begin at
- xadr. pcnt parameters will be passed (on the new task stack). The parameters
- are in an array addressed by padr. The new task will have a stack of ssiz
- bytes and a dynamic memory area of dsiz bytes. dsiz may be zero to indicate
- that no dynamic memory is required. sadr will recieve a termination code when
- the task terminates. If sadr is _NULL, an abreviated task is created. _F is
- returned if insufficient memory is available. Otherwise the address of the
- t_ftask table is returned. */
- {
- extern int t__halt(); /* return address */
- struct t_task *tsk; /* task control table pointer (t_task) */
- struct t_scls *pq; /* priority queue pointer */
- struct t_xstck *sp; /* execution stack pointer */
- pointer *ss; /* stack start */
- unsigned *pr; /* parameter pointer */
- unsigned ln; /* task control table length */
- int i; /* iteration variable */
- char *s; /* pointer */
- char *sptr; /* execution stack pointer */
- logical crtflg; /* system state flag storage */
- t__syntr( &crtflg ); /* enter system state */
- ln = sizeof( struct t_task ); /* allocate task control table */
- if( ( tsk = mm_aloc( ln ) ) == _NULL ) goto err1;
- ssiz += sizeof( struct t_xstck ); /* allocate stack */
- if( ( ss = tsk -> t_axstk = mm_aloc( ssiz ) ) == _NULL )goto err2;
- tsk -> t_type = T_ATASK; /* indicate abreviated task control table */
- tsk -> t_wttk = 0; /* indicate not waiting */
- tsk -> t_ratsk = sys_task; /* task family linkage */
- tsk -> t_pstsk = _tsk -> t_ldtsk;
- tsk -> t_nstsk =
- tsk -> t_fdtsk =
- tsk -> t_ldtsk = _NULL;
- _tsk -> t_ldtsk = tsk;
- if( tsk -> t_pstsk == _NULL )_tsk -> t_fdtsk = tsk;
- else tsk -> t_pstsk -> t_nstsk = tsk;
- if( prty > _tschd -> t_sclsl ) /* adjust priority */
- prty = _tschd -> t_sclsl-1;
- tsk -> t_cls = prty; /* set priority */
- pq = _tschd -> t_sclsp[ prty ]; /* set scheduling array pointer */
- ++pq -> t_sct; /* scheduling linkage */
- tsk -> t_pqtsk = pq -> t_lqtsk;
- tsk -> t_nqtsk = _NULL;
- if( tsk -> t_pqtsk == _NULL )pq -> t_fqtsk = tsk;
- else tsk -> t_pqtsk -> t_nqtsk = tsk;
- pq -> t_lqtsk = tsk;
- tsk -> t_xtm0 = /* no execution time yet */
- tsk -> t_xtm1 =
- tsk -> t_xtm2 = 0;
- pr = sptr = ss+ssiz-2*pcnt; /* initialize execution stack & t_ps */
- tsk -> t_ps.sys_sp =
- sp = sptr - sizeof( struct t_xstck );
- sp -> t_xbp = ss + ssiz;
- sp -> t_xbase = ss;
- while( pcnt-- )*pr++ = *padr++;
- for( i = 0, s = &tsk -> t_ps; i++ < sizeof( struct sys_parm ); )*s = 0;
- tsk -> t_ps.sys_ds =
- tsk -> t_ps.sys_es =
- tsk -> t_ps.sys_ss =
- sp -> t_xds =
- sp -> t_xes = _tsk -> t_ps.sys_ds;
- sp -> t_xdi =
- sp -> t_xsi =
- sp -> t_xdx =
- sp -> t_xcx =
- sp -> t_xbx =
- sp -> t_xax = _NULL;
- sp -> t_xip = xadr;
- tsk -> t_ps.sys_cs =
- sp -> t_xcs =
- _tsk -> t_ps.sys_cs;
- tsk -> t_ps.sys_pf =
- sp -> t_xpf = SYS_IF;
- tsk -> t_ps.sys_ip =
- sp -> t_retip = &t__halt;
- t__syxit( &crtflg ); /* exit system state */
- return tsk; /* return */
- err3: mm_free( tsk -> t_ps.sys_ss );
- err2: mm_free( tsk );
- err1: t__syxit( &crtflg );
- return _NULL;
- }
-
- /*
- t__halt terminate task
- */
- t__halt()
- /*
- If a subtask returns into its orginal stack, control will pass to t__halt.
- This function deletes the subtask and then clears the sys_task pointer just
- before returning on the system stack (to reenter the security kernel). */
- {
- logical haltflg; /* system state flag storage */
- t__syntr( &haltflg ); /* enter system state */
- t_rtmark( &_tsk -> t_ratsk -> t_xtm0 ); /* accumulate pseudo time */
- t_del( sys_task, _F ); /* delete current task */
- sys_task = _NULL; /* indicate task terminated */
- while(_T)t_term(); /* return to security kernel */
- }
-
- /*
- t_del delete task
- */
- t_del( tsk, st )
- struct t_task *tsk;
- int st;
- /*
- Task tsk is killed. st is the status returned to the calling program.
- */
- {
- #define tskf ( ( struct t_ftask * )tsk ) /** (t_ftask) */
- struct t_task *t; /* task control table pointer */
- logical delflg; /* system state flag storage */
- t__syntr( &delflg ); /* enter system state */
- while( ( t = tsk -> t_fdtsk ) )t_del( t, st ); /* delete subtasks first */
- if( tsk -> t_pstsk ) /* family linkage */
- tsk -> t_pstsk -> t_nstsk = tsk -> t_nstsk;
- else tsk -> t_ratsk -> t_ldtsk = tsk -> t_nstsk;
- if( tsk -> t_nstsk )
- tsk -> t_nstsk -> t_pstsk = tsk -> t_pstsk;
- else tsk -> t_ratsk -> t_fdtsk = tsk -> t_pstsk;
- if( tsk -> t_pqtsk ) /* queue linkage */
- tsk -> t_pqtsk -> t_nqtsk = tsk -> t_nqtsk;
- else if( ( tsk -> t_type&T_P )
- && ( _tschd -> t_sclsp[ tsk -> t_cls ] -> t_fqtsk == tsk ) )
- _tschd -> t_sclsp[ tsk -> t_cls ] -> t_fqtsk = tsk -> t_nqtsk;
- else if( ( tsk -> t_type&T_W ) && ( _tschd -> t_fwtsk == tsk ) )
- _tschd -> t_fwtsk = tsk -> t_nqtsk;
- else if( ( tsk -> t_type&T_SW ) && ( _tschd -> t_fswtsk == tsk ) )
- _tschd -> t_fswtsk = tsk -> t_nqtsk;
- else if( ( tsk -> t_type&T_X ) && ( _tschd -> t_fxtsk == tsk ) )
- _tschd -> t_fxtsk = tsk -> t_nqtsk;
- if( tsk -> t_nqtsk )tsk -> t_nqtsk -> t_pqtsk = tsk -> t_pqtsk;
- else if( ( tsk -> t_type&T_P )
- && ( _tschd -> t_sclsp[ tsk -> t_cls ] -> t_lqtsk == tsk ) )
- _tschd -> t_sclsp[tsk -> t_cls] -> t_lqtsk = tsk -> t_pqtsk;
- else if( ( tsk -> t_type&T_W ) && ( _tschd -> t_fwtsk == tsk ) )
- _tschd -> t_lwtsk = tsk -> t_pqtsk;
- else if( ( tsk -> t_type&T_SW ) && ( _tschd -> t_fswtsk == tsk ) )
- _tschd -> t_lswtsk = tsk -> t_pqtsk;
- else if( ( tsk -> t_type&T_X ) && ( _tschd -> t_fxtsk == tsk ) )
- _tschd -> t_lxtsk = tsk -> t_pqtsk;
- t = sys_task; /* save current t_task pointer */
- sys_task = tsk -> t_ratsk; /* set ancestor task */
- mm_free( tsk -> t_ps.sys_ss ); /* free stack */
- mm_free( tsk ); /* free t_task table */
- sys_task = t; /* restore current task pointer */
- t__syxit( &delflg ); /* exit system state */
- return _F; /* return */
- }
-
- /*
- mm_aloc memory allocation
- */
- mm_aloc(ln)
- unsigned ln;
- /*
- ln bytes are allocated from the heap. The address of the first byte is
- returned. If there is not enough available memory to satisfy the request,
- _NULL is returned. */
- {
- return malloc(ln); /* allocate storage */
- }
-
- /*
- mm_free memory deallocation
- */
- mm_free(st)
- char *st;
- /*
- st is the address returned by a previous call to function mm_free. The storage
- previously allocated is made available for future use. The normal return is
- _F. _E is returned if st does not point to an area previously allocated by
- mm_aloc. */
- {
- return free(st); /* deallocate storage */
- }
-
- /*
- main test program
- */
- main()
- /*
- This function serves to test the task scheduler. Two tasks are created, each
- of which increments a variable. The original task continually displays the
- counts, as well as its own iteration number. Depressing any key will cause a
- return to MS-DOS. */
- {
- int ctr1, ctr2, ctr3; /* counters */
- int count(); /* counting subroutine */
- int param[ 2 ]; /* parameter array */
- printf("tasktest (C) 1986 Ken Berry- All Rights Reserved\n");
- printf("Tele task scheduler: 1986 September 2 version (DDJ mod)\n\n");
- t__init(); /* initialize task scheduler */
- ctr1 = ctr2 = ctr3 = 0; /* initialize counters */
- param[ 0 ] = &ctr1; /* create first task */
- param[ 1 ] = 1;
- t_crt( count, 2, ¶m, 256, 0, 0, 0);
- param[ 0 ] = &ctr2; /* create second task */
- param[ 1 ] = 2;
- t_crt( count, 2, ¶m, 256, 0, 0, 0);
- while( !kbhit() ) /* loop until key depressed */
- {
- ++ctr3; /* increment main loop count */
- printf("main = %d, task 1 = %d, task 2 = %d\n", ctr3, ctr1, ctr2 );
- }
- getch(); /* discard termination character */
- t__term(); /* terminate task scheduler */
- return _F; /* return to MSvDOS */
- }
-
- count(ctr,inc)
- int *ctr,inc;
- {
- while(_T) /* infinite loop */
- {
- *ctr += inc; /* update counter */
- }
- }
-
-
-