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