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