This source file includes following definitions.
- show_task
- show_state
- math_state_restore
- schedule
- sys_pause
- wake_one_task
- wake_up
- __sleep_on
- interruptible_sleep_on
- sleep_on
- ticks_to_floppy_on
- floppy_off
- do_floppy_timer
- add_timer
- update_avg
- 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
14 #define TIMER_IRQ 0
15
16 #include <linux/signal.h>
17 #include <linux/sched.h>
18 #include <linux/timer.h>
19 #include <linux/kernel.h>
20 #include <linux/sys.h>
21 #include <linux/fdreg.h>
22 #include <linux/errno.h>
23 #include <linux/time.h>
24 #include <linux/ptrace.h>
25
26 #include <asm/system.h>
27 #include <asm/io.h>
28 #include <asm/segment.h>
29
30 int need_resched = 0;
31
32 #define _S(nr) (1<<((nr)-1))
33 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
34
35 static void show_task(int nr,struct task_struct * p)
36 {
37 int i,j = 4096-sizeof(struct task_struct);
38
39 printk("%d: pid=%d, state=%d, father=%d, child=%d, ",(p == current)?-nr:nr,p->pid,
40 p->state, p->p_pptr->pid, p->p_cptr ? p->p_cptr->pid : -1);
41 i=0;
42 while (i<j && !((char *)(p+1))[i])
43 i++;
44 printk("%d/%d chars free in kstack\n\r",i,j);
45 printk(" PC=%08X.", *(1019 + (unsigned long *) p));
46 if (p->p_ysptr || p->p_osptr)
47 printk(" Younger sib=%d, older sib=%d\n\r",
48 p->p_ysptr ? p->p_ysptr->pid : -1,
49 p->p_osptr ? p->p_osptr->pid : -1);
50 else
51 printk("\n\r");
52 }
53
54 void show_state(void)
55 {
56 int i;
57
58 printk("\rTask-info:\n\r");
59 for (i=0 ; i<NR_TASKS ; i++)
60 if (task[i])
61 show_task(i,task[i]);
62 }
63
64 #define LATCH (1193180/HZ)
65
66 extern void mem_use(void);
67
68 extern int timer_interrupt(void);
69 extern int system_call(void);
70
71 union task_union {
72 struct task_struct task;
73 char stack[PAGE_SIZE];
74 };
75
76 static union task_union init_task = {INIT_TASK, };
77
78 unsigned long volatile jiffies=0;
79 unsigned long startup_time=0;
80 int jiffies_offset = 0;
81
82
83
84
85
86 struct task_struct *current = &(init_task.task);
87 struct task_struct *last_task_used_math = NULL;
88
89 struct task_struct * task[NR_TASKS] = {&(init_task.task), };
90
91 long user_stack [ PAGE_SIZE>>2 ] ;
92
93 struct {
94 long * a;
95 short b;
96 } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
97
98
99
100
101 void math_state_restore()
102 {
103 if (last_task_used_math == current)
104 return;
105 __asm__("fwait");
106 if (last_task_used_math) {
107 __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
108 }
109 last_task_used_math=current;
110 if (current->used_math) {
111 __asm__("frstor %0"::"m" (current->tss.i387));
112 } else {
113 __asm__("fninit"::);
114 current->used_math=1;
115 }
116 }
117
118
119
120
121
122
123
124
125
126
127 void schedule(void)
128 {
129 int i,next,c;
130 struct task_struct ** p;
131
132
133
134 need_resched = 0;
135 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
136 if (*p) {
137 if ((*p)->timeout && (*p)->timeout < jiffies)
138 if ((*p)->state == TASK_INTERRUPTIBLE) {
139 (*p)->timeout = 0;
140 wake_one_task(*p);
141 }
142 if (((*p)->signal & ~(*p)->blocked) &&
143 (*p)->state==TASK_INTERRUPTIBLE)
144 wake_one_task(*p);
145 }
146
147
148
149 while (1) {
150 c = -1;
151 next = 0;
152 i = NR_TASKS;
153 p = &task[NR_TASKS];
154 while (--i) {
155 if (!*--p)
156 continue;
157 if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
158 c = (*p)->counter, next = i;
159 }
160 if (c) break;
161 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
162 if (*p)
163 (*p)->counter = ((*p)->counter >> 1) +
164 (*p)->priority;
165 }
166 switch_to(next);
167 }
168
169 int sys_pause(void)
170 {
171 unsigned long old_blocked;
172 unsigned long mask;
173 struct sigaction * sa = current->sigaction;
174
175 old_blocked = current->blocked;
176 for (mask=1 ; mask ; sa++,mask += mask)
177 if (sa->sa_handler == SIG_IGN)
178 current->blocked |= mask;
179 current->state = TASK_INTERRUPTIBLE;
180 schedule();
181 current->blocked = old_blocked;
182 return -EINTR;
183 }
184
185 void wake_one_task(struct task_struct * p)
186 {
187 p->state = TASK_RUNNING;
188 if (p->counter > current->counter)
189 need_resched = 1;
190 }
191
192
193
194
195
196 void wake_up(struct wait_queue **q)
197 {
198 struct wait_queue *tmp, *next;
199 struct task_struct * p;
200 unsigned long flags;
201
202 if (!q || !(next = *q))
203 return;
204 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
205 do {
206 tmp = next;
207 next = tmp->next;
208 if (p = tmp->task) {
209 if (p->state == TASK_ZOMBIE)
210 printk("wake_up: TASK_ZOMBIE\n");
211 else if (p->state != TASK_STOPPED) {
212 p->state = TASK_RUNNING;
213 if (p->counter > current->counter)
214 need_resched = 1;
215 }
216 }
217 tmp->next = NULL;
218 } while (next && next != *q);
219 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
220 }
221
222 static inline void __sleep_on(struct wait_queue **p, int state)
223 {
224 unsigned long flags;
225
226 if (!p)
227 return;
228 if (current == task[0])
229 panic("task[0] trying to sleep");
230 if (current->wait.next)
231 printk("__sleep_on: wait->next exists\n");
232 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
233 current->state = state;
234 add_wait_queue(p,¤t->wait);
235 sti();
236 schedule();
237 remove_wait_queue(p,¤t->wait);
238 __asm__("pushl %0 ; popfl"::"r" (flags));
239 }
240
241 void interruptible_sleep_on(struct wait_queue **p)
242 {
243 __sleep_on(p,TASK_INTERRUPTIBLE);
244 }
245
246 void sleep_on(struct wait_queue **p)
247 {
248 __sleep_on(p,TASK_UNINTERRUPTIBLE);
249 }
250
251
252
253
254
255
256 static struct wait_queue * wait_motor[4] = {NULL,NULL,NULL,NULL};
257 static int mon_timer[4]={0,0,0,0};
258 static int moff_timer[4]={0,0,0,0};
259 unsigned char current_DOR = 0x0C;
260
261 int ticks_to_floppy_on(unsigned int nr)
262 {
263 extern unsigned char selected;
264 unsigned char mask = 0x10 << nr;
265
266 if (nr>3)
267 panic("floppy_on: nr>3");
268 moff_timer[nr]=10000;
269 cli();
270 mask |= current_DOR;
271 if (!selected) {
272 mask &= 0xFC;
273 mask |= nr;
274 }
275 if (mask != current_DOR) {
276 outb(mask,FD_DOR);
277 if ((mask ^ current_DOR) & 0xf0)
278 mon_timer[nr] = HZ/2;
279 else if (mon_timer[nr] < 2)
280 mon_timer[nr] = 2;
281 current_DOR = mask;
282 }
283 sti();
284 return mon_timer[nr];
285 }
286
287 void floppy_off(unsigned int nr)
288 {
289 moff_timer[nr]=3*HZ;
290 }
291
292 void do_floppy_timer(void)
293 {
294 int i;
295 unsigned char mask = 0x10;
296
297 for (i=0 ; i<4 ; i++,mask <<= 1) {
298 if (!(mask & current_DOR))
299 continue;
300 if (mon_timer[i]) {
301 if (!--mon_timer[i])
302 wake_up(i+wait_motor);
303 } else if (!moff_timer[i]) {
304 current_DOR &= ~mask;
305 outb(current_DOR,FD_DOR);
306 } else
307 moff_timer[i]--;
308 }
309 }
310
311 #define TIME_REQUESTS 64
312
313 static struct timer_list {
314 long jiffies;
315 void (*fn)();
316 struct timer_list * next;
317 } timer_list[TIME_REQUESTS] = { { 0, NULL, NULL }, };
318
319 static struct timer_list * next_timer = NULL;
320
321 void add_timer(long jiffies, void (*fn)(void))
322 {
323 struct timer_list * p;
324
325 if (!fn)
326 return;
327 cli();
328 if (jiffies <= 0)
329 (fn)();
330 else {
331 for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
332 if (!p->fn)
333 break;
334 if (p >= timer_list + TIME_REQUESTS)
335 panic("No more time requests free");
336 p->fn = fn;
337 p->jiffies = jiffies;
338 p->next = next_timer;
339 next_timer = p;
340 while (p->next && p->next->jiffies < p->jiffies) {
341 p->jiffies -= p->next->jiffies;
342 fn = p->fn;
343 p->fn = p->next->fn;
344 p->next->fn = fn;
345 jiffies = p->jiffies;
346 p->jiffies = p->next->jiffies;
347 p->next->jiffies = jiffies;
348 p = p->next;
349 }
350 }
351 sti();
352 }
353
354 #define FSHIFT 11
355 #define FSCALE (1<<FSHIFT)
356
357
358
359
360 static unsigned long cexp[3] = {
361 1884,
362 2014,
363 2037,
364 };
365 unsigned long averunnable[3] = { 0, };
366
367 void update_avg(void)
368 {
369 int i, n=0;
370 struct task_struct **p;
371
372 for(p = &LAST_TASK; p > &FIRST_TASK; --p)
373 if (*p && ((*p)->state == TASK_RUNNING ||
374 (*p)->state == TASK_UNINTERRUPTIBLE))
375 ++n;
376
377 for (i = 0; i < 3; ++i)
378 averunnable[i] = (cexp[i] * averunnable[i] +
379 n * FSCALE * (FSCALE - cexp[i])) >> FSHIFT;
380 }
381
382 unsigned long timer_active = 0;
383 struct timer_struct timer_table[32];
384
385
386
387
388
389
390
391 static void do_timer(int regs)
392 {
393 unsigned long mask;
394 struct timer_struct *tp = timer_table+0;
395 struct task_struct ** task_p;
396 static int avg_cnt = 0;
397
398 jiffies++;
399 if (3 & ((struct pt_regs *) regs)->cs)
400 current->utime++;
401 else {
402 current->stime++;
403
404 if (current->it_virt_value && !(--current->it_virt_value)) {
405 current->it_virt_value = current->it_virt_incr;
406 send_sig(SIGVTALRM,current,1);
407 }
408 }
409 if (--avg_cnt < 0) {
410 avg_cnt = 500;
411 update_avg();
412 }
413 if ((--current->counter)<=0) {
414 current->counter=0;
415 need_resched = 1;
416 }
417
418 for (task_p = &LAST_TASK; task_p >= &FIRST_TASK; task_p--)
419 if (*task_p && (*task_p)->it_real_value
420 && !(--(*task_p)->it_real_value)) {
421 send_sig(SIGALRM,*task_p,1);
422 (*task_p)->it_real_value = (*task_p)->it_real_incr;
423 need_resched = 1;
424 }
425
426 if (current->it_prof_value && !(--current->it_prof_value)) {
427 current->it_prof_value = current->it_prof_incr;
428 send_sig(SIGPROF,current,1);
429 }
430 for (mask = 1 ; mask ; tp++,mask += mask) {
431 if (mask > timer_active)
432 break;
433 if (!(mask & timer_active))
434 continue;
435 if (tp->expires > jiffies)
436 continue;
437 timer_active &= ~mask;
438 tp->fn();
439 sti();
440 }
441 if (next_timer) {
442 next_timer->jiffies--;
443 while (next_timer && next_timer->jiffies <= 0) {
444 void (*fn)(void);
445
446 fn = next_timer->fn;
447 next_timer->fn = NULL;
448 next_timer = next_timer->next;
449 (fn)();
450 }
451 }
452 if (current_DOR & 0xf0)
453 do_floppy_timer();
454 }
455
456 int sys_alarm(long seconds)
457 {
458 extern int _setitimer(int, struct itimerval *, struct itimerval *);
459 struct itimerval new, old;
460
461 new.it_interval.tv_sec = new.it_interval.tv_usec = 0;
462 new.it_value.tv_sec = seconds;
463 new.it_value.tv_usec = 0;
464 _setitimer(ITIMER_REAL, &new, &old);
465 return(old.it_value.tv_sec + (old.it_value.tv_usec / 1000000));
466 }
467
468 int sys_getpid(void)
469 {
470 return current->pid;
471 }
472
473 int sys_getppid(void)
474 {
475 return current->p_pptr->pid;
476 }
477
478 int sys_getuid(void)
479 {
480 return current->uid;
481 }
482
483 int sys_geteuid(void)
484 {
485 return current->euid;
486 }
487
488 int sys_getgid(void)
489 {
490 return current->gid;
491 }
492
493 int sys_getegid(void)
494 {
495 return current->egid;
496 }
497
498 int sys_nice(long increment)
499 {
500 if (increment < 0 && !suser())
501 return -EPERM;
502 if (increment >= current->priority)
503 increment = current->priority-1;
504 current->priority -= increment;
505 return 0;
506 }
507
508 void sched_init(void)
509 {
510 int i;
511 struct desc_struct * p;
512
513 if (sizeof(struct sigaction) != 16)
514 panic("Struct sigaction MUST be 16 bytes");
515 set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
516 set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
517 set_system_gate(0x80,&system_call);
518 p = gdt+2+FIRST_TSS_ENTRY;
519 for(i=1 ; i<NR_TASKS ; i++) {
520 task[i] = NULL;
521 p->a=p->b=0;
522 p++;
523 p->a=p->b=0;
524 p++;
525 }
526
527 __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
528 ltr(0);
529 lldt(0);
530 outb_p(0x36,0x43);
531 outb_p(LATCH & 0xff , 0x40);
532 outb(LATCH >> 8 , 0x40);
533 request_irq(TIMER_IRQ,do_timer);
534 }