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