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