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:
Go to the source code of this file.
Defines | |
#define | IN_EXEC |
Functions | |
void | idle_task (void) |
void | task_dumpinfo (regs_t *regs) |
task_t * | create_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_t * | find_priority_lte (task_t *pTask, schar priority) |
Find a task with prior <= priority starting \p pTask, walking prior . | |
task_t * | find_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_t * | find_imperative_task (task_t *pCurrent) |
Finds task soonest to run, with ->priority > pCurrent->priority . | |
__inline__ task_t * | find_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 |
|
|
|
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.
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:
|
Voluntarily give up CPU time, sleep for
Unlinks
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:
|
Load
Definition at line 345 of file exec.c. References bmemcpy(), task_struct::regs, task_t, and tempregs. Referenced by task_select().
|
Here is the call graph for this function:
|
Save
Definition at line 335 of file exec.c. References bmemcpy(), task_struct::regs, task_t, and tempregs. Referenced by task_select().
|
Here is the call graph for this function:
|
Alloc and init
Also sets
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:
|
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:
|
Prepares the global
MUST be called before
Definition at line 561 of file exec.c. References bfree(), bmemset(), create_task(), exec, exec_idle(), execbase_struct::idle_task, and task_struct::stack.
|
Here is the call graph for this function:
|
Finds task soonest to run, with
Walks the
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 } |
|
Find a task with
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:
|
Find a task with
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 } |
|
Finds the highest priority task that is behind schedule.
Walks the priority list, starting at
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:
|
|
|
Insert
If
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 } |
|
Insert
If
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 } |
|
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
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:
|
Extra code that wants to be in
Extra code that wants to be in
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 } |
|
Handles comparisons between continuously wrapping ushort counters.
Compares two
Definition at line 363 of file exec.c. Referenced by find_nextrun_lte(), find_urgent_task(), and task_select().
|
|
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:
|
Prepares
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:
|
Unlinks
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 } |
|
Unlinks
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 } |
|
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(). |
|
Definition at line 39 of file exec.c. Referenced by context_restore2(), and context_save2(). |