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

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

unix.superglobalmegacorp.com

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