From e3fae2b680304e5b77f13c0dee5576173d7b0b1d Mon Sep 17 00:00:00 2001 From: derek mcquay Date: Sun, 10 Apr 2016 09:23:15 -0700 Subject: [PATCH] adding in ecen425 RTOS final lab --- ecen425/DelayQueue.c | 141 +++++ ecen425/DelayQueue.h | 14 + ecen425/Makefile | 36 ++ ecen425/MessageQueue.c | 85 +++ ecen425/PriorityQueue.c | 129 +++++ ecen425/PriorityQueue.h | 16 + ecen425/Semaphore.c | 61 +++ ecen425/clib.h | 29 + ecen425/clib.s | 1111 +++++++++++++++++++++++++++++++++++++++ ecen425/lab6app.c | 187 +++++++ ecen425/lab6defs.h | 13 + ecen425/myinth.c | 40 ++ ecen425/myisr.s | 118 +++++ ecen425/test.c | 272 ++++++++++ ecen425/yakc.c | 206 ++++++++ ecen425/yakk.h | 100 ++++ ecen425/yaks.s | 39 ++ ecen425/yaku.h | 8 + 18 files changed, 2605 insertions(+) create mode 100644 ecen425/DelayQueue.c create mode 100644 ecen425/DelayQueue.h create mode 100644 ecen425/Makefile create mode 100644 ecen425/MessageQueue.c create mode 100644 ecen425/PriorityQueue.c create mode 100644 ecen425/PriorityQueue.h create mode 100644 ecen425/Semaphore.c create mode 100644 ecen425/clib.h create mode 100644 ecen425/clib.s create mode 100644 ecen425/lab6app.c create mode 100644 ecen425/lab6defs.h create mode 100644 ecen425/myinth.c create mode 100644 ecen425/myisr.s create mode 100644 ecen425/test.c create mode 100644 ecen425/yakc.c create mode 100644 ecen425/yakk.h create mode 100644 ecen425/yaks.s create mode 100644 ecen425/yaku.h diff --git a/ecen425/DelayQueue.c b/ecen425/DelayQueue.c new file mode 100644 index 0000000..395fffb --- /dev/null +++ b/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; + } + +} + diff --git a/ecen425/DelayQueue.h b/ecen425/DelayQueue.h new file mode 100644 index 0000000..eef8b36 --- /dev/null +++ b/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 diff --git a/ecen425/Makefile b/ecen425/Makefile new file mode 100644 index 0000000..b25b84e --- /dev/null +++ b/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 diff --git a/ecen425/MessageQueue.c b/ecen425/MessageQueue.c new file mode 100644 index 0000000..534714c --- /dev/null +++ b/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; + +} + + + + diff --git a/ecen425/PriorityQueue.c b/ecen425/PriorityQueue.c new file mode 100644 index 0000000..e7766df --- /dev/null +++ b/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; + } +} diff --git a/ecen425/PriorityQueue.h b/ecen425/PriorityQueue.h new file mode 100644 index 0000000..e43d0bd --- /dev/null +++ b/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 diff --git a/ecen425/Semaphore.c b/ecen425/Semaphore.c new file mode 100644 index 0000000..c5c7a56 --- /dev/null +++ b/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; + +} diff --git a/ecen425/clib.h b/ecen425/clib.h new file mode 100644 index 0000000..a53eea8 --- /dev/null +++ b/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 diff --git a/ecen425/clib.s b/ecen425/clib.s new file mode 100644 index 0000000..53a8df8 --- /dev/null +++ b/ecen425/clib.s @@ -0,0 +1,1111 @@ + CPU 8086 + ORG 0h +InterruptVectorTable: + ; Internal x86 Interrupts: + dd 0 ; Reserved (Div err) ; Int 00h + dd 0 ; Reserved (Step) ; Int 01h + dd 0 ; Reserved (NMI) ; Int 02h + dd 0 ; Reserved (Break) ; Int 03h + dd 0 ; Reserved (Overflow) ; Int 04h + dd 0 ; Int 05h + dd 0 ; Int 06h + dd 0 ; Int 07h + ; Hardware Interrupts: + dd RESET ; Reset ; Int 08h (IRQ 0) + dd TICK ; Tick ; Int 09h (IRQ 1) + dd KEYBOARD ; Keyboard ; Int 0Ah (IRQ 2) + dd 0 ; Simptris Game Over ; Int 0Bh (IRQ 3) + dd 0 ; Simptris New Piece ; Int 0Ch (IRQ 4) + dd 0 ; Simptris Received ; Int 0Dh (IRQ 5) + dd 0 ; Simptris Touchdown ; Int 0Eh (IRQ 6) + dd 0 ; Simptris Clear ; Int 0Fh (IRQ 7) + ; Software Interrupts: + dd 0 ; Reserved (PC BIOS) ; Int 10h + dd 0 ; Int 11h + dd 0 ; Int 12h + dd 0 ; Int 13h + dd 0 ; Int 14h + dd 0 ; Int 15h + dd 0 ; Int 16h + dd 0 ; Int 17h + dd 0 ; Int 18h + dd 0 ; Int 19h + dd 0 ; Int 1Ah + dd 0 ; Int 1Bh + dd 0 ; Int 1Ch + dd 0 ; Int 1Dh + dd 0 ; Int 1Eh + dd 0 ; Int 1Fh + dd TRAP ; Int 20h + dd 0 ; Reserved (DOS) ; Int 21h + dd 0 ; Simptris Services ; Int 22h + dd 0 ; Int 23h + dd 0 ; Int 24h + dd 0 ; Int 25h + dd 0 ; Int 26h + dd 0 ; Int 27h + dd 0 ; Int 28h + dd 0 ; Int 29h + dd 0 ; Int 2Ah + dd 0 ; Int 2Bh + dd 0 ; Int 2Ch + dd 0 ; Int 2Dh + dd 0 ; Int 2Eh + dd 0 ; Int 2Fh +KeyBuffer: ; Address 0xC0 + dw 0 +NewPieceType: ; Address 0xC2 + dw 0 +NewPieceID: ; Address 0xC4 + dw 0 +NewPieceOrientation: ; Address 0xC6 + dw 0 +NewPieceColumn: ; Address 0xC8 + dw 0 +TouchdownID: ; Address 0xCA + dw 0 +ScreenBitMap0: ; Address 0xCC + dw 0 +ScreenBitMap1: + dw 0 +ScreenBitMap2: + dw 0 +ScreenBitMap3: + dw 0 +ScreenBitMap4: + dw 0 +ScreenBitMap5: + dw 0 +TIMES 100h-($-$$) db 0 ; Fill up to (but not including) address 100h with 0 + jmp main +; This file contains support routines for 32-bit on the 8086. +; It is intended for use code generated by the C86 compiler. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SR_asldiv: ; l1 /= l2 + push bp + mov bp,sp + push bx + mov bx,[bp+4] ; Get address of l1 (was push3) + push word [bp+8] ; Push hi l2 (was push1) + push word [bp+6] ; Push lo l2 (was push2) + push word [bx+2] ; Push hi l1 + push word [bx] ; Push lo l1 + call SR_ldiv + mov bx,[bp+4] ; Restore l1 address + mov [bx+2],dx ; Store result + mov [bx],ax + pop bx + pop bp + ret +SR_aslmod: ; l1 %= l2 + push bp + mov bp,sp + push bx + mov bx,[bp+4] ; Get address of l1 (was push3) + push word [bp+8] ; Push hi l2 (was push1) + push word [bp+6] ; Push lo l2 (was push2) + push word [bx+2] ; Push hi l1 + push word [bx] ; Push lo l1 + call SR_lmod + mov bx,[bp+4] ; Restore l1 address + mov [bx+2],dx ; Store result + mov [bx],ax + pop bx + pop bp + ret +SR_aslmul: ; l1 *= l2 + push bp + mov bp,sp + push bx + mov bx,[bp+4] ; Get address of l1 (was push3) + push word [bp+8] ; Push hi l2 (was push1) + push word [bp+6] ; Push lo l2 (was push2) + push word [bx+2] ; Push hi l1 + push word [bx] ; Push lo l1 + call SR_lmul + add sp,8 + mov bx,[bp+4] ; Restore l1 address + mov [bx+2],dx ; Store result + mov [bx],ax + pop bx + pop bp + ret +SR_aslshl: ; l1 <<= l2 + push bp + mov bp,sp + push bx + mov bx,[bp+4] ; Get address of l1 (was push3) + push word [bp+8] ; Push hi l2 (was push1) + push word [bp+6] ; Push lo l2 (was push2) + push word [bx+2] ; Push hi l1 + push word [bx] ; Push lo l1 + call SR_lshl + add sp,8 + mov bx,[bp+4] ; Restore l1 address + mov [bx+2],dx ; Store result + mov [bx],ax + pop bx + pop bp + ret +SR_aslshr: ; l1 >>= l2 + push bp + mov bp,sp + push bx + mov bx,[bp+4] ; Get address of l1 (was push3) + push word [bp+8] ; Push hi l2 (was push1) + push word [bp+6] ; Push lo l2 (was push2) + push word [bx+2] ; Push hi l1 + push word [bx] ; Push lo l1 + call SR_lshr + add sp,8 + mov bx,[bp+4] ; Restore l1 address + mov [bx+2],dx ; Store result + mov [bx],ax + pop bx + pop bp + ret + + +SR_asuldiv: ; u1 /= u2 + push bp + mov bp,sp + push bx + mov bx,[bp+4] ; Get address of u1 (was push3) + push word [bp+8] ; Push hi u2 (was push1) + push word [bp+6] ; Push lo u2 (was push2) + push word [bx+2] ; Push hi u1 + push word [bx] ; Push lo u1 + call SR_uldiv + mov bx,[bp+4] ; Restore u1 address + mov [bx+2],dx ; Store result + mov [bx],ax + pop bx + pop bp + ret +SR_asilmod: ; u1 %= u2 + push bp + mov bp,sp + push bx + mov bx,[bp+4] ; Get address of u1 (was push3) + push word [bp+8] ; Push hi u2 (was push1) + push word [bp+6] ; Push lo u2 (was push2) + push word [bx+2] ; Push hi u1 + push word [bx] ; Push lo u1 + call SR_ilmod + mov bx,[bp+4] ; Restore u1 address + mov [bx+2],dx ; Store result + mov [bx],ax + pop bx + pop bp + ret +SR_asulmul: ; u1 *= u2 + push bp + mov bp,sp + push bx + mov bx,[bp+4] ; Get address of u1 (was push3) + push word [bp+8] ; Push hi u2 (was push1) + push word [bp+6] ; Push lo u2 (was push2) + push word [bx+2] ; Push hi u1 + push word [bx] ; Push lo u1 + call SR_ulmul + add sp,8 + mov bx,[bp+4] ; Restore u1 address + mov [bx+2],dx ; Store result + mov [bx],ax + pop bx + pop bp + ret +SR_asulshl: ; u1 << u2 + push bp + mov bp,sp + push bx + mov bx,[bp+4] ; Get address of u1 (was push3) + push word [bp+8] ; Push hi u2 (was push1) + push word [bp+6] ; Push lo u2 (was push2) + push word [bx+2] ; Push hi u1 + push word [bx] ; Push lo u1 + call SR_ulshl + add sp,8 + mov bx,[bp+4] ; Restore u1 address + mov [bx+2],dx ; Store result + mov [bx],ax + pop bx + pop bp + ret +SR_asulshr: ; u1 >> u2 + push bp + mov bp,sp + push bx + mov bx,[bp+4] ; Get address of u1 (was push3) + push word [bp+8] ; Push hi u2 (was push1) + push word [bp+6] ; Push lo u2 (was push2) + push word [bx+2] ; Push hi u1 + push word [bx] ; Push lo u1 + call SR_ulshr + add sp,8 + mov bx,[bp+4] ; Restore u1 address + mov [bx+2],dx ; Store result + mov [bx],ax + pop bx + pop bp + ret + + +; Main 32-bit routines begin here: + +SR_ldiv: ; N_LDIV@ + pop cx + push cs + push cx + ; LDIV@ + xor cx,cx + jmp LSR_01 +SR_uldiv: ; N_LUDIV@ + pop cx + push cs + push cx + ; F_LUDIV@ + mov cx,0001 + jmp LSR_01 +SR_lmod: ; N_LMOD@ + pop cx + push cs + push cx + ; F_LMOD@ + mov cx,0002 + jmp LSR_01 +SR_ilmod: ; N_LUMOD@ + pop cx + push cs + push cx + ; LUMOD@ + mov cx,0003 +LSR_01: + push bp + push si + push di + mov bp,sp + mov di,cx + mov ax,[bp+0Ah] + mov dx,[bp+0Ch] + mov bx,[bp+0Eh] + mov cx,[bp+10h] + or cx,cx + jne LSR_02 + or dx,dx + je LSR_10 + or bx,bx + je LSR_10 +LSR_02: + test di,0001 + jne LSR_04 + or dx,dx + jns LSR_03 + neg dx + neg ax + sbb dx,0000 + or di,000Ch +LSR_03: + or cx,cx + jns LSR_04 + neg cx + neg bx + sbb cx,0000 + xor di,0004 +LSR_04: + mov bp,cx + mov cx,0020h + push di + xor di,di + xor si,si +LSR_05: + shl ax,1 + rcl dx,1 + rcl si,1 + rcl di,1 + cmp di,bp + jb LSR_07 + ja LSR_06 + cmp si,bx + jb LSR_07 +LSR_06: + sub si,bx + sbb di,bp + inc ax +LSR_07: + loop LSR_05 + pop bx + test bx,0002 + je LSR_08 + mov ax,si + mov dx,di + shr bx,1 +LSR_08: + test bx,0004h + je LSR_09 + neg dx + neg ax + sbb dx,0000 +LSR_09: + pop di + pop si + pop bp + retf 0008 +LSR_10: + div bx + test di,0002 + je LSR_11 + xchg dx,ax +LSR_11: + xor dx,dx + jmp LSR_09 +SR_lshl: ; N_LXLSH@ +SR_ulshl: + ; r = a << b + pop bx + push cs + push bx + + push bp + mov bp,sp + + push cx ; C86 doesn't expect use of cx or bx + + mov ax, [bp+6] ; pop loword(a) + mov dx, [bp+8] ; pop hiword(a) + mov cx, [bp+10] ; pop word(b) + + ; LXLSH@ + cmp cl,10h + jnb LSR_12 + mov bx,ax + shl ax,cl + shl dx,cl + neg cl + add cl,10h + shr bx,cl + or dx,bx + pop cx + pop bp + retf +LSR_12: + sub cl,10h + xchg dx,ax + xor ax,ax + shl dx,cl + pop cx + pop bp + retf +SR_lshr: ; N_LXRSH@ + ; r = a >> b + pop bx + push cs + push bx + + push bp + mov bp,sp + + push cx ; C86 doesn't expect use of cx or bx + + mov ax, [bp+6] ; pop loword(a) + mov dx, [bp+8] ; pop hiword(a) + mov cx, [bp+10] ; pop word(b) + + ; LXRSH@ + cmp cl,10h + jnb LSR_13 + mov bx,dx + shr ax,cl + sar dx,cl + neg cl + add cl,10h + shl bx,cl + or ax,bx + pop cx + pop bp + retf +LSR_13: + sub cl,10h + xchg dx,ax + cwd + sar ax,cl + pop cx + pop bp + retf +SR_ulshr: ; N_LXURSH@ + ; r = a >> b + pop bx + push cs + push bx + + push bp + mov bp,sp + + push cx ; C86 doesn't expect use of cx or bx + + mov ax, [bp+6] ; pop loword(a) + mov dx, [bp+8] ; pop hiword(a) + mov cx, [bp+10] ; pop word(b) + + ; LXURSH@ + cmp cl,10h + jnb LSR_14 + mov bx,dx + shr ax,cl + shr dx,cl + neg cl + add cl,10h + shl bx,cl + or ax,bx + pop cx + pop bp + retf +LSR_14: + sub cl,10h + xchg dx,ax + xor dx,dx + shr ax,cl + pop cx + pop bp + retf +SR_lmul: ; N_LXMUL@ +SR_ulmul: + ; r = a * b + push bp + push si + mov bp,sp + + push cx ; C86 doesn't expect use of cx or bx + push bx + + mov bx, [bp+6] ; pop loword(a) + mov cx, [bp+8] ; pop hiword(a) + mov ax, [bp+10] ; pop loword(b) + mov dx, [bp+12] ; pop hiword(b) + + xchg si,ax + xchg dx,ax + test ax,ax + je LSR_15 + mul bx +LSR_15: + jcxz LSR_16 + xchg cx,ax + mul si + add ax,cx +LSR_16: + xchg si,ax + mul bx + add dx,si + pop bx + pop cx + pop si + pop bp + ret + +; Generated by c86 (BYU-NASM) 5.1 (beta) from clib.c + CPU 8086 + ALIGN 2 + jmp main ; Jump to program start +new_line: + db 13,10,36 + ALIGN 2 +signalEOI: + jmp L_clib_1 +L_clib_2: + mov al, 0x20 + out 0x20, al + mov sp, bp + pop bp + ret +L_clib_1: + push bp + mov bp, sp + jmp L_clib_2 + ALIGN 2 +exit: + jmp L_clib_4 +L_clib_5: + mov ah, 4Ch + mov al, [bp+4] + int 21h + mov sp, bp + pop bp + ret +L_clib_4: + push bp + mov bp, sp + jmp L_clib_5 + ALIGN 2 +print: + jmp L_clib_7 +L_clib_8: + mov ah, 40h + mov bx, 1 + mov cx, [bp+6] + mov dx, [bp+4] + int 21h + mov sp, bp + pop bp + ret +L_clib_7: + push bp + mov bp, sp + jmp L_clib_8 + ALIGN 2 +printChar: + jmp L_clib_10 +L_clib_11: + mov ah, 2 + mov dl, [bp+4] + int 21h + mov sp, bp + pop bp + ret +L_clib_10: + push bp + mov bp, sp + jmp L_clib_11 + ALIGN 2 +printNewLine: + jmp L_clib_13 +L_clib_14: + mov ah, 9 + mov dx, new_line + int 21h + mov sp, bp + pop bp + ret +L_clib_13: + push bp + mov bp, sp + jmp L_clib_14 + ALIGN 2 +printString: + jmp L_clib_16 +L_clib_17: + xor si,si + mov bx, [bp+4] + jmp printString2 + printString1: + inc si + printString2: + cmp byte [bx+si],0 + jne printString1 + mov dx, bx + mov cx, si + mov ah, 40h + mov bx, 1 + int 21h + mov sp, bp + pop bp + ret +L_clib_16: + push bp + mov bp, sp + push cx + jmp L_clib_17 + ALIGN 2 +printInt: + jmp L_clib_19 +L_clib_20: + mov word [bp-2], 0 + mov word [bp-4], 10000 + cmp word [bp+4], 0 + jge L_clib_21 + mov byte [bp-10], 45 + inc word [bp-2] + mov ax, word [bp+4] + neg ax + mov word [bp+4], ax +L_clib_21: + mov ax, word [bp+4] + test ax, ax + jne L_clib_22 + mov word [bp-4], 1 + jmp L_clib_23 +L_clib_22: + jmp L_clib_25 +L_clib_24: + mov ax, word [bp-4] + cwd + mov cx, 10 + idiv cx + mov word [bp-4], ax +L_clib_25: + mov ax, word [bp+4] + cwd + idiv word [bp-4] + test ax, ax + je L_clib_24 +L_clib_26: +L_clib_23: + jmp L_clib_28 +L_clib_27: + mov ax, word [bp+4] + xor dx, dx + div word [bp-4] + add al, 48 + mov si, word [bp-2] + lea dx, [bp-10] + add si, dx + mov byte [si], al + inc word [bp-2] + mov ax, word [bp+4] + xor dx, dx + div word [bp-4] + mov ax, dx + mov word [bp+4], ax + mov ax, word [bp-4] + cwd + mov cx, 10 + idiv cx + mov word [bp-4], ax + mov ax, word [bp-4] + mov word [bp-4], ax +L_clib_28: + cmp word [bp-4], 0 + jg L_clib_27 +L_clib_29: + push word [bp-2] + lea ax, [bp-10] + push ax + call print + add sp, 4 + mov sp, bp + pop bp + ret +L_clib_19: + push bp + mov bp, sp + sub sp, 10 + jmp L_clib_20 + ALIGN 2 +printLong: + jmp L_clib_31 +L_clib_32: + mov word [bp-2], 0 + mov word [bp-6], 51712 + mov word [bp-4], 15258 + cmp word [bp+6], 0 + jg L_clib_33 + jl L_clib_34 + cmp word [bp+4], 0 + jae L_clib_33 +L_clib_34: + mov byte [bp-17], 45 + inc word [bp-2] + mov ax, word [bp+4] + mov dx, word [bp+6] + neg ax + adc dx, 0 + neg dx + mov word [bp+4], ax + mov word [bp+6], dx +L_clib_33: + mov ax, word [bp+4] + mov dx, word [bp+6] + or dx, ax + jne L_clib_35 + mov word [bp-6], 1 + mov word [bp-4], 0 + jmp L_clib_36 +L_clib_35: + jmp L_clib_38 +L_clib_37: + mov ax, 10 + xor dx, dx + push dx + push ax + lea ax, [bp-6] + push ax + call SR_asldiv +L_clib_38: + push word [bp-4] + push word [bp-6] + push word [bp+6] + push word [bp+4] + call SR_ldiv + or dx, ax + je L_clib_37 +L_clib_39: +L_clib_36: + jmp L_clib_41 +L_clib_40: + push word [bp-4] + push word [bp-6] + push word [bp+6] + push word [bp+4] + call SR_uldiv + add al, 48 + mov si, word [bp-2] + lea dx, [bp-17] + add si, dx + mov byte [si], al + inc word [bp-2] + push word [bp-4] + push word [bp-6] + push word [bp+6] + push word [bp+4] + call SR_lmod + mov word [bp+4], ax + mov word [bp+6], dx + mov ax, 10 + xor dx, dx + push dx + push ax + lea ax, [bp-6] + push ax + call SR_asldiv +L_clib_41: + cmp word [bp-4], 0 + jg L_clib_40 + jne L_clib_43 + cmp word [bp-6], 0 + ja L_clib_40 +L_clib_43: +L_clib_42: + push word [bp-2] + lea ax, [bp-17] + push ax + call print + add sp, 4 + mov sp, bp + pop bp + ret +L_clib_31: + push bp + mov bp, sp + sub sp, 18 + jmp L_clib_32 + ALIGN 2 +printUInt: + jmp L_clib_45 +L_clib_46: + mov word [bp-2], 0 + mov word [bp-4], 10000 + mov ax, word [bp+4] + test ax, ax + jne L_clib_47 + mov word [bp-4], 1 + jmp L_clib_48 +L_clib_47: + jmp L_clib_50 +L_clib_49: + mov ax, word [bp-4] + xor dx, dx + mov cx, 10 + div cx + mov word [bp-4], ax +L_clib_50: + mov ax, word [bp+4] + xor dx, dx + div word [bp-4] + test ax, ax + je L_clib_49 +L_clib_51: +L_clib_48: + jmp L_clib_53 +L_clib_52: + mov ax, word [bp+4] + xor dx, dx + div word [bp-4] + add al, 48 + mov si, word [bp-2] + lea dx, [bp-10] + add si, dx + mov byte [si], al + inc word [bp-2] + mov ax, word [bp+4] + xor dx, dx + div word [bp-4] + mov word [bp+4], dx + mov ax, word [bp-4] + xor dx, dx + mov cx, 10 + div cx + mov word [bp-4], ax +L_clib_53: + mov ax, word [bp-4] + test ax, ax + jne L_clib_52 +L_clib_54: + push word [bp-2] + lea ax, [bp-10] + push ax + call print + add sp, 4 + mov sp, bp + pop bp + ret +L_clib_45: + push bp + mov bp, sp + sub sp, 10 + jmp L_clib_46 + ALIGN 2 +printULong: + jmp L_clib_56 +L_clib_57: + mov word [bp-2], 0 + mov word [bp-6], 51712 + mov word [bp-4], 15258 + mov ax, word [bp+4] + mov dx, word [bp+6] + or dx, ax + jne L_clib_58 + mov word [bp-6], 1 + mov word [bp-4], 0 + jmp L_clib_59 +L_clib_58: + jmp L_clib_61 +L_clib_60: + mov ax, 10 + xor dx, dx + push dx + push ax + lea ax, [bp-6] + push ax + call SR_asuldiv +L_clib_61: + push word [bp-4] + push word [bp-6] + push word [bp+6] + push word [bp+4] + call SR_uldiv + or dx, ax + je L_clib_60 +L_clib_62: +L_clib_59: + jmp L_clib_64 +L_clib_63: + push word [bp-4] + push word [bp-6] + push word [bp+6] + push word [bp+4] + call SR_uldiv + add al, 48 + mov si, word [bp-2] + lea dx, [bp-17] + add si, dx + mov byte [si], al + inc word [bp-2] + push word [bp-4] + push word [bp-6] + lea ax, [bp+4] + push ax + call SR_asilmod + mov ax, 10 + xor dx, dx + push dx + push ax + lea ax, [bp-6] + push ax + call SR_asuldiv +L_clib_64: + mov ax, word [bp-6] + mov dx, word [bp-4] + or dx, ax + jne L_clib_63 +L_clib_65: + push word [bp-2] + lea ax, [bp-17] + push ax + call print + add sp, 4 + mov sp, bp + pop bp + ret +L_clib_56: + push bp + mov bp, sp + sub sp, 18 + jmp L_clib_57 + ALIGN 2 +printByte: + jmp L_clib_67 +L_clib_68: + mov al, byte [bp+4] + cbw + mov cx, 4 + sar ax, cl + and ax, 15 + mov byte [bp-1], al + cmp byte [bp-1], 9 + jle L_clib_69 + mov al, byte [bp-1] + cbw + sub ax, 10 + add ax, 65 + jmp L_clib_70 +L_clib_69: + mov al, byte [bp-1] + cbw + add ax, 48 +L_clib_70: + mov byte [bp-3], al + mov al, byte [bp+4] + and al, 15 + mov byte [bp-1], al + cmp byte [bp-1], 9 + jle L_clib_71 + mov al, byte [bp-1] + cbw + sub ax, 10 + add ax, 65 + jmp L_clib_72 +L_clib_71: + mov al, byte [bp-1] + cbw + add ax, 48 +L_clib_72: + mov byte [bp-2], al + mov ax, 2 + push ax + lea ax, [bp-3] + push ax + call print + add sp, 4 + mov sp, bp + pop bp + ret +L_clib_67: + push bp + mov bp, sp + sub sp, 4 + jmp L_clib_68 + ALIGN 2 +printWord: + jmp L_clib_74 +L_clib_75: + mov word [bp-2], 3 + jmp L_clib_77 +L_clib_76: + mov ax, word [bp+4] + and ax, 15 + mov byte [bp-3], al + cmp byte [bp-3], 9 + jle L_clib_80 + mov al, byte [bp-3] + cbw + sub ax, 10 + add ax, 65 + jmp L_clib_81 +L_clib_80: + mov al, byte [bp-3] + cbw + add ax, 48 +L_clib_81: + mov si, word [bp-2] + lea dx, [bp-7] + add si, dx + mov byte [si], al + mov ax, word [bp+4] + mov cx, 4 + sar ax, cl + mov word [bp+4], ax +L_clib_79: + dec word [bp-2] +L_clib_77: + cmp word [bp-2], 0 + jge L_clib_76 +L_clib_78: + mov ax, 4 + push ax + lea ax, [bp-7] + push ax + call print + add sp, 4 + mov sp, bp + pop bp + ret +L_clib_74: + push bp + mov bp, sp + sub sp, 8 + jmp L_clib_75 + ALIGN 2 +printDWord: + jmp L_clib_83 +L_clib_84: + lea ax, [bp+4] + mov si, ax + mov ax, word [si] + mov word [bp-6], ax + lea ax, [bp+4] + mov si, ax + add si, 2 + mov ax, word [si] + mov word [bp-8], ax + mov word [bp-2], 3 + jmp L_clib_86 +L_clib_85: + mov ax, word [bp-6] + and ax, 15 + mov byte [bp-3], al + cmp byte [bp-3], 9 + jle L_clib_89 + mov al, byte [bp-3] + cbw + sub ax, 10 + add ax, 65 + jmp L_clib_90 +L_clib_89: + mov al, byte [bp-3] + cbw + add ax, 48 +L_clib_90: + mov dx, word [bp-2] + add dx, 4 + mov si, dx + lea dx, [bp-16] + add si, dx + mov byte [si], al + mov ax, word [bp-6] + mov cx, 4 + sar ax, cl + mov word [bp-6], ax + mov ax, word [bp-8] + and ax, 15 + mov byte [bp-3], al + cmp byte [bp-3], 9 + jle L_clib_91 + mov al, byte [bp-3] + cbw + sub ax, 10 + add ax, 65 + jmp L_clib_92 +L_clib_91: + mov al, byte [bp-3] + cbw + add ax, 48 +L_clib_92: + mov si, word [bp-2] + lea dx, [bp-16] + add si, dx + mov byte [si], al + mov ax, word [bp-8] + mov cx, 4 + sar ax, cl + mov word [bp-8], ax +L_clib_88: + dec word [bp-2] +L_clib_86: + cmp word [bp-2], 0 + jge L_clib_85 +L_clib_87: + mov ax, 8 + push ax + lea ax, [bp-16] + push ax + call print + add sp, 4 + mov sp, bp + pop bp + ret +L_clib_83: + push bp + mov bp, sp + sub sp, 16 + jmp L_clib_84 + diff --git a/ecen425/lab6app.c b/ecen425/lab6app.c new file mode 100644 index 0000000..6c88b33 --- /dev/null +++ b/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(); +} diff --git a/ecen425/lab6defs.h b/ecen425/lab6defs.h new file mode 100644 index 0000000..28a8ea1 --- /dev/null +++ b/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; +}; diff --git a/ecen425/myinth.c b/ecen425/myinth.c new file mode 100644 index 0000000..0146911 --- /dev/null +++ b/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(); +} diff --git a/ecen425/myisr.s b/ecen425/myisr.s new file mode 100644 index 0000000..72c7312 --- /dev/null +++ b/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 + diff --git a/ecen425/test.c b/ecen425/test.c new file mode 100644 index 0000000..0c15501 --- /dev/null +++ b/ecen425/test.c @@ -0,0 +1,272 @@ +//#include "../include/yakk.h" +//#include "../include/yaku.h" +#include + +#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; + +} diff --git a/ecen425/yakc.c b/ecen425/yakc.c new file mode 100644 index 0000000..dd6af0f --- /dev/null +++ b/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(); + +} + + diff --git a/ecen425/yakk.h b/ecen425/yakk.h new file mode 100644 index 0000000..f46fc6a --- /dev/null +++ b/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 diff --git a/ecen425/yaks.s b/ecen425/yaks.s new file mode 100644 index 0000000..69ef5dc --- /dev/null +++ b/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 diff --git a/ecen425/yaku.h b/ecen425/yaku.h new file mode 100644 index 0000000..a7f4e39 --- /dev/null +++ b/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