Annotation of linux/kernel/sched.c, revision 1.1.1.3

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.