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