|
|
1.1 ! root 1: /* ! 2: * 'sched.c' is the main kernel file. It contains scheduling primitives ! 3: * (sleep_on, wakeup, schedule etc) as well as a number of simple system ! 4: * call functions (type getpid(), which just extracts a field from ! 5: * current-task ! 6: */ ! 7: #include <linux/sched.h> ! 8: #include <linux/kernel.h> ! 9: #include <signal.h> ! 10: #include <linux/sys.h> ! 11: #include <asm/system.h> ! 12: #include <asm/io.h> ! 13: #include <asm/segment.h> ! 14: ! 15: #define LATCH (1193180/HZ) ! 16: ! 17: extern void mem_use(void); ! 18: ! 19: extern int timer_interrupt(void); ! 20: extern int system_call(void); ! 21: ! 22: union task_union { ! 23: struct task_struct task; ! 24: char stack[PAGE_SIZE]; ! 25: }; ! 26: ! 27: static union task_union init_task = {INIT_TASK,}; ! 28: ! 29: long volatile jiffies=0; ! 30: long startup_time=0; ! 31: struct task_struct *current = &(init_task.task), *last_task_used_math = NULL; ! 32: ! 33: struct task_struct * task[NR_TASKS] = {&(init_task.task), }; ! 34: ! 35: long user_stack [ PAGE_SIZE>>2 ] ; ! 36: ! 37: struct { ! 38: long * a; ! 39: short b; ! 40: } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 }; ! 41: /* ! 42: * 'math_state_restore()' saves the current math information in the ! 43: * old math state array, and gets the new ones from the current task ! 44: */ ! 45: void math_state_restore() ! 46: { ! 47: if (last_task_used_math) ! 48: __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387)); ! 49: if (current->used_math) ! 50: __asm__("frstor %0"::"m" (current->tss.i387)); ! 51: else { ! 52: __asm__("fninit"::); ! 53: current->used_math=1; ! 54: } ! 55: last_task_used_math=current; ! 56: } ! 57: ! 58: /* ! 59: * 'schedule()' is the scheduler function. This is GOOD CODE! There ! 60: * probably won't be any reason to change this, as it should work well ! 61: * in all circumstances (ie gives IO-bound processes good response etc). ! 62: * The one thing you might take a look at is the signal-handler code here. ! 63: * ! 64: * NOTE!! Task 0 is the 'idle' task, which gets called when no other ! 65: * tasks can run. It can not be killed, and it cannot sleep. The 'state' ! 66: * information in task[0] is never used. ! 67: */ ! 68: void schedule(void) ! 69: { ! 70: int i,next,c; ! 71: struct task_struct ** p; ! 72: ! 73: /* check alarm, wake up any interruptible tasks that have got a signal */ ! 74: ! 75: for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) ! 76: if (*p) { ! 77: if ((*p)->alarm && (*p)->alarm < jiffies) { ! 78: (*p)->signal |= (1<<(SIGALRM-1)); ! 79: (*p)->alarm = 0; ! 80: } ! 81: if ((*p)->signal && (*p)->state==TASK_INTERRUPTIBLE) ! 82: (*p)->state=TASK_RUNNING; ! 83: } ! 84: ! 85: /* this is the scheduler proper: */ ! 86: ! 87: while (1) { ! 88: c = -1; ! 89: next = 0; ! 90: i = NR_TASKS; ! 91: p = &task[NR_TASKS]; ! 92: while (--i) { ! 93: if (!*--p) ! 94: continue; ! 95: if ((*p)->state == TASK_RUNNING && (*p)->counter > c) ! 96: c = (*p)->counter, next = i; ! 97: } ! 98: if (c) break; ! 99: for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) ! 100: if (*p) ! 101: (*p)->counter = ((*p)->counter >> 1) + ! 102: (*p)->priority; ! 103: } ! 104: switch_to(next); ! 105: } ! 106: ! 107: int sys_pause(void) ! 108: { ! 109: current->state = TASK_INTERRUPTIBLE; ! 110: schedule(); ! 111: return 0; ! 112: } ! 113: ! 114: void sleep_on(struct task_struct **p) ! 115: { ! 116: struct task_struct *tmp; ! 117: ! 118: if (!p) ! 119: return; ! 120: if (current == &(init_task.task)) ! 121: panic("task[0] trying to sleep"); ! 122: tmp = *p; ! 123: *p = current; ! 124: current->state = TASK_UNINTERRUPTIBLE; ! 125: schedule(); ! 126: if (tmp) ! 127: tmp->state=0; ! 128: } ! 129: ! 130: void interruptible_sleep_on(struct task_struct **p) ! 131: { ! 132: struct task_struct *tmp; ! 133: ! 134: if (!p) ! 135: return; ! 136: if (current == &(init_task.task)) ! 137: panic("task[0] trying to sleep"); ! 138: tmp=*p; ! 139: *p=current; ! 140: repeat: current->state = TASK_INTERRUPTIBLE; ! 141: schedule(); ! 142: if (*p && *p != current) { ! 143: (**p).state=0; ! 144: goto repeat; ! 145: } ! 146: *p=NULL; ! 147: if (tmp) ! 148: tmp->state=0; ! 149: } ! 150: ! 151: void wake_up(struct task_struct **p) ! 152: { ! 153: if (p && *p) { ! 154: (**p).state=0; ! 155: *p=NULL; ! 156: } ! 157: } ! 158: ! 159: void do_timer(long cpl) ! 160: { ! 161: if (cpl) ! 162: current->utime++; ! 163: else ! 164: current->stime++; ! 165: if ((--current->counter)>0) return; ! 166: current->counter=0; ! 167: if (!cpl) return; ! 168: schedule(); ! 169: } ! 170: ! 171: int sys_alarm(long seconds) ! 172: { ! 173: current->alarm = (seconds>0)?(jiffies+HZ*seconds):0; ! 174: return seconds; ! 175: } ! 176: ! 177: int sys_getpid(void) ! 178: { ! 179: return current->pid; ! 180: } ! 181: ! 182: int sys_getppid(void) ! 183: { ! 184: return current->father; ! 185: } ! 186: ! 187: int sys_getuid(void) ! 188: { ! 189: return current->uid; ! 190: } ! 191: ! 192: int sys_geteuid(void) ! 193: { ! 194: return current->euid; ! 195: } ! 196: ! 197: int sys_getgid(void) ! 198: { ! 199: return current->gid; ! 200: } ! 201: ! 202: int sys_getegid(void) ! 203: { ! 204: return current->egid; ! 205: } ! 206: ! 207: int sys_nice(long increment) ! 208: { ! 209: if (current->priority-increment>0) ! 210: current->priority -= increment; ! 211: return 0; ! 212: } ! 213: ! 214: int sys_signal(long signal,long addr,long restorer) ! 215: { ! 216: long i; ! 217: ! 218: switch (signal) { ! 219: case SIGHUP: case SIGINT: case SIGQUIT: case SIGILL: ! 220: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGUSR1: ! 221: case SIGSEGV: case SIGUSR2: case SIGPIPE: case SIGALRM: ! 222: case SIGCHLD: ! 223: i=(long) current->sig_fn[signal-1]; ! 224: current->sig_fn[signal-1] = (fn_ptr) addr; ! 225: current->sig_restorer = (fn_ptr) restorer; ! 226: return i; ! 227: default: return -1; ! 228: } ! 229: } ! 230: ! 231: void sched_init(void) ! 232: { ! 233: int i; ! 234: struct desc_struct * p; ! 235: ! 236: set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss)); ! 237: set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt)); ! 238: p = gdt+2+FIRST_TSS_ENTRY; ! 239: for(i=1;i<NR_TASKS;i++) { ! 240: task[i] = NULL; ! 241: p->a=p->b=0; ! 242: p++; ! 243: p->a=p->b=0; ! 244: p++; ! 245: } ! 246: ltr(0); ! 247: lldt(0); ! 248: outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */ ! 249: outb_p(LATCH & 0xff , 0x40); /* LSB */ ! 250: outb(LATCH >> 8 , 0x40); /* MSB */ ! 251: set_intr_gate(0x20,&timer_interrupt); ! 252: outb(inb_p(0x21)&~0x01,0x21); ! 253: set_system_gate(0x80,&system_call); ! 254: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.