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

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

unix.superglobalmegacorp.com

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