00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00023 #include "../include/beeos.h"
00024 #include "../include/bstring.h"
00025 #include "../include/bmalloc.h"
00026 #define IN_EXEC
00027 #include "../include/exec.h"
00028 #include <stdarg.h>
00029 #include "../include/bprintf.h"
00030 #ifdef HOSTED_BUILD
00031 # include <stdio.h>
00032 #else
00033 # include "../include/asm/ports.h"
00034 # include "../include/ect.h"
00035 #endif
00036
00037
00038 execbase_t exec;
00039 regs_t tempregs;
00040
00041
00042 void idle_task (void);
00043 void task_dumpinfo (regs_t *regs);
00044
00045 task_t *create_task(void (*func)(void), schar priority, ushort nextrun, ushort stacksize);
00046 void unlink_time (task_t *pTask);
00047 void unlink_prior (task_t *pTask);
00048 task_t *find_priority_lte(task_t *pTask, schar priority);
00049 task_t *find_nextrun_lte(task_t *pTask, ushort time);
00050 void insert_task_prior(task_t *pPrior, task_t *pTask);
00051 void insert_task_time(task_t *pTime, task_t *pTask);
00052
00053 __inline__ void context_save2(task_t *pTask);
00054 __inline__ void context_restore2(task_t *pTask);
00055 __inline__ slong now_cmp (ushort a, ushort b, ushort now);
00056 __inline__ task_t *find_imperative_task(task_t *pCurrent);
00057 __inline__ task_t *find_urgent_task(ushort now);
00058 ushort task_select (void);
00059 void isr_exec (void) __attribute__ ((interrupt));
00060 void exec_idle (void);
00061
00065 void task_dumpinfo (regs_t *regs)
00066 {
00067 bputs("taskdump:\r\n");
00068
00069
00070
00071
00072
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 }
00087
00104 task_t *create_task (void (*func)(void), schar priority, ushort nextrun, ushort stacksize)
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;
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
00125
00126 return pTask;
00127 }
00128
00134 void unlink_time (task_t *pTask)
00135 {
00136
00137 if (NULL == pTask->prev_time) exec.head_time = pTask->next_time;
00138 else pTask->prev_time->next_time = pTask->next_time;
00139
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 }
00147
00153 void unlink_prior (task_t *pTask)
00154 {
00155
00156 if (NULL == pTask->prev_prior) exec.head_prior = pTask->next_prior;
00157 else pTask->prev_prior->next_prior = pTask->next_prior;
00158
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 }
00166
00167
00175 task_t *find_priority_lte (task_t *pTask, schar priority)
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 }
00186
00194 task_t *find_nextrun_lte (task_t *pTask, ushort time)
00195 {
00196 bool searching = true;
00197
00198 while ( (NULL != pTask->next_time) && (searching) ) {
00199
00200 if (now_cmp(pTask->nextrun, time, time) <= 0) searching = false;
00201 else pTask = pTask->next_time;
00202 }
00203
00204 return pTask;
00205 }
00206
00217 void insert_task_prior (task_t *pPrior, task_t *pTask)
00218 {
00219 if (NULL == pPrior) {
00220 pTask->prev_prior = 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 }
00234
00245 void insert_task_time (task_t *pTime, task_t *pTask)
00246 {
00247 if (NULL == pTime) {
00248 pTask->prev_time = 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 }
00262
00277 void addtask (void (*func)(void), schar priority, ushort nextrun, ushort stacksize)
00278 {
00279 task_t *new_task = create_task(func, priority, nextrun, stacksize);
00280 task_t *pPrior, *pTime;
00281
00282 if (NULL != exec.head_time) {
00283 pPrior = find_priority_lte(exec.head_prior, priority);
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 }
00296
00314 void bsleep (ushort sleeptime)
00315 {
00316 task_t *pTime;
00317
00318 exec.current->nextrun = TOUSHORT(TCNT_H) + (ushort) MSEC2TCNT(sleeptime);
00319 ASM_SEI;
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;
00326
00327 ASM_SWI;
00328
00329 return;
00330 }
00331
00335 __inline__ void context_save2 (task_t *pTask)
00336 {
00337 bmemcpy((char *)&(pTask->regs), (char *)&tempregs, sizeof(tempregs));
00338
00339 return;
00340 }
00341
00345 __inline__ void context_restore2 (task_t *pTask)
00346 {
00347 bmemcpy((char *)&tempregs, (char *)&(pTask->regs), sizeof(tempregs));
00348
00349 return;
00350 }
00351
00363 __inline__ slong now_cmp (ushort a, ushort b, ushort now)
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 }
00372
00387 __inline__ task_t *find_imperative_task (task_t *pCurrent)
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 }
00400
00412 __inline__ task_t *find_urgent_task (ushort now)
00413 {
00414 task_t *pUrgent = exec.head_prior;
00415 bool searching = true;
00416
00417 while ((NULL != pUrgent->next_prior) && (searching)) {
00418
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 }
00426
00472 ushort task_select (void)
00473 {
00474 ushort now = TOUSHORT(TCNT_H);
00475 ushort nextswitch = 0;
00476 task_t *lastrun = exec.current;
00477 task_t *pImperative = NULL;
00478
00479 exec.current = exec.head_time;
00480
00481 if (now_cmp(exec.current->nextrun, now, now) <= 0) {
00482
00483
00484 if (now_cmp(exec.current->next_time->nextrun, now, now) <= 0) {
00485
00486
00487
00488 exec.current = find_urgent_task(now);
00489 }
00490
00491 pImperative = find_imperative_task(exec.current);
00492 if (NULL != pImperative) nextswitch = pImperative->nextrun;
00493 else exec.blocked = true;
00494 if (exec.current != lastrun) {
00495 context_save2(lastrun);
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;
00503 } else {
00504 nextswitch = exec.current->nextrun;
00505 exec.idle = true;
00506 context_restore2(exec.idle_task);
00507 }
00508
00509 return nextswitch;
00510 }
00511
00520 void isr_exec_stuff (void)
00521 {
00522 TFLG1 |= BIT7;
00523 if (TFLG2 & ~ECT_TOF) TFLG2 |= ECT_TOF;
00524 if (exec.blocked) TIE &= ~BIT7;
00525
00526 else TIE |= BIT7;
00527 PORTA ^= 0x01;
00528
00529 return;
00530 }
00531
00541 void isr_exec (void)
00542 {
00543 ASM_SEI;
00544 CONTEXT_SAVE();
00545
00546 TOUSHORT(TC7_H) = task_select();
00547 isr_exec_stuff();
00548
00549 CONTEXT_RESTORE();
00550 ASM_CLI;
00551
00552 return;
00553 }
00554
00561 void execprep (void)
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 }
00570
00577 void exec_idle (void)
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 }