adding in ecen425 RTOS final lab
This commit is contained in:
parent
4014513685
commit
e3fae2b680
141
ecen425/DelayQueue.c
Normal file
141
ecen425/DelayQueue.c
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#include "DelayQueue.h"
|
||||||
|
#include "PriorityQueue.h"
|
||||||
|
#include "yakk.h"
|
||||||
|
#include "clib.h"
|
||||||
|
|
||||||
|
extern DelayQueue delayQueue;
|
||||||
|
extern PriorityQueue readyQueue;
|
||||||
|
|
||||||
|
void initializeDelayQueue() {
|
||||||
|
delayQueue.size = 0;
|
||||||
|
delayQueue.head = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tickClock() {
|
||||||
|
|
||||||
|
TCB* current;
|
||||||
|
TCB* temp;
|
||||||
|
|
||||||
|
//Size == 0
|
||||||
|
YKEnterMutex();
|
||||||
|
if (delayQueue.size == 0) {
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = delayQueue.head;
|
||||||
|
if (delayQueue.size == 1) {
|
||||||
|
current->delayCount--;
|
||||||
|
if (current->delayCount == 0) {
|
||||||
|
delayQueue.head = null;
|
||||||
|
delayQueue.size = 0;
|
||||||
|
current->next = null;
|
||||||
|
current->prev = null;
|
||||||
|
current->state = T_READY;
|
||||||
|
YKExitMutex();
|
||||||
|
insertPriorityQueue(&readyQueue, current);
|
||||||
|
//printString("\nAfter insert\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current->delayCount--;
|
||||||
|
while (current != null) {
|
||||||
|
current = delayQueue.head;
|
||||||
|
if (current->delayCount == 0) {
|
||||||
|
delayQueue.head = current->next;
|
||||||
|
if (current->next != null) {
|
||||||
|
current->next->prev = null;
|
||||||
|
}
|
||||||
|
current->next = null;
|
||||||
|
current->prev = null;
|
||||||
|
current->state = T_READY;
|
||||||
|
temp = current;
|
||||||
|
delayQueue.size--;
|
||||||
|
insertPriorityQueue(&readyQueue, temp);
|
||||||
|
current = delayQueue.head;
|
||||||
|
} else {
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void insertDelayQueue(TCB* tcb) {
|
||||||
|
|
||||||
|
TCB* current;
|
||||||
|
unsigned int sumCount;
|
||||||
|
unsigned int oldSumCount;
|
||||||
|
|
||||||
|
if (tcb == null) return;
|
||||||
|
|
||||||
|
//Size = 0
|
||||||
|
YKEnterMutex();
|
||||||
|
if (delayQueue.size == 0) {
|
||||||
|
delayQueue.head = tcb;
|
||||||
|
tcb->next = null;
|
||||||
|
tcb->prev = null;
|
||||||
|
delayQueue.size++;
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Size > 0
|
||||||
|
current = delayQueue.head;
|
||||||
|
sumCount = 0;
|
||||||
|
oldSumCount = 0;
|
||||||
|
while (current != null) {
|
||||||
|
sumCount += current->delayCount;
|
||||||
|
if (tcb->delayCount < sumCount) {
|
||||||
|
tcb->next = current;
|
||||||
|
tcb->prev = current->prev;
|
||||||
|
if (current == delayQueue.head) {
|
||||||
|
delayQueue.head = tcb;
|
||||||
|
} else {
|
||||||
|
current->prev->next = tcb;
|
||||||
|
}
|
||||||
|
current->prev = tcb;
|
||||||
|
delayQueue.size++;
|
||||||
|
tcb->delayCount = tcb->delayCount - oldSumCount;
|
||||||
|
current->delayCount = current->delayCount - tcb->delayCount;
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (current->next == null) {
|
||||||
|
current->next = tcb;
|
||||||
|
tcb->prev = current;
|
||||||
|
tcb->next = null;
|
||||||
|
delayQueue.size++;
|
||||||
|
tcb->delayCount = tcb->delayCount - sumCount;
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
oldSumCount = sumCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void printDelayQueue(void) {
|
||||||
|
|
||||||
|
TCB* current;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
current = delayQueue.head;
|
||||||
|
printString("Printing Delay Queue with size ");
|
||||||
|
printInt(delayQueue.size);
|
||||||
|
printNewLine();
|
||||||
|
|
||||||
|
while (current != null) {
|
||||||
|
printInt(current->priority);
|
||||||
|
printString(" ");
|
||||||
|
printInt(current->delayCount);
|
||||||
|
printNewLine();
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
14
ecen425/DelayQueue.h
Normal file
14
ecen425/DelayQueue.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef DELAY_QUEUE_H
|
||||||
|
#define DELAY_QUEUE_H
|
||||||
|
|
||||||
|
#include "yakk.h"
|
||||||
|
|
||||||
|
void initializeDelayQueue(void);
|
||||||
|
|
||||||
|
void tickClock(void);
|
||||||
|
|
||||||
|
void insertDelayQueue(TCB* tcb);
|
||||||
|
|
||||||
|
void printDelayQueue(void);
|
||||||
|
|
||||||
|
#endif
|
36
ecen425/Makefile
Normal file
36
ecen425/Makefile
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
lab6.bin: lab6.s
|
||||||
|
nasm lab6.s -o lab6.bin -l lab6.lst
|
||||||
|
|
||||||
|
lab6.s: clib.s myinth.s yakc.s PriorityQueue.s DelayQueue.s Semaphore.s MessageQueue.s lab6app.s
|
||||||
|
cat clib.s myisr.s myinth.s yaks.s yakc.s PriorityQueue.s DelayQueue.s Semaphore.s MessageQueue.s lab6app.s > lab6.s
|
||||||
|
|
||||||
|
myinth.s: myinth.c
|
||||||
|
cpp myinth.c myinth.i
|
||||||
|
c86 -g myinth.i myinth.s
|
||||||
|
|
||||||
|
PriorityQueue.s: PriorityQueue.c
|
||||||
|
cpp PriorityQueue.c PriorityQueue.i
|
||||||
|
c86 -g PriorityQueue.i PriorityQueue.s
|
||||||
|
|
||||||
|
DelayQueue.s: DelayQueue.c
|
||||||
|
cpp DelayQueue.c DelayQueue.i
|
||||||
|
c86 -g DelayQueue.i DelayQueue.s
|
||||||
|
|
||||||
|
Semaphore.s: Semaphore.c
|
||||||
|
cpp Semaphore.c Semaphore.i
|
||||||
|
c86 -g Semaphore.i Semaphore.s
|
||||||
|
|
||||||
|
MessageQueue.s: MessageQueue.c
|
||||||
|
cpp MessageQueue.c MessageQueue.i
|
||||||
|
c86 -g MessageQueue.i MessageQueue.s
|
||||||
|
|
||||||
|
lab6app.s: lab6app.c
|
||||||
|
cpp lab6app.c lab6app.i
|
||||||
|
c86 -g lab6app.i lab6app.s
|
||||||
|
|
||||||
|
yakc.s: yakc.c
|
||||||
|
cpp yakc.c yakc.i
|
||||||
|
c86 -g yakc.i yakc.s
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm lab6.bin lab6.lst lab6.s myinth.s myinth.i DelayQueue.s DelayQueue.i yakc.s yakc.i PriorityQueue.i PriorityQueue.s Semaphore.i Semaphore.s MessageQueue.i MessageQueue.s lab6app.i lab6app.s
|
85
ecen425/MessageQueue.c
Normal file
85
ecen425/MessageQueue.c
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#include "yakk.h"
|
||||||
|
#include "clib.h"
|
||||||
|
#include "PriorityQueue.h"
|
||||||
|
|
||||||
|
extern PriorityQueue readyQueue;
|
||||||
|
|
||||||
|
YKQ* YKQCreate(void** start, unsigned size) {
|
||||||
|
|
||||||
|
YKQ* newMessageQueue;
|
||||||
|
|
||||||
|
newMessageQueue = getNewQueue();
|
||||||
|
if (newMessageQueue == null) exit(NEW_QUEUE_FAILED);
|
||||||
|
|
||||||
|
initializePriorityQueue(&(newMessageQueue->queue));
|
||||||
|
newMessageQueue->messages = start;
|
||||||
|
newMessageQueue->maxSize = size;
|
||||||
|
newMessageQueue->currentSize = 0;
|
||||||
|
|
||||||
|
return newMessageQueue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
129
ecen425/PriorityQueue.c
Normal file
129
ecen425/PriorityQueue.c
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#include "yakk.h"
|
||||||
|
#include "PriorityQueue.h"
|
||||||
|
#include "clib.h"
|
||||||
|
|
||||||
|
void initializePriorityQueue(PriorityQueue* queue) {
|
||||||
|
queue->size = 0;
|
||||||
|
queue->head = null;
|
||||||
|
queue->tail = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void insertPriorityQueue(PriorityQueue* queue, TCB* tcb) {
|
||||||
|
|
||||||
|
TCB* temp;
|
||||||
|
|
||||||
|
if(tcb == null) return;
|
||||||
|
|
||||||
|
//list is empty
|
||||||
|
YKEnterMutex();
|
||||||
|
if (queue->size == 0) {
|
||||||
|
queue->head = tcb;
|
||||||
|
queue->tail = tcb;
|
||||||
|
tcb->next = null;
|
||||||
|
tcb->prev = null;
|
||||||
|
queue->size = 1;
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//size of the list = 1
|
||||||
|
if (queue->size == 1) {
|
||||||
|
if (queue->head->priority < tcb->priority) {
|
||||||
|
queue->head->next = tcb;
|
||||||
|
tcb->prev = queue->head;
|
||||||
|
tcb->next = null;
|
||||||
|
queue->tail = tcb;
|
||||||
|
queue->size++;
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
tcb->next = queue->head;
|
||||||
|
tcb->prev = null;
|
||||||
|
queue->tail->prev = tcb;
|
||||||
|
queue->head = tcb;
|
||||||
|
queue->size++;
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//size of the priorityQueue > 1
|
||||||
|
temp = queue->head;
|
||||||
|
while (temp != null) {
|
||||||
|
if (temp->priority > tcb->priority) {
|
||||||
|
tcb->next = temp;
|
||||||
|
tcb->prev = temp->prev;
|
||||||
|
if (temp == queue->head) {
|
||||||
|
queue->head = tcb;
|
||||||
|
} else {
|
||||||
|
temp->prev->next = tcb;
|
||||||
|
}
|
||||||
|
temp->prev = tcb;
|
||||||
|
queue->size++;
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
temp = temp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
//tcb has lowest priority
|
||||||
|
queue->tail->next = tcb;
|
||||||
|
tcb->prev = queue->tail;
|
||||||
|
queue->tail = tcb;
|
||||||
|
tcb->next = null;
|
||||||
|
queue->size++;
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TCB* peekPriorityQueue(PriorityQueue* queue) {
|
||||||
|
|
||||||
|
return queue->head;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TCB* removePriorityQueue(PriorityQueue* queue) {
|
||||||
|
|
||||||
|
TCB* retValue;
|
||||||
|
|
||||||
|
//Size of the list = 0
|
||||||
|
YKEnterMutex();
|
||||||
|
if (queue->size == 0) {
|
||||||
|
YKExitMutex();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//size of the list = 1
|
||||||
|
if (queue->size == 1) {
|
||||||
|
retValue = queue->head;
|
||||||
|
retValue->next = null;
|
||||||
|
retValue->prev = null;
|
||||||
|
queue->size--;
|
||||||
|
queue->head = null;
|
||||||
|
queue->tail = null;
|
||||||
|
YKExitMutex();
|
||||||
|
return retValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//size of the list > 1
|
||||||
|
retValue = queue->head;
|
||||||
|
queue->head = queue->head->next;
|
||||||
|
queue->head->prev = null;
|
||||||
|
queue->size--;
|
||||||
|
retValue->next = null;
|
||||||
|
retValue->prev = null;
|
||||||
|
YKExitMutex();
|
||||||
|
return retValue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void printPriorityQueue(PriorityQueue* queue) {
|
||||||
|
TCB* current;
|
||||||
|
|
||||||
|
while (current != null) {
|
||||||
|
printInt(current->priority);
|
||||||
|
printNewLine();
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
}
|
16
ecen425/PriorityQueue.h
Normal file
16
ecen425/PriorityQueue.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef PRIORITY_QUEUE_H
|
||||||
|
#define PRIORITY_QUEUE_H
|
||||||
|
|
||||||
|
#include "yakk.h"
|
||||||
|
|
||||||
|
void initializePriorityQueue(PriorityQueue* queue);
|
||||||
|
|
||||||
|
void insertPriorityQueue(PriorityQueue* queue, TCB* tcb);
|
||||||
|
|
||||||
|
TCB* peekPriorityQueue(PriorityQueue* queue);
|
||||||
|
|
||||||
|
TCB* removePriorityQueue(PriorityQueue* queue);
|
||||||
|
|
||||||
|
void printPriorityQueue(PriorityQueue* queue);
|
||||||
|
|
||||||
|
#endif
|
61
ecen425/Semaphore.c
Normal file
61
ecen425/Semaphore.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "yakk.h"
|
||||||
|
#include "clib.h"
|
||||||
|
#include "PriorityQueue.h"
|
||||||
|
|
||||||
|
extern PriorityQueue readyQueue;
|
||||||
|
|
||||||
|
YKSEM* YKSemCreate(int initialValue) {
|
||||||
|
YKSEM* newSemaphore;
|
||||||
|
|
||||||
|
newSemaphore = getNewSem();
|
||||||
|
if (newSemaphore == null) exit(NEW_SEM_FAILED);
|
||||||
|
|
||||||
|
initializePriorityQueue(&(newSemaphore->queue));
|
||||||
|
newSemaphore->value = initialValue;
|
||||||
|
|
||||||
|
return newSemaphore;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void YKSemPend(YKSEM* semaphore) {
|
||||||
|
|
||||||
|
TCB* runningTask;
|
||||||
|
|
||||||
|
YKEnterMutex();
|
||||||
|
if (semaphore->value < 1) {
|
||||||
|
semaphore->value--;
|
||||||
|
runningTask = removePriorityQueue(&readyQueue);
|
||||||
|
runningTask->state = T_BLOCKED;
|
||||||
|
insertPriorityQueue((&(semaphore->queue)), runningTask);
|
||||||
|
YKExitMutex();
|
||||||
|
asm("int 0x20");
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
semaphore->value--;
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void YKSemPost(YKSEM* semaphore) {
|
||||||
|
|
||||||
|
TCB* readyTask;
|
||||||
|
|
||||||
|
YKEnterMutex();
|
||||||
|
semaphore->value++;
|
||||||
|
readyTask = removePriorityQueue(&(semaphore->queue));
|
||||||
|
if (readyTask == null) {
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
readyTask->state = T_READY;
|
||||||
|
insertPriorityQueue(&readyQueue, readyTask);
|
||||||
|
YKExitMutex();
|
||||||
|
if (YKGetISRCallDepth() == 0) {
|
||||||
|
asm("int 0x20");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
29
ecen425/clib.h
Normal file
29
ecen425/clib.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef CLIB_H
|
||||||
|
#define CLIB_H
|
||||||
|
|
||||||
|
// Header file for clib.s output routines
|
||||||
|
|
||||||
|
// Text Output:
|
||||||
|
void print(char *string, int length); // Print length bytes of string
|
||||||
|
void printNewLine(void); // Print carriage return and line feed
|
||||||
|
void printChar(char c); // Print character c
|
||||||
|
void printString(char *string); // Print string
|
||||||
|
|
||||||
|
// Decimal Output:
|
||||||
|
void printInt(int val);
|
||||||
|
void printLong(long val);
|
||||||
|
void printUInt(unsigned val);
|
||||||
|
void printULong(unsigned long val);
|
||||||
|
|
||||||
|
// Hexadecimal Output:
|
||||||
|
void printByte(char val);
|
||||||
|
void printWord(int val);
|
||||||
|
void printDWord(long val);
|
||||||
|
|
||||||
|
// Program Control:
|
||||||
|
void exit(unsigned char code); // Terminate with exit code
|
||||||
|
|
||||||
|
// PIC Functions:
|
||||||
|
void signalEOI(void); // Send non-specific EOI to PIC
|
||||||
|
|
||||||
|
#endif
|
1111
ecen425/clib.s
Normal file
1111
ecen425/clib.s
Normal file
File diff suppressed because it is too large
Load Diff
187
ecen425/lab6app.c
Normal file
187
ecen425/lab6app.c
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
File: lab6app.c
|
||||||
|
Revision date: 4 November 2009
|
||||||
|
Description: Application code for EE 425 lab 6 (Message queues)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "clib.h"
|
||||||
|
#include "yakk.h" /* contains kernel definitions */
|
||||||
|
#include "lab6defs.h" /* contains definitions for this lab */
|
||||||
|
|
||||||
|
#define TASK_STACK_SIZE 512 /* stack size in words */
|
||||||
|
#define MSGQSIZE 10
|
||||||
|
|
||||||
|
struct msg MsgArray[MSGARRAYSIZE]; /* buffers for message content */
|
||||||
|
|
||||||
|
int ATaskStk[TASK_STACK_SIZE]; /* a stack for each task */
|
||||||
|
int BTaskStk[TASK_STACK_SIZE];
|
||||||
|
int STaskStk[TASK_STACK_SIZE];
|
||||||
|
|
||||||
|
int GlobalFlag;
|
||||||
|
|
||||||
|
void *MsgQ[MSGQSIZE]; /* space for message queue */
|
||||||
|
YKQ *MsgQPtr; /* actual name of queue */
|
||||||
|
|
||||||
|
void ATask(void) /* processes data in messages */
|
||||||
|
{
|
||||||
|
struct msg *tmp;
|
||||||
|
int min, max, count;
|
||||||
|
|
||||||
|
min = 100;
|
||||||
|
max = 0;
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
tmp = (struct msg *) YKQPend(MsgQPtr); /* get next msg */
|
||||||
|
|
||||||
|
/* check sequence count in msg; were msgs dropped? */
|
||||||
|
if (tmp->tick != count+1)
|
||||||
|
{
|
||||||
|
print("! Dropped msgs: tick ", 21);
|
||||||
|
if (tmp->tick - (count+1) > 1) {
|
||||||
|
printInt(count+1);
|
||||||
|
printChar('-');
|
||||||
|
printInt(tmp->tick-1);
|
||||||
|
printNewLine();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printInt(tmp->tick-1);
|
||||||
|
printNewLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update sequence count */
|
||||||
|
count = tmp->tick;
|
||||||
|
|
||||||
|
/* process data; update statistics for this sample */
|
||||||
|
if (tmp->data < min)
|
||||||
|
min = tmp->data;
|
||||||
|
if (tmp->data > max)
|
||||||
|
max = tmp->data;
|
||||||
|
|
||||||
|
/* output min, max, tick values */
|
||||||
|
print("Ticks: ", 7);
|
||||||
|
printInt(count);
|
||||||
|
print("\t", 1);
|
||||||
|
print("Min: ", 5);
|
||||||
|
printInt(min);
|
||||||
|
print("\t", 1);
|
||||||
|
print("Max: ", 5);
|
||||||
|
printInt(max);
|
||||||
|
printNewLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTask(void) /* saturates the CPU for 5 ticks */
|
||||||
|
{
|
||||||
|
int busycount, curval, j, flag, chcount;
|
||||||
|
unsigned tickNum;
|
||||||
|
|
||||||
|
curval = 1001;
|
||||||
|
chcount = 0;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
YKDelayTask(2);
|
||||||
|
|
||||||
|
if (GlobalFlag == 1)
|
||||||
|
{ /* flag set -- loop for 5 ticks */
|
||||||
|
YKEnterMutex();
|
||||||
|
//busycount = YKTickNum;
|
||||||
|
busycount = getYKTickNum();
|
||||||
|
YKExitMutex();
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
YKEnterMutex();
|
||||||
|
//tickNum = YKTickNum;
|
||||||
|
tickNum = getYKTickNum();
|
||||||
|
YKExitMutex();
|
||||||
|
if(tickNum >= busycount + 5) break;
|
||||||
|
|
||||||
|
curval += 2; /* evaluate next number */
|
||||||
|
flag = 0;
|
||||||
|
for (j = 3; (j*j) < curval; j += 2)
|
||||||
|
{
|
||||||
|
if (curval % j == 0)
|
||||||
|
{
|
||||||
|
flag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!flag)
|
||||||
|
{
|
||||||
|
printChar('.'); /* output a marker for each prime */
|
||||||
|
if (++chcount > 75)
|
||||||
|
{
|
||||||
|
printNewLine();
|
||||||
|
chcount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printNewLine();
|
||||||
|
chcount = 0;
|
||||||
|
GlobalFlag = 0; /* clear flag */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void STask(void) /* tracks 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;
|
||||||
|
setYKIdleCount(0);
|
||||||
|
YKDelayTask(5);
|
||||||
|
//max = YKIdleCount / 25;
|
||||||
|
max = getYKIdleCount() / 25;
|
||||||
|
//YKIdleCount = 0;
|
||||||
|
setYKIdleCount(0);
|
||||||
|
|
||||||
|
YKNewTask(BTask, (void *) &BTaskStk[TASK_STACK_SIZE], 10);
|
||||||
|
YKNewTask(ATask, (void *) &ATaskStk[TASK_STACK_SIZE], 20);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
YKDelayTask(20);
|
||||||
|
|
||||||
|
YKEnterMutex();
|
||||||
|
//switchCount = YKCtxSwCount;
|
||||||
|
switchCount = getYKCtxSwCount();
|
||||||
|
//idleCount = YKIdleCount;
|
||||||
|
idleCount = getYKIdleCount();
|
||||||
|
YKExitMutex();
|
||||||
|
|
||||||
|
printString("<<<<< Context switches: ");
|
||||||
|
printInt((int)switchCount);
|
||||||
|
printString(", CPU usage: ");
|
||||||
|
tmp = (int) (idleCount/max);
|
||||||
|
printInt(100-tmp);
|
||||||
|
printString("% >>>>>\r\n");
|
||||||
|
|
||||||
|
YKEnterMutex();
|
||||||
|
//YKCtxSwCount = 0;
|
||||||
|
setYKCtxSwCount(0);
|
||||||
|
//YKIdleCount = 0;
|
||||||
|
setYKIdleCount(0);
|
||||||
|
YKExitMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
YKInitialize();
|
||||||
|
|
||||||
|
/* create queue, at least one user task, etc. */
|
||||||
|
GlobalFlag = 0;
|
||||||
|
MsgQPtr = YKQCreate(MsgQ, MSGQSIZE);
|
||||||
|
YKNewTask(STask, (void *) &STaskStk[TASK_STACK_SIZE], 30);
|
||||||
|
|
||||||
|
YKRun();
|
||||||
|
}
|
13
ecen425/lab6defs.h
Normal file
13
ecen425/lab6defs.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
File: lab6defs.h
|
||||||
|
Revision date: 4 November
|
||||||
|
Description: Required definitions for EE 425 lab 6 (Message queues)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MSGARRAYSIZE 20
|
||||||
|
|
||||||
|
struct msg
|
||||||
|
{
|
||||||
|
int tick;
|
||||||
|
int data;
|
||||||
|
};
|
40
ecen425/myinth.c
Normal file
40
ecen425/myinth.c
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "clib.h"
|
||||||
|
#include "yakk.h"
|
||||||
|
#include "lab6defs.h"
|
||||||
|
#include "DelayQueue.h"
|
||||||
|
|
||||||
|
extern unsigned int YKTickCounter;
|
||||||
|
extern int GlobalFlag;
|
||||||
|
extern struct msg MsgArray[];
|
||||||
|
extern YKQ* MsgQPtr;
|
||||||
|
|
||||||
|
void resetHandler() {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tickHandler() {
|
||||||
|
|
||||||
|
static int next = 0;
|
||||||
|
static int data = 0;
|
||||||
|
|
||||||
|
tickClock();
|
||||||
|
YKEnterMutex();
|
||||||
|
YKTickCounter++;
|
||||||
|
YKExitMutex();
|
||||||
|
|
||||||
|
MsgArray[next].tick = YKTickCounter;
|
||||||
|
data = (data + 89) % 100;
|
||||||
|
MsgArray[next].data = data;
|
||||||
|
if (YKQPost(MsgQPtr, (void*) &(MsgArray[next])) == 0)
|
||||||
|
printString(" TickISR: queue overflow! \n");
|
||||||
|
else if (++next >= MSGARRAYSIZE)
|
||||||
|
next = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboardHandler() {
|
||||||
|
|
||||||
|
YKEnterMutex();
|
||||||
|
GlobalFlag = 1;
|
||||||
|
YKExitMutex();
|
||||||
|
}
|
118
ecen425/myisr.s
Normal file
118
ecen425/myisr.s
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
RESET:
|
||||||
|
|
||||||
|
call resetHandler ;calling C interrupt handler
|
||||||
|
|
||||||
|
|
||||||
|
TICK:
|
||||||
|
|
||||||
|
push ax
|
||||||
|
push bx
|
||||||
|
push cx
|
||||||
|
push dx
|
||||||
|
push di
|
||||||
|
push si
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
push bp
|
||||||
|
call YKGetISRCallDepth
|
||||||
|
test ax, ax
|
||||||
|
jnz tick_1
|
||||||
|
mov si, [currentTask]
|
||||||
|
add si, word 0x4
|
||||||
|
mov [si], sp
|
||||||
|
|
||||||
|
tick_1:
|
||||||
|
call YKEnterISR
|
||||||
|
|
||||||
|
sti ;enabling interrupts
|
||||||
|
call tickHandler ;calling C interrupt handler
|
||||||
|
cli ;disabling interrupts
|
||||||
|
|
||||||
|
mov al, 0x20 ;Load nonspecific EOI value (0x20) into register al
|
||||||
|
out 0x20, al ;Write EOI to PIC (port 0x20)
|
||||||
|
|
||||||
|
call YKExitISR
|
||||||
|
|
||||||
|
pop bp
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
pop si
|
||||||
|
pop di
|
||||||
|
pop dx
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
iret ;returning from ISR
|
||||||
|
|
||||||
|
KEYBOARD:
|
||||||
|
|
||||||
|
push ax
|
||||||
|
push bx
|
||||||
|
push cx
|
||||||
|
push dx
|
||||||
|
push di
|
||||||
|
push si
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
push bp
|
||||||
|
call YKGetISRCallDepth
|
||||||
|
test ax, ax
|
||||||
|
jnz keyboard_1
|
||||||
|
mov si, [currentTask]
|
||||||
|
add si, word 0x4
|
||||||
|
mov [si], sp
|
||||||
|
|
||||||
|
keyboard_1:
|
||||||
|
call YKEnterISR
|
||||||
|
|
||||||
|
sti ;enabling interrupts
|
||||||
|
call keyboardHandler ;calling C interrupt handler
|
||||||
|
cli ;disabling interrupts
|
||||||
|
|
||||||
|
mov al, 0x20 ;Load nonspecific EOI value (0x20) into register al
|
||||||
|
out 0x20, al ;Write EOI to PIC (port 0x20)
|
||||||
|
|
||||||
|
call YKExitISR
|
||||||
|
|
||||||
|
pop bp
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
pop si
|
||||||
|
pop di
|
||||||
|
pop dx
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
iret ;returning from ISR
|
||||||
|
|
||||||
|
TRAP:
|
||||||
|
|
||||||
|
push ax
|
||||||
|
push bx
|
||||||
|
push cx
|
||||||
|
push dx
|
||||||
|
push di
|
||||||
|
push si
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
push bp
|
||||||
|
mov si, [currentTask]
|
||||||
|
add si, word 0x4
|
||||||
|
mov [si], sp
|
||||||
|
|
||||||
|
call YKScheduler
|
||||||
|
|
||||||
|
pop bp
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
pop si
|
||||||
|
pop di
|
||||||
|
pop dx
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
iret
|
||||||
|
|
272
ecen425/test.c
Normal file
272
ecen425/test.c
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
//#include "../include/yakk.h"
|
||||||
|
//#include "../include/yaku.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define null 0
|
||||||
|
#define MAX_TASKS 10
|
||||||
|
|
||||||
|
typedef struct TCB TCB;
|
||||||
|
|
||||||
|
struct TCB {
|
||||||
|
unsigned int tid;
|
||||||
|
unsigned char priority;
|
||||||
|
void* stackPointer;
|
||||||
|
unsigned int state;
|
||||||
|
unsigned int delayCount;
|
||||||
|
TCB* next;
|
||||||
|
TCB* prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct TaskBlock TaskBlock;
|
||||||
|
|
||||||
|
struct TaskBlock {
|
||||||
|
TCB tasks[MAX_TASKS+1];
|
||||||
|
unsigned int nextFreeTCB;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct DelayQueue DelayQueue;
|
||||||
|
|
||||||
|
struct DelayQueue {
|
||||||
|
TCB* head;
|
||||||
|
unsigned int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct ReadyQueue ReadyQueue;
|
||||||
|
|
||||||
|
struct ReadyQueue {
|
||||||
|
TCB* head;
|
||||||
|
TCB* tail;
|
||||||
|
unsigned int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static TaskBlock taskBlock;
|
||||||
|
static DelayQueue delayQueue;
|
||||||
|
static ReadyQueue readyQueue;
|
||||||
|
|
||||||
|
TCB* getNewTCB(void) {
|
||||||
|
|
||||||
|
TCB* task;
|
||||||
|
if (taskBlock.nextFreeTCB < MAX_TASKS + 1) {
|
||||||
|
printf("nextFreeBlock = %d\n", taskBlock.nextFreeTCB);
|
||||||
|
task = &taskBlock.tasks[taskBlock.nextFreeTCB];
|
||||||
|
taskBlock.nextFreeTCB++;
|
||||||
|
return task;
|
||||||
|
} else {
|
||||||
|
printf("TCBFullError\n");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void tickClock() {
|
||||||
|
|
||||||
|
TCB* current;
|
||||||
|
TCB* temp;
|
||||||
|
|
||||||
|
//Size == 0
|
||||||
|
if (delayQueue.size == 0) return;
|
||||||
|
|
||||||
|
//Size > 0
|
||||||
|
current = delayQueue.head;
|
||||||
|
while (current != null) {
|
||||||
|
current->delayCount--;
|
||||||
|
temp = current;
|
||||||
|
if (temp->delayCount == 0) {
|
||||||
|
removeDelayQueue(temp);
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void insertDelayQueue(TCB* tcb) {
|
||||||
|
|
||||||
|
TCB* current;
|
||||||
|
unsigned int sumCount;
|
||||||
|
|
||||||
|
if (tcb == null) return;
|
||||||
|
|
||||||
|
//Size = 0
|
||||||
|
if (delayQueue.size == 0) {
|
||||||
|
delayQueue.head = tcb;
|
||||||
|
tcb->next = null;
|
||||||
|
tcb->prev = null;
|
||||||
|
delayQueue.size++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Size > 0
|
||||||
|
current = delayQueue.head;
|
||||||
|
sumCount = 0;
|
||||||
|
while (current != null) {
|
||||||
|
sumCount += current->delayCount;
|
||||||
|
if (tcb->delayCount < sumCount) {
|
||||||
|
tcb->prev = current->prev;
|
||||||
|
tcb->next = current;
|
||||||
|
if (current == delayQueue.head) {
|
||||||
|
delayQueue.head = tcb;
|
||||||
|
current->prev->next = tcb;
|
||||||
|
}
|
||||||
|
current->prev = tcb;
|
||||||
|
delayQueue.size++;
|
||||||
|
tcb->delayCount = tcb->delayCount - sumCount;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (current->next == null) {
|
||||||
|
current->next = tcb;
|
||||||
|
tcb->prev = current;
|
||||||
|
tcb->next = null;
|
||||||
|
delayQueue.size++;
|
||||||
|
tcb->delayCount = tcb->delayCount - sumCount;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeDelayQueue(TCB* tcb) {
|
||||||
|
|
||||||
|
TCB* current;
|
||||||
|
TCB* temp;
|
||||||
|
|
||||||
|
if (tcb == null) return;
|
||||||
|
|
||||||
|
current = delayQueue.head;
|
||||||
|
while (current != null) {
|
||||||
|
if (current->priority = tcb->priority) {
|
||||||
|
if (current == delayQueue.head) {
|
||||||
|
temp = current;
|
||||||
|
current = current->next;
|
||||||
|
delayQueue.head = temp->next;
|
||||||
|
temp->next->prev = null;
|
||||||
|
delayQueue.size--;
|
||||||
|
temp->next = null;
|
||||||
|
temp->prev = null;
|
||||||
|
insertReadyQueue(temp);
|
||||||
|
} else if (current->next == null) {
|
||||||
|
temp = current;
|
||||||
|
current = current->next;
|
||||||
|
temp->prev->next = null;
|
||||||
|
delayQueue.size--;
|
||||||
|
insertReadyQueue(temp);
|
||||||
|
} else {
|
||||||
|
temp = current;
|
||||||
|
current = current->next;
|
||||||
|
temp->prev->next = temp->next;
|
||||||
|
temp->next->prev = temp->prev;
|
||||||
|
temp->next = null;
|
||||||
|
temp->prev = null;
|
||||||
|
delayQueue.size--;
|
||||||
|
insertReadyQueue(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeReadyQueue() {
|
||||||
|
readyQueue.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void insertReadyQueue(TCB* tcb) {
|
||||||
|
|
||||||
|
if(tcb == null) return;
|
||||||
|
|
||||||
|
//list is empty
|
||||||
|
if (readyQueue.size == 0) {
|
||||||
|
readyQueue.head = tcb;
|
||||||
|
readyQueue.tail = tcb;
|
||||||
|
tcb->next = null;
|
||||||
|
tcb->prev = null;
|
||||||
|
readyQueue.size = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//size of the list = 1
|
||||||
|
if (readyQueue.head == readyQueue.tail) {
|
||||||
|
if (readyQueue.head->priority < tcb->priority) {
|
||||||
|
readyQueue.head->next = tcb;
|
||||||
|
tcb->prev = readyQueue.head;
|
||||||
|
tcb->next = null;
|
||||||
|
readyQueue.tail = tcb;
|
||||||
|
readyQueue.size++;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
tcb->next = readyQueue.head;
|
||||||
|
tcb->prev = null;
|
||||||
|
readyQueue.tail->prev = tcb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//size of the readyQueue > 1
|
||||||
|
TCB* temp = readyQueue.head;
|
||||||
|
while (temp != null) {
|
||||||
|
if (temp->priority > tcb->priority) {
|
||||||
|
tcb->next = temp;
|
||||||
|
tcb->prev = temp->prev;
|
||||||
|
temp->prev = tcb;
|
||||||
|
if (temp == readyQueue.head) readyQueue.head = tcb;
|
||||||
|
readyQueue.size++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
temp = temp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
//tcb has lowest priority
|
||||||
|
readyQueue.tail->next = tcb;
|
||||||
|
tcb->prev = readyQueue.tail;
|
||||||
|
readyQueue.tail = tcb;
|
||||||
|
tcb->next = null;
|
||||||
|
readyQueue.size++;
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TCB* removeReadyQueue() {
|
||||||
|
|
||||||
|
TCB* retValue;
|
||||||
|
|
||||||
|
//size of the list = 1
|
||||||
|
if (readyQueue.head == readyQueue.tail) {
|
||||||
|
retValue = readyQueue.head;
|
||||||
|
readyQueue.size--;
|
||||||
|
readyQueue.head = null;
|
||||||
|
readyQueue.tail = null;
|
||||||
|
return retValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//size of the list > 1
|
||||||
|
retValue = readyQueue.head;
|
||||||
|
readyQueue.head = readyQueue.head->next;
|
||||||
|
readyQueue.size--;
|
||||||
|
return retValue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
|
TCB* tasks[5];
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 10; i += 2 ) {
|
||||||
|
TCB* tcb1 = getNewTCB();
|
||||||
|
tasks[i / 2] = getNewTCB();
|
||||||
|
tcb1->tid = i / 2;
|
||||||
|
tasks[i / 2]->delayCount = i / 2;
|
||||||
|
tasks[i / 2]->tid = i / 2;
|
||||||
|
tcb1->priority = i / 2;
|
||||||
|
insertReadyQueue(tcb1);
|
||||||
|
insertDelayQueue(tasks[i / 2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i += 2) {
|
||||||
|
TCB* tcb1 = removeReadyQueue();
|
||||||
|
printf("Task %d was removed with priority %d\n", tcb1->tid, tcb1->priority);
|
||||||
|
printf("Task %d was removed with delta delay %d\n", tasks[i / 2]->tid, tasks[i / 2]->delayCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
206
ecen425/yakc.c
Normal file
206
ecen425/yakc.c
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
#include "clib.h"
|
||||||
|
#include "yakk.h"
|
||||||
|
#include "yaku.h"
|
||||||
|
#include "PriorityQueue.h"
|
||||||
|
#include "DelayQueue.h"
|
||||||
|
|
||||||
|
//User Accessible Variables
|
||||||
|
unsigned int YKCtxSwCount = 0;
|
||||||
|
unsigned int YKIdleCount = 0;
|
||||||
|
unsigned int YKTickCounter = 0;
|
||||||
|
|
||||||
|
//Kernel Accessible Variables
|
||||||
|
static unsigned int ISRCallDepth = 0;
|
||||||
|
TCB* currentTask = null;
|
||||||
|
PriorityQueue readyQueue;
|
||||||
|
DelayQueue delayQueue;
|
||||||
|
static TaskBlock taskBlock;
|
||||||
|
static SemBlock semBlock;
|
||||||
|
static MsgQueueBlock msgQueueBlock;
|
||||||
|
static int idleTaskStack[IDLETASKSTACKSIZE];
|
||||||
|
static enum KernelState kernelState = K_BLOCKED;
|
||||||
|
|
||||||
|
unsigned int getYKCtxSwCount() {
|
||||||
|
return YKCtxSwCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int getYKIdleCount() {
|
||||||
|
return YKIdleCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int getYKTickNum() {
|
||||||
|
return YKTickCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setYKIdleCount(int value) {
|
||||||
|
YKIdleCount = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setYKCtxSwCount(int value) {
|
||||||
|
YKCtxSwCount = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void YKEnterISR(void) {
|
||||||
|
YKEnterMutex();
|
||||||
|
ISRCallDepth++;
|
||||||
|
YKExitMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void YKExitISR(void) {
|
||||||
|
YKEnterMutex();
|
||||||
|
ISRCallDepth--;
|
||||||
|
if (ISRCallDepth == 0) {
|
||||||
|
YKExitMutex();
|
||||||
|
YKScheduler();
|
||||||
|
}
|
||||||
|
YKExitMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int YKGetISRCallDepth(void) {
|
||||||
|
|
||||||
|
return ISRCallDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void YKInitialize(void) {
|
||||||
|
|
||||||
|
YKEnterMutex();
|
||||||
|
|
||||||
|
//Set up queues
|
||||||
|
initializePriorityQueue(&readyQueue);
|
||||||
|
initializeDelayQueue();
|
||||||
|
|
||||||
|
//Set up Task Block
|
||||||
|
taskBlock.nextFreeTCB == 0;
|
||||||
|
//
|
||||||
|
|
||||||
|
//Set up Idle Task
|
||||||
|
YKNewTask(YKIdleTask, &idleTaskStack[IDLETASKSTACKSIZE], 100);
|
||||||
|
//
|
||||||
|
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void YKScheduler(void) {
|
||||||
|
|
||||||
|
TCB* readyTask;
|
||||||
|
YKEnterMutex();
|
||||||
|
if (kernelState == K_BLOCKED) return;
|
||||||
|
readyTask = peekPriorityQueue(&readyQueue);
|
||||||
|
if (readyTask == null) exit(READY_QUEUE_EMPTY);
|
||||||
|
if (readyTask != currentTask) {
|
||||||
|
currentTask = readyTask;
|
||||||
|
currentTask->state = T_READY;
|
||||||
|
YKCtxSwCount++;
|
||||||
|
readyTask->state = T_RUNNING;
|
||||||
|
YKDispatcher(readyTask);
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void YKNewTask(void (*task)(void), void* taskStack, unsigned char priority) {
|
||||||
|
|
||||||
|
TCB* newTask;
|
||||||
|
|
||||||
|
//Obtain a TCB
|
||||||
|
newTask = getNewTCB();
|
||||||
|
if (newTask == null) exit(NEW_TASK_FAILED);
|
||||||
|
|
||||||
|
//Fill TCB
|
||||||
|
newTask->tid = 0;
|
||||||
|
newTask->priority = priority;
|
||||||
|
newTask->stackPointer = ((void*)((int*) taskStack - 12));
|
||||||
|
newTask->state = T_READY;
|
||||||
|
newTask->delayCount = 0;
|
||||||
|
newTask->next = null;
|
||||||
|
newTask->prev = null;
|
||||||
|
|
||||||
|
//Set up Stack
|
||||||
|
asm("push bx");
|
||||||
|
asm("push cx");
|
||||||
|
asm("mov bx, [bp+6]"); //Get address of stack
|
||||||
|
asm("mov cx, [bp+4]"); //Get address of function pointer
|
||||||
|
asm("mov [bx-2], word 0x0200"); //Move flag register onto the stack
|
||||||
|
asm("mov [bx-4], word 0x0");
|
||||||
|
asm("mov [bx-6], cx");
|
||||||
|
asm("pop cx");
|
||||||
|
asm("pop bx");
|
||||||
|
|
||||||
|
insertPriorityQueue(&readyQueue, newTask);
|
||||||
|
asm("int 0x20");
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TCB* getNewTCB(void) {
|
||||||
|
|
||||||
|
TCB* task;
|
||||||
|
if (taskBlock.nextFreeTCB < MAX_TASKS + 1) {
|
||||||
|
task = &taskBlock.TCBPool[taskBlock.nextFreeTCB++];
|
||||||
|
return task;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
YKSEM* getNewSem(void) {
|
||||||
|
|
||||||
|
YKSEM* semaphore;
|
||||||
|
if (semBlock.nextFreeSem < MAX_SEMS) {
|
||||||
|
semaphore = &semBlock.SemPool[semBlock.nextFreeSem++];
|
||||||
|
return semaphore;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
YKQ* getNewQueue(void) {
|
||||||
|
|
||||||
|
YKQ* messageQueue;
|
||||||
|
if (msgQueueBlock.nextFreeQueue < MAX_QUEUES) {
|
||||||
|
messageQueue = &msgQueueBlock.QueuePool[msgQueueBlock.nextFreeQueue++];
|
||||||
|
return messageQueue;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void YKRun(void) {
|
||||||
|
|
||||||
|
YKEnterMutex();
|
||||||
|
kernelState = K_RUNNING;
|
||||||
|
YKScheduler();
|
||||||
|
YKExitMutex();
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void YKDelayTask(unsigned int count) {
|
||||||
|
|
||||||
|
TCB* delayedTask;
|
||||||
|
|
||||||
|
if (count == 0) return;
|
||||||
|
|
||||||
|
delayedTask = removePriorityQueue(&readyQueue);
|
||||||
|
delayedTask->state = T_BLOCKED;
|
||||||
|
delayedTask->delayCount = count;
|
||||||
|
insertDelayQueue(delayedTask);
|
||||||
|
asm("int 0x20");
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void YKTickHandler(void) {
|
||||||
|
|
||||||
|
tickClock();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
100
ecen425/yakk.h
Normal file
100
ecen425/yakk.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#ifndef YAKK_H
|
||||||
|
#define YAKK_H
|
||||||
|
|
||||||
|
#include "yaku.h"
|
||||||
|
|
||||||
|
#define null 0
|
||||||
|
#define IDLETASKSTACKSIZE 512
|
||||||
|
|
||||||
|
//Error Codes
|
||||||
|
#define NEW_TASK_FAILED 1
|
||||||
|
#define READY_QUEUE_EMPTY 2
|
||||||
|
#define NEW_SEM_FAILED 3
|
||||||
|
#define NEW_QUEUE_FAILED 4
|
||||||
|
|
||||||
|
//Kernel Data Structures
|
||||||
|
|
||||||
|
enum TaskState {T_BLOCKED, T_READY, T_RUNNING};
|
||||||
|
enum KernelState {K_BLOCKED, K_RUNNING};
|
||||||
|
|
||||||
|
typedef struct TCB {
|
||||||
|
unsigned int tid;
|
||||||
|
unsigned char priority;
|
||||||
|
void* stackPointer;
|
||||||
|
enum TaskState state;
|
||||||
|
unsigned int delayCount;
|
||||||
|
struct TCB* next;
|
||||||
|
struct TCB* prev;
|
||||||
|
} TCB;
|
||||||
|
|
||||||
|
typedef struct TaskBlock {
|
||||||
|
TCB TCBPool[MAX_TASKS+1];
|
||||||
|
unsigned int nextFreeTCB;
|
||||||
|
} TaskBlock;
|
||||||
|
|
||||||
|
typedef struct PriorityQueue {
|
||||||
|
TCB* head;
|
||||||
|
TCB* tail;
|
||||||
|
unsigned int size;
|
||||||
|
} PriorityQueue;
|
||||||
|
|
||||||
|
typedef struct DelayQueue {
|
||||||
|
TCB* head;
|
||||||
|
unsigned int size;
|
||||||
|
} DelayQueue;
|
||||||
|
|
||||||
|
typedef struct Semaphore {
|
||||||
|
int value;
|
||||||
|
PriorityQueue queue;
|
||||||
|
} YKSEM;
|
||||||
|
|
||||||
|
typedef struct SemBlock {
|
||||||
|
YKSEM SemPool[MAX_SEMS];
|
||||||
|
unsigned int nextFreeSem;
|
||||||
|
} SemBlock;
|
||||||
|
|
||||||
|
typedef struct MessageQueue {
|
||||||
|
void** messages;
|
||||||
|
unsigned int currentSize;
|
||||||
|
unsigned int maxSize;
|
||||||
|
PriorityQueue queue;
|
||||||
|
} YKQ;
|
||||||
|
|
||||||
|
typedef struct MessageQueueBlock {
|
||||||
|
YKQ QueuePool[MAX_QUEUES];
|
||||||
|
unsigned int nextFreeQueue;
|
||||||
|
} MsgQueueBlock;
|
||||||
|
|
||||||
|
//Kernel API
|
||||||
|
void YKInitialize(void);
|
||||||
|
void YKEnterMutex(void);
|
||||||
|
void YKExitMutex(void);
|
||||||
|
void YKIdleTask(void);
|
||||||
|
void YKNewTask(void (* task) (void), void *taskStack, unsigned char priority);
|
||||||
|
void YKDelayTask(unsigned count);
|
||||||
|
void YKEnterISR(void);
|
||||||
|
void YKExitISR(void);
|
||||||
|
unsigned int YKGetISRCallDepth(void);
|
||||||
|
void YKScheduler(void);
|
||||||
|
void YKDispatcher(TCB* readyTask);
|
||||||
|
void YKTickHandler(void);
|
||||||
|
YKSEM* YKSemCreate(int initialValue);
|
||||||
|
void YKSemPend(YKSEM* semaphore);
|
||||||
|
void YKSemPost(YKSEM* semaphore);
|
||||||
|
YKQ* YKQCreate(void** start, unsigned size);
|
||||||
|
void* YKQPend(YKQ* queue);
|
||||||
|
int YKQPost(YKQ* queue, void* msg);
|
||||||
|
//YKEVENT* YKEventCreate(unsigned initialValue);
|
||||||
|
//void YKEventSet(YKEVENT* event, unsigned eventMask);
|
||||||
|
//void YKEVentReset(YKEVENT* event, unsigned eventMask);
|
||||||
|
TCB* getNewTCB(void);
|
||||||
|
YKSEM* getNewSem(void);
|
||||||
|
YKQ* getNewQueue(void);
|
||||||
|
void YKRun(void);
|
||||||
|
unsigned int getYKCtxSwCount();
|
||||||
|
unsigned int getYKIdelCount();
|
||||||
|
void setYKIdelCount(int value);
|
||||||
|
void setYKCtxSwCount(int value);
|
||||||
|
unsigned int getYKTickNum();
|
||||||
|
|
||||||
|
#endif
|
39
ecen425/yaks.s
Normal file
39
ecen425/yaks.s
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
YKIdleTask:
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
|
||||||
|
yak_loop:
|
||||||
|
inc word [YKIdleCount]
|
||||||
|
jmp yak_loop
|
||||||
|
|
||||||
|
YKDispatcher:
|
||||||
|
|
||||||
|
cli
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
|
||||||
|
mov bx, [bp+4] ;Obtain stack pointer from TCB
|
||||||
|
mov sp, [bx+4] ;Load stack pointer into SP
|
||||||
|
|
||||||
|
pop bp
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
pop si
|
||||||
|
pop di
|
||||||
|
pop dx
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
iret
|
||||||
|
|
||||||
|
YKEnterMutex:
|
||||||
|
|
||||||
|
cli
|
||||||
|
ret
|
||||||
|
|
||||||
|
YKExitMutex:
|
||||||
|
|
||||||
|
sti
|
||||||
|
ret
|
8
ecen425/yaku.h
Normal file
8
ecen425/yaku.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef YAKU_H
|
||||||
|
#define YAKU_H
|
||||||
|
|
||||||
|
#define MAX_TASKS 10
|
||||||
|
#define MAX_SEMS 10
|
||||||
|
#define MAX_QUEUES 10
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user