void handleNewPieceTask() { int type; while(1) { //wait for a new piece to be created YKSemPend(newPieceSEM); YKEnterMutex(); type = NewPieceType; /*printString("NEW PIECE id = "); printInt(NewPieceID); printString(" type = "); printInt(NewPieceType); printString(" column = "); printInt(NewPieceColumn); printString(" Orientation = "); printInt(NewPieceOrientation); printNewLine();//*/ YKExitMutex(); //Accessing global variables, so better be in mutex if(type) //Straight piece { straightPieceHandler(); } else //square piece { cornerPieceHandler(); } } }
int YKQPost(YKQ* queue, void* msg) { TCB* readyTask; int retVal; YKEnterMutex(); if (queue->currentSize < queue->maxSize) { queue->messages[queue->currentSize] = msg; queue->currentSize++; retVal = 1; } else { retVal = 1; } readyTask = removePriorityQueue(&(queue->queue)); if (readyTask == null) { YKExitMutex(); return retVal; } else { readyTask->state = T_READY; insertPriorityQueue(&readyQueue, readyTask); YKExitMutex(); if (YKGetISRCallDepth() == 0) { asm("int 0x20"); } } return retVal; }
void* YKQPend(YKQ* queue) { void* message; int i; TCB* runningTask; if (queue == null) return null; YKEnterMutex(); if (*queue->messages == null) { runningTask = removePriorityQueue(&readyQueue); runningTask->state = T_BLOCKED; insertPriorityQueue((&(queue->queue)), runningTask); YKExitMutex(); asm("int 0x20"); } message = queue->messages[0]; for (i = 0; i < queue->currentSize-1; i++) { queue->messages[i] = queue->messages[i+1]; } queue->currentSize--; queue->messages[queue->currentSize] = null; YKExitMutex(); return message; }
void YKIdleTask(void) { while(1) { YKEnterMutex(); YKIdleTask = YKIdleTask+1; YKExitMutex(); } }
void newPieceHandler(void) { /* This function needs to get the details of the new simptris piece and place a new piece on the piece queue. It obtains the next piece from the piece array using a static counter. */ static unsigned int nextPiece; int temp; //Build new piece YKEnterMutex(); //printString("NewPieceHandler\n"); /*printInt(NewPieceID); printNewLine(); printInt(NewPieceType); printNewLine(); printInt(NewPieceOrientation); printNewLine(); printInt(NewPieceColumn);*/ PiecesArray[nextPiece].id = NewPieceID; PiecesArray[nextPiece].type = NewPieceType; PiecesArray[nextPiece].orientation = NewPieceOrientation; PiecesArray[nextPiece].column = NewPieceColumn; YKExitMutex(); YKQPost(PiecesQPtr, &PiecesArray[nextPiece]); if (nextPiece+1 < MSGQSIZE) { nextPiece++; } else { nextPiece = 0; } return; }
//Initalizing code ----------------------------------------------------------------------------- void YKInitialize() { //Initializes all required kernel data structures int i; YKEnterMutex(); //Initalize the YKAvailTCBList queue YKAvailTCBList = &(YKTCBArray[0]); for (i = 0; i < MAXTASKS; i++) { if(i != 0) { YKTCBArray[i].prev = &(YKTCBArray[i-1]); } YKTCBArray[i].next = &(YKTCBArray[i+1]); } YKTCBArray[0].prev = NULL; YKTCBArray[MAXTASKS].next = NULL; if(MAXTASKS > 0) { YKTCBArray[MAXTASKS].prev = &(YKTCBArray[MAXTASKS - 1]); } YKReadyList = NULL; YKSuspList = NULL; nestedInterruptLevel = 0; curTask = NULL; YKNewTask(YKIdleTask, (void *)&IdleStk[IDLESTACKSIZE], 100); }
//YKEventPend unsigned YKEventPend(YKEVENT *event, unsigned eventMask, int waitMode) { int i; YKEnterMutex(); if(waitMode == EVENT_WAIT_ALL) { if(event->flags == eventMask) { return event->flags; } } else // wait mode any { if((event->flags & eventMask) > 0) { return event->flags; } } YKReadyList->waitMode = waitMode; YKReadyList->eventMask = eventMask; YKMoveTCB(YKReadyList, &YKReadyList, &(event->blockedList)); YKScheduler(1); return event->flags; }
void Task(void) { unsigned idleCount; unsigned numCtxSwitches; printString("Task started.\n"); while (1) { printString("Delaying task...\n"); YKDelayTask(2); YKEnterMutex(); numCtxSwitches = YKCtxSwCount; idleCount = YKIdleCount; YKIdleCount = 0; YKExitMutex(); printString("Task running after "); printUInt(numCtxSwitches); printString(" context switches! YKIdleCount is "); printUInt(idleCount); printString(".\n"); } }
void YKInitialize(){ int i; YKEnterMutex(); YKIMRInit(0x00); running = 0; YKIdleCount = 0; YKCtxSwCount = 0; YKCurTask = NULL; YKRdyList = NULL; YKSuspList = NULL; nestingLevel = 0; YKTickNum = 0; YKAvaiSems = MAXSEMS; // Initialize locations for TCB YKAvailTCBList = &(YKTCBArray[0]); for (i = 0; i < MAXTASKS; i++){ YKTCBArray[i].next = &(YKTCBArray[i+1]); YKTCBArray[MAXTASKS].prev = NULL; } YKTCBArray[MAXTASKS].next = NULL; YKTCBArray[MAXTASKS].prev = NULL; YKNewTask(YKIdleTask,(void *) &(idleStk[IDLE_STACK_SIZE]),100); }
//YKEventSet void YKEventSet(YKEVENT *event, unsigned eventMask) { TCBptr current, next; int i; YKEnterMutex(); current = event->blockedList; event->flags = event->flags | eventMask; while(current != NULL) { next = current->next; if(current->waitMode == EVENT_WAIT_ALL) { if(current->eventMask == event->flags) { YKMoveTCB(current, &(event->blockedList), &YKReadyList); } } else { if((event->flags & eventMask) > 0) { YKMoveTCB(current, &(event->blockedList), &YKReadyList); } } current = next; } if(nestedInterruptLevel == 0) //if not in an interrupt { YKScheduler(1); } }
unsigned YKEventPend(YKEVENT *event, unsigned eventMask, int waitMode){ int conditionMet = 0; int i; unsigned flags; TCBptr temp, temp2, iter; YKEnterMutex(); // ------- Test if Conditions are met --------// conditionMet = checkConditions(event->flags, eventMask, waitMode); // -------- If condition met, return. Else, block --------// if (conditionMet){ flags = event->flags; YKExitMutex(); return flags; } else{ // Remove calling task's TCB from ready list temp = YKRdyList; // Hold the first ready task // Remove it from Ready list YKRdyList = temp->next; if (YKRdyList != NULL) YKRdyList->prev = NULL; // modify TCB, put in suspended list temp->state = BLOCKED; temp->flags = eventMask; temp->waitMode = waitMode; // Put task at event's blocked list if (event->waitingOn == NULL){ event->waitingOn = temp; temp->next = NULL; temp->prev = NULL; } else{ iter = event->waitingOn; temp2 = NULL; while (iter != NULL && iter->priority < temp->priority){ temp2 = iter; iter = iter->next; } if (iter == NULL){//At end temp2->next = temp; temp->prev = temp; temp->next = NULL; } else{ // insert before iterator temp->next = iter; temp->prev = temp2; iter->prev = temp; if (temp2 == NULL)//inserted at beginning of list event->waitingOn = temp; else temp2->next = temp; } } YKScheduler(ContextNotSaved); flags = event->flags; YKExitMutex(); } return flags; }
int YKQPost(YKQ *queue, void *msg) { int return_value; // put message into queue YKEnterMutex(); if (queue->size != queue->max_length ) { ++(queue->size); queue->base_addr[queue->tail] = msg; if ( queue->tail == (queue->max_length - 1) ) queue->tail = 0; else ++(queue->tail); if (queue->size == 1) { YKBlockQ2Ready(queue); if (YKISRDepth == 0) { YKExitMutex(); YKScheduler(); } } return_value = 1; } else return_value = 0; YKExitMutex(); return return_value; }
void YKInitialize(void){ YKEnterMutex(); //Create Idle task and add it to the ready queue //printString("YKInitialize\n"); YKNewTask(&YKIdleTask, (void *)&idleStk[IDLE_STACK_SIZE], 100); //new task adds to queue for us }
void *YKQPend(YKQ *queue){ void * tempMsg; TCBptr temp, temp2, iter; TOP: YKEnterMutex(); if (queue->numOfMsgs > 0){ // not empty // remove oldest message tempMsg = queue->baseAddress[queue->removeLoc]; queue->removeLoc++; // handle roll over if (queue->removeLoc >= queue->numOfEntries){ queue->removeLoc = 0; } queue->numOfMsgs--; } else { // Remove calling task's TCB from ready list temp = YKRdyList; // Hold the first ready task // Remove it from Ready list YKRdyList = temp->next; if (YKRdyList != NULL) YKRdyList->prev = NULL; // modify TCB, put in suspended list temp->state = BLOCKED; // Put task at queue's blocked list if (queue->blockedOn == NULL){ queue->blockedOn = temp; temp->next = NULL; temp->prev = NULL; } else{ iter = queue->blockedOn; temp2 = NULL; while (iter != NULL && iter->priority < temp->priority){ temp2 = iter; iter = iter->next; } if (iter == NULL){//At end temp2->next = temp; temp->prev = temp; temp->next = NULL; } else{ // insert before iterator temp->next = iter; temp->prev = temp2; iter->prev = temp; if (temp2 == NULL)//inserted at beginning of list queue->blockedOn = temp; else temp2->next = temp; } } YKScheduler(ContextNotSaved); goto TOP; } YKExitMutex(); return tempMsg; }
void YKScheduler(int saveContext){ YKEnterMutex(); if(YKRdyList != YKCurTask){ YKCtxSwCount++; YKDispatcher(saveContext); } YKExitMutex(); }
void YKIdleTask(){ while(1){ YKEnterMutex(); YKIdleCount++; YKExitMutex(); } }
void YKNewTask(void (* task)(void), void *stackptr, unsigned char priority){ int i; unsigned *stackIter; TCBptr insertion, iter2; YKEnterMutex(); insertion = YKAvailTCBList; if(insertion == NULL){ return; } YKAvailTCBList = insertion->next; insertion->state = READY; insertion->priority = priority; insertion->delay = 0; insertion->flags = 0; insertion->waitMode = 0; if (YKRdyList == NULL) /* is this first insertion? */ { YKRdyList = insertion; insertion->next = NULL; insertion->prev = NULL; } else /* not first insertion */ { iter2 = YKRdyList; /* insert in sorted ready list */ while (iter2->priority < insertion->priority) iter2 = iter2->next; /* assumes idle task is at end */ if (iter2->prev == NULL) /* insert in list before tmp2 */ YKRdyList = insertion; else iter2->prev->next = insertion; insertion->prev = iter2->prev; insertion->next = iter2; iter2->prev = insertion; } stackIter = (unsigned *)stackptr; stackIter -=13; for(i=0; i<13; i++) { if (i == 10) { stackIter[i] = (unsigned)task; } else if (i == 12) { stackIter[i] = FLAGB; // Set the interrupt flag } else { stackIter[i] = 0; } } insertion->stackptr = (void *)stackIter; if(running == 1) { YKScheduler(ContextNotSaved); } YKExitMutex(); }
void YKExitISR(void) { YKEnterMutex(); ISRCallDepth--; if (ISRCallDepth == 0) { YKExitMutex(); YKScheduler(); } YKExitMutex(); }
void YKRun(void) { YKEnterMutex(); kernelState = K_RUNNING; YKScheduler(); YKExitMutex(); return; }
//YKEventReset void YKEventReset(YKEVENT *event, unsigned eventMask) { YKEnterMutex(); event->flags = event->flags & (~eventMask); if(nestedInterruptLevel == 0) { YKExitMutex(); } }
void YKIdleTask(){ printString("in idle\r\n"); while(1){ YKEnterMutex(); YKIdleCount++; YKExitMutex(); } }
void YKDelayTask(int count) { /* Delays a task for specified number of clock ticks*/ YKEnterMutex(); runningTask->delay=count; suspendTask(runningTask); YKExitMutex(); YKScheduler(0); }
void YKDelayTask(unsigned count) { YKEnterMutex(); YKReadyList->delay = count; YKMoveTCB(YKReadyList, &YKReadyList, &YKSuspList); YKScheduler(1); }
void YKExitISR(void) { YKEnterMutex(); nestedInterruptLevel--; if(nestedInterruptLevel == 0) { YKScheduler(0); } }
void YKNewTask (void (*task)(void), void* taskStack, int priority) { //Creates a new task //sets up tcb and stack frame int i; int temp; //Set up new TCB for task //printString("YAK is creating a new task"); //printWord(task); //printNewLine(); YKEnterMutex(); YKAvailTCBList->task = task; YKAvailTCBList->stackptr = taskStack; YKAvailTCBList->state = READY; YKAvailTCBList->priority = priority; YKAvailTCBList->delay = 0; (int*)YKAvailTCBList->stackptr = (int*)YKAvailTCBList->stackptr - WORD_SIZE_IN_BYTES; temp = YKAvailTCBList->stackptr; //Set Top of ready queue to point to this task //printString("SAVING CONTEXT\n\r"); //printString("STACK PTR START = "); //printWord(YKAvailTCBList->stackptr); //printNewLine(); *((int*)YKAvailTCBList->stackptr) = INIT_CFLAGS; //cflags (int*)YKAvailTCBList->stackptr = (int*)YKAvailTCBList->stackptr - WORD_SIZE_IN_BYTES; *((int*)YKAvailTCBList->stackptr) = 0; //CS (int*)YKAvailTCBList->stackptr = (int*)YKAvailTCBList->stackptr - WORD_SIZE_IN_BYTES; *((int*)YKAvailTCBList->stackptr) = (int*)task; // ip (int*)YKAvailTCBList->stackptr = (int*)YKAvailTCBList->stackptr - WORD_SIZE_IN_BYTES; for(i = 0; i < NUM_REGS; i++) { *((int*)YKAvailTCBList->stackptr) = 0x0; (int*)YKAvailTCBList->stackptr = (int*)YKAvailTCBList->stackptr - WORD_SIZE_IN_BYTES; } *((int*)YKAvailTCBList->stackptr) = temp; //printString("STACK PTR end = "); //printWord(YKAvailTCBList->stackptr); //printNewLine(); //printString("CONTEXT SAVED\n\r"); if(curTask == NULL) { curTask = YKReadyList; } YKMoveTCB(YKAvailTCBList, &YKAvailTCBList, &YKReadyList); if(curTask->priority == YKReadyList->priority) { return; } if(!initializing) { YKScheduler(1); } }
YKSEM* YKSemCreate(int initialValue){ static int index = 0; //create sem at index YKEnterMutex(); SStack[index].ID = index; SStack[index].value = initialValue; YKExitMutex(); //return address and increment index return &SStack[index++]; }
void YKEventSet(YKEVENT *event, unsigned eventMask){ int i; int taskMadeReady = 0; TCBptr iter, temp, temp2, next; unsigned flags; YKEnterMutex(); // ----- Set Flag Group ---- // for (i = 0; i < 16; i++){ if (eventMask & BIT(i)){ event->flags |= BIT(i); } } flags = event->flags; // ----- check Conditions ---- // iter = event->waitingOn; while (iter != NULL){ // if conditions are met for that task, put in ready list if (checkConditions(flags, iter->flags, iter->waitMode)){ // remove from pending list next = iter->next; // check if the task to remove is the head if (iter == event->waitingOn){ event->waitingOn = iter->next; } if (iter->prev != NULL) iter->prev->next = iter->next; if (iter->next != NULL) iter->next->prev = iter->prev; // modify TCB of that task, place in ready list iter->state = READY; // Put in Rdy List temp2 = YKRdyList; while (temp2->priority < iter->priority){ temp2 = temp2->next; } if (temp2->prev == NULL){ YKRdyList = iter; } else{ temp2->prev->next = iter; } iter->prev = temp2->prev; iter->next = temp2; temp2->prev = iter; taskMadeReady = 1; iter = next; } else { iter = iter->next; } } // call scheduler if not called from ISR and a task was made ready if (taskMadeReady && nestingLevel == 0) YKScheduler(ContextNotSaved); YKExitMutex(); }
void TaskStat(void) /* a task to track statistics */ { unsigned max, switchCount, idleCount; int tmp; YKDelayTask(1); printString("Welcome to the YAK kernel\r\n"); printString("Determining CPU capacity\r\n"); YKDelayTask(1); YKIdleCount = 0; YKDelayTask(5); max = YKIdleCount / 25; YKIdleCount = 0; YKNewTask(TaskPrime, (void *) &TaskPRMStk[TASK_STACK_SIZE], 32); YKNewTask(TaskWord, (void *) &TaskWStk[TASK_STACK_SIZE], 10); YKNewTask(TaskSpace, (void *) &TaskSStk[TASK_STACK_SIZE], 11); YKNewTask(TaskPunc, (void *) &TaskPStk[TASK_STACK_SIZE], 12); while (1) { YKDelayTask(20); YKEnterMutex(); switchCount = YKCtxSwCount; idleCount = YKIdleCount; YKExitMutex(); printString ("<<<<< Context switches: "); printInt((int)switchCount); printString(", CPU usage: "); tmp = (int) (idleCount/max); printInt(100-tmp); printString("% >>>>>\r\n"); YKEnterMutex(); YKCtxSwCount = 0; YKIdleCount = 0; YKExitMutex(); } }
void YKEventReset(YKEVENT *event, unsigned eventMask){ int i; YKEnterMutex(); for (i = 0; i < 16; i++){ // If the specified bit is set in the mask, clear it in the event flags if (eventMask & BIT(i)){ event->flags &= ~(BIT(i)); } } YKExitMutex(); }
//Semaphores -------------------------------------------------------------------------------- YKSEM* YKSemCreate(int initialValue) { int semaphore; YKEnterMutex(); semaphore = nextUnusedSemaphore; ++nextUnusedSemaphore; semaphoreArray[semaphore].count = initialValue; semaphoreArray[semaphore].blockedList = NULL; //YKExitMutex(); return &semaphoreArray[semaphore]; }