kern

view src/sched.c @ 55:88a6c4e192f9

Fixed most important task switching bugs. Now it seems that I can switch in and out of user space reliably.
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 15 Aug 2011 04:03:39 +0300
parents 23abbeea4d5f
children 0be4615594df
line source
1 #include <stdio.h>
2 #include <assert.h>
3 #include "sched.h"
4 #include "proc.h"
5 #include "intr.h"
6 #include "asmops.h"
7 #include "config.h"
9 #define EMPTY(q) ((q)->head == 0)
11 struct proc_list {
12 struct process *head, *tail;
13 };
15 static void idle_proc(void);
16 static void ins_back(struct proc_list *list, struct process *proc);
17 static void ins_front(struct proc_list *list, struct process *proc);
18 static void remove(struct proc_list *list, struct process *proc);
19 static int hash_addr(void *addr);
21 static struct proc_list runq;
22 static struct proc_list zombieq;
24 #define HTBL_SIZE 101
25 static struct proc_list wait_htable[HTBL_SIZE];
28 void schedule(void)
29 {
30 disable_intr();
32 if(EMPTY(&runq)) {
33 idle_proc();
34 /* this won't return, it'll just wake up in an interrupt later */
35 }
37 /* if the current process exhausted its timeslice,
38 * move it to the back of the queue.
39 */
40 if(runq.head->ticks_left <= 0) {
41 if(runq.head->next) {
42 struct process *proc = runq.head;
43 remove(&runq, proc);
44 ins_back(&runq, proc);
45 }
47 /* start a new timeslice */
48 runq.head->ticks_left = TIMESLICE_TICKS;
49 }
51 /* always enter context_switch with interrupts disabled */
52 context_switch(runq.head->id);
53 }
55 void add_proc(int pid)
56 {
57 int istate;
58 struct process *proc;
60 istate = get_intr_state();
61 disable_intr();
63 proc = get_process(pid);
65 ins_back(&runq, proc);
66 proc->state = STATE_RUNNABLE;
68 set_intr_state(istate);
69 }
71 /* block the process until we get a wakeup call for address ev */
72 void wait(void *wait_addr)
73 {
74 struct process *p;
75 int hash_idx;
77 disable_intr();
79 p = get_current_proc();
80 assert(p);
82 /* remove it from the runqueue ... */
83 remove(&runq, p);
85 /* and place it in the wait hash table based on sleep_addr */
86 hash_idx = hash_addr(wait_addr);
87 ins_back(wait_htable + hash_idx, p);
89 p->state = STATE_BLOCKED;
90 p->wait_addr = wait_addr;
91 }
93 /* wake up all the processes sleeping on this address */
94 void wakeup(void *wait_addr)
95 {
96 int hash_idx;
97 struct process *iter;
98 struct proc_list *list;
100 hash_idx = hash_addr(wait_addr);
101 list = wait_htable + hash_idx;
103 iter = list->head;
104 while(iter) {
105 if(iter->wait_addr == wait_addr) {
106 /* found one, remove it, and make it runnable */
107 struct process *p = iter;
108 iter = iter->next;
110 remove(list, p);
111 p->state = STATE_RUNNABLE;
112 ins_back(&runq, p);
113 } else {
114 iter = iter->next;
115 }
116 }
117 }
119 static void idle_proc(void)
120 {
121 /* make sure we send any pending EOIs if needed.
122 * end_of_irq will actually check if it's needed first.
123 */
124 struct intr_frame *ifrm = get_intr_frame();
125 end_of_irq(INTR_TO_IRQ(ifrm->inum));
127 /* make sure interrupts are enabled before halting */
128 enable_intr();
129 halt_cpu();
130 }
133 /* list operations */
134 static void ins_back(struct proc_list *list, struct process *proc)
135 {
136 if(EMPTY(list)) {
137 list->head = proc;
138 } else {
139 list->tail->next = proc;
140 }
142 proc->next = 0;
143 proc->prev = list->tail;
144 list->tail = proc;
145 }
147 static void ins_front(struct proc_list *list, struct process *proc)
148 {
149 if(EMPTY(list)) {
150 list->tail = proc;
151 } else {
152 list->head->prev = proc;
153 }
155 proc->next = list->head;
156 proc->prev = 0;
157 list->head = proc;
158 }
160 static void remove(struct proc_list *list, struct process *proc)
161 {
162 if(proc->prev) {
163 proc->prev->next = proc->next;
164 }
165 if(proc->next) {
166 proc->next->prev = proc->prev;
167 }
168 if(list->head == proc) {
169 list->head = proc->next;
170 }
171 if(list->tail == proc) {
172 list->tail = proc->prev;
173 }
174 }
176 static int hash_addr(void *addr)
177 {
178 return (uint32_t)addr % HTBL_SIZE;
179 }