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