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