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