Browse Source

adding in ecen425 RTOS final lab

Derek McQuay 2 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 @@
1
+#include "DelayQueue.h"
2
+#include "PriorityQueue.h"
3
+#include "yakk.h"
4
+#include "clib.h"
5
+
6
+extern DelayQueue delayQueue;
7
+extern PriorityQueue readyQueue;
8
+
9
+void initializeDelayQueue() {
10
+	delayQueue.size = 0;
11
+	delayQueue.head = null;
12
+}
13
+
14
+void tickClock() {
15
+
16
+	TCB* current;
17
+   	TCB* temp;
18
+	
19
+	//Size == 0
20
+	YKEnterMutex();
21
+	if (delayQueue.size == 0) {
22
+		YKExitMutex();		
23
+		return;
24
+	}
25
+	
26
+	current = delayQueue.head;
27
+	if (delayQueue.size == 1) {
28
+		current->delayCount--;
29
+		if (current->delayCount == 0) {
30
+			delayQueue.head = null;
31
+			delayQueue.size = 0;
32
+			current->next = null;
33
+			current->prev = null;
34
+			current->state = T_READY;
35
+			YKExitMutex();
36
+			insertPriorityQueue(&readyQueue, current);
37
+			//printString("\nAfter insert\n");
38
+			return;
39
+		}
40
+		YKExitMutex();
41
+		return; 
42
+	}
43
+
44
+	current->delayCount--;
45
+	while (current != null) {
46
+		current = delayQueue.head;
47
+		if (current->delayCount == 0) {
48
+			delayQueue.head = current->next;
49
+			if (current->next != null) {
50
+				current->next->prev = null;
51
+			}
52
+			current->next = null;
53
+			current->prev = null;
54
+			current->state = T_READY;
55
+			temp = current;
56
+			delayQueue.size--;
57
+			insertPriorityQueue(&readyQueue, temp);
58
+			current = delayQueue.head;
59
+		} else {
60
+			YKExitMutex();
61
+			return;
62
+		}
63
+	}
64
+
65
+}
66
+
67
+void insertDelayQueue(TCB* tcb) {
68
+    
69
+	TCB* current;
70
+	unsigned int sumCount;
71
+	unsigned int oldSumCount;    
72
+  
73
+	if (tcb == null) return;
74
+    
75
+	//Size = 0
76
+	YKEnterMutex();
77
+     if (delayQueue.size == 0) {
78
+         delayQueue.head = tcb;
79
+         tcb->next = null;
80
+         tcb->prev = null;
81
+         delayQueue.size++;
82
+		YKExitMutex();
83
+         return;
84
+     }
85
+    
86
+     //Size > 0
87
+     current = delayQueue.head;
88
+     sumCount = 0;
89
+	 oldSumCount = 0;
90
+     while (current != null) {
91
+         sumCount += current->delayCount;
92
+		if (tcb->delayCount < sumCount) {
93
+			tcb->next = current;
94
+			tcb->prev = current->prev;
95
+     		if (current == delayQueue.head) {
96
+                    delayQueue.head = tcb;
97
+            	} else {
98
+				current->prev->next = tcb;
99
+			}
100
+            	current->prev = tcb;
101
+            	delayQueue.size++;
102
+			tcb->delayCount = tcb->delayCount - oldSumCount;
103
+            	current->delayCount = current->delayCount - tcb->delayCount;
104
+			YKExitMutex();
105
+            	return;
106
+        	}
107
+        	if (current->next == null) {
108
+        	    current->next = tcb;
109
+        	    tcb->prev = current;
110
+        	    tcb->next = null;
111
+        	    delayQueue.size++;
112
+        	    tcb->delayCount = tcb->delayCount - sumCount;
113
+			YKExitMutex();
114
+        	    return;
115
+        	}
116
+        	current = current->next;
117
+			oldSumCount = sumCount;
118
+    	}
119
+ 
120
+}
121
+
122
+void printDelayQueue(void) {
123
+
124
+	TCB* current;
125
+	int i;
126
+
127
+	current = delayQueue.head;
128
+	printString("Printing Delay Queue with size ");
129
+	printInt(delayQueue.size);
130
+	printNewLine();
131
+	
132
+	while (current != null) {
133
+		printInt(current->priority);
134
+		printString(" ");
135
+		printInt(current->delayCount);
136
+		printNewLine();
137
+		current = current->next;
138
+	}
139
+
140
+}
141
+

+ 14
- 0
ecen425/DelayQueue.h View File

@@ -0,0 +1,14 @@
1
+#ifndef DELAY_QUEUE_H
2
+#define DELAY_QUEUE_H
3
+
4
+#include "yakk.h"
5
+
6
+void initializeDelayQueue(void);
7
+
8
+void tickClock(void);
9
+
10
+void insertDelayQueue(TCB* tcb);
11
+
12
+void printDelayQueue(void);
13
+
14
+#endif

+ 36
- 0
ecen425/Makefile View File

@@ -0,0 +1,36 @@
1
+lab6.bin:	lab6.s
2
+			nasm lab6.s -o lab6.bin -l lab6.lst
3
+
4
+lab6.s:		clib.s myinth.s yakc.s PriorityQueue.s DelayQueue.s Semaphore.s MessageQueue.s lab6app.s
5
+			cat clib.s myisr.s myinth.s yaks.s yakc.s PriorityQueue.s DelayQueue.s Semaphore.s MessageQueue.s lab6app.s > lab6.s
6
+
7
+myinth.s:		myinth.c
8
+			cpp myinth.c myinth.i
9
+			c86 -g myinth.i myinth.s
10
+
11
+PriorityQueue.s:   PriorityQueue.c
12
+				cpp PriorityQueue.c PriorityQueue.i
13
+				c86 -g PriorityQueue.i PriorityQueue.s
14
+
15
+DelayQueue.s:   DelayQueue.c
16
+				cpp DelayQueue.c DelayQueue.i
17
+				c86 -g DelayQueue.i DelayQueue.s
18
+
19
+Semaphore.s:	Semaphore.c
20
+			cpp Semaphore.c Semaphore.i
21
+			c86 -g Semaphore.i Semaphore.s
22
+
23
+MessageQueue.s:	MessageQueue.c
24
+			cpp MessageQueue.c MessageQueue.i
25
+			c86 -g MessageQueue.i MessageQueue.s
26
+
27
+lab6app.s:	lab6app.c
28
+			cpp lab6app.c lab6app.i
29
+			c86 -g lab6app.i lab6app.s
30
+
31
+yakc.s:		yakc.c
32
+			cpp yakc.c yakc.i
33
+			c86 -g yakc.i yakc.s
34
+
35
+clean:		
36
+			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 @@
1
+#include "yakk.h"
2
+#include "clib.h"
3
+#include "PriorityQueue.h"
4
+
5
+extern PriorityQueue readyQueue;
6
+
7
+YKQ* YKQCreate(void** start, unsigned size) {
8
+
9
+	YKQ* newMessageQueue;
10
+
11
+	newMessageQueue = getNewQueue();
12
+	if (newMessageQueue == null) exit(NEW_QUEUE_FAILED);
13
+
14
+	initializePriorityQueue(&(newMessageQueue->queue));
15
+	newMessageQueue->messages = start;
16
+	newMessageQueue->maxSize = size;
17
+	newMessageQueue->currentSize = 0;
18
+
19
+	return newMessageQueue;
20
+
21
+}
22
+
23
+void* YKQPend(YKQ* queue) {
24
+
25
+	void* message;
26
+	int i;
27
+	TCB* runningTask;
28
+
29
+	if (queue == null) return null;
30
+	
31
+	YKEnterMutex();
32
+	if (*queue->messages == null) {
33
+		runningTask = removePriorityQueue(&readyQueue);
34
+		runningTask->state = T_BLOCKED;
35
+		insertPriorityQueue((&(queue->queue)), runningTask);
36
+		YKExitMutex();
37
+		asm("int 0x20");
38
+	}
39
+
40
+	message = queue->messages[0];
41
+	for (i = 0; i < queue->currentSize-1; i++) {
42
+		queue->messages[i] = queue->messages[i+1];
43
+	}
44
+	queue->currentSize--;
45
+	queue->messages[queue->currentSize] = null;
46
+
47
+	YKExitMutex();
48
+	return message;
49
+	
50
+}
51
+
52
+int YKQPost(YKQ* queue, void* msg) {
53
+
54
+	TCB* readyTask;
55
+	int retVal;
56
+
57
+	YKEnterMutex();
58
+	if (queue->currentSize < queue->maxSize) {
59
+		queue->messages[queue->currentSize] = msg;
60
+		queue->currentSize++;
61
+		retVal = 1;
62
+
63
+	} else {
64
+		retVal = 1;
65
+	}
66
+		
67
+	readyTask = removePriorityQueue(&(queue->queue));
68
+	if (readyTask == null) {
69
+		YKExitMutex();
70
+		return retVal;
71
+	} else {
72
+		readyTask->state = T_READY;
73
+		insertPriorityQueue(&readyQueue, readyTask);
74
+		YKExitMutex();
75
+		if (YKGetISRCallDepth() == 0) {
76
+			asm("int 0x20");
77
+		}
78
+	}
79
+	return retVal;
80
+
81
+}
82
+
83
+
84
+
85
+

+ 129
- 0
ecen425/PriorityQueue.c View File

@@ -0,0 +1,129 @@
1
+#include "yakk.h"
2
+#include "PriorityQueue.h"
3
+#include "clib.h"
4
+
5
+void initializePriorityQueue(PriorityQueue* queue) {
6
+	queue->size = 0;
7
+	queue->head = null;
8
+	queue->tail = null;
9
+}
10
+
11
+void insertPriorityQueue(PriorityQueue* queue, TCB* tcb) {
12
+
13
+	TCB* temp;
14
+
15
+	if(tcb == null) return;
16
+
17
+	//list is empty
18
+	YKEnterMutex();
19
+	if (queue->size == 0) {		
20
+		queue->head = tcb;
21
+		queue->tail = tcb;
22
+		tcb->next = null;
23
+		tcb->prev = null;
24
+		queue->size = 1;
25
+		YKExitMutex();
26
+		return;
27
+	}
28
+
29
+	//size of the list = 1
30
+	if (queue->size == 1) {		
31
+		if (queue->head->priority < tcb->priority) {
32
+			queue->head->next = tcb;
33
+			tcb->prev = queue->head;
34
+			tcb->next = null;
35
+			queue->tail = tcb;
36
+			queue->size++;
37
+			YKExitMutex();
38
+			return;
39
+		} else {
40
+			tcb->next = queue->head;
41
+			tcb->prev = null;
42
+			queue->tail->prev = tcb;
43
+			queue->head = tcb;
44
+			queue->size++;
45
+			YKExitMutex();
46
+			return;
47
+		}
48
+	}
49
+
50
+	//size of the priorityQueue > 1 
51
+	temp = queue->head;
52
+	while (temp != null) {
53
+		if (temp->priority > tcb->priority) {
54
+			tcb->next = temp;
55
+			tcb->prev = temp->prev;
56
+			if (temp == queue->head) {
57
+				queue->head = tcb;
58
+			} else {
59
+				temp->prev->next = tcb;
60
+			}
61
+			temp->prev = tcb;
62
+			queue->size++;
63
+			YKExitMutex();
64
+			return;
65
+		}
66
+		temp = temp->next;
67
+	}	
68
+
69
+	//tcb has lowest priority
70
+	queue->tail->next = tcb;
71
+	tcb->prev = queue->tail;
72
+	queue->tail = tcb;
73
+	tcb->next = null;
74
+	queue->size++;
75
+	YKExitMutex();
76
+	return;
77
+
78
+}
79
+
80
+TCB* peekPriorityQueue(PriorityQueue* queue) {	
81
+
82
+	return queue->head;
83
+		
84
+}
85
+
86
+TCB* removePriorityQueue(PriorityQueue* queue) {
87
+
88
+	TCB* retValue;
89
+
90
+	//Size of the list = 0
91
+	YKEnterMutex();
92
+	if (queue->size == 0) {
93
+		YKExitMutex();
94
+		return null;
95
+	}
96
+        
97
+	//size of the list = 1
98
+	if (queue->size == 1) {
99
+		retValue = queue->head;
100
+		retValue->next = null;
101
+		retValue->prev = null;
102
+		queue->size--;
103
+		queue->head = null;
104
+		queue->tail = null;
105
+		YKExitMutex();
106
+		return retValue;
107
+	}
108
+
109
+	//size of the list > 1
110
+	retValue = queue->head;
111
+	queue->head = queue->head->next;
112
+	queue->head->prev = null;
113
+	queue->size--;
114
+	retValue->next = null;
115
+	retValue->prev = null;
116
+	YKExitMutex();
117
+	return retValue;	
118
+
119
+}
120
+
121
+void printPriorityQueue(PriorityQueue* queue) {
122
+	TCB* current;
123
+	
124
+	while (current != null) {
125
+		printInt(current->priority);
126
+		printNewLine();
127
+		current = current->next;
128
+	}
129
+}

+ 16
- 0
ecen425/PriorityQueue.h View File

@@ -0,0 +1,16 @@
1
+#ifndef PRIORITY_QUEUE_H
2
+#define PRIORITY_QUEUE_H
3
+
4
+#include "yakk.h"
5
+
6
+void initializePriorityQueue(PriorityQueue* queue);
7
+
8
+void insertPriorityQueue(PriorityQueue* queue, TCB* tcb);
9
+
10
+TCB* peekPriorityQueue(PriorityQueue* queue);
11
+
12
+TCB* removePriorityQueue(PriorityQueue* queue);
13
+
14
+void printPriorityQueue(PriorityQueue* queue);
15
+
16
+#endif

+ 61
- 0
ecen425/Semaphore.c View File

@@ -0,0 +1,61 @@
1
+#include "yakk.h"
2
+#include "clib.h"
3
+#include "PriorityQueue.h"
4
+
5
+extern PriorityQueue readyQueue;
6
+
7
+YKSEM* YKSemCreate(int initialValue) {
8
+	YKSEM* newSemaphore;
9
+
10
+	newSemaphore = getNewSem();
11
+	if (newSemaphore == null) exit(NEW_SEM_FAILED);
12
+
13
+	initializePriorityQueue(&(newSemaphore->queue));
14
+	newSemaphore->value = initialValue;
15
+
16
+	return newSemaphore;
17
+
18
+}
19
+
20
+void YKSemPend(YKSEM* semaphore) {
21
+
22
+	TCB* runningTask;
23
+
24
+	YKEnterMutex();
25
+	if (semaphore->value < 1) {
26
+		semaphore->value--;
27
+		runningTask = removePriorityQueue(&readyQueue);
28
+		runningTask->state = T_BLOCKED;
29
+		insertPriorityQueue((&(semaphore->queue)), runningTask);
30
+		YKExitMutex();
31
+		asm("int 0x20");
32
+		return;
33
+
34
+	} else {
35
+		semaphore->value--;
36
+		YKExitMutex();
37
+		return;
38
+	}
39
+
40
+}
41
+
42
+void YKSemPost(YKSEM* semaphore) {
43
+	
44
+	TCB* readyTask;
45
+
46
+	YKEnterMutex();
47
+	semaphore->value++;
48
+	readyTask = removePriorityQueue(&(semaphore->queue));
49
+	if (readyTask == null) {
50
+		YKExitMutex();
51
+		return;
52
+	}
53
+	readyTask->state = T_READY;
54
+	insertPriorityQueue(&readyQueue, readyTask);
55
+	YKExitMutex();
56
+	if (YKGetISRCallDepth() == 0) {
57
+		asm("int 0x20");
58
+	}
59
+	return;
60
+
61
+}

+ 29
- 0
ecen425/clib.h View File

@@ -0,0 +1,29 @@
1
+#ifndef CLIB_H
2
+#define CLIB_H
3
+
4
+// Header file for clib.s output routines
5
+
6
+// Text Output:
7
+void print(char *string, int length); // Print length bytes of string
8
+void printNewLine(void);              // Print carriage return and line feed
9
+void printChar(char c);               // Print character c
10
+void printString(char *string);       // Print string
11
+
12
+// Decimal Output:
13
+void printInt(int val);
14
+void printLong(long val);
15
+void printUInt(unsigned val);
16
+void printULong(unsigned long val);
17
+
18
+// Hexadecimal Output:
19
+void printByte(char val);
20
+void printWord(int val);
21
+void printDWord(long val);
22
+
23
+// Program Control:
24
+void exit(unsigned char code);        // Terminate with exit code
25
+
26
+// PIC Functions:
27
+void signalEOI(void);                 // Send non-specific EOI to PIC
28
+
29
+#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 @@
1
+/* 
2
+File: lab6app.c
3
+Revision date: 4 November 2009
4
+Description: Application code for EE 425 lab 6 (Message queues)
5
+*/
6
+
7
+#include "clib.h"
8
+#include "yakk.h"                   /* contains kernel definitions */
9
+#include "lab6defs.h"               /* contains definitions for this lab */
10
+
11
+#define TASK_STACK_SIZE   512       /* stack size in words */
12
+#define MSGQSIZE          10
13
+
14
+struct msg MsgArray[MSGARRAYSIZE];  /* buffers for message content */
15
+
16
+int ATaskStk[TASK_STACK_SIZE];      /* a stack for each task */
17
+int BTaskStk[TASK_STACK_SIZE];
18
+int STaskStk[TASK_STACK_SIZE];
19
+
20
+int GlobalFlag;
21
+
22
+void *MsgQ[MSGQSIZE];           /* space for message queue */
23
+YKQ *MsgQPtr;                   /* actual name of queue */
24
+
25
+void ATask(void)                /* processes data in messages */
26
+{
27
+    struct msg *tmp;
28
+    int min, max, count;
29
+        
30
+    min = 100;
31
+    max = 0;
32
+    count = 0;
33
+    
34
+    while (1)
35
+    {
36
+        tmp = (struct msg *) YKQPend(MsgQPtr); /* get next msg */
37
+                
38
+        /* check sequence count in msg; were msgs dropped? */
39
+        if (tmp->tick != count+1)
40
+        {
41
+            print("! Dropped msgs: tick ", 21);
42
+            if (tmp->tick - (count+1) > 1) {
43
+                printInt(count+1);
44
+                printChar('-');
45
+                printInt(tmp->tick-1);
46
+                printNewLine();
47
+            }
48
+            else {
49
+                printInt(tmp->tick-1);
50
+                printNewLine();
51
+            }
52
+        }
53
+                
54
+        /* update sequence count */
55
+        count = tmp->tick;
56
+                
57
+        /* process data; update statistics for this sample */
58
+        if (tmp->data < min)
59
+            min = tmp->data;
60
+        if (tmp->data > max)
61
+            max = tmp->data;
62
+                
63
+        /* output min, max, tick values */
64
+        print("Ticks: ", 7);
65
+        printInt(count);
66
+        print("\t", 1);
67
+        print("Min: ", 5);
68
+        printInt(min);
69
+        print("\t", 1);
70
+        print("Max: ", 5);
71
+        printInt(max);
72
+        printNewLine();
73
+    }
74
+}
75
+
76
+void BTask(void)                /* saturates the CPU for 5 ticks */
77
+{
78
+    int busycount, curval, j, flag, chcount;
79
+    unsigned tickNum;
80
+        
81
+    curval = 1001;
82
+    chcount = 0;
83
+    
84
+    while (1)
85
+    {
86
+        YKDelayTask(2);
87
+        
88
+        if (GlobalFlag == 1)
89
+        {                           /* flag set -- loop for 5 ticks */
90
+            YKEnterMutex();
91
+            //busycount = YKTickNum;
92
+            busycount = getYKTickNum();
93
+            YKExitMutex();
94
+            
95
+            while (1)
96
+            {
97
+                YKEnterMutex();
98
+                //tickNum = YKTickNum;
99
+                tickNum = getYKTickNum();
100
+                YKExitMutex();
101
+                if(tickNum >= busycount + 5) break;                
102
+                
103
+                curval += 2;        /* evaluate next number */
104
+                flag = 0;
105
+                for (j = 3; (j*j) < curval; j += 2)
106
+                {
107
+                    if (curval % j == 0)
108
+                    {
109
+                        flag = 1;
110
+                        break;
111
+                    }
112
+                }
113
+                if (!flag)
114
+                {
115
+                    printChar('.'); /* output a marker for each prime */
116
+                    if (++chcount > 75)
117
+                    {
118
+                        printNewLine();
119
+                        chcount = 0;
120
+                    }
121
+                }
122
+            }
123
+            printNewLine();
124
+            chcount = 0;
125
+            GlobalFlag = 0;        /* clear flag */
126
+        }
127
+    }
128
+}
129
+
130
+void STask(void)                /* tracks statistics */
131
+{
132
+    unsigned max, switchCount, idleCount;
133
+    int tmp;
134
+
135
+    YKDelayTask(1);
136
+    printString("Welcome to the YAK kernel\r\n");
137
+    printString("Determining CPU capacity\r\n");
138
+    YKDelayTask(1);
139
+    //YKIdleCount = 0;
140
+    setYKIdleCount(0);
141
+    YKDelayTask(5);
142
+    //max = YKIdleCount / 25;
143
+    max = getYKIdleCount() / 25;
144
+    //YKIdleCount = 0;
145
+    setYKIdleCount(0);
146
+
147
+    YKNewTask(BTask, (void *) &BTaskStk[TASK_STACK_SIZE], 10);
148
+    YKNewTask(ATask, (void *) &ATaskStk[TASK_STACK_SIZE], 20);
149
+    
150
+    while (1)
151
+    {
152
+        YKDelayTask(20);
153
+        
154
+        YKEnterMutex();
155
+        //switchCount = YKCtxSwCount;
156
+        switchCount = getYKCtxSwCount();
157
+        //idleCount = YKIdleCount;
158
+        idleCount = getYKIdleCount();
159
+        YKExitMutex();
160
+        
161
+        printString("<<<<< Context switches: ");
162
+        printInt((int)switchCount);
163
+        printString(", CPU usage: ");
164
+        tmp = (int) (idleCount/max);
165
+        printInt(100-tmp);
166
+        printString("% >>>>>\r\n");
167
+        
168
+        YKEnterMutex();
169
+        //YKCtxSwCount = 0;
170
+        setYKCtxSwCount(0);
171
+        //YKIdleCount = 0;
172
+        setYKIdleCount(0);
173
+        YKExitMutex();
174
+    }
175
+}   
176
+
177
+void main(void)
178
+{
179
+    YKInitialize();
180
+    
181
+    /* create queue, at least one user task, etc. */
182
+    GlobalFlag = 0;
183
+    MsgQPtr = YKQCreate(MsgQ, MSGQSIZE);
184
+    YKNewTask(STask, (void *) &STaskStk[TASK_STACK_SIZE], 30);
185
+    
186
+    YKRun();
187
+}

+ 13
- 0
ecen425/lab6defs.h View File

@@ -0,0 +1,13 @@
1
+/* 
2
+File: lab6defs.h
3
+Revision date: 4 November
4
+Description: Required definitions for EE 425 lab 6 (Message queues)
5
+*/
6
+
7
+#define MSGARRAYSIZE      20
8
+
9
+struct msg 
10
+{
11
+    int tick;
12
+    int data;
13
+};

+ 40
- 0
ecen425/myinth.c View File

@@ -0,0 +1,40 @@
1
+#include "clib.h"
2
+#include "yakk.h"
3
+#include "lab6defs.h"
4
+#include "DelayQueue.h"
5
+
6
+extern unsigned int YKTickCounter;
7
+extern int GlobalFlag;
8
+extern struct msg MsgArray[];
9
+extern YKQ* MsgQPtr;
10
+
11
+void resetHandler() {
12
+	exit(0);
13
+}
14
+
15
+void tickHandler() {
16
+
17
+	static int next = 0;
18
+	static int data = 0;
19
+
20
+	tickClock();
21
+	YKEnterMutex();
22
+	YKTickCounter++;
23
+	YKExitMutex();
24
+
25
+	MsgArray[next].tick = YKTickCounter;
26
+	data = (data + 89) % 100;
27
+	MsgArray[next].data = data;
28
+	if (YKQPost(MsgQPtr, (void*) &(MsgArray[next])) == 0)
29
+		printString("  TickISR: queue overflow! \n");
30
+	else if (++next >= MSGARRAYSIZE)
31
+		next = 0;
32
+
33
+}
34
+
35
+void keyboardHandler() {
36
+
37
+	YKEnterMutex();
38
+	GlobalFlag = 1;
39
+	YKExitMutex();
40
+}

+ 118
- 0
ecen425/myisr.s View File

@@ -0,0 +1,118 @@
1
+RESET:
2
+
3
+		call 	resetHandler	;calling C interrupt handler
4
+
5
+
6
+TICK:
7
+
8
+		push 	ax
9
+		push 	bx
10
+		push 	cx
11
+		push 	dx
12
+		push 	di
13
+		push 	si
14
+		push 	ds
15
+		push 	es
16
+		push 	bp
17
+		call		YKGetISRCallDepth
18
+		test		ax, ax
19
+		jnz		tick_1
20
+		mov		si, [currentTask]
21
+		add		si, word 0x4
22
+		mov 		[si], sp
23
+
24
+tick_1:
25
+		call	YKEnterISR
26
+
27
+		sti					;enabling interrupts
28
+		call	tickHandler		;calling C interrupt handler
29
+		cli					;disabling interrupts
30
+
31
+		mov 		al, 0x20			;Load nonspecific EOI value (0x20) into register al
32
+		out		0x20, al		;Write EOI to PIC (port 0x20)
33
+
34
+		call	YKExitISR
35
+
36
+		pop		bp
37
+		pop		es
38
+		pop		ds
39
+		pop		si
40
+		pop		di
41
+		pop		dx
42
+		pop		cx
43
+		pop		bx
44
+		pop		ax
45
+
46
+		iret					;returning from ISR
47
+
48
+KEYBOARD:
49
+
50
+		push 	ax
51
+		push 	bx
52
+		push 	cx
53
+		push 	dx
54
+		push 	di
55
+		push 	si
56
+		push 	ds
57
+		push 	es
58
+		push 	bp
59
+		call		YKGetISRCallDepth
60
+		test		ax, ax
61
+		jnz		keyboard_1
62
+		mov		si, [currentTask]
63
+		add		si, word 0x4
64
+		mov 		[si], sp	
65
+
66
+keyboard_1:		
67
+		call	YKEnterISR
68
+		
69
+		sti						;enabling interrupts
70
+		call	keyboardHandler ;calling C interrupt handler
71
+		cli						;disabling interrupts
72
+
73
+		mov     al, 0x20		;Load nonspecific EOI value (0x20) into register al
74
+		out		0x20, al		;Write EOI to PIC (port 0x20)
75
+
76
+		call	YKExitISR
77
+
78
+		pop		bp
79
+		pop		es
80
+		pop		ds
81
+		pop		si
82
+		pop		di
83
+		pop		dx
84
+		pop		cx
85
+		pop		bx
86
+		pop		ax
87
+
88
+		iret					;returning from ISR
89
+
90
+TRAP:
91
+
92
+		push 	ax
93
+		push 	bx
94
+		push 	cx
95
+		push 	dx
96
+		push 	di
97
+		push 	si
98
+		push 	ds
99
+		push 	es
100
+		push 	bp
101
+		mov		si, [currentTask]
102
+		add		si, word 0x4
103
+		mov 		[si], sp
104
+
105
+		call 	YKScheduler
106
+
107
+		pop		bp
108
+		pop		es
109
+		pop		ds
110
+		pop		si
111
+		pop		di
112
+		pop		dx
113
+		pop		cx
114
+		pop		bx
115
+		pop		ax
116
+
117
+		iret
118
+

+ 272
- 0
ecen425/test.c View File

@@ -0,0 +1,272 @@
1
+//#include "../include/yakk.h"
2
+//#include "../include/yaku.h"
3
+#include <stdio.h>
4
+
5
+#define null 0
6
+#define MAX_TASKS 10
7
+
8
+typedef struct TCB TCB;
9
+
10
+struct TCB {
11
+	unsigned int tid;
12
+	unsigned char priority;
13
+	void* stackPointer;	
14
+	unsigned int state;	
15
+	unsigned int delayCount;
16
+	TCB* next;
17
+	TCB* prev;
18
+};
19
+
20
+typedef struct TaskBlock TaskBlock;
21
+
22
+struct TaskBlock {
23
+	TCB tasks[MAX_TASKS+1];
24
+	unsigned int nextFreeTCB;	
25
+};
26
+
27
+typedef struct DelayQueue DelayQueue;
28
+
29
+struct DelayQueue {
30
+	TCB* head;
31
+	unsigned int size;
32
+};
33
+
34
+typedef struct ReadyQueue ReadyQueue;
35
+
36
+struct ReadyQueue {
37
+	TCB* head;
38
+	TCB* tail;
39
+	unsigned int size;
40
+};
41
+
42
+static TaskBlock taskBlock;
43
+static DelayQueue delayQueue;
44
+static ReadyQueue readyQueue;
45
+
46
+TCB* getNewTCB(void) {
47
+
48
+	TCB* task;
49
+	if (taskBlock.nextFreeTCB < MAX_TASKS + 1) {
50
+                printf("nextFreeBlock = %d\n", taskBlock.nextFreeTCB);
51
+                task = &taskBlock.tasks[taskBlock.nextFreeTCB];
52
+		taskBlock.nextFreeTCB++;
53
+		return task;
54
+	} else {
55
+		printf("TCBFullError\n");		
56
+		return null;
57
+	}
58
+
59
+}
60
+
61
+void tickClock() {
62
+
63
+	TCB* current;
64
+        TCB* temp;
65
+	
66
+	//Size == 0
67
+	if (delayQueue.size == 0) return;
68
+	
69
+	//Size > 0
70
+	current = delayQueue.head;
71
+	while (current != null) {
72
+            current->delayCount--;
73
+            temp = current;
74
+            if (temp->delayCount == 0) {
75
+                removeDelayQueue(temp);
76
+            }
77
+            current = current->next;
78
+	}
79
+
80
+}
81
+
82
+void insertDelayQueue(TCB* tcb) {
83
+    
84
+    TCB* current;
85
+    unsigned int sumCount;
86
+      
87
+    if (tcb == null) return;
88
+    
89
+    //Size = 0
90
+    if (delayQueue.size == 0) {
91
+        delayQueue.head = tcb;
92
+        tcb->next = null;
93
+        tcb->prev = null;
94
+        delayQueue.size++;
95
+        return;
96
+    }
97
+    
98
+    //Size > 0
99
+    current = delayQueue.head;
100
+    sumCount = 0;
101
+    while (current != null) {
102
+        sumCount += current->delayCount;
103
+        if (tcb->delayCount < sumCount) {
104
+            tcb->prev = current->prev;
105
+            tcb->next = current;
106
+            if (current == delayQueue.head) {
107
+                delayQueue.head = tcb;
108
+                current->prev->next = tcb;
109
+            }
110
+            current->prev = tcb;
111
+            delayQueue.size++;
112
+            tcb->delayCount = tcb->delayCount - sumCount;
113
+            return;
114
+        }
115
+        if (current->next == null) {
116
+            current->next = tcb;
117
+            tcb->prev = current;
118
+            tcb->next = null;
119
+            delayQueue.size++;
120
+            tcb->delayCount = tcb->delayCount - sumCount;
121
+            return;
122
+        }
123
+        current = current->next;
124
+    }
125
+    
126
+}
127
+
128
+void removeDelayQueue(TCB* tcb) {
129
+    
130
+    TCB* current;
131
+    TCB* temp;
132
+    
133
+    if (tcb == null) return;
134
+    
135
+    current = delayQueue.head;
136
+    while (current != null) {
137
+        if (current->priority = tcb->priority) {
138
+            if (current == delayQueue.head) {
139
+                temp = current;
140
+                current = current->next;
141
+                delayQueue.head = temp->next;
142
+                temp->next->prev = null;
143
+                delayQueue.size--;
144
+                temp->next = null;
145
+                temp->prev = null;
146
+                insertReadyQueue(temp);
147
+            } else if (current->next == null) {
148
+                temp = current;
149
+                current = current->next;
150
+                temp->prev->next = null;
151
+                delayQueue.size--;
152
+                insertReadyQueue(temp);
153
+            } else {
154
+                temp = current;
155
+                current = current->next;
156
+                temp->prev->next = temp->next;
157
+                temp->next->prev = temp->prev;
158
+                temp->next = null;
159
+                temp->prev = null;
160
+                delayQueue.size--;
161
+                insertReadyQueue(temp);
162
+            }
163
+        } 
164
+    }
165
+    
166
+    
167
+}
168
+
169
+void initializeReadyQueue() {
170
+	readyQueue.size = 0;
171
+}
172
+
173
+void insertReadyQueue(TCB* tcb) {
174
+
175
+	if(tcb == null) return;
176
+
177
+	//list is empty
178
+	if (readyQueue.size == 0) {
179
+		readyQueue.head = tcb;
180
+		readyQueue.tail = tcb;
181
+		tcb->next = null;
182
+		tcb->prev = null;
183
+		readyQueue.size = 1;
184
+		return;
185
+	}
186
+
187
+	//size of the list = 1
188
+	if (readyQueue.head == readyQueue.tail) {		
189
+		if (readyQueue.head->priority < tcb->priority) {
190
+			readyQueue.head->next = tcb;
191
+			tcb->prev = readyQueue.head;
192
+			tcb->next = null;
193
+			readyQueue.tail = tcb;
194
+			readyQueue.size++;
195
+			return;
196
+		} else {
197
+			tcb->next = readyQueue.head;
198
+			tcb->prev = null;
199
+			readyQueue.tail->prev = tcb;
200
+		}
201
+	}
202
+
203
+	//size of the readyQueue > 1
204
+	TCB* temp = readyQueue.head;
205
+	while (temp != null) {
206
+		if (temp->priority > tcb->priority) {
207
+			tcb->next = temp;
208
+			tcb->prev = temp->prev;
209
+			temp->prev = tcb;
210
+			if (temp == readyQueue.head) readyQueue.head = tcb;
211
+			readyQueue.size++;
212
+			return;
213
+		}
214
+		temp = temp->next;
215
+	}	
216
+
217
+	//tcb has lowest priority
218
+	readyQueue.tail->next = tcb;
219
+	tcb->prev = readyQueue.tail;
220
+	readyQueue.tail = tcb;
221
+	tcb->next = null;
222
+	readyQueue.size++;
223
+	return;
224
+
225
+}
226
+
227
+TCB* removeReadyQueue() {
228
+
229
+	TCB* retValue;
230
+        
231
+	//size of the list = 1
232
+	if (readyQueue.head == readyQueue.tail) {
233
+		retValue = readyQueue.head;
234
+		readyQueue.size--;
235
+		readyQueue.head = null;
236
+		readyQueue.tail = null;
237
+		return retValue;
238
+	}
239
+
240
+	//size of the list > 1
241
+	retValue = readyQueue.head;
242
+	readyQueue.head = readyQueue.head->next;
243
+	readyQueue.size--;
244
+	return retValue;	
245
+
246
+}
247
+
248
+int main(int argc, char** argv) {
249
+     
250
+    TCB* tasks[5];
251
+    
252
+    int i;    
253
+    for (i = 0; i < 10; i += 2 ) {
254
+        TCB* tcb1 = getNewTCB();        
255
+        tasks[i / 2] = getNewTCB();        
256
+        tcb1->tid = i / 2;        
257
+        tasks[i / 2]->delayCount = i / 2;        
258
+        tasks[i / 2]->tid = i / 2;        
259
+        tcb1->priority = i / 2;        
260
+        insertReadyQueue(tcb1);       
261
+        insertDelayQueue(tasks[i / 2]);	
262
+    }
263
+                
264
+    for (i = 0; i < 10; i += 2) {    
265
+        TCB* tcb1 = removeReadyQueue();
266
+        printf("Task %d was removed with priority %d\n", tcb1->tid, tcb1->priority);        
267
+        printf("Task %d was removed with delta delay %d\n", tasks[i / 2]->tid, tasks[i / 2]->delayCount);        
268
+    }
269
+	
270
+	return 0;
271
+
272
+}

+ 206
- 0
ecen425/yakc.c View File

@@ -0,0 +1,206 @@
1
+#include "clib.h"
2
+#include "yakk.h"
3
+#include "yaku.h"
4
+#include "PriorityQueue.h"
5
+#include "DelayQueue.h"
6
+
7
+//User Accessible Variables
8
+unsigned int YKCtxSwCount = 0;
9
+unsigned int YKIdleCount = 0;
10
+unsigned int YKTickCounter = 0;
11
+
12
+//Kernel Accessible Variables
13
+static unsigned int ISRCallDepth = 0;
14
+TCB* currentTask = null;
15
+PriorityQueue readyQueue;
16
+DelayQueue delayQueue;
17
+static TaskBlock taskBlock;
18
+static SemBlock semBlock;
19
+static MsgQueueBlock msgQueueBlock;
20
+static int idleTaskStack[IDLETASKSTACKSIZE];
21
+static enum KernelState kernelState = K_BLOCKED;
22
+
23
+unsigned int getYKCtxSwCount() {
24
+    return YKCtxSwCount;
25
+}
26
+
27
+unsigned int getYKIdleCount() {
28
+    return YKIdleCount;
29
+}
30
+
31
+unsigned int getYKTickNum() {
32
+    return YKTickCounter;
33
+}
34
+
35
+void setYKIdleCount(int value) {
36
+    YKIdleCount = value;
37
+}
38
+
39
+void setYKCtxSwCount(int value) {
40
+    YKCtxSwCount = value;
41
+}
42
+
43
+void YKEnterISR(void) {
44
+	YKEnterMutex();
45
+	ISRCallDepth++;
46
+	YKExitMutex();
47
+}
48
+
49
+void YKExitISR(void) {
50
+	YKEnterMutex();
51
+	ISRCallDepth--;
52
+	if (ISRCallDepth == 0) {
53
+		YKExitMutex();		
54
+		YKScheduler();
55
+	}
56
+	YKExitMutex();
57
+}
58
+
59
+unsigned int YKGetISRCallDepth(void) {
60
+		
61
+	return ISRCallDepth;
62
+}
63
+
64
+void YKInitialize(void) {
65
+
66
+	YKEnterMutex();
67
+
68
+	//Set up queues
69
+	initializePriorityQueue(&readyQueue);
70
+	initializeDelayQueue();
71
+
72
+	//Set up Task Block
73
+	taskBlock.nextFreeTCB == 0;
74
+	//
75
+		
76
+	//Set up Idle Task
77
+	YKNewTask(YKIdleTask, &idleTaskStack[IDLETASKSTACKSIZE], 100);
78
+	//
79
+
80
+	YKExitMutex();
81
+	return;
82
+
83
+}
84
+
85
+void YKScheduler(void) {
86
+
87
+	TCB* readyTask; 
88
+	YKEnterMutex();
89
+	if (kernelState == K_BLOCKED) return;
90
+	readyTask = peekPriorityQueue(&readyQueue);
91
+	if (readyTask == null) exit(READY_QUEUE_EMPTY);
92
+	if (readyTask != currentTask) {
93
+		currentTask = readyTask;
94
+		currentTask->state = T_READY;
95
+		YKCtxSwCount++;
96
+		readyTask->state = T_RUNNING;
97
+		YKDispatcher(readyTask);
98
+		YKExitMutex();
99
+		return;
100
+	}
101
+	YKExitMutex();
102
+	return;
103
+}
104
+
105
+void YKNewTask(void (*task)(void), void* taskStack, unsigned char priority) {
106
+
107
+	TCB* newTask;	
108
+	
109
+	//Obtain a TCB
110
+	newTask = getNewTCB();
111
+	if (newTask == null) exit(NEW_TASK_FAILED);
112
+
113
+	//Fill TCB
114
+	newTask->tid = 0;
115
+	newTask->priority = priority;
116
+	newTask->stackPointer = ((void*)((int*) taskStack - 12));
117
+	newTask->state = T_READY;
118
+	newTask->delayCount = 0;
119
+	newTask->next = null;
120
+	newTask->prev = null;
121
+
122
+	//Set up Stack
123
+	asm("push bx");
124
+	asm("push cx");
125
+	asm("mov bx, [bp+6]"); //Get address of stack
126
+	asm("mov cx, [bp+4]"); //Get address of function pointer
127
+	asm("mov [bx-2], word 0x0200"); //Move flag register onto the stack
128
+	asm("mov [bx-4], word 0x0");	
129
+	asm("mov [bx-6], cx");
130
+	asm("pop cx");
131
+	asm("pop bx");
132
+
133
+	insertPriorityQueue(&readyQueue, newTask);
134
+	asm("int 0x20");
135
+	return; 
136
+
137
+}
138
+
139
+TCB* getNewTCB(void) {
140
+	
141
+	TCB* task;
142
+	if (taskBlock.nextFreeTCB < MAX_TASKS + 1) {
143
+          task = &taskBlock.TCBPool[taskBlock.nextFreeTCB++];
144
+		return task;
145
+	} else {
146
+		return null;
147
+	}
148
+
149
+}
150
+
151
+YKSEM* getNewSem(void) {
152
+	
153
+	YKSEM* semaphore;
154
+	if (semBlock.nextFreeSem < MAX_SEMS) {
155
+          semaphore = &semBlock.SemPool[semBlock.nextFreeSem++];
156
+		return semaphore;
157
+	} else {
158
+		return null;
159
+	}
160
+
161
+}
162
+
163
+YKQ* getNewQueue(void) {
164
+	
165
+	YKQ* messageQueue;
166
+	if (msgQueueBlock.nextFreeQueue < MAX_QUEUES) {
167
+		messageQueue = &msgQueueBlock.QueuePool[msgQueueBlock.nextFreeQueue++];
168
+		return messageQueue;
169
+	} else {
170
+		return null;
171
+	}
172
+
173
+}
174
+
175
+void YKRun(void) {
176
+
177
+	YKEnterMutex();
178
+	kernelState = K_RUNNING;
179
+	YKScheduler();
180
+	YKExitMutex();
181
+	return;
182
+
183
+}
184
+
185
+void YKDelayTask(unsigned int count) {
186
+
187
+	TCB* delayedTask;
188
+
189
+	if (count == 0) return;
190
+
191
+	delayedTask = removePriorityQueue(&readyQueue);
192
+	delayedTask->state = T_BLOCKED;
193
+	delayedTask->delayCount = count;
194
+	insertDelayQueue(delayedTask);
195
+	asm("int 0x20");
196
+	return;
197
+
198
+}
199
+
200
+void YKTickHandler(void) {
201
+
202
+	tickClock();
203
+
204
+}
205
+
206
+

+ 100
- 0
ecen425/yakk.h View File

@@ -0,0 +1,100 @@
1
+#ifndef YAKK_H
2
+#define YAKK_H
3
+
4
+#include "yaku.h"
5
+
6
+#define null 0
7
+#define IDLETASKSTACKSIZE 512
8
+
9
+//Error Codes
10
+#define NEW_TASK_FAILED 1
11
+#define READY_QUEUE_EMPTY 2
12
+#define NEW_SEM_FAILED 3
13
+#define NEW_QUEUE_FAILED 4
14
+
15
+//Kernel Data Structures
16
+
17
+enum TaskState {T_BLOCKED, T_READY, T_RUNNING};
18
+enum KernelState {K_BLOCKED, K_RUNNING};
19
+
20
+typedef struct TCB {
21
+	unsigned int tid;
22
+	unsigned char priority;
23
+	void* stackPointer;	
24
+	enum TaskState state;	
25
+	unsigned int delayCount;
26
+	struct TCB* next;
27
+	struct TCB* prev;
28
+} TCB;
29
+
30
+typedef struct TaskBlock {
31
+	TCB TCBPool[MAX_TASKS+1];
32
+	unsigned int nextFreeTCB;	
33
+} TaskBlock;
34
+
35
+typedef struct PriorityQueue {
36
+	TCB* head;
37
+	TCB* tail;
38
+	unsigned int size;
39
+} PriorityQueue;
40
+
41
+typedef struct DelayQueue {
42
+	TCB* head;
43
+	unsigned int size;
44
+} DelayQueue;
45
+
46
+typedef struct Semaphore {
47
+	int value;
48
+	PriorityQueue queue;
49
+} YKSEM;
50
+
51
+typedef struct SemBlock {
52
+	YKSEM SemPool[MAX_SEMS];
53
+	unsigned int nextFreeSem;
54
+} SemBlock;
55
+
56
+typedef struct MessageQueue {
57
+	void** messages;
58
+	unsigned int currentSize;
59
+	unsigned int maxSize;
60
+	PriorityQueue queue;
61
+} YKQ;
62
+
63
+typedef struct MessageQueueBlock {
64
+	YKQ QueuePool[MAX_QUEUES];
65
+	unsigned int nextFreeQueue;
66
+} MsgQueueBlock;
67
+
68
+//Kernel API
69
+void YKInitialize(void);
70
+void YKEnterMutex(void);
71
+void YKExitMutex(void);
72
+void YKIdleTask(void);
73
+void YKNewTask(void (* task) (void), void *taskStack, unsigned char priority);
74
+void YKDelayTask(unsigned count);
75
+void YKEnterISR(void);
76
+void YKExitISR(void);
77
+unsigned int YKGetISRCallDepth(void);
78
+void YKScheduler(void);
79
+void YKDispatcher(TCB* readyTask);
80
+void YKTickHandler(void);
81
+YKSEM* YKSemCreate(int initialValue);
82
+void YKSemPend(YKSEM* semaphore);
83
+void YKSemPost(YKSEM* semaphore);
84
+YKQ* YKQCreate(void** start, unsigned size);
85
+void* YKQPend(YKQ* queue);
86
+int YKQPost(YKQ* queue, void* msg);
87
+//YKEVENT* YKEventCreate(unsigned initialValue);
88
+//void YKEventSet(YKEVENT* event, unsigned eventMask);
89
+//void YKEVentReset(YKEVENT* event, unsigned eventMask);
90
+TCB* getNewTCB(void);
91
+YKSEM* getNewSem(void);
92
+YKQ* getNewQueue(void);
93
+void YKRun(void);
94
+unsigned int getYKCtxSwCount();
95
+unsigned int getYKIdelCount(); 
96
+void setYKIdelCount(int value);
97
+void setYKCtxSwCount(int value);
98
+unsigned int getYKTickNum();
99
+
100
+#endif

+ 39
- 0
ecen425/yaks.s View File

@@ -0,0 +1,39 @@
1
+YKIdleTask:
2
+	
3
+		push		bp
4
+		mov		bp, sp
5
+
6
+yak_loop:
7
+		inc		word [YKIdleCount]		
8
+		jmp		yak_loop
9
+
10
+YKDispatcher:
11
+
12
+		cli
13
+		push 	bp
14
+		mov		bp, sp		
15
+
16
+		mov		bx, [bp+4]	;Obtain stack pointer from TCB
17
+		mov		sp, [bx+4]	;Load stack pointer into SP
18
+
19
+		pop		bp
20
+		pop		es
21
+		pop		ds
22
+		pop		si
23
+		pop		di
24
+		pop		dx
25
+		pop		cx
26
+		pop		bx
27
+		pop		ax
28
+
29
+		iret
30
+
31
+YKEnterMutex:
32
+
33
+		cli
34
+		ret
35
+
36
+YKExitMutex:
37
+		
38
+		sti
39
+		ret

+ 8
- 0
ecen425/yaku.h View File

@@ -0,0 +1,8 @@
1
+#ifndef YAKU_H
2
+#define YAKU_H
3
+
4
+#define MAX_TASKS 10
5
+#define MAX_SEMS 10
6
+#define MAX_QUEUES 10
7
+
8
+#endif

Loading…
Cancel
Save