Annotation of researchv10no/sys/os/clock.c, revision 1.1.1.1

1.1       root        1: #include "sys/param.h"
                      2: #include "sys/systm.h"
                      3: #include "sys/meter.h"
                      4: #include "sys/callout.h"
                      5: #include "sys/user.h"
                      6: #include "sys/proc.h"
                      7: #include "sys/psl.h"
                      8: #include "sys/vm.h"
                      9: #include "sys/buf.h"
                     10: #include "sys/text.h"
                     11: #include "sys/vlimit.h"
                     12: #include "sys/mtpr.h"
                     13: #include "sys/clock.h"
                     14: 
                     15: int    queueflag;
                     16: 
                     17: /*
                     18:  * trivial kernel profiling; quite expensive in space
                     19:  */
                     20: #define        KMAX    (200*1024)      /* max kernel text */
                     21: #define        KPSIZE  (50*256)        /* number of buckets */
                     22: #define        KPROF   1
                     23: #if KPROF
                     24: long kprof[KPSIZE];
                     25: #endif
                     26: 
                     27: 
                     28: /*
                     29:  * Hardclock is called straight from
                     30:  * the real time clock interrupt.
                     31:  * We limit the work we do at real clock interrupt time to:
                     32:  *     reloading clock
                     33:  *     decrementing time to callouts
                     34:  *     recording cpu time usage
                     35:  *     modifying priority of current process
                     36:  *     arrange for soft clock interrupt
                     37:  *     kernel pc profiling
                     38:  *
                     39:  * At software (softclock) interrupt time we:
                     40:  *     implement callouts
                     41:  *     maintain date
                     42:  *     lightning bolt wakeup (every second)
                     43:  *     alarm clock signals
                     44:  *     jab the scheduler
                     45:  *
                     46:  * On the vax softclock interrupts are implemented by
                     47:  * software interrupts.  Note that we may have multiple softclock
                     48:  * interrupts compressed into one (due to excessive interrupt load),
                     49:  * but that hardclock interrupts should never be lost.
                     50:  */
                     51: /*ARGSUSED*/
                     52: hardclock(pc, ps)
                     53:        caddr_t pc;
                     54: {
                     55:        register struct callout *p1;
                     56:        register struct proc *pp;
                     57:        register int s, cpstate;
                     58: 
                     59:        /*
                     60:         * reprime clock
                     61:         */
                     62:        clkreld();
                     63: 
                     64:        /*
                     65:         * update callout times
                     66:         */
                     67:        for (p1 = calltodo.c_next; p1 && p1->c_time <= 0; p1 = p1->c_next)
                     68:                ;
                     69:        if (p1)
                     70:                p1->c_time--;
                     71:        pp = u.u_procp;
                     72:        if (USERMODE(ps)) {
                     73:                u.u_vm.vm_utime++;
                     74:                if (pp->p_nice > NZERO)
                     75:                        cpstate = CP_NICE;
                     76:                else
                     77:                        cpstate = CP_USER;
                     78:                s = 1;
                     79:        } else {
                     80: #if KPROF
                     81:                s = (long)pc - KSTART;
                     82:                if (s < 0)
                     83:                        s = 0;  /* shouldn't */
                     84:                else if (s >= KMAX)
                     85:                        s = KMAX - 1;
                     86:                s /= KMAX/KPSIZE;
                     87:                kprof[s]++;
                     88: #endif
                     89:                cpstate = CP_SYS;
                     90:                if (queueflag) {
                     91:                        cpstate = CP_QUEUE;
                     92:                        s = 0;
                     93:                } else if (noproc) {
                     94:                        if (BASEPRI(ps) == 0)
                     95:                                cpstate = CP_IDLE;
                     96:                        s = 0;
                     97:                } else {
                     98:                        u.u_vm.vm_stime++;
                     99:                        s = 1;
                    100:                }
                    101:        }
                    102:        cp_time[cpstate]++;
                    103:        /*
                    104:         * Adjust priority of current process.
                    105:         */
                    106:        if (s) {
                    107:                pp->p_cpticks++;
                    108:                if(++pp->p_cpu == 0)
                    109:                        --pp->p_cpu;
                    110:        }
                    111:        ++lbolt;
                    112:        setsoftclock();
                    113: }
                    114: 
                    115: #define cpuave(a,b) ((int)(((int)((a)*(b)))/((b)+1)))
                    116: extern double avenrun[];
                    117: /*
                    118:  * Constant for decay filter for cpu usage field
                    119:  * in process table (used by ps au).
                    120:  */
                    121: static float ccpu = 0.9512294245;              /* exp(-1/20) */
                    122: 
                    123: /*
                    124:  * Software clock interrupt.
                    125:  * This routine runs at lower priority than device interrupts.
                    126:  *
                    127:  * Processes have their (32-bit) priority depend on their owner's ``normalised
                    128:  * usage'' of resources. However, V9's low-level scheduler only has 127 priorities,
                    129:  * (in fact, only 32, so that someone could use an 'ffs' instruction),
                    130:  * so we normalise this ``sharepri'' into the 7-bit ``usrpri''. Note that
                    131:  * the 'ffs' hack means that (after PUSER) there are only 20 real priorities
                    132:  * for processes to run in, and that defined kernel priorities should differ
                    133:  * by more than 4 to be meaningful.
                    134:  */
                    135: /*ARGSUSED*/
                    136: softclock(pc, ps)
                    137:        caddr_t pc;
                    138: {
                    139:        register struct callout *p1;
                    140:        register struct proc *pp;
                    141:        register int a, s;
                    142:        extern char *panicstr;
                    143: 
                    144:        /*
                    145:         * Perform callouts (but not after panics)
                    146:         */
                    147:        if (panicstr == 0) {
                    148:                for (;;) {
                    149:                        register caddr_t arg;
                    150:                        register int (*func)();
                    151: 
                    152:                        s = spl7();
                    153:                        if ((p1 = calltodo.c_next) == 0 || p1->c_time > 0) {
                    154:                                splx(s);
                    155:                                break;
                    156:                        }
                    157:                        calltodo.c_next = p1->c_next;
                    158:                        arg = p1->c_arg;
                    159:                        func = p1->c_func;
                    160:                        p1->c_next = callfree;
                    161:                        callfree = p1;
                    162:                        (void) splx(s);
                    163:                        (*func)(arg);
                    164:                }
                    165:        }
                    166: 
                    167:        /*
                    168:         * If idling and processes are waiting to swap in,
                    169:         * check on them.
                    170:         */
                    171:        if (noproc && runin) {
                    172:                runin = 0;
                    173:                wakeup((caddr_t)&runin);
                    174:        }
                    175:        if (lbolt % (HZ/10) == 0) {
                    176:                runrun++;
                    177:                aston();
                    178:        }
                    179: 
                    180:        /*
                    181:         * Lightning bolt every second:
                    182:         *      sleep timeouts
                    183:         *      process priority recomputation
                    184:         *      process %cpu averaging
                    185:         *      p_time and p_slptime for the swapper
                    186:         *      kick swapper if processes want in
                    187:         */
                    188:        if (lbolt >= HZ) {
                    189:                /* meaningless on VAX; meant for hardclock */
                    190:                if (BASEPRI(ps))
                    191:                        return;
                    192:                time += lbolt / HZ;
                    193:                lbolt %= HZ;
                    194:                wakeup((caddr_t)&lbolt);
                    195:                for (pp = proc; pp < procNPROC; pp++)
                    196:                if ((a=pp->p_stat)!=0 && a!=SZOMB) {
                    197:                        if (pp->p_time != 127)
                    198:                                pp->p_time++;
                    199:                        if (pp->p_clktim && --pp->p_clktim == 0)
                    200:                                psignal(pp, SIGALRM);
                    201:                        if (pp->p_tsleep && --pp->p_tsleep == 0) {
                    202:                                s = spl6();
                    203:                                switch (pp->p_stat) {   /* != a if interrupted */
                    204: 
                    205:                                case SSLEEP:
                    206:                                        setrun(pp);
                    207:                                        break;
                    208: 
                    209:                                case SSTOP:
                    210:                                        unsleep(pp);
                    211:                                        break;
                    212:                                }
                    213:                                pp->p_flag |= STIMO;
                    214:                                splx(s);
                    215:                        }
                    216:                        if (a==SSLEEP || a==SSTOP)
                    217:                                if (pp->p_slptime != 127)
                    218:                                        pp->p_slptime++;
                    219:                        /*
                    220:                         * update silly numbers for ps to print
                    221:                         */
                    222:                        if (pp->p_flag&SLOAD)
                    223:                                pp->p_pctcpu = ccpu*pp->p_pctcpu +
                    224:                                    (1.0 - ccpu) * (pp->p_cpticks/(float)HZ);
                    225:                        pp->p_cpticks = 0;
                    226: 
                    227:                        /*
                    228:                         * Update p_cpu for scheduling
                    229:                         */
                    230:                        a = cpuave(pp->p_cpu, 2*avenrun[0]);
                    231:                        if (a < 0)
                    232:                                a = 0;
                    233:                        if (a > 255)
                    234:                                a = 255;
                    235:                        pp->p_cpu = a;
                    236:                        (void) setpri(pp);
                    237:                        /*
                    238:                         * p_usrpri == new process priority
                    239:                         * now fix p_pri to match, carefully
                    240:                         */
                    241:                        s = spl6();
                    242:                        if (pp->p_pri >= PUSER && pp->p_pri != pp->p_usrpri) {
                    243:                                if ((pp != u.u_procp || noproc) && pp->p_stat == SRUN &&
                    244:                                    (pp->p_flag & SLOAD)) {
                    245:                                        remrq(pp);
                    246:                                        pp->p_pri = pp->p_usrpri;
                    247:                                        setrq(pp);
                    248:                                } else
                    249:                                        pp->p_pri = pp->p_usrpri;
                    250:                        }
                    251:                        splx(s);
                    252:                }
                    253:                if (runin!=0) {
                    254:                        runin = 0;
                    255:                        wakeup((caddr_t)&runin);
                    256:                }
                    257:        }
                    258:        if (noproc)
                    259:                return;
                    260:        pp = u.u_procp;
                    261:        /*
                    262:         * If trapped user-mode, give it a profiling tick.
                    263:         */
                    264:        if (USERMODE(ps) && u.u_prof.pr_scale) {
                    265:                pp->p_flag |= SOWEUPC;
                    266:                aston();
                    267:        }
                    268:        /*
                    269:         * random statistics, apparently computed just so
                    270:         * that programs like ps can print them?  not a good reason
                    271:         */
                    272:        s = pp->p_rssize;
                    273:        u.u_vm.vm_idsrss += s;
                    274:        if (pp->p_textp) {
                    275:                a = pp->p_textp->x_rssize;
                    276:                s += a;
                    277:                u.u_vm.vm_ixrss += a;
                    278:        }
                    279:        if (s > u.u_vm.vm_maxrss)
                    280:                u.u_vm.vm_maxrss = s;
                    281:        /*
                    282:         * cpu time limit
                    283:         */
                    284:        if ((u.u_vm.vm_utime+u.u_vm.vm_stime+1)/HZ > u.u_limit[LIM_CPU]) {
                    285:                psignal(pp, SIGXCPU);
                    286:                if (u.u_limit[LIM_CPU] < INFINITY - 5)
                    287:                        u.u_limit[LIM_CPU] += 5;
                    288:        }
                    289: }
                    290: 
                    291: /*
                    292:  * Timeout is called to arrange that
                    293:  * fun(arg) is called in tim/HZ seconds.
                    294:  * An entry is linked into the callout
                    295:  * structure.  The time in each structure
                    296:  * entry is the number of HZ's more
                    297:  * than the previous entry.
                    298:  * In this way, decrementing the
                    299:  * first entry has the effect of
                    300:  * updating all entries.
                    301:  *
                    302:  * The panic is there because there is nothing
                    303:  * intelligent to be done if an entry won't fit.
                    304:  */
                    305: timeout(fun, arg, tim)
                    306:        int (*fun)();
                    307:        caddr_t arg;
                    308: {
                    309:        register struct callout *p1, *p2, *pnew;
                    310:        register int t;
                    311:        int s;
                    312: 
                    313:        t = tim;
                    314:        s = spl7();
                    315:        pnew = callfree;
                    316:        if (pnew == NULL)
                    317:                panic("timeout table overflow");
                    318:        callfree = pnew->c_next;
                    319:        pnew->c_arg = arg;
                    320:        pnew->c_func = fun;
                    321:        for (p1 = &calltodo; (p2 = p1->c_next) && p2->c_time < t; p1 = p2)
                    322:                t -= p2->c_time;
                    323:        p1->c_next = pnew;
                    324:        pnew->c_next = p2;
                    325:        pnew->c_time = t;
                    326:        if (p2)
                    327:                p2->c_time -= t;
                    328:        splx(s);
                    329: }
                    330: 
                    331: /*
                    332:  *      Delay goes to sleep on a unique address for a
                    333:  *      guaranteed minimum period ticks/HZ secs.
                    334:  *      Because a timeout() can't be cancelled, the process
                    335:  *      will be unkillable while asleep.  Beware of giving
                    336:  *      delay() an argument of more than a few hundred.
                    337:  *
                    338:  * used by one device driver and by sys nap.
                    339:  * do we really need it?
                    340:  */
                    341: delay(ticks)
                    342: {
                    343:         register int    x;
                    344:         extern wakeup();
                    345: 
                    346:         if (ticks<=0)
                    347:                 return;
                    348:         x = spl7();
                    349:         timeout(wakeup, (caddr_t)u.u_procp+1, ticks);
                    350:         sleep((caddr_t)u.u_procp+1, PZERO-1);
                    351:         splx(x);
                    352: }
                    353: 
                    354: /*
                    355:  * init callouts
                    356:  * called from main
                    357:  */
                    358: 
                    359: callinit()
                    360: {
                    361:        register int i;
                    362: 
                    363:        callfree = callout;
                    364:        for (i = 1; i < calloutcnt; i++)
                    365:                callout[i-1].c_next = &callout[i];
                    366: }

unix.superglobalmegacorp.com

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