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