Browse Source

adding in ecen425 RTOS final lab

master
Derek McQuay 5 years ago
parent
commit
e3fae2b680
  1. 141
      ecen425/DelayQueue.c
  2. 14
      ecen425/DelayQueue.h
  3. 36
      ecen425/Makefile
  4. 85
      ecen425/MessageQueue.c
  5. 129
      ecen425/PriorityQueue.c
  6. 16
      ecen425/PriorityQueue.h
  7. 61
      ecen425/Semaphore.c
  8. 29
      ecen425/clib.h
  9. 1111
      ecen425/clib.s
  10. 187
      ecen425/lab6app.c
  11. 13
      ecen425/lab6defs.h
  12. 40
      ecen425/myinth.c
  13. 118
      ecen425/myisr.s
  14. 272
      ecen425/test.c
  15. 206
      ecen425/yakc.c
  16. 100
      ecen425/yakk.h
  17. 39
      ecen425/yaks.s
  18. 8
      ecen425/yaku.h

141
ecen425/DelayQueue.c

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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
File diff suppressed because it is too large
View File

187
ecen425/lab6app.c

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -0,0 +1,8 @@
#ifndef YAKU_H
#define YAKU_H
#define MAX_TASKS 10
#define MAX_SEMS 10
#define MAX_QUEUES 10
#endif
Loading…
Cancel
Save