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

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

unix.superglobalmegacorp.com

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