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

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>
1.1.1.5   root       14: #include <linux/timer.h>
1.1       root       15: #include <linux/kernel.h>
                     16: #include <linux/sys.h>
1.1.1.2   root       17: #include <linux/fdreg.h>
1.1       root       18: #include <asm/system.h>
                     19: #include <asm/io.h>
                     20: #include <asm/segment.h>
                     21: 
1.1.1.2   root       22: #include <signal.h>
1.1.1.5   root       23: #include <errno.h>
1.1.1.2   root       24: 
                     25: #define _S(nr) (1<<((nr)-1))
                     26: #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
                     27: 
                     28: void show_task(int nr,struct task_struct * p)
                     29: {
1.1.1.3   root       30:        int i,j = 4096-sizeof(struct task_struct);
                     31: 
1.1.1.4   root       32:        printk("%d: pid=%d, state=%d, father=%d, child=%d, ",nr,p->pid,
                     33:                p->state, p->p_pptr->pid, p->p_cptr ? p->p_cptr->pid : -1);
1.1.1.3   root       34:        i=0;
                     35:        while (i<j && !((char *)(p+1))[i])
                     36:                i++;
1.1.1.4   root       37:        printk("%d/%d chars free in kstack\n\r",i,j);
                     38:        printk("   PC=%08X.", *(1019 + (unsigned long *) p));
                     39:        if (p->p_ysptr || p->p_osptr) 
                     40:                printk("   Younger sib=%d, older sib=%d\n\r", 
                     41:                        p->p_ysptr ? p->p_ysptr->pid : -1,
                     42:                        p->p_osptr ? p->p_osptr->pid : -1);
                     43:        else
                     44:                printk("\n\r");
1.1.1.2   root       45: }
                     46: 
1.1.1.4   root       47: void show_state(void)
1.1.1.2   root       48: {
1.1.1.7 ! root       49:        static int lock = 0;
1.1.1.2   root       50:        int i;
                     51: 
1.1.1.7 ! root       52:        cli();
        !            53:        if (lock) {
        !            54:                sti();
        !            55:                return;
        !            56:        }
        !            57:        lock = 1;
        !            58:        sti();
1.1.1.4   root       59:        printk("\rTask-info:\n\r");
1.1.1.7 ! root       60:        for (i=0 ; i<NR_TASKS ; i++)
1.1.1.2   root       61:                if (task[i])
                     62:                        show_task(i,task[i]);
1.1.1.7 ! root       63:        lock = 0;
1.1.1.2   root       64: }
                     65: 
1.1       root       66: #define LATCH (1193180/HZ)
                     67: 
                     68: extern void mem_use(void);
                     69: 
                     70: extern int timer_interrupt(void);
                     71: extern int system_call(void);
                     72: 
                     73: union task_union {
                     74:        struct task_struct task;
                     75:        char stack[PAGE_SIZE];
                     76: };
                     77: 
                     78: static union task_union init_task = {INIT_TASK,};
                     79: 
1.1.1.4   root       80: unsigned long volatile jiffies=0;
                     81: unsigned long startup_time=0;
                     82: int jiffies_offset = 0;                /* # clock ticks to add to get "true
                     83:                                   time".  Should always be less than
                     84:                                   1 second's worth.  For time fanatics
                     85:                                   who like to syncronize their machines
                     86:                                   to WWV :-) */
                     87: 
1.1.1.2   root       88: struct task_struct *current = &(init_task.task);
                     89: struct task_struct *last_task_used_math = NULL;
1.1       root       90: 
                     91: struct task_struct * task[NR_TASKS] = {&(init_task.task), };
                     92: 
                     93: long user_stack [ PAGE_SIZE>>2 ] ;
                     94: 
                     95: struct {
                     96:        long * a;
                     97:        short b;
                     98:        } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
                     99: /*
                    100:  *  'math_state_restore()' saves the current math information in the
                    101:  * old math state array, and gets the new ones from the current task
                    102:  */
                    103: void math_state_restore()
                    104: {
1.1.1.2   root      105:        if (last_task_used_math == current)
                    106:                return;
1.1.1.3   root      107:        __asm__("fwait");
1.1.1.2   root      108:        if (last_task_used_math) {
1.1       root      109:                __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
1.1.1.2   root      110:        }
1.1.1.3   root      111:        last_task_used_math=current;
1.1.1.2   root      112:        if (current->used_math) {
1.1       root      113:                __asm__("frstor %0"::"m" (current->tss.i387));
1.1.1.2   root      114:        } else {
1.1       root      115:                __asm__("fninit"::);
                    116:                current->used_math=1;
                    117:        }
                    118: }
                    119: 
                    120: /*
1.1.1.5   root      121:  *  'schedule()' is the scheduler function. It's a very simple and nice
                    122:  * scheduler: it's not perfect, but certainly works for most things.
1.1       root      123:  * The one thing you might take a look at is the signal-handler code here.
                    124:  *
                    125:  *   NOTE!!  Task 0 is the 'idle' task, which gets called when no other
                    126:  * tasks can run. It can not be killed, and it cannot sleep. The 'state'
                    127:  * information in task[0] is never used.
                    128:  */
                    129: void schedule(void)
                    130: {
                    131:        int i,next,c;
                    132:        struct task_struct ** p;
                    133: 
                    134: /* check alarm, wake up any interruptible tasks that have got a signal */
                    135: 
                    136:        for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
                    137:                if (*p) {
1.1.1.6   root      138:                        if ((*p)->timeout && (*p)->timeout < jiffies)
                    139:                                if ((*p)->state == TASK_INTERRUPTIBLE) {
                    140:                                        (*p)->timeout = 0;
1.1.1.4   root      141:                                        (*p)->state = TASK_RUNNING;
1.1.1.6   root      142:                                }
1.1       root      143:                        if ((*p)->alarm && (*p)->alarm < jiffies) {
1.1.1.4   root      144:                                (*p)->signal |= (1<<(SIGALRM-1));
                    145:                                (*p)->alarm = 0;
                    146:                        }
1.1.1.5   root      147:                        if (((*p)->signal & ~(*p)->blocked) &&
1.1.1.2   root      148:                        (*p)->state==TASK_INTERRUPTIBLE)
1.1       root      149:                                (*p)->state=TASK_RUNNING;
                    150:                }
                    151: 
                    152: /* this is the scheduler proper: */
                    153: 
                    154:        while (1) {
                    155:                c = -1;
                    156:                next = 0;
                    157:                i = NR_TASKS;
                    158:                p = &task[NR_TASKS];
                    159:                while (--i) {
                    160:                        if (!*--p)
                    161:                                continue;
                    162:                        if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
                    163:                                c = (*p)->counter, next = i;
                    164:                }
                    165:                if (c) break;
                    166:                for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
                    167:                        if (*p)
                    168:                                (*p)->counter = ((*p)->counter >> 1) +
                    169:                                                (*p)->priority;
                    170:        }
                    171:        switch_to(next);
                    172: }
                    173: 
                    174: int sys_pause(void)
                    175: {
1.1.1.5   root      176:        unsigned long old_blocked;
                    177:        unsigned long mask;
                    178:        struct sigaction * sa = current->sigaction;
                    179: 
                    180:        old_blocked = current->blocked;
                    181:        for (mask=1 ; mask ; sa++,mask += mask)
                    182:                if (sa->sa_handler == SIG_IGN)
                    183:                        current->blocked |= mask;
1.1       root      184:        current->state = TASK_INTERRUPTIBLE;
                    185:        schedule();
1.1.1.5   root      186:        current->blocked = old_blocked;
                    187:        return -EINTR;
1.1       root      188: }
                    189: 
1.1.1.6   root      190: void wake_up(struct task_struct **p)
                    191: {
                    192:        struct task_struct * wakeup_ptr, * tmp;
                    193: 
                    194:        if (p && *p) {
                    195:                wakeup_ptr = *p;
                    196:                *p = NULL;
                    197:                while (wakeup_ptr && wakeup_ptr != task[0]) {
                    198:                        if (wakeup_ptr->state == TASK_STOPPED)
                    199:                                printk("wake_up: TASK_STOPPED\n");
                    200:                        else if (wakeup_ptr->state == TASK_ZOMBIE)
                    201:                                printk("wake_up: TASK_ZOMBIE\n");
                    202:                        else
                    203:                                wakeup_ptr->state = TASK_RUNNING;
                    204:                        tmp = wakeup_ptr->next_wait;
                    205:                        wakeup_ptr->next_wait = task[0];
                    206:                        wakeup_ptr = tmp;
                    207:                }
                    208:        }
                    209: }
                    210: 
1.1.1.4   root      211: static inline void __sleep_on(struct task_struct **p, int state)
1.1       root      212: {
1.1.1.5   root      213:        unsigned int flags;
1.1       root      214: 
                    215:        if (!p)
                    216:                return;
1.1.1.6   root      217:        if (current == task[0])
1.1       root      218:                panic("task[0] trying to sleep");
1.1.1.5   root      219:        __asm__("pushfl ; popl %0":"=r" (flags));
1.1.1.6   root      220:        current->next_wait = *p;
                    221:        task[0]->next_wait = NULL;
1.1       root      222:        *p = current;
1.1.1.4   root      223:        current->state = state;
1.1.1.5   root      224:        sti();
1.1.1.6   root      225:        schedule();
                    226:        if (current->next_wait != task[0])
                    227:                wake_up(p);
                    228:        current->next_wait = NULL;
1.1.1.5   root      229:        __asm__("pushl %0 ; popfl"::"r" (flags));
1.1       root      230: }
                    231: 
                    232: void interruptible_sleep_on(struct task_struct **p)
                    233: {
1.1.1.4   root      234:        __sleep_on(p,TASK_INTERRUPTIBLE);
                    235: }
1.1       root      236: 
1.1.1.4   root      237: void sleep_on(struct task_struct **p)
                    238: {
                    239:        __sleep_on(p,TASK_UNINTERRUPTIBLE);
1.1       root      240: }
                    241: 
1.1.1.2   root      242: /*
                    243:  * OK, here are some floppy things that shouldn't be in the kernel
                    244:  * proper. They are here because the floppy needs a timer, and this
                    245:  * was the easiest way of doing it.
                    246:  */
                    247: static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
                    248: static int  mon_timer[4]={0,0,0,0};
                    249: static int moff_timer[4]={0,0,0,0};
                    250: unsigned char current_DOR = 0x0C;
                    251: 
                    252: int ticks_to_floppy_on(unsigned int nr)
                    253: {
1.1.1.3   root      254:        extern unsigned char selected;
                    255:        unsigned char mask = 0x10 << nr;
1.1.1.2   root      256: 
                    257:        if (nr>3)
                    258:                panic("floppy_on: nr>3");
                    259:        moff_timer[nr]=10000;           /* 100 s = very big :-) */
                    260:        cli();                          /* use floppy_off to turn it off */
1.1.1.3   root      261:        mask |= current_DOR;
                    262:        if (!selected) {
                    263:                mask &= 0xFC;
                    264:                mask |= nr;
                    265:        }
                    266:        if (mask != current_DOR) {
                    267:                outb(mask,FD_DOR);
                    268:                if ((mask ^ current_DOR) & 0xf0)
                    269:                        mon_timer[nr] = HZ/2;
                    270:                else if (mon_timer[nr] < 2)
                    271:                        mon_timer[nr] = 2;
                    272:                current_DOR = mask;
1.1.1.2   root      273:        }
                    274:        sti();
                    275:        return mon_timer[nr];
                    276: }
                    277: 
                    278: void floppy_off(unsigned int nr)
                    279: {
                    280:        moff_timer[nr]=3*HZ;
                    281: }
                    282: 
                    283: void do_floppy_timer(void)
                    284: {
                    285:        int i;
                    286:        unsigned char mask = 0x10;
                    287: 
                    288:        for (i=0 ; i<4 ; i++,mask <<= 1) {
                    289:                if (!(mask & current_DOR))
                    290:                        continue;
                    291:                if (mon_timer[i]) {
                    292:                        if (!--mon_timer[i])
                    293:                                wake_up(i+wait_motor);
                    294:                } else if (!moff_timer[i]) {
                    295:                        current_DOR &= ~mask;
                    296:                        outb(current_DOR,FD_DOR);
                    297:                } else
                    298:                        moff_timer[i]--;
                    299:        }
                    300: }
                    301: 
                    302: #define TIME_REQUESTS 64
                    303: 
                    304: static struct timer_list {
                    305:        long jiffies;
                    306:        void (*fn)();
                    307:        struct timer_list * next;
1.1.1.7 ! root      308: } timer_list[TIME_REQUESTS] = { { 0, NULL, NULL }, };
        !           309: 
        !           310: static struct timer_list * next_timer = NULL;
1.1.1.2   root      311: 
                    312: void add_timer(long jiffies, void (*fn)(void))
                    313: {
                    314:        struct timer_list * p;
                    315: 
                    316:        if (!fn)
                    317:                return;
                    318:        cli();
                    319:        if (jiffies <= 0)
                    320:                (fn)();
                    321:        else {
                    322:                for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
                    323:                        if (!p->fn)
                    324:                                break;
                    325:                if (p >= timer_list + TIME_REQUESTS)
                    326:                        panic("No more time requests free");
                    327:                p->fn = fn;
                    328:                p->jiffies = jiffies;
                    329:                p->next = next_timer;
                    330:                next_timer = p;
                    331:                while (p->next && p->next->jiffies < p->jiffies) {
                    332:                        p->jiffies -= p->next->jiffies;
                    333:                        fn = p->fn;
                    334:                        p->fn = p->next->fn;
                    335:                        p->next->fn = fn;
                    336:                        jiffies = p->jiffies;
                    337:                        p->jiffies = p->next->jiffies;
                    338:                        p->next->jiffies = jiffies;
                    339:                        p = p->next;
                    340:                }
                    341:        }
                    342:        sti();
                    343: }
                    344: 
1.1.1.5   root      345: unsigned long timer_active = 0;
                    346: struct timer_struct timer_table[32];
                    347: 
1.1       root      348: void do_timer(long cpl)
                    349: {
1.1.1.5   root      350:        unsigned long mask;
                    351:        struct timer_struct *tp = timer_table+0;
1.1.1.4   root      352: 
1.1.1.5   root      353:        for (mask = 1 ; mask ; tp++,mask += mask) {
                    354:                if (mask > timer_active)
                    355:                        break;
                    356:                if (!(mask & timer_active))
                    357:                        continue;
                    358:                if (tp->expires > jiffies)
                    359:                        continue;
                    360:                timer_active &= ~mask;
                    361:                tp->fn();
                    362:        }
1.1.1.3   root      363: 
1.1       root      364:        if (cpl)
                    365:                current->utime++;
                    366:        else
                    367:                current->stime++;
1.1.1.3   root      368: 
1.1.1.2   root      369:        if (next_timer) {
                    370:                next_timer->jiffies--;
                    371:                while (next_timer && next_timer->jiffies <= 0) {
                    372:                        void (*fn)(void);
                    373:                        
                    374:                        fn = next_timer->fn;
                    375:                        next_timer->fn = NULL;
                    376:                        next_timer = next_timer->next;
                    377:                        (fn)();
                    378:                }
                    379:        }
                    380:        if (current_DOR & 0xf0)
                    381:                do_floppy_timer();
1.1       root      382:        if ((--current->counter)>0) return;
                    383:        current->counter=0;
                    384:        if (!cpl) return;
                    385:        schedule();
                    386: }
                    387: 
                    388: int sys_alarm(long seconds)
                    389: {
1.1.1.2   root      390:        int old = current->alarm;
                    391: 
                    392:        if (old)
                    393:                old = (old - jiffies) / HZ;
1.1       root      394:        current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
1.1.1.2   root      395:        return (old);
1.1       root      396: }
                    397: 
                    398: int sys_getpid(void)
                    399: {
                    400:        return current->pid;
                    401: }
                    402: 
                    403: int sys_getppid(void)
                    404: {
1.1.1.4   root      405:        return current->p_pptr->pid;
1.1       root      406: }
                    407: 
                    408: int sys_getuid(void)
                    409: {
                    410:        return current->uid;
                    411: }
                    412: 
                    413: int sys_geteuid(void)
                    414: {
                    415:        return current->euid;
                    416: }
                    417: 
                    418: int sys_getgid(void)
                    419: {
                    420:        return current->gid;
                    421: }
                    422: 
                    423: int sys_getegid(void)
                    424: {
                    425:        return current->egid;
                    426: }
                    427: 
                    428: int sys_nice(long increment)
                    429: {
1.1.1.5   root      430:        if (increment < 0 && !suser())
                    431:                return -EPERM;
                    432:        if (increment > current->priority)
                    433:                increment = current->priority-1;
                    434:        current->priority -= increment;
1.1       root      435:        return 0;
                    436: }
                    437: 
                    438: void sched_init(void)
                    439: {
                    440:        int i;
                    441:        struct desc_struct * p;
                    442: 
1.1.1.2   root      443:        if (sizeof(struct sigaction) != 16)
                    444:                panic("Struct sigaction MUST be 16 bytes");
1.1       root      445:        set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
                    446:        set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
                    447:        p = gdt+2+FIRST_TSS_ENTRY;
1.1.1.5   root      448:        for(i=1 ; i<NR_TASKS ; i++) {
1.1       root      449:                task[i] = NULL;
                    450:                p->a=p->b=0;
                    451:                p++;
                    452:                p->a=p->b=0;
                    453:                p++;
                    454:        }
1.1.1.3   root      455: /* Clear NT, so that we won't have troubles with that later on */
                    456:        __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
1.1       root      457:        ltr(0);
                    458:        lldt(0);
                    459:        outb_p(0x36,0x43);              /* binary, mode 3, LSB/MSB, ch 0 */
                    460:        outb_p(LATCH & 0xff , 0x40);    /* LSB */
                    461:        outb(LATCH >> 8 , 0x40);        /* MSB */
                    462:        set_intr_gate(0x20,&timer_interrupt);
                    463:        outb(inb_p(0x21)&~0x01,0x21);
                    464:        set_system_gate(0x80,&system_call);
                    465: }

unix.superglobalmegacorp.com

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