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