Main Page | Modules | Data Structures | File List | Data Fields | Globals

exec.c File Reference


Detailed Description

Provides the BeeOS multithreaded time sharing scheduler features.

Definition in file exec.c.

#include "../include/beeos.h"
#include "../include/bstring.h"
#include "../include/bmalloc.h"
#include "../include/exec.h"
#include <stdarg.h>
#include "../include/bprintf.h"
#include "../include/asm/ports.h"
#include "../include/ect.h"

Include dependency graph for exec.c:

Include dependency graph

Go to the source code of this file.

Defines

#define IN_EXEC

Functions

void idle_task (void)
void task_dumpinfo (regs_t *regs)
task_tcreate_task (void(*func)(void), schar priority, ushort nextrun, ushort stacksize)
 Alloc and init task_t struct with params passed in.

void unlink_time (task_t *pTask)
 Unlinks pTask from the time list.

void unlink_prior (task_t *pTask)
 Unlinks pTask from the priority list.

task_tfind_priority_lte (task_t *pTask, schar priority)
 Find a task with prior <= priority starting \p pTask, walking prior.

task_tfind_nextrun_lte (task_t *pTask, ushort time)
 Find a task with nextrun <= time starting at pTask, walking time.

void insert_task_prior (task_t *pPrior, task_t *pTask)
 Insert pTask @ just after pPrior in the prior list.

void insert_task_time (task_t *pTime, task_t *pTask)
 Insert pTask @ just after pTime in the time list.

__inline__ void context_save2 (task_t *pTask)
 Save tempregs into pTask for CONTEXT_SAVE macro.

__inline__ void context_restore2 (task_t *pTask)
 Load tempregs with pTask->regs for CONTEXT_RESTORE macro.

__inline__ slong now_cmp (ushort a, ushort b, ushort now)
 Handles comparisons between continuously wrapping ushort counters.

__inline__ task_tfind_imperative_task (task_t *pCurrent)
 Finds task soonest to run, with ->priority > pCurrent->priority.

__inline__ task_tfind_urgent_task (ushort now)
 Finds the highest priority task that is behind schedule.

ushort task_select (void)
 Prepares tempregs for isr_exec(), calc's new exec timer alarm.

void addtask (void(*func)(void), schar priority, ushort nextrun, ushort stacksize)
 Creates & inserts (@ sorted positions) a task into exec task list.

void bsleep (ushort sleeptime)
 Voluntarily give up CPU time, sleep for sleeptime ms.

void isr_exec_stuff (void)
 Extra code that wants to be in isr_exec().

void isr_exec (void)
 BeeOS Real Time task scheduler interrupt service routine (ISR).

void execprep (void)
 Prepares the global execbase_t exec struct; creates idle task.

void exec_idle (void)
 isr_exec() can't restore a NULL context if no tasks are scheduled to run, so this is it.


Variables

execbase_t exec
regs_t tempregs


Define Documentation

#define IN_EXEC
 

Definition at line 26 of file exec.c.


Function Documentation

void addtask void(*  func)(void),
schar  priority,
ushort  nextrun,
ushort  stacksize
 

Creates & inserts (@ sorted positions) a task into exec task list.

After creating & initialising the new task, finds where the task should be inserted into in both the priorty and time exec list.

Parameters:
func Function pointer to task being added
priority A signed char value representing a unique priority, determines location in the exec priority list.
nextrun The first time this task should be scheduled to run, determines location in the exec time list.
stacksize The initial stack size for this task.
Warning:
Does not check for func \== NULL. Also assumes that if exec.head_time is NULL, then so must be exec.head_prior.

Definition at line 277 of file exec.c.

References create_task(), exec, find_nextrun_lte(), find_priority_lte(), execbase_struct::head_prior, execbase_struct::head_time, insert_task_prior(), insert_task_time(), NULL, execbase_struct::numtasks, schar, task_t, and ushort.

00278 {
00279     task_t *new_task = create_task(func, priority, nextrun, stacksize);
00280     task_t *pPrior, *pTime;
00281     
00282     if (NULL != exec.head_time) {   /* Assume head_time reflects head_prior */ 
00283         pPrior = find_priority_lte(exec.head_prior, priority);  /* NULL state. */
00284         pTime = find_nextrun_lte(exec.head_time, nextrun);
00285     } else {
00286         pPrior = NULL;
00287         pTime = NULL;
00288     }
00289     insert_task_prior(pPrior, new_task);
00290     insert_task_time(pTime, new_task);
00291 
00292     exec.numtasks++;
00293 
00294     return;
00295 }

Here is the call graph for this function:

void bsleep ushort  sleeptime  ) 
 

Voluntarily give up CPU time, sleep for sleeptime ms.

Unlinks exec.current from the time list, then calculates nextrun using sleeptime. Finds new location in time list and inserts it there. Sets exec.idle, clears exec.blocked, and then invokes isr_exec with an SWI.

Parameters:
sleeptime The length of time to sleep for, relative to NOW. sleeptime is approx. millisecond units.
Blocking Tasks
Does not re-enable exec timer when called by tasks during blocked state; bsleep() clears exec.blocked flag and then invokes isr_exec() using an SWI. isr_exec() will enable the exec timer apon seeing that exec.blocked is false.

Definition at line 314 of file exec.c.

References ASM_CLI, ASM_SEI, ASM_SWI, execbase_struct::blocked, execbase_struct::current, exec, find_nextrun_lte(), execbase_struct::head_time, execbase_struct::idle, insert_task_time(), MSEC2TCNT, task_struct::nextrun, task_t, TCNT_H, TOUSHORT, unlink_time(), and ushort.

Referenced by btnscan_chk(), lbdrv_chg(), and misc().

00315 {
00316     task_t *pTime;
00317     
00318     exec.current->nextrun = TOUSHORT(TCNT_H) + (ushort) MSEC2TCNT(sleeptime);
00319     ASM_SEI;    /* Don't want other tasks mangling the list in mid-search. */
00320     unlink_time(exec.current);
00321     pTime = find_nextrun_lte(exec.head_time, exec.current->nextrun);
00322     insert_task_time(pTime, exec.current);
00323     ASM_CLI;
00324     exec.idle = true;
00325     exec.blocked = false;   /* If a blocking task just finished, */
00326                         /* clear flag so isr_exec() can re-enable exec timer. */
00327     ASM_SWI;    /* Trigger an INTR to enter isr_exec() */
00328     
00329     return;
00330 }

Here is the call graph for this function:

__inline__ void context_restore2 task_t pTask  ) 
 

Load tempregs with pTask->regs for CONTEXT_RESTORE macro.

Definition at line 345 of file exec.c.

References bmemcpy(), task_struct::regs, task_t, and tempregs.

Referenced by task_select().

00346 {
00347     bmemcpy((char *)&tempregs, (char *)&(pTask->regs), sizeof(tempregs));   
00348     
00349     return;
00350 }

Here is the call graph for this function:

__inline__ void context_save2 task_t pTask  ) 
 

Save tempregs into pTask for CONTEXT_SAVE macro.

Definition at line 335 of file exec.c.

References bmemcpy(), task_struct::regs, task_t, and tempregs.

Referenced by task_select().

00336 {
00337     bmemcpy((char *)&(pTask->regs),     (char *)&tempregs, sizeof(tempregs));
00338     
00339     return;
00340 }

Here is the call graph for this function:

task_t * create_task void(*  func)(void),
schar  priority,
ushort  nextrun,
ushort  stacksize
 

Alloc and init task_t struct with params passed in.

Also sets regs to consecutive values to assist stack debugging. Alloc's task_t struct. Alloc's task_t->stack. Alloc'd stack is zeroed by using bremalloc().

Parameters:
func Function pointer for new task.
priority Unique priority level for the new task.
nextrun The initial nextrun value; can be used to delay execution.
stacksize The number of bytes to allocate for the stack.
Return values:
pTask The newly created and initialised task node. next_*, prev_* linked list pointers are NULL. insert_task_*() func's should be used to place pTask in the exec task list, or just call addtask().
Note:
Used by addtask(), and also execprep() for exec_idle task.

Definition at line 104 of file exec.c.

References regs_struct::_d, regs_struct::_tmp, regs_struct::_xy, regs_struct::_z, bremalloc(), regs_struct::CCR, regs_struct::D, task_struct::func, GCC_SOFTREGCOUNT, regs_struct::IX, regs_struct::IY, MSEC2TCNT, task_struct::nextrun, NULL, regs_struct::PC, task_struct::priority, task_struct::regs, schar, regs_struct::SP, task_struct::stack, task_struct::stacksize, task_t, TCNT_H, TOUSHORT, uchar, and ushort.

Referenced by addtask(), and execprep().

00105 {
00106     uchar i;
00107     task_t *pTask = (task_t *) bremalloc(sizeof(task_t), NULL);
00108     
00109     pTask->func = func;
00110     pTask->priority = priority;
00111     pTask->nextrun = TOUSHORT(TCNT_H) + (ushort) MSEC2TCNT(nextrun);
00112     pTask->stacksize = stacksize;
00113     pTask->stack = (char *) bremalloc(stacksize, NULL);
00114     pTask->regs.SP = TOUSHORT(pTask->stack) + stacksize;
00115     pTask->regs.PC = (ushort) func;
00116     pTask->regs.IY = 0x1918;    /* Non-zero for stack debugging. */
00117     pTask->regs.IX = 0x1716;
00118     pTask->regs.D = 0x1514;
00119     pTask->regs.CCR = 0x13;
00120     pTask->regs._tmp = 0x12;
00121     pTask->regs._z = 0x11;
00122     pTask->regs._xy = 0x10;
00123     for (i = 0; i < GCC_SOFTREGCOUNT; i++) pTask->regs._d[i] = i;
00124     /*bmemset((char *) &(task_ptr->regs), '\0', sizeof(regs_t));*/
00125     
00126     return pTask;
00127 }

Here is the call graph for this function:

void exec_idle void   ) 
 

isr_exec() can't restore a NULL context if no tasks are scheduled to run, so this is it.

See also:
isr_exec, task_select

Definition at line 577 of file exec.c.

References execbase_struct::activetasks, bprintf(), bputs(), exec, and uchar.

Referenced by execprep().

00578 {
00579     uchar temp;
00580     
00581     bputs("exec_idle().\r\n");
00582     while (1 == 1) {
00583         if (temp != exec.activetasks) {
00584             bprintf(10, "idle: activetasks=%i, was %i.\r\n", exec.activetasks, temp);
00585             temp = exec.activetasks;
00586         }
00587     }
00588     
00589     return;
00590 }

Here is the call graph for this function:

void execprep void   ) 
 

Prepares the global execbase_t exec struct; creates idle task.

MUST be called before isr_exec is first invoked.

See also:
isr_exec, task_select, add_task

Definition at line 561 of file exec.c.

References bfree(), bmemset(), create_task(), exec, exec_idle(), execbase_struct::idle_task, and task_struct::stack.

00562 {
00563     bmemset((char *)&exec, 0, sizeof(exec));
00564     exec.idle_task = create_task (exec_idle, -127, 0, 0);
00565     bfree(exec.idle_task->stack);
00566     exec.idle_task->stack = (void *)0x3FFF;
00567     
00568     return;
00569 }

Here is the call graph for this function:

__inline__ task_t * find_imperative_task task_t pCurrent  ) 
 

Finds task soonest to run, with ->priority > pCurrent->priority.

Walks the time list, working towards exec.tail_time (since the idea is that a task in the future will interrupt pCurrent), starting at pCurrent, comparing priority values with pCurrent->priority as it goes.

Parameters:
pCurrent The "current" task in the time list. It's envisaged that this task would almost always match exec.head_time.
Return values:
pImperative If no suitable task is found, returns NULL, otherwise it returns the "imperative" task.
See also:
task_select

Definition at line 387 of file exec.c.

References task_struct::next_time, NULL, task_struct::priority, and task_t.

Referenced by task_select().

00388 {
00389     task_t *pImperative = pCurrent;
00390     bool searching = true;
00391     
00392     while ((NULL != pImperative->next_time) && (searching)) {
00393         pImperative = pImperative->next_time;
00394         if (pImperative->priority > pCurrent->priority) searching = false;
00395     }
00396 
00397     if (!searching) return pImperative;
00398         else return NULL;
00399 }

task_t * find_nextrun_lte task_t pTask,
ushort  time
 

Find a task with nextrun <= time starting at pTask, walking time.

Parameters:
pTask The task node at which to start searching time list.
time The time to compare each pTask's ->nextrun with.
Return values:
pTask Will == original pTask passed in if search hits the end.
Warning:
Does not check for pTask == NULL.

Definition at line 194 of file exec.c.

References task_struct::next_time, task_struct::nextrun, now_cmp(), NULL, task_t, and ushort.

Referenced by addtask(), and bsleep().

00195 {
00196     bool searching = true;
00197     
00198     while ( (NULL != pTask->next_time) && (searching) ) {
00199         /* if (pTask->nextrun <= time) searching = false; */
00200         if (now_cmp(pTask->nextrun, time, time) <= 0) searching = false;
00201         else pTask = pTask->next_time;
00202     }
00203     
00204     return pTask;
00205 }

Here is the call graph for this function:

task_t * find_priority_lte task_t pTask,
schar  priority
 

Find a task with prior <= priority starting \p pTask, walking prior.

Parameters:
pTask The task node at which to start searching prior list.
priority The priority to compare each pTask's ->priority with.
Return values:
pTask Will == original pTask passed in if search hits the end.
Warning:
Does not check for pTask == NULL.

Definition at line 175 of file exec.c.

References task_struct::next_prior, NULL, task_struct::priority, schar, and task_t.

Referenced by addtask().

00176 {
00177     bool searching = true;
00178     
00179     while ( (NULL != pTask->next_prior) && (searching) ) {
00180         if (pTask->priority <= priority) searching = false;
00181         else pTask = pTask->next_prior;
00182     }
00183     
00184     return pTask;
00185 }

__inline__ task_t * find_urgent_task ushort  now  ) 
 

Finds the highest priority task that is behind schedule.

Walks the priority list, starting at exec.head_prior. Stops walking when the first task that is behind schedule relative to now is found.

Parameters:
now Current exec timer value used to determine if a task node is behind schedule, according to the ->nextrun values.
Return values:
pUrgent If no suitable task is found, returns NULL; otherwise returns the "urgent" pTask.

Definition at line 412 of file exec.c.

References exec, execbase_struct::head_prior, task_struct::next_prior, task_struct::nextrun, now_cmp(), NULL, task_t, and ushort.

Referenced by task_select().

00413 {
00414     task_t *pUrgent = exec.head_prior;
00415     bool searching = true;
00416     
00417     while ((NULL != pUrgent->next_prior) && (searching)) {
00418         /* if (pUrgent->nextrun <= now) */
00419         if (0 >= now_cmp(pUrgent->nextrun, now, now)) searching = false;
00420             else pUrgent = pUrgent->next_prior;
00421     }
00422     
00423     if (!searching) return pUrgent;
00424         else return NULL;
00425 }

Here is the call graph for this function:

void idle_task void   ) 
 

void insert_task_prior task_t pPrior,
task_t pTask
 

Insert pTask @ just after pPrior in the prior list.

If pPrior is NULL, assigns exec.head_prior = pTask. If pPrior->next_prior is NULL, assigns exec.tail_prior = pTask.

Parameters:
pPrior The task node in the priority list that pTask will be inserted after.
pTask The task node to insert into the priority list.
Warning:
Does not check for pTask == NULL.

Definition at line 217 of file exec.c.

References exec, execbase_struct::head_prior, task_struct::next_prior, NULL, task_struct::prev_prior, execbase_struct::tail_prior, and task_t.

Referenced by addtask().

00218 {
00219     if (NULL == pPrior) {   /* Make pTask head_prior. */
00220         pTask->prev_prior = NULL;   /* Not necessary, probably already NULL.. */
00221         pTask->next_prior = exec.head_prior;
00222         if (NULL != exec.head_prior) exec.head_prior->prev_prior = pTask;
00223         exec.head_prior = pTask;
00224     } else {
00225         if (NULL != pPrior->next_prior) pPrior->next_prior->prev_prior = pTask;
00226         else exec.tail_prior = pTask;
00227         pTask->next_prior = pPrior->next_prior;
00228         pTask->prev_prior = pPrior;
00229         pPrior->next_prior = pTask;
00230     }
00231     
00232     return;
00233 }

void insert_task_time task_t pTime,
task_t pTask
 

Insert pTask @ just after pTime in the time list.

If pTime is NULL, assigns exec.head_time = pTask. If pTime->next_prior is NULL, assigns exec.tail_time = pTask.

Parameters:
pTime The task node in the time list that pTask will be inserted after.
pTask The task node to insert into the time list.
Warning:
Does not check for pTask == NULL.

Definition at line 245 of file exec.c.

References exec, execbase_struct::head_time, task_struct::next_time, NULL, task_struct::prev_time, execbase_struct::tail_time, and task_t.

Referenced by addtask(), and bsleep().

00246 {
00247     if (NULL == pTime) {        /* Make pTask head_time. */
00248         pTask->prev_time = NULL;    /* Not necessary, probably already NULL.. */
00249         pTask->next_time = exec.head_time;
00250         if (NULL != exec.head_time) exec.head_time->prev_time = pTask;
00251         exec.head_time = pTask;
00252     } else {
00253         if (NULL != pTime->next_time) pTime->next_time->prev_time = pTask;
00254         else exec.tail_time = pTask;
00255         pTask->next_time = pTime->next_time;
00256         pTask->prev_time = pTime;
00257         pTime->next_time = pTask;
00258     }
00259 
00260     return;
00261 }

void isr_exec void   ) 
 

BeeOS Real Time task scheduler interrupt service routine (ISR).

1. Block interrupts 2. Save context 3. Prep new context 4. Set exec timer 5. Restore new context 6. Enable interrupts

Note:
See notes in isr_exec_stuff() regarding the proper place to add code.
See also:
task_select, isr_exec_stuff

Definition at line 541 of file exec.c.

References ASM_CLI, ASM_SEI, isr_exec_stuff(), task_select(), TC7_H, and TOUSHORT.

00542 {
00543     ASM_SEI;
00544     CONTEXT_SAVE(); /* MUST be as close as possible to start; preserve stack/regs */
00545 
00546     TOUSHORT(TC7_H) = task_select();    /* Get new task, set isr_exec timer TC7. */
00547     isr_exec_stuff();   /* Extra code should go in this func; lest GCC dare use 
00548     * _d0.._dn softregisters and invalidate CONTEXT_RESTORE/CONTEXT_SAVE. */
00549     CONTEXT_RESTORE();  /* As close as possible to end; preserve stack/regs */
00550     ASM_CLI;
00551     
00552     return;
00553 }

Here is the call graph for this function:

void isr_exec_stuff void   ) 
 

Extra code that wants to be in isr_exec().

Extra code that wants to be in isr_exec() should live in here, so that GCC doesn't try to push extra softregs on entry of isr_exec().

Note:
Exec timer is TC7. TCNT prescaler is set to max. (128).
See also:
isr_exec

Definition at line 520 of file exec.c.

References BIT7, execbase_struct::blocked, ECT_TOF, exec, PORTA, TFLG1, TFLG2, and TIE.

Referenced by isr_exec().

00521 {
00522     TFLG1 |= BIT7;                          /* Clear TC7 interrupt */
00523     if (TFLG2 & ~ECT_TOF) TFLG2 |= ECT_TOF; /* Clear overflow flag if set */
00524     if (exec.blocked) TIE &= ~BIT7; /* If current task is not to be interrupted, */
00525         /* disable exec timer. Only an SWI from bsleep() can invoke exec. */
00526     else TIE |= BIT7;   /* Else re-enable exec timer. */
00527     PORTA ^= 0x01;      /* ... "debug" output */
00528     
00529     return;
00530 }

__inline__ slong now_cmp ushort  a,
ushort  b,
ushort  now
 

Handles comparisons between continuously wrapping ushort counters.

Compares two ushorts that may have wrapped. Uses now for a reference point; numbers less than now are considered as being in the future, IE. of greater value than numbers more than now.

Parameters:
a Counter value a
b Counter value b
now Reference counter value
Return values:
(A-B) Essentially returns a - b.

Definition at line 363 of file exec.c.

References slong, and ushort.

Referenced by find_nextrun_lte(), find_urgent_task(), and task_select().

00364 {
00365     slong A = (slong) a, B = (slong) b;
00366     
00367     if (a < now) A += (slong) 65535;
00368     if (b < now) B += (slong) 65535;
00369     
00370     return A - B;
00371 }

void task_dumpinfo regs_t regs  ) 
 

Definition at line 65 of file exec.c.

References regs_struct::_d, regs_struct::_tmp, regs_struct::_xy, regs_struct::_z, bprintf(), bputs(), regs_struct::CCR, regs_struct::D, regs_struct::IX, regs_struct::IY, regs_struct::PC, regs_t, and regs_struct::SP.

00066 {
00067     bputs("taskdump:\r\n");
00068     /*bprintf(10, "   nextrun: %x.\r\n", (sshort) pTask->nextrun);
00069     bprintf(10, "   stacksize: %x.\r\n", (sshort) pTask->stacksize);
00070     bprintf(10, "   func: %x.\r\n", (sshort) pTask->func);
00071     bprintf(10, "   stack: %x.\r\n", (sshort) pTask->stack);
00072     bprintf(10, "   priority: %x.\r\n", (sshort) pTask->priority);*/
00073     bprintf(10, "   SP: %x.\r\n", regs->SP);
00074     bprintf(10, "   pc: %x.\r\n", regs->PC);
00075     bprintf(10, "   iy: %x.\r\n", regs->IY);
00076     bprintf(10, "   ix: %x.\r\n", regs->IX);
00077     bprintf(10, "   d: %x.\r\n", regs->D);
00078     bprintf(10, "   _ccr: %x.\r\n", regs->CCR);
00079     bprintf(10, "   _tmp: %x.\r\n", regs->_tmp);
00080     bprintf(10, "   _z: %x.\r\n", regs->_z);
00081     bprintf(10, "   _xy: %x.\r\n", regs->_xy);
00082     bprintf(10, "   _d1: %x.\r\n", regs->_d[0]);
00083     bprintf(10, "   _d2: %x.\r\n", regs->_d[1]);
00084     
00085     return;
00086 }

Here is the call graph for this function:

ushort task_select void   ) 
 

Prepares tempregs for isr_exec(), calc's new exec timer alarm.

  • Returns the timer value that will trigger the next isr_exec() INTR
  • Sets up the tempregs global context struct for isr_exec() to restore.
Scheduler description
The BeeOS scheduler uses a Real Time philiosphy. isr_exec() is never invoked if it doesn't need to be; there is no fixed time slice or quantum.
This scheduler keeps task nodes in two doubly-linked lists. One list is sorted by time, with the next task wanting to be run at the head of the queue. The other is sorted by priority, with the highest priority task at the head of the queue.
When deciding which task should next be run, task_select() will try to choose the task at the head of the time list (if its time is now), and set the isr_exec() timer "alarm" to trigger for the next task in the time list.
However, if things are behind schedule, task_select() will always use the highest priority task that is behind schedule.
Tasks are re-positioned in the time list when they call bsleep(). If the highest priority task never calls bsleep(), it will never be interrupted for a lower priority task and no other tasks will run. bsleep() is useful for making use of delay periods.
Note:
It seems that the task/priority lists only have to be single linked lists. Will fix later.

Doesn't bother modifying tempregs if the context to be restored was already loaded.

Problem: TCNT timer wraps too fast, max. < 1 sec delays?

Return values:
nextswitch New exec timer value to trigger next interrupt. If the highest priority task is already running, sets exec.blocked, which causes isr_exec() to disable the exec timer. This prevents isr_exec() being invoked until the current task is finished; task_select() then returns zero. isr_exec() can only then be invoked by a bsleep() call.
See also:
isr_exec, bsleep, addtask

Definition at line 472 of file exec.c.

References execbase_struct::activetasks, execbase_struct::blocked, context_restore2(), context_save2(), execbase_struct::current, exec, find_imperative_task(), find_urgent_task(), execbase_struct::head_time, execbase_struct::idle, execbase_struct::idle_task, task_struct::next_time, task_struct::nextrun, now_cmp(), NULL, task_struct::sleeping, task_t, TCNT_H, TOUSHORT, and ushort.

Referenced by isr_exec().

00473 {
00474     ushort now = TOUSHORT(TCNT_H);  /* Need to substitute for slower timer... */
00475     ushort nextswitch = 0;          /* Return value */
00476     task_t *lastrun = exec.current; /* Used to check if tempregs needs update */
00477     task_t *pImperative = NULL;     /* Task that needs to intr current task */
00478     
00479     exec.current = exec.head_time;  /* Head of time list, ie. soonest to run. */
00480         /* if (exec.current->nextrun <= now) */     /* Is a task scheduled  */
00481     if (now_cmp(exec.current->nextrun, now, now) <= 0) {    /* right now? */
00482         /* Initially, exec.current is simply head_time. */
00483         /* if (exec.current->next_time->nextrun <= now) {*/ /* Behind schedule? */
00484         if (now_cmp(exec.current->next_time->nextrun, now, now) <= 0) {
00485             /* Here, at least first two tasks @ head_time are behind schedule; */
00486             /* head_time is ignored and instead the highest priority, behind */
00487             /* schedule task shall become the current task. */
00488             exec.current = find_urgent_task(now);
00489         }
00490         /* Now find out which task should interrupt the new current task */
00491         pImperative = find_imperative_task(exec.current);   /* Poss. NULL */
00492         if (NULL != pImperative) nextswitch = pImperative->nextrun;
00493             else exec.blocked = true;   /* Inhibit exec timer; highest pri. run */
00494         if (exec.current != lastrun) {  /* Don't bother saving/loading context */
00495             context_save2(lastrun);     /* if current was already loaded */
00496             context_restore2(exec.current);
00497             if (false != exec.current->sleeping) {
00498                 exec.current->sleeping = false;
00499                 exec.activetasks++;
00500             }
00501         }
00502         exec.idle = false;  /* Purpose unclear ... should reflect activetasks */
00503     } else {        /* This is now idle time; just set the alarm for head_time. */
00504         nextswitch = exec.current->nextrun;
00505         exec.idle = true;   /* Not sure what this does yet... */
00506         context_restore2(exec.idle_task);
00507     }
00508     
00509     return nextswitch;
00510 }

Here is the call graph for this function:

void unlink_prior task_t pTask  ) 
 

Unlinks pTask from the priority list.

Parameters:
pTask The task to unlink; it becomes orphaned from the priority list.
Warning:
Does not check for pTask == NULL.

Definition at line 153 of file exec.c.

References exec, execbase_struct::head_prior, task_struct::next_prior, NULL, task_struct::prev_prior, execbase_struct::tail_prior, and task_t.

00154 {
00155     /* If pTask was the head task, reassign exec.head_prior. */
00156     if (NULL == pTask->prev_prior) exec.head_prior = pTask->next_prior;
00157         else pTask->prev_prior->next_prior = pTask->next_prior;
00158     /* If pTask was the tail task, reassign exec.tail_time. */
00159     if (NULL == pTask->next_prior) exec.tail_prior = pTask->prev_prior;
00160         else pTask->next_prior->prev_prior = pTask->prev_prior;
00161     pTask->prev_prior = NULL;
00162     pTask->next_prior = NULL;
00163             
00164     return;
00165 }

void unlink_time task_t pTask  ) 
 

Unlinks pTask from the time list.

Parameters:
pTask The task to unlink; it becomes orphaned from the time list.
Warning:
Does not check for pTask == NULL.

Definition at line 134 of file exec.c.

References exec, execbase_struct::head_time, task_struct::next_time, NULL, task_struct::prev_time, execbase_struct::tail_time, and task_t.

Referenced by bsleep().

00135 {   
00136     /* If pTask was the head task, reassign exec.head_time. */
00137     if (NULL == pTask->prev_time) exec.head_time = pTask->next_time;
00138         else pTask->prev_time->next_time = pTask->next_time;
00139     /* If pTask was the tail task, reassign exec.tail_time. */
00140     if (NULL == pTask->next_time) exec.tail_time = pTask->prev_time;
00141         else pTask->next_time->prev_time = pTask->prev_time;
00142     pTask->prev_time = NULL;
00143     pTask->next_time = NULL;
00144             
00145     return;
00146 }


Variable Documentation

execbase_t exec
 

Definition at line 38 of file exec.c.

Referenced by addtask(), bsleep(), exec_idle(), execprep(), find_urgent_task(), insert_task_prior(), insert_task_time(), isr_exec_stuff(), task_select(), unlink_prior(), and unlink_time().

regs_t tempregs
 

Definition at line 39 of file exec.c.

Referenced by context_restore2(), and context_save2().


Generated on Sat Apr 10 17:08:16 2004 for BeeOS by doxygen 1.3.6-20040222