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

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

unix.superglobalmegacorp.com

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