This source file includes following definitions.
- show_task
- show_stat
- math_state_restore
- schedule
- sys_pause
- sleep_on
- interruptible_sleep_on
- wake_up
- ticks_to_floppy_on
- floppy_on
- floppy_off
- do_floppy_timer
- add_timer
- do_timer
- sys_alarm
- sys_getpid
- sys_getppid
- sys_getuid
- sys_geteuid
- sys_getgid
- sys_getegid
- sys_nice
- sched_init
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/sched.h>
14 #include <linux/kernel.h>
15 #include <linux/sys.h>
16 #include <linux/fdreg.h>
17 #include <asm/system.h>
18 #include <asm/io.h>
19 #include <asm/segment.h>
20
21 #include <signal.h>
22
23 #define _S(nr) (1<<((nr)-1))
24 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
25
26 void show_task(int nr,struct task_struct * p)
27 {
28 int i,j = 4096-sizeof(struct task_struct);
29
30 printk("%d: pid=%d, state=%d, ",nr,p->pid,p->state);
31 i=0;
32 while (i<j && !((char *)(p+1))[i])
33 i++;
34 printk("%d (of %d) chars free in kernel stack\n\r",i,j);
35 }
36
37 void show_stat(void)
38 {
39 int i;
40
41 for (i=0;i<NR_TASKS;i++)
42 if (task[i])
43 show_task(i,task[i]);
44 }
45
46 #define LATCH (1193180/HZ)
47
48 extern void mem_use(void);
49
50 extern int timer_interrupt(void);
51 extern int system_call(void);
52
53 union task_union {
54 struct task_struct task;
55 char stack[PAGE_SIZE];
56 };
57
58 static union task_union init_task = {INIT_TASK,};
59
60 long volatile jiffies=0;
61 long startup_time=0;
62 struct task_struct *current = &(init_task.task);
63 struct task_struct *last_task_used_math = NULL;
64
65 struct task_struct * task[NR_TASKS] = {&(init_task.task), };
66
67 long user_stack [ PAGE_SIZE>>2 ] ;
68
69 struct {
70 long * a;
71 short b;
72 } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
73
74
75
76
77 void math_state_restore()
78 {
79 if (last_task_used_math == current)
80 return;
81 __asm__("fwait");
82 if (last_task_used_math) {
83 __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
84 }
85 last_task_used_math=current;
86 if (current->used_math) {
87 __asm__("frstor %0"::"m" (current->tss.i387));
88 } else {
89 __asm__("fninit"::);
90 current->used_math=1;
91 }
92 }
93
94
95
96
97
98
99
100
101
102
103
104 void schedule(void)
105 {
106 int i,next,c;
107 struct task_struct ** p;
108
109
110
111 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
112 if (*p) {
113 if ((*p)->alarm && (*p)->alarm < jiffies) {
114 (*p)->signal |= (1<<(SIGALRM-1));
115 (*p)->alarm = 0;
116 }
117 if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
118 (*p)->state==TASK_INTERRUPTIBLE)
119 (*p)->state=TASK_RUNNING;
120 }
121
122
123
124 while (1) {
125 c = -1;
126 next = 0;
127 i = NR_TASKS;
128 p = &task[NR_TASKS];
129 while (--i) {
130 if (!*--p)
131 continue;
132 if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
133 c = (*p)->counter, next = i;
134 }
135 if (c) break;
136 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
137 if (*p)
138 (*p)->counter = ((*p)->counter >> 1) +
139 (*p)->priority;
140 }
141 switch_to(next);
142 }
143
144 int sys_pause(void)
145 {
146 current->state = TASK_INTERRUPTIBLE;
147 schedule();
148 return 0;
149 }
150
151 void sleep_on(struct task_struct **p)
152 {
153 struct task_struct *tmp;
154
155 if (!p)
156 return;
157 if (current == &(init_task.task))
158 panic("task[0] trying to sleep");
159 tmp = *p;
160 *p = current;
161 current->state = TASK_UNINTERRUPTIBLE;
162 schedule();
163 if (tmp)
164 tmp->state=0;
165 }
166
167 void interruptible_sleep_on(struct task_struct **p)
168 {
169 struct task_struct *tmp;
170
171 if (!p)
172 return;
173 if (current == &(init_task.task))
174 panic("task[0] trying to sleep");
175 tmp=*p;
176 *p=current;
177 repeat: current->state = TASK_INTERRUPTIBLE;
178 schedule();
179 if (*p && *p != current) {
180 (**p).state=0;
181 goto repeat;
182 }
183 *p=NULL;
184 if (tmp)
185 tmp->state=0;
186 }
187
188 void wake_up(struct task_struct **p)
189 {
190 if (p && *p) {
191 (**p).state=0;
192 *p=NULL;
193 }
194 }
195
196
197
198
199
200
201 static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
202 static int mon_timer[4]={0,0,0,0};
203 static int moff_timer[4]={0,0,0,0};
204 unsigned char current_DOR = 0x0C;
205
206 int ticks_to_floppy_on(unsigned int nr)
207 {
208 extern unsigned char selected;
209 unsigned char mask = 0x10 << nr;
210
211 if (nr>3)
212 panic("floppy_on: nr>3");
213 moff_timer[nr]=10000;
214 cli();
215 mask |= current_DOR;
216 if (!selected) {
217 mask &= 0xFC;
218 mask |= nr;
219 }
220 if (mask != current_DOR) {
221 outb(mask,FD_DOR);
222 if ((mask ^ current_DOR) & 0xf0)
223 mon_timer[nr] = HZ/2;
224 else if (mon_timer[nr] < 2)
225 mon_timer[nr] = 2;
226 current_DOR = mask;
227 }
228 sti();
229 return mon_timer[nr];
230 }
231
232 void floppy_on(unsigned int nr)
233 {
234 cli();
235 while (ticks_to_floppy_on(nr))
236 sleep_on(nr+wait_motor);
237 sti();
238 }
239
240 void floppy_off(unsigned int nr)
241 {
242 moff_timer[nr]=3*HZ;
243 }
244
245 void do_floppy_timer(void)
246 {
247 int i;
248 unsigned char mask = 0x10;
249
250 for (i=0 ; i<4 ; i++,mask <<= 1) {
251 if (!(mask & current_DOR))
252 continue;
253 if (mon_timer[i]) {
254 if (!--mon_timer[i])
255 wake_up(i+wait_motor);
256 } else if (!moff_timer[i]) {
257 current_DOR &= ~mask;
258 outb(current_DOR,FD_DOR);
259 } else
260 moff_timer[i]--;
261 }
262 }
263
264 #define TIME_REQUESTS 64
265
266 static struct timer_list {
267 long jiffies;
268 void (*fn)();
269 struct timer_list * next;
270 } timer_list[TIME_REQUESTS], * next_timer = NULL;
271
272 void add_timer(long jiffies, void (*fn)(void))
273 {
274 struct timer_list * p;
275
276 if (!fn)
277 return;
278 cli();
279 if (jiffies <= 0)
280 (fn)();
281 else {
282 for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
283 if (!p->fn)
284 break;
285 if (p >= timer_list + TIME_REQUESTS)
286 panic("No more time requests free");
287 p->fn = fn;
288 p->jiffies = jiffies;
289 p->next = next_timer;
290 next_timer = p;
291 while (p->next && p->next->jiffies < p->jiffies) {
292 p->jiffies -= p->next->jiffies;
293 fn = p->fn;
294 p->fn = p->next->fn;
295 p->next->fn = fn;
296 jiffies = p->jiffies;
297 p->jiffies = p->next->jiffies;
298 p->next->jiffies = jiffies;
299 p = p->next;
300 }
301 }
302 sti();
303 }
304
305 void do_timer(long cpl)
306 {
307 extern int beepcount;
308 extern void sysbeepstop(void);
309
310 if (beepcount)
311 if (!--beepcount)
312 sysbeepstop();
313
314 if (cpl)
315 current->utime++;
316 else
317 current->stime++;
318
319 if (next_timer) {
320 next_timer->jiffies--;
321 while (next_timer && next_timer->jiffies <= 0) {
322 void (*fn)(void);
323
324 fn = next_timer->fn;
325 next_timer->fn = NULL;
326 next_timer = next_timer->next;
327 (fn)();
328 }
329 }
330 if (current_DOR & 0xf0)
331 do_floppy_timer();
332 if ((--current->counter)>0) return;
333 current->counter=0;
334 if (!cpl) return;
335 schedule();
336 }
337
338 int sys_alarm(long seconds)
339 {
340 int old = current->alarm;
341
342 if (old)
343 old = (old - jiffies) / HZ;
344 current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
345 return (old);
346 }
347
348 int sys_getpid(void)
349 {
350 return current->pid;
351 }
352
353 int sys_getppid(void)
354 {
355 return current->father;
356 }
357
358 int sys_getuid(void)
359 {
360 return current->uid;
361 }
362
363 int sys_geteuid(void)
364 {
365 return current->euid;
366 }
367
368 int sys_getgid(void)
369 {
370 return current->gid;
371 }
372
373 int sys_getegid(void)
374 {
375 return current->egid;
376 }
377
378 int sys_nice(long increment)
379 {
380 if (current->priority-increment>0)
381 current->priority -= increment;
382 return 0;
383 }
384
385 void sched_init(void)
386 {
387 int i;
388 struct desc_struct * p;
389
390 if (sizeof(struct sigaction) != 16)
391 panic("Struct sigaction MUST be 16 bytes");
392 set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
393 set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
394 p = gdt+2+FIRST_TSS_ENTRY;
395 for(i=1;i<NR_TASKS;i++) {
396 task[i] = NULL;
397 p->a=p->b=0;
398 p++;
399 p->a=p->b=0;
400 p++;
401 }
402
403 __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
404 ltr(0);
405 lldt(0);
406 outb_p(0x36,0x43);
407 outb_p(LATCH & 0xff , 0x40);
408 outb(LATCH >> 8 , 0x40);
409 set_intr_gate(0x20,&timer_interrupt);
410 outb(inb_p(0x21)&~0x01,0x21);
411 set_system_gate(0x80,&system_call);
412 }