rev |
line source |
nuclear@51
|
1 #include <stdio.h>
|
nuclear@51
|
2 #include "sched.h"
|
nuclear@51
|
3 #include "proc.h"
|
nuclear@51
|
4 #include "intr.h"
|
nuclear@51
|
5 #include "asmops.h"
|
nuclear@51
|
6 #include "config.h"
|
nuclear@51
|
7
|
nuclear@51
|
8 #define EMPTY(q) ((q).head == 0)
|
nuclear@51
|
9
|
nuclear@51
|
10 struct proc_list {
|
nuclear@51
|
11 struct process *head, *tail;
|
nuclear@51
|
12 };
|
nuclear@51
|
13
|
nuclear@51
|
14 static void ins_back(struct proc_list *q, struct process *proc);
|
nuclear@51
|
15 static void ins_front(struct proc_list *q, struct process *proc);
|
nuclear@51
|
16 static void remove(struct proc_list *q, struct process *proc);
|
nuclear@51
|
17
|
nuclear@51
|
18 static struct proc_list runq;
|
nuclear@51
|
19 static struct proc_list waitq;
|
nuclear@51
|
20 static struct proc_list zombieq;
|
nuclear@51
|
21
|
nuclear@51
|
22 void schedule(void)
|
nuclear@51
|
23 {
|
nuclear@52
|
24 disable_intr();
|
nuclear@52
|
25
|
nuclear@51
|
26 if(EMPTY(runq)) {
|
nuclear@51
|
27 /* idle "process".
|
nuclear@51
|
28 * make sure interrupts are enabled before halting
|
nuclear@51
|
29 */
|
nuclear@51
|
30 enable_intr();
|
nuclear@51
|
31 halt_cpu();
|
nuclear@52
|
32 printf("fuck you!\n");
|
nuclear@51
|
33 /* this won't return, it'll just wake up in an interrupt later */
|
nuclear@51
|
34 }
|
nuclear@51
|
35
|
nuclear@51
|
36 /* if the current process exhausted its timeslice,
|
nuclear@51
|
37 * move it to the back of the queue.
|
nuclear@51
|
38 */
|
nuclear@51
|
39 if(runq.head->ticks_left <= 0) {
|
nuclear@51
|
40 if(runq.head->next) {
|
nuclear@51
|
41 struct process *proc = runq.head;
|
nuclear@51
|
42 remove(&runq, proc);
|
nuclear@51
|
43 ins_back(&runq, proc);
|
nuclear@51
|
44 }
|
nuclear@51
|
45
|
nuclear@51
|
46 /* start a new timeslice */
|
nuclear@51
|
47 runq.head->ticks_left = TIMESLICE_TICKS;
|
nuclear@51
|
48 }
|
nuclear@51
|
49
|
nuclear@51
|
50 /* no need to re-enable interrupts, they will be enabled with the iret */
|
nuclear@51
|
51 context_switch(runq.head->id);
|
nuclear@51
|
52 }
|
nuclear@51
|
53
|
nuclear@51
|
54 int add_proc(int pid, enum proc_state state)
|
nuclear@51
|
55 {
|
nuclear@51
|
56 int istate;
|
nuclear@51
|
57 struct proc_list *q;
|
nuclear@52
|
58 struct process *proc;
|
nuclear@51
|
59
|
nuclear@51
|
60 istate = get_intr_state();
|
nuclear@51
|
61 disable_intr();
|
nuclear@51
|
62
|
nuclear@52
|
63 proc = get_process(pid);
|
nuclear@52
|
64
|
nuclear@53
|
65 q = state == STATE_RUNNABLE ? &runq : &waitq;
|
nuclear@51
|
66
|
nuclear@51
|
67 ins_back(q, proc);
|
nuclear@51
|
68 proc->state = state;
|
nuclear@51
|
69
|
nuclear@51
|
70 set_intr_state(istate);
|
nuclear@51
|
71 return 0;
|
nuclear@51
|
72 }
|
nuclear@51
|
73
|
nuclear@51
|
74 int block_proc(int pid)
|
nuclear@51
|
75 {
|
nuclear@51
|
76 int istate;
|
nuclear@51
|
77 struct process *proc = get_process(pid);
|
nuclear@51
|
78
|
nuclear@53
|
79 if(proc->state != STATE_RUNNABLE) {
|
nuclear@51
|
80 printf("block_proc: process %d not running\n", pid);
|
nuclear@51
|
81 return -1;
|
nuclear@51
|
82 }
|
nuclear@51
|
83
|
nuclear@51
|
84 istate = get_intr_state();
|
nuclear@51
|
85 disable_intr();
|
nuclear@51
|
86
|
nuclear@51
|
87 remove(&runq, proc);
|
nuclear@51
|
88 ins_back(&waitq, proc);
|
nuclear@51
|
89 proc->state = STATE_BLOCKED;
|
nuclear@51
|
90
|
nuclear@51
|
91 set_intr_state(istate);
|
nuclear@51
|
92 return 0;
|
nuclear@51
|
93 }
|
nuclear@51
|
94
|
nuclear@51
|
95 int unblock_proc(int pid)
|
nuclear@51
|
96 {
|
nuclear@51
|
97 int istate;
|
nuclear@51
|
98 struct process *proc = get_process(pid);
|
nuclear@51
|
99
|
nuclear@51
|
100 if(proc->state != STATE_BLOCKED) {
|
nuclear@51
|
101 printf("unblock_proc: process %d not blocked\n", pid);
|
nuclear@51
|
102 return -1;
|
nuclear@51
|
103 }
|
nuclear@51
|
104
|
nuclear@51
|
105 istate = get_intr_state();
|
nuclear@51
|
106 disable_intr();
|
nuclear@51
|
107
|
nuclear@51
|
108 remove(&waitq, proc);
|
nuclear@51
|
109 ins_back(&runq, proc);
|
nuclear@53
|
110 proc->state = STATE_RUNNABLE;
|
nuclear@51
|
111
|
nuclear@51
|
112 set_intr_state(istate);
|
nuclear@51
|
113 return 0;
|
nuclear@51
|
114 }
|
nuclear@51
|
115
|
nuclear@51
|
116
|
nuclear@51
|
117 static void ins_back(struct proc_list *q, struct process *proc)
|
nuclear@51
|
118 {
|
nuclear@51
|
119 if(EMPTY(*q)) {
|
nuclear@51
|
120 q->head = proc;
|
nuclear@51
|
121 } else {
|
nuclear@51
|
122 q->tail->next = proc;
|
nuclear@51
|
123 }
|
nuclear@51
|
124
|
nuclear@51
|
125 proc->next = 0;
|
nuclear@51
|
126 proc->prev = q->tail;
|
nuclear@51
|
127 q->tail = proc;
|
nuclear@51
|
128 }
|
nuclear@51
|
129
|
nuclear@51
|
130 static void ins_front(struct proc_list *q, struct process *proc)
|
nuclear@51
|
131 {
|
nuclear@51
|
132 if(EMPTY(*q)) {
|
nuclear@51
|
133 q->tail = proc;
|
nuclear@51
|
134 } else {
|
nuclear@51
|
135 q->head->prev = proc;
|
nuclear@51
|
136 }
|
nuclear@51
|
137
|
nuclear@51
|
138 proc->next = q->head;
|
nuclear@51
|
139 proc->prev = 0;
|
nuclear@51
|
140 q->head = proc;
|
nuclear@51
|
141 }
|
nuclear@51
|
142
|
nuclear@51
|
143 static void remove(struct proc_list *q, struct process *proc)
|
nuclear@51
|
144 {
|
nuclear@51
|
145 if(proc->prev) {
|
nuclear@51
|
146 proc->prev->next = proc->next;
|
nuclear@51
|
147 }
|
nuclear@51
|
148 if(proc->next) {
|
nuclear@51
|
149 proc->next->prev = proc->prev;
|
nuclear@51
|
150 }
|
nuclear@51
|
151 if(q->head == proc) {
|
nuclear@51
|
152 q->head = proc->next;
|
nuclear@51
|
153 }
|
nuclear@51
|
154 if(q->tail == proc) {
|
nuclear@51
|
155 q->tail = proc->prev;
|
nuclear@51
|
156 }
|
nuclear@51
|
157 }
|