UbixOS V2 2.0

sched.c
Go to the documentation of this file.
1 /*-
2 * Copyright (c) 2002-2018 The UbixOS Project.
3 * All rights reserved.
4 *
5 * This was developed by Christopher W. Olsen for the UbixOS Project.
6 *
7 * Redistribution and use in source and binary forms, with or without modification, are permitted
8 * provided that the following conditions are met:
9 *
10 * 1) Redistributions of source code must retain the above copyright notice, this list of
11 * conditions, the following disclaimer and the list of authors.
12 * 2) Redistributions in binary form must reproduce the above copyright notice, this list of
13 * conditions, the following disclaimer and the list of authors in the documentation and/or
14 * other materials provided with the distribution.
15 * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to
16 * endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/_null.h>
30 #include <ubixos/sched.h>
31 #include <ubixos/kpanic.h>
32 #include <ubixos/spinlock.h>
33 #include <ubixos/endtask.h>
34 #include <ubixos/wait.h>
35 #include <vfs/mount.h>
36 #include <lib/kmalloc.h>
37 #include <lib/kprintf.h>
38 #include <vmm/vmm.h>
39 #include <sys/gdt.h>
40 #include <sys/idt.h>
41 #include <isa/8259.h>
42 #include <string.h>
43 #include <assert.h>
44 #include <sys/descrip.h>
45
46 #include <ubixos/spinlock.h>
47
48 static kTask_t *taskList = 0x0;
49 static kTask_t *delList = 0x0;
50 static uint32_t nextID = 1;
51
52 kTask_t *_current = 0x0;
53 kTask_t *_usedMath = 0x0;
54
55 static struct spinLock schedulerSpinLock = SPIN_LOCK_INITIALIZER;
56
57 int need_resched = 0;
58
59 /************************************************************************
60
61 Function: int sched_init()
62
63 Description: This function is used to enable the kernel scheduler
64
65 Notes:
66
67 02/20/2004 - Approved for quality
68
69 ************************************************************************/
70
71 int sched_init() {
72 taskList = (kTask_t *) kmalloc(sizeof(kTask_t));
73 if (taskList == 0x0)
74 kpanic("Unable to create task list");
75
76 taskList->id = nextID++;
77
78 /* Print out information on scheduler */
79 kprintf("sched0 - Address: [0x%X]\n", taskList);
80
81 /* Return so we know everything went well */
82 return (0x0);
83 }
84
85 void sched() {
86 uint32_t memAddr = 0x0;
87 kTask_t *tmpTask = 0x0;
88 kTask_t *delTask = 0x0;
89
90 if (spinTryLock(&schedulerSpinLock))
91 return;
92
93 tmpTask = ((_current == 0) ? 0 : _current->next);
94 schedStart:
95
96 /* Yield the next task from the current prio queue */
97 for (; tmpTask != 0x0; tmpTask = tmpTask->next) {
98 if (tmpTask->state == FORK)
99 tmpTask->state = READY;
100
101 if (tmpTask->state == READY) {
102 _current->state = (_current->state == DEAD) ? DEAD : READY;
103 _current = tmpTask;
104 break;
105 }
106 else if (tmpTask->state == DEAD) {
107 delTask = tmpTask;
108 if (delTask->parent != 0x0) {
109 delTask->parent->children -= 1;
110 delTask->parent->last_exit = delTask->id;
111 delTask->parent->state = READY;
112 }
113
114 tmpTask = tmpTask->next;
115 sched_deleteTask(delTask->id);
116 sched_addDelTask(delTask);
117 goto schedStart;
118 }
119 }
120
121 /* Finished all the tasks, restarting the list */
122 if (0x0 == tmpTask) {
123 tmpTask = taskList;
124 goto schedStart;
125 }
126
127 if (_current->state == READY || _current->state == RUNNING) {
128
129 if (_current->oInfo.v86Task == 0x1) {
130 irqDisable(0x0);
131 kprintf("IRQD(%i): 0x%X*0x%X:0x%X@, esp: 0x%X:0x%X, ebp: 0x%X:0x%X ds: 0x%X", _current->id, _current->tss.eflags, _current->tss.cs, _current->tss.eip, _current->tss.ss, _current->tss.esp, _current->tss.ss, _current->tss.ebp,_current->tss.ds);
132 kprintf("ss0: 0x%X, esp0: 0x%X", _current->tss.ss0, _current->tss.esp0);
133 }
134
135 asm("cli");
136
137 memAddr = (uint32_t) &(_current->tss);
138 ubixGDT[4].descriptor.baseLow = (memAddr & 0xFFFF);
139 ubixGDT[4].descriptor.baseMed = ((memAddr >> 16) & 0xFF);
140 ubixGDT[4].descriptor.baseHigh = (memAddr >> 24);
141 ubixGDT[4].descriptor.access = '\x89';
142
143 _current->state = RUNNING;
144
145 spinUnlock(&schedulerSpinLock);
146
147 asm("sti");
148 asm("ljmp $0x20,$0");
149 }
150 else {
151 spinUnlock(&schedulerSpinLock);
152 }
153
154 return;
155 }
156
157 kTask_t *schedNewTask() {
158 int i = 0;
159
160 kTask_t *tmpTask = (kTask_t *) kmalloc(sizeof(kTask_t));
161
162 struct file *fp = 0x0;
163
164 if (tmpTask == 0x0)
165 kpanic("Error: schedNewTask() - kmalloc failed trying to initialize a new task struct\n");
166
167 memset(tmpTask, 0x0, sizeof(kTask_t));
168
169 /* Filling in tasks attrs */
170 tmpTask->usedMath = 0x0;
171 tmpTask->state = NEW;
172
173 memcpy(tmpTask->username, "UbixOS", 6);
174
175 /* HACK */
176 for (i = 0; i < 3; i++) {
177 fp = (void *) kmalloc(sizeof(struct file));
178 //kprintf("DB: [0x%X]\n", (uint32_t) fp);
179 tmpTask->td.o_files[i] = (void *) fp;
180 fp->f_flag = 0x4;
181 }
182
183 spinLock(&schedulerSpinLock);
184 tmpTask->id = nextID++;
185 tmpTask->next = taskList;
186 tmpTask->prev = 0x0;
187 taskList->prev = tmpTask;
188 taskList = tmpTask;
189
190 spinUnlock(&schedulerSpinLock);
191
192 return (tmpTask);
193 }
194
195 int sched_deleteTask(pidType id) {
196 kTask_t *tmpTask = 0x0;
197
198 /* Checking each task from the prio queue */
199 for (tmpTask = taskList; tmpTask != 0x0; tmpTask = tmpTask->next) {
200 if (tmpTask->id == id) {
201 if (tmpTask->prev != 0x0)
202 tmpTask->prev->next = tmpTask->next;
203 if (tmpTask->next != 0x0)
204 tmpTask->next->prev = tmpTask->prev;
205 if (taskList == tmpTask)
206 taskList = tmpTask->next;
207
208 return (0x0);
209 }
210 }
211 return (0x1);
212 }
213
214 int sched_addDelTask(kTask_t *tmpTask) {
215 tmpTask->next = delList;
216 tmpTask->prev = 0x0;
217 if (delList != 0x0)
218 delList->prev = tmpTask;
219 delList = tmpTask;
220 return (0x0);
221 }
222
223 kTask_t *sched_getDelTask() {
224 kTask_t *tmpTask = 0x0;
225
226 if (delList == 0x0)
227 return (0x0);
228
229 tmpTask = delList;
230 delList = delList->next;
231 return (tmpTask);
232 }
233
234 kTask_t *schedFindTask(uint32_t id) {
235 kTask_t *tmpTask = 0x0;
236
237 for (tmpTask = taskList; tmpTask; tmpTask = tmpTask->next) {
238 if (tmpTask->id == id)
239 return (tmpTask);
240 }
241
242 return (0x0);
243 }
244
245 /************************************************************************
246
247 Function: void schedEndTask()
248
249 Description: This function will end a task
250
251 Notes:
252
253 02/20/2004 - Approved for quality
254
255 ************************************************************************/
256 void schedEndTask(pidType pid) {
257 endTask(_current->id);
258 sched_yield();
259 }
260
261 /************************************************************************
262
263 Function: int schedEndTask()
264
265 Description: This function will yield a task
266
267 Notes:
268
269 02/20/2004 - Approved for quality
270
271 ************************************************************************/
272
273 void sched_yield() {
274 sched();
275 }
276
277 /*
278 asm(
279 ".globl sched_yield \n"
280 "sched_yield: \n"
281 " cli \n"
282 " call sched \n"
283 );
284 */
285
286 /************************************************************************
287
288 Function: int sched_setStatus(pidType pid,tState state)
289
290 Description: Change the tasks status
291
292 Notes:
293
294 ************************************************************************/
295 int sched_setStatus(pidType pid, tState state) {
296 kTask_t *tmpTask = schedFindTask(pid);
297 if (tmpTask == 0x0)
298 return (0x1);
299 tmpTask->state = state;
300 return (0x0);
301 }
302
303 void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait) {
304 unsigned long flags;
305
306 save_flags(flags);
307 cli();
308 if (!*p) {
309 wait->next = wait;
310 *p = wait;
311 }
312 else {
313 wait->next = (*p)->next;
314 (*p)->next = wait;
315 }
316 restore_flags(flags);
317 }
318
319 void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait) {
320 unsigned long flags;
321 struct wait_queue * tmp;
322
323 save_flags(flags);
324 cli();
325 if ((*p == wait) && ((*p = wait->next) == wait)) {
326 *p = NULL;
327 }
328 else {
329 tmp = wait;
330 while (tmp->next != wait) {
331 tmp = tmp->next;
332 }
333 tmp->next = wait->next;
334 }
335 wait->next = NULL;
336 restore_flags(flags);
337 }
338
339 void wake_up_interruptible(struct wait_queue **q) {
340 struct wait_queue *tmp;
341 kTask_t *p;
342
343 if (!q || !(tmp = *q))
344 return;
345 do {
346 if ((p = tmp->task) != NULL) {
347 if (p->state == INTERRUPTIBLE) {
348 p->state = RUNNING;
349 if (p->counter > _current->counter)
350 need_resched = 1;
351 }
352 }
353 if (!tmp->next) {
354 kprintf("wait_queue is bad (eip = %08lx)\n", ((unsigned long *) q)[-1]);
355 kprintf(" q = %p\n", q);
356 kprintf(" *q = %p\n", *q);
357 kprintf(" tmp = %p\n", tmp);
358 break;
359 }
360 tmp = tmp->next;
361 } while (tmp != *q);
362 }
363
364 void wake_up(struct wait_queue **q) {
365 struct wait_queue *tmp;
366 kTask_t * p;
367
368 if (!q || !(tmp = *q))
369 return;
370 do {
371 if ((p = tmp->task) != NULL) {
372 if ((p->state == UNINTERRUPTIBLE) || (p->state == INTERRUPTIBLE)) {
373 p->state = RUNNING;
374 if (p->counter > _current->counter)
375 need_resched = 1;
376 }
377 }
378 if (!tmp->next) {
379 kprintf("wait_queue is bad (eip = %08lx)\n", ((unsigned long *) q)[-1]);
380 kprintf(" q = %p\n", q);
381 kprintf(" *q = %p\n", *q);
382 kprintf(" tmp = %p\n", tmp);
383 break;
384 }
385 tmp = tmp->next;
386 } while (tmp != *q);
387 }
8259.h
taskStruct
Definition: sched.h:62
spinlock.h
gdt.h
sched_addDelTask
int sched_addDelTask(kTask_t *tmpTask)
Definition: sched.c:186
descriptorTableUnion::descriptor
struct gdtDescriptor descriptor
Definition: gdt.h:84
ubixGDT
union descriptorTableUnion ubixGDT[11]
_usedMath
kTask_t * _usedMath
Definition: sched.c:51
tssStruct::eip
long eip
Definition: tss.h:47
restore_flags
#define restore_flags(x)
Definition: wait.h:50
schedEndTask
void schedEndTask(pidType pid)
Definition: sched.c:228
thread::o_files
void * o_files[512]
Definition: thread.h:42
string.h
idt.h
file::f_flag
uint32_t f_flag
Definition: descrip.h:68
NEW
Definition: sched.h:47
irqDisable
void irqDisable(uInt16 irqNo)
file
Definition: descrip.h:67
taskStruct::prev
struct taskStruct * prev
Definition: sched.h:65
taskStruct::username
char username[256]
Definition: sched.h:91
tssStruct::ds
short ds
Definition: tss.h:60
assert.h
taskStruct::counter
uint32_t counter
Definition: sched.h:84
spinUnlock
void spinUnlock(spinLock_t *lock)
Definition: spinlock.c:36
tssStruct::eflags
long eflags
Definition: tss.h:48
vmm.h
tssStruct::esp0
long esp0
Definition: tss.h:37
remove_wait_queue
void remove_wait_queue(struct wait_queue **p, struct wait_queue *wait)
Definition: sched.c:315
endtask.h
RUNNING
Definition: sched.h:47
taskStruct::tss
struct tssStruct tss
Definition: sched.h:67
sched_init
int sched_init()
Definition: sched.c:66
SPIN_LOCK_INITIALIZER
#define SPIN_LOCK_INITIALIZER
Definition: spinlock.h:36
FORK
Definition: sched.h:47
tssStruct::ss0
short ss0
Definition: tss.h:38
add_wait_queue
void add_wait_queue(struct wait_queue **p, struct wait_queue *wait)
Definition: sched.c:299
wake_up_interruptible
void wake_up_interruptible(struct wait_queue **q)
Definition: sched.c:335
sched.h
kpanic
void kpanic(const char *fmt,...)
print panic message and halt system
Definition: kpanic.c:41
gdtDescriptor::access
unsigned char access
Definition: gdt.h:70
memcpy
void * memcpy(const void *dst, const void *src, size_t length)
taskStruct::td
struct thread td
Definition: sched.h:78
spinLock
void spinLock(spinLock_t *lock)
Definition: spinlock.c:55
wait.h
tssStruct::esp
long esp
Definition: tss.h:50
kpanic.h
taskStruct::id
pidType id
Definition: sched.h:63
schedFindTask
kTask_t * schedFindTask(uInt32 id)
Definition: sched.c:207
UNINTERRUPTIBLE
Definition: sched.h:47
save_flags
#define save_flags(x)
Definition: wait.h:48
kprintf.h
tssStruct::ss
short ss
Definition: tss.h:58
uint32_t
__uint32_t uint32_t
Definition: types.h:46
osInfo::v86Task
uInt8 v86Task
Definition: sched.h:52
taskStruct::usedMath
uInt16 usedMath
Definition: sched.h:76
taskStruct::parent
struct taskStruct * parent
Definition: sched.h:90
DEAD
Definition: sched.h:47
wake_up
void wake_up(struct wait_queue **q)
Definition: sched.c:360
taskStruct::next
struct taskStruct * next
Definition: sched.h:66
endTask
void endTask(pidType)
Definition: endtask.c:44
_current
kTask_t * _current
Definition: sched.c:50
sched_setStatus
int sched_setStatus(pidType pid, tState state)
Definition: sched.c:265
need_resched
int need_resched
Definition: sched.c:57
pidType
int pidType
Definition: types.h:75
tssStruct::cs
short cs
Definition: tss.h:56
schedNewTask
kTask_t * schedNewTask()
Definition: sched.c:135
wait_queue::task
struct taskStruct * task
Definition: wait.h:35
gdtDescriptor::baseLow
unsigned short baseLow
Definition: gdt.h:68
tssStruct::ebp
long ebp
Definition: tss.h:51
kmalloc
void * kmalloc(uInt32 len)
Definition: kmalloc.c:241
spinLock
Definition: spinlock.h:41
taskStruct::state
tState state
Definition: sched.h:72
descrip.h
taskStruct::last_exit
uint32_t last_exit
Definition: sched.h:89
memset
void * memset(void *dst, int c, size_t length)
gdtDescriptor::baseMed
unsigned char baseMed
Definition: gdt.h:69
gdtDescriptor::baseHigh
unsigned char baseHigh
Definition: gdt.h:73
READY
Definition: sched.h:47
mount.h
taskStruct::children
uint32_t children
Definition: sched.h:88
wait_queue::next
struct wait_queue * next
Definition: wait.h:36
_null.h
cli
#define cli()
Definition: wait.h:45
wait_queue
Definition: wait.h:34
kprintf
int kprintf(const char *,...)
Definition: kprintf.c:259
sched_deleteTask
int sched_deleteTask(pidType id)
Definition: sched.c:167
INTERRUPTIBLE
Definition: sched.h:47
spinTryLock
int spinTryLock(spinLock_t *lock)
Definition: spinlock.c:47
kmalloc.h
taskStruct::oInfo
struct osInfo oInfo
Definition: sched.h:69
sched_getDelTask
kTask_t * sched_getDelTask()
Definition: sched.c:195
tState
tState
Definition: sched.h:46
sched
void sched()
Definition: sched.c:80
sched_yield
void sched_yield()
Definition: sched.c:244
NULL
#define NULL
Definition: fat_string.h:17