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