UbixOS  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 
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 
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 
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 
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 
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