|
|
1.1 root 1: /*
1.1.1.2 root 2: * linux/kernel/sched.c
3: *
4: * (C) 1991 Linus Torvalds
5: */
6:
7: /*
1.1 root 8: * 'sched.c' is the main kernel file. It contains scheduling primitives
9: * (sleep_on, wakeup, schedule etc) as well as a number of simple system
10: * call functions (type getpid(), which just extracts a field from
11: * current-task
12: */
13: #include <linux/sched.h>
1.1.1.5 root 14: #include <linux/timer.h>
1.1 root 15: #include <linux/kernel.h>
16: #include <linux/sys.h>
1.1.1.2 root 17: #include <linux/fdreg.h>
1.1 root 18: #include <asm/system.h>
19: #include <asm/io.h>
20: #include <asm/segment.h>
21:
1.1.1.2 root 22: #include <signal.h>
1.1.1.5 root 23: #include <errno.h>
1.1.1.2 root 24:
25: #define _S(nr) (1<<((nr)-1))
26: #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
27:
28: void show_task(int nr,struct task_struct * p)
29: {
1.1.1.3 root 30: int i,j = 4096-sizeof(struct task_struct);
31:
1.1.1.4 root 32: printk("%d: pid=%d, state=%d, father=%d, child=%d, ",nr,p->pid,
33: p->state, p->p_pptr->pid, p->p_cptr ? p->p_cptr->pid : -1);
1.1.1.3 root 34: i=0;
35: while (i<j && !((char *)(p+1))[i])
36: i++;
1.1.1.4 root 37: printk("%d/%d chars free in kstack\n\r",i,j);
38: printk(" PC=%08X.", *(1019 + (unsigned long *) p));
39: if (p->p_ysptr || p->p_osptr)
40: printk(" Younger sib=%d, older sib=%d\n\r",
41: p->p_ysptr ? p->p_ysptr->pid : -1,
42: p->p_osptr ? p->p_osptr->pid : -1);
43: else
44: printk("\n\r");
1.1.1.2 root 45: }
46:
1.1.1.4 root 47: void show_state(void)
1.1.1.2 root 48: {
49: int i;
50:
1.1.1.4 root 51: printk("\rTask-info:\n\r");
1.1.1.2 root 52: for (i=0;i<NR_TASKS;i++)
53: if (task[i])
54: show_task(i,task[i]);
55: }
56:
1.1 root 57: #define LATCH (1193180/HZ)
58:
59: extern void mem_use(void);
60:
61: extern int timer_interrupt(void);
62: extern int system_call(void);
63:
64: union task_union {
65: struct task_struct task;
66: char stack[PAGE_SIZE];
67: };
68:
69: static union task_union init_task = {INIT_TASK,};
70:
1.1.1.4 root 71: unsigned long volatile jiffies=0;
72: unsigned long startup_time=0;
73: int jiffies_offset = 0; /* # clock ticks to add to get "true
74: time". Should always be less than
75: 1 second's worth. For time fanatics
76: who like to syncronize their machines
77: to WWV :-) */
78:
1.1.1.2 root 79: struct task_struct *current = &(init_task.task);
80: struct task_struct *last_task_used_math = NULL;
1.1 root 81:
82: struct task_struct * task[NR_TASKS] = {&(init_task.task), };
83:
84: long user_stack [ PAGE_SIZE>>2 ] ;
85:
86: struct {
87: long * a;
88: short b;
89: } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
90: /*
91: * 'math_state_restore()' saves the current math information in the
92: * old math state array, and gets the new ones from the current task
93: */
94: void math_state_restore()
95: {
1.1.1.2 root 96: if (last_task_used_math == current)
97: return;
1.1.1.3 root 98: __asm__("fwait");
1.1.1.2 root 99: if (last_task_used_math) {
1.1 root 100: __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
1.1.1.2 root 101: }
1.1.1.3 root 102: last_task_used_math=current;
1.1.1.2 root 103: if (current->used_math) {
1.1 root 104: __asm__("frstor %0"::"m" (current->tss.i387));
1.1.1.2 root 105: } else {
1.1 root 106: __asm__("fninit"::);
107: current->used_math=1;
108: }
109: }
110:
111: /*
1.1.1.5 root 112: * 'schedule()' is the scheduler function. It's a very simple and nice
113: * scheduler: it's not perfect, but certainly works for most things.
1.1 root 114: * The one thing you might take a look at is the signal-handler code here.
115: *
116: * NOTE!! Task 0 is the 'idle' task, which gets called when no other
117: * tasks can run. It can not be killed, and it cannot sleep. The 'state'
118: * information in task[0] is never used.
119: */
120: void schedule(void)
121: {
122: int i,next,c;
123: struct task_struct ** p;
124:
125: /* check alarm, wake up any interruptible tasks that have got a signal */
126:
127: for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
128: if (*p) {
1.1.1.6 ! root 129: if ((*p)->timeout && (*p)->timeout < jiffies)
! 130: if ((*p)->state == TASK_INTERRUPTIBLE) {
! 131: (*p)->timeout = 0;
1.1.1.4 root 132: (*p)->state = TASK_RUNNING;
1.1.1.6 ! root 133: }
1.1 root 134: if ((*p)->alarm && (*p)->alarm < jiffies) {
1.1.1.4 root 135: (*p)->signal |= (1<<(SIGALRM-1));
136: (*p)->alarm = 0;
137: }
1.1.1.5 root 138: if (((*p)->signal & ~(*p)->blocked) &&
1.1.1.2 root 139: (*p)->state==TASK_INTERRUPTIBLE)
1.1 root 140: (*p)->state=TASK_RUNNING;
141: }
142:
143: /* this is the scheduler proper: */
144:
145: while (1) {
146: c = -1;
147: next = 0;
148: i = NR_TASKS;
149: p = &task[NR_TASKS];
150: while (--i) {
151: if (!*--p)
152: continue;
153: if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
154: c = (*p)->counter, next = i;
155: }
156: if (c) break;
157: for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
158: if (*p)
159: (*p)->counter = ((*p)->counter >> 1) +
160: (*p)->priority;
161: }
162: switch_to(next);
163: }
164:
165: int sys_pause(void)
166: {
1.1.1.5 root 167: unsigned long old_blocked;
168: unsigned long mask;
169: struct sigaction * sa = current->sigaction;
170:
171: old_blocked = current->blocked;
172: for (mask=1 ; mask ; sa++,mask += mask)
173: if (sa->sa_handler == SIG_IGN)
174: current->blocked |= mask;
1.1 root 175: current->state = TASK_INTERRUPTIBLE;
176: schedule();
1.1.1.5 root 177: current->blocked = old_blocked;
178: return -EINTR;
1.1 root 179: }
180:
1.1.1.6 ! root 181: void wake_up(struct task_struct **p)
! 182: {
! 183: struct task_struct * wakeup_ptr, * tmp;
! 184:
! 185: if (p && *p) {
! 186: wakeup_ptr = *p;
! 187: *p = NULL;
! 188: while (wakeup_ptr && wakeup_ptr != task[0]) {
! 189: if (wakeup_ptr->state == TASK_STOPPED)
! 190: printk("wake_up: TASK_STOPPED\n");
! 191: else if (wakeup_ptr->state == TASK_ZOMBIE)
! 192: printk("wake_up: TASK_ZOMBIE\n");
! 193: else
! 194: wakeup_ptr->state = TASK_RUNNING;
! 195: tmp = wakeup_ptr->next_wait;
! 196: wakeup_ptr->next_wait = task[0];
! 197: wakeup_ptr = tmp;
! 198: }
! 199: }
! 200: }
! 201:
1.1.1.4 root 202: static inline void __sleep_on(struct task_struct **p, int state)
1.1 root 203: {
1.1.1.5 root 204: unsigned int flags;
1.1 root 205:
206: if (!p)
207: return;
1.1.1.6 ! root 208: if (current == task[0])
1.1 root 209: panic("task[0] trying to sleep");
1.1.1.5 root 210: __asm__("pushfl ; popl %0":"=r" (flags));
1.1.1.6 ! root 211: current->next_wait = *p;
! 212: task[0]->next_wait = NULL;
1.1 root 213: *p = current;
1.1.1.4 root 214: current->state = state;
1.1.1.5 root 215: sti();
1.1.1.6 ! root 216: schedule();
! 217: if (current->next_wait != task[0])
! 218: wake_up(p);
! 219: current->next_wait = NULL;
1.1.1.5 root 220: __asm__("pushl %0 ; popfl"::"r" (flags));
1.1 root 221: }
222:
223: void interruptible_sleep_on(struct task_struct **p)
224: {
1.1.1.4 root 225: __sleep_on(p,TASK_INTERRUPTIBLE);
226: }
1.1 root 227:
1.1.1.4 root 228: void sleep_on(struct task_struct **p)
229: {
230: __sleep_on(p,TASK_UNINTERRUPTIBLE);
1.1 root 231: }
232:
1.1.1.2 root 233: /*
234: * OK, here are some floppy things that shouldn't be in the kernel
235: * proper. They are here because the floppy needs a timer, and this
236: * was the easiest way of doing it.
237: */
238: static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
239: static int mon_timer[4]={0,0,0,0};
240: static int moff_timer[4]={0,0,0,0};
241: unsigned char current_DOR = 0x0C;
242:
243: int ticks_to_floppy_on(unsigned int nr)
244: {
1.1.1.3 root 245: extern unsigned char selected;
246: unsigned char mask = 0x10 << nr;
1.1.1.2 root 247:
248: if (nr>3)
249: panic("floppy_on: nr>3");
250: moff_timer[nr]=10000; /* 100 s = very big :-) */
251: cli(); /* use floppy_off to turn it off */
1.1.1.3 root 252: mask |= current_DOR;
253: if (!selected) {
254: mask &= 0xFC;
255: mask |= nr;
256: }
257: if (mask != current_DOR) {
258: outb(mask,FD_DOR);
259: if ((mask ^ current_DOR) & 0xf0)
260: mon_timer[nr] = HZ/2;
261: else if (mon_timer[nr] < 2)
262: mon_timer[nr] = 2;
263: current_DOR = mask;
1.1.1.2 root 264: }
265: sti();
266: return mon_timer[nr];
267: }
268:
269: void floppy_off(unsigned int nr)
270: {
271: moff_timer[nr]=3*HZ;
272: }
273:
274: void do_floppy_timer(void)
275: {
276: int i;
277: unsigned char mask = 0x10;
278:
279: for (i=0 ; i<4 ; i++,mask <<= 1) {
280: if (!(mask & current_DOR))
281: continue;
282: if (mon_timer[i]) {
283: if (!--mon_timer[i])
284: wake_up(i+wait_motor);
285: } else if (!moff_timer[i]) {
286: current_DOR &= ~mask;
287: outb(current_DOR,FD_DOR);
288: } else
289: moff_timer[i]--;
290: }
291: }
292:
293: #define TIME_REQUESTS 64
294:
295: static struct timer_list {
296: long jiffies;
297: void (*fn)();
298: struct timer_list * next;
299: } timer_list[TIME_REQUESTS], * next_timer = NULL;
300:
301: void add_timer(long jiffies, void (*fn)(void))
302: {
303: struct timer_list * p;
304:
305: if (!fn)
306: return;
307: cli();
308: if (jiffies <= 0)
309: (fn)();
310: else {
311: for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
312: if (!p->fn)
313: break;
314: if (p >= timer_list + TIME_REQUESTS)
315: panic("No more time requests free");
316: p->fn = fn;
317: p->jiffies = jiffies;
318: p->next = next_timer;
319: next_timer = p;
320: while (p->next && p->next->jiffies < p->jiffies) {
321: p->jiffies -= p->next->jiffies;
322: fn = p->fn;
323: p->fn = p->next->fn;
324: p->next->fn = fn;
325: jiffies = p->jiffies;
326: p->jiffies = p->next->jiffies;
327: p->next->jiffies = jiffies;
328: p = p->next;
329: }
330: }
331: sti();
332: }
333:
1.1.1.5 root 334: unsigned long timer_active = 0;
335: struct timer_struct timer_table[32];
336:
1.1 root 337: void do_timer(long cpl)
338: {
1.1.1.5 root 339: unsigned long mask;
340: struct timer_struct *tp = timer_table+0;
1.1.1.4 root 341:
1.1.1.5 root 342: for (mask = 1 ; mask ; tp++,mask += mask) {
343: if (mask > timer_active)
344: break;
345: if (!(mask & timer_active))
346: continue;
347: if (tp->expires > jiffies)
348: continue;
349: timer_active &= ~mask;
350: tp->fn();
351: }
1.1.1.3 root 352:
1.1 root 353: if (cpl)
354: current->utime++;
355: else
356: current->stime++;
1.1.1.3 root 357:
1.1.1.2 root 358: if (next_timer) {
359: next_timer->jiffies--;
360: while (next_timer && next_timer->jiffies <= 0) {
361: void (*fn)(void);
362:
363: fn = next_timer->fn;
364: next_timer->fn = NULL;
365: next_timer = next_timer->next;
366: (fn)();
367: }
368: }
369: if (current_DOR & 0xf0)
370: do_floppy_timer();
1.1 root 371: if ((--current->counter)>0) return;
372: current->counter=0;
373: if (!cpl) return;
374: schedule();
375: }
376:
377: int sys_alarm(long seconds)
378: {
1.1.1.2 root 379: int old = current->alarm;
380:
381: if (old)
382: old = (old - jiffies) / HZ;
1.1 root 383: current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
1.1.1.2 root 384: return (old);
1.1 root 385: }
386:
387: int sys_getpid(void)
388: {
389: return current->pid;
390: }
391:
392: int sys_getppid(void)
393: {
1.1.1.4 root 394: return current->p_pptr->pid;
1.1 root 395: }
396:
397: int sys_getuid(void)
398: {
399: return current->uid;
400: }
401:
402: int sys_geteuid(void)
403: {
404: return current->euid;
405: }
406:
407: int sys_getgid(void)
408: {
409: return current->gid;
410: }
411:
412: int sys_getegid(void)
413: {
414: return current->egid;
415: }
416:
417: int sys_nice(long increment)
418: {
1.1.1.5 root 419: if (increment < 0 && !suser())
420: return -EPERM;
421: if (increment > current->priority)
422: increment = current->priority-1;
423: current->priority -= increment;
1.1 root 424: return 0;
425: }
426:
427: void sched_init(void)
428: {
429: int i;
430: struct desc_struct * p;
431:
1.1.1.2 root 432: if (sizeof(struct sigaction) != 16)
433: panic("Struct sigaction MUST be 16 bytes");
1.1 root 434: set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
435: set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
436: p = gdt+2+FIRST_TSS_ENTRY;
1.1.1.5 root 437: for(i=1 ; i<NR_TASKS ; i++) {
1.1 root 438: task[i] = NULL;
439: p->a=p->b=0;
440: p++;
441: p->a=p->b=0;
442: p++;
443: }
1.1.1.3 root 444: /* Clear NT, so that we won't have troubles with that later on */
445: __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
1.1 root 446: ltr(0);
447: lldt(0);
448: outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */
449: outb_p(LATCH & 0xff , 0x40); /* LSB */
450: outb(LATCH >> 8 , 0x40); /* MSB */
451: set_intr_gate(0x20,&timer_interrupt);
452: outb(inb_p(0x21)&~0x01,0x21);
453: set_system_gate(0x80,&system_call);
454: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.