static void * _yield(struct coroutine *co) { assert(_scheduler() == co->sched); co->stack_lowest = (uint8_t*)&co; co->result = NULL; _switch_context(&co->ctx, &co->sched->ctx); return co->result; }
static void _push_coroutine(struct scheduler *s, struct coroutine *co) { struct scheduler *self = _scheduler(); if (s == self) { queue_push(s->self_queue, co); } else { pthread_mutex_lock(&s->queue_mutex); s->lock_queue_n += 1; queue_push(s->lock_queue, co); pthread_mutex_unlock(&s->queue_mutex); pthread_cond_signal(&s->queue_signal); } }
inline static void _resume(struct coroutine *co) { struct scheduler *s = co->sched; assert(s == _scheduler()); if (co->inited) { _copy_stack(co); } else { // init in the same thread as coroutine context. co->inited = true; _make_context(co, &s->ctx, &s->stack); } co->status = STATUS_RUNNING; _switch_context(&s->ctx, &co->ctx); }
void interrupt (TIMER_INTERRUPT_VECTOR) _timerIsr(void) { /* make this local vars static so as to store on the heap instead * of the stack. This avoids stack smashing. */ static uint8_t* stackPtrTmp; static uint8_t scheduledTask; static int32_t elapsedTime, curTime; // TODO remove post demo static bool_t printedMutex = false; /* acknowledge interrupt */ TFLG2_TOF = 1; /* get current stackPtr */ { asm STS stackPtrTmp; } /* Save stack ptr * special case on main loop. * The main loop stack pointer is saved in a seperate variable*/ if (MAIN_LOOP_PRIORITY == _currentTask) { _mainLoopStackPtr = stackPtrTmp; } else { taskArray[_currentTask].stackPtr = stackPtrTmp; } /* Set current stack to ISR stack. * The ISR stack keeps the ISR from stack smashing * an uninitialized task's stack. * start at lowest memory address in stack, note this is ptr arithmatic. */ stackPtrTmp = _ISRstack + TASK_STACK_SIZE - 1; { asm LDS stackPtrTmp; } /* update time variables */ timerUpdateCurrent(); /* update task timing - note that this requires interrupts be disabled */ elapsedTime = timerElapsedTime(); _updateTaskTimes(elapsedTime); /* Run the scheduler every time through the ISR * The scheduler determines which task to run once the * ISR returns. */ scheduledTask = _scheduler(); /* If serial dubugging is enabled and we have we just changed tasks, * print information about the current state of all tasks. */ if (_debug && scheduledTask != _currentTask) { curTime = timerGetCurrentMsec(); _debugPrint(scheduledTask, curTime); } // TODO remove after demo /* task 4 is set to run but task 3 is ready to run */ if ((false == printedMutex) && (scheduledTask == 4) && (taskArray[3].enabled == true) && (taskArray[3].timeToNextRun <= 0) ) { serialWrite("HA I GOT YOUR MUTEX!!\n", 23); printedMutex = true; } else if (scheduledTask != 4){ printedMutex = false; } /* Special case if scheduler has no tasks to run. * In this case the returned index is _numTasks. * The main loop will be run until a task is ready * to run. Otherwise simply use the designated task's * stack ptr. */ if ( MAIN_LOOP_PRIORITY == scheduledTask ) { stackPtrTmp = _mainLoopStackPtr; } else { if ( false == taskArray[scheduledTask].running ) { /* Create launch stack if not currently running * This operation sets the stack pointer. */ _createNewStack(scheduledTask); } /* grab stack ptr */ stackPtrTmp = taskArray[scheduledTask].stackPtr; /* task is now runing */ taskArray[scheduledTask].running = true; } /* Set global current task to the scheduled task */ _currentTask = scheduledTask; /* Set stack pointer to the current task stack pointer */ { asm LDS stackPtrTmp; } /* ISR does an RTI to return to the current stack. The * RTI restores all of the state (registers, cond codes, etc) * if the task was running before or simply loads the dummy * state (as set by the create stack function) if the task * is being initialized. */ }