Browse Source

adding in ecen425 RTOS final lab

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

+ 141
- 0
ecen425/DelayQueue.c View 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
- 0
ecen425/DelayQueue.h View 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
- 0
ecen425/Makefile View 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
- 0
ecen425/MessageQueue.c View 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
- 0
ecen425/PriorityQueue.c View 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
- 0
ecen425/PriorityQueue.h View 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
- 0
ecen425/Semaphore.c View 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
- 0
ecen425/clib.h View 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
- 0
ecen425/clib.s
File diff suppressed because it is too large
View File


+ 187
- 0
ecen425/lab6app.c View 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
- 0
ecen425/lab6defs.h View 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
- 0
ecen425/myinth.c View 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
- 0
ecen425/myisr.s View 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
- 0
ecen425/test.c View 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
- 0
ecen425/yakc.c View 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
- 0
ecen425/yakk.h View 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
- 0
ecen425/yaks.s View 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
- 0
ecen425/yaku.h View 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…
Cancel
Save