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