Annotation of coherent/b/STREAMS/coh.386/clock.c, revision 1.1.1.1

1.1       root        1: /* $Header: /src386/STREAMS/coh.386/RCS/clock.c,v 2.3 93/08/09 13:35:15 bin Exp Locker: bin $ */
                      2: /* (lgl-
                      3:  *     The information contained herein is a trade secret of Mark Williams
                      4:  *     Company, and  is confidential information.  It is provided  under a
                      5:  *     license agreement,  and may be  copied or disclosed  only under the
                      6:  *     terms of  that agreement.  Any  reproduction or disclosure  of this
                      7:  *     material without the express written authorization of Mark Williams
                      8:  *     Company or persuant to the license agreement is unlawful.
                      9:  *
                     10:  *     COHERENT Version 5.0
                     11:  *     Copyright (c) 1982, 1993.
                     12:  *     An unpublished work by Mark Williams Company, Chicago.
                     13:  *     All rights reserved.
                     14:  -lgl) */
                     15: /*
                     16:  * Coherent.
                     17:  * Clock.
                     18:  * The clock comes in two parts.  There is the routine `clock' which
                     19:  * gets called every tick at high priority.  It does the minimum it
                     20:  * can and returns as soon as possible.  The second routine, `stand',
                     21:  * gets called whenever we are about to return from an interrupt to
                     22:  * user mode at low priority.  It can look at flags that the clock set
                     23:  * and do the things the clock really wanted to do but didn't have time.
                     24:  * Stand is truly the kernel of the system.
                     25:  *
                     26:  * 90/08/13    Hal Snyder              /usr/src/sys/coh/clock.c
                     27:  * Add external altclk to allow polled device drivers.
                     28:  * (extern'ed in coherent.h)
                     29:  * 
                     30:  * 87/10/26    Allan cornish           /usr/src/sys/coh/clock.c
                     31:  * Timed functions are now invoked with TIM * tp as second argument.
                     32:  * This facilitates the use of timed functions within loadable drivers.
                     33:  *
                     34:  * 87/07/07    Allan Cornish           /usr/src/sys/coh/clock.c
                     35:  * Clocks static variable added - incremented by clock, decremented by stand().
                     36:  * Lbolt variable added - clock ticks since startup - incremented by stand().
                     37:  * Support for multiple timing queues ported from RTX.
                     38:  *
                     39:  * 87/01/05    Allan Cornish           /usr/src/sys/coh/clock.c
                     40:  * stand() now only wakes &stimer if swap timer is active.
                     41:  *
                     42:  * 86/11/24    Allan Cornish           /usr/src/sys/coh/clock.c
                     43:  * Added support for new t_last field in tim struct.
                     44:  *
                     45:  * 86/11/19    Allan Cornish           /usr/src/sys/coh/clock.c
                     46:  * Stand() calls defend() to execute functions deferred from interrupt level.
                     47:  */
                     48: 
                     49: #include <common/_gregset.h>
                     50: #include <common/_tricks.h>
                     51: 
                     52: #include <kernel/sigproc.h>
                     53: #include <kernel/timeout.h>
                     54: #include <sys/coherent.h>
                     55: #include <sys/con.h>
                     56: #include <sys/proc.h>
                     57: #include <sys/sched.h>
                     58: #include <sys/stat.h>
                     59: 
                     60: int (*altclk)();       /* pointer to higher-speed clock function */
                     61: 
                     62: #if    ! _I386
                     63: int altsel;    /* if nonzero, CS for LOADABLE driver owning altclk() */
                     64: #endif
                     65: 
                     66: int clocks;
                     67: 
                     68: #ifdef TRACER
                     69: 
                     70: extern char    stext;
                     71: extern char    __end_text;
                     72: 
                     73: #endif
                     74: 
                     75: /*
                     76:  * This routine is called once every tick (1/HZ seconds).
                     77:  * It gets called with the program counter that was interrupted
                     78:  * and the CPL of the interrupted code (0..3).
                     79:  */
                     80: clock(pc, umode)
                     81: caddr_t pc;
                     82: {
                     83:        register PROC *pp;
                     84: 
                     85:        /*
                     86:         * Ignore clock interrupts till we are ready.
                     87:         */
                     88:        if (batflag == 0)
                     89:                return;
                     90: 
                     91:        /*
                     92:         * Hook for alternate clock interrupt;
                     93:         * Call polling function ("altclk") if there is one.
                     94:         *
                     95:         * For near function, "altsel" is 0 and "altclk" is offset.
                     96:         * For far function, "altsel" is the CS selector and "altclk"
                     97:         * is the offset.
                     98:         *
                     99:         * Since the polling function ends with a near rather than
                    100:         * far return, far invocation is via ld_call() (ldas.s) which uses
                    101:         * the despatch routine at CS:4 (ld.s) in any loadable driver.
                    102:         */
                    103:        if (altclk) {
                    104: #if    ! _I386
                    105:                if (altsel) {   /* will do far call to altclk fn */
                    106:                        if (ld_call (altsel, altclk))
                    107:                                return;
                    108:                } else
                    109: #endif
                    110:                        if ((* altclk) ())
                    111:                                return;
                    112:        }
                    113: 
                    114:        /*
                    115:         * Update timers.  Decrement time slice.
                    116:         */
                    117:        utimer += 1;
                    118:        clocks += 1;
                    119:        timer.t_tick += 1;
                    120:        quantum -= 1;
                    121: 
                    122: #if    ! _I386
                    123:        /*
                    124:         * Give processes their schedule values per tick.
                    125:         */
                    126:        if (procq.p_lforw->p_cval > CVCLOCK) {
                    127:                procq.p_lforw->p_cval -= CVCLOCK;
                    128:                procq.p_cval += CVCLOCK;
                    129:        }
                    130: #endif
                    131: 
                    132:        /*
                    133:         * Tax current process and update his times.
                    134:         */
                    135:        pp = SELF;
                    136: #if    ! _I386
                    137:        pp->p_cval >>= 1;
                    138: #endif
                    139:        if (umode == R_USR) {
                    140:                pp->p_utime ++;
                    141:                u.u_ppc = pc;
                    142:        } else
                    143:                pp->p_stime ++;
                    144: }
                    145: 
                    146: /*
                    147:  * stand()
                    148:  *
                    149:  * Called when there is an interrupt or trap, and the system is about to
                    150:  * return to user mode (or to the idle process).
                    151:  */
                    152: 
                    153: void
                    154: stand (regset)
                    155: gregset_t      regset;
                    156: {
                    157:        int s;
                    158: 
                    159: #ifdef TIMING
                    160:        /*
                    161:         * Every 500th call to stand(), dump logged intervals.
                    162:         *
                    163:         * Log a group of events doing
                    164:         *      LOGIN(label);
                    165:         *      ...
                    166:         *      LOGOUT();
                    167:         *
                    168:         * If you want to group several selected events in one total,
                    169:         * do LOGPAUSE() to halt between events and LOGRESUME() to
                    170:         * add in the time for another event.  Event count is displayed.
                    171:         * For example:
                    172:         *      LOGIN(label);
                    173:         *      while (...) {
                    174:         *              LOGPAUSE();
                    175:         *              ... stuff you don't want timed...
                    176:         *              LOGRESUME();
                    177:         *              ... stuff you want timed...
                    178:         *      }
                    179:         *      LOGOUT();
                    180:         *
                    181:         * Display is for the 3 longest intervals seen in latest logging
                    182:         * period.
                    183:         *
                    184:         * Timing between in & out is displayed with ~1 usec resolution.
                    185:         * Overhead per event is ~20 usec.
                    186:         */
                    187:        static int call_ct; /* DEBUG */
                    188: 
                    189:        call_ct++;
                    190:        if (call_ct >= 500) {
                    191:                call_ct = 0;
                    192:                LOGLIST();
                    193:        }
                    194: #endif
                    195: 
                    196:        u.u_error = 0;
                    197: 
                    198:        /*
                    199:         * Update the clock.
                    200:         */
                    201: 
                    202:        while (timer.t_tick >= HZ) {
                    203: #ifdef TRACER
                    204:                extern  int     checkTheSum ();
                    205:                static  int     check_check;
                    206: 
                    207:                if (check_check ++ > 120) {
                    208:                        check_check = 0;
                    209:                        checkTheSum ();
                    210:                }
                    211: #endif
                    212:                timer.t_time ++;
                    213:                timer.t_tick -= HZ;
                    214:                outflag = 1;
                    215:        }
                    216: 
                    217:        /*
                    218:         * Check expiration of quantum.
                    219:         */
                    220: 
                    221:        if (quantum <= 0) {
                    222:                quantum = 0;
                    223:                disflag = 1;
                    224:        }
                    225: 
                    226:        /*
                    227:         * Check the timed function queue if necessary.
                    228:         */
                    229: 
                    230:        while (clocks) {
                    231:                register TIM * np;
                    232:                register TIM * tp;
                    233: 
                    234:                /*
                    235:                 * Update [serviced] clock ticks since startup.
                    236:                 */
                    237:                lbolt ++;
                    238:                clocks --;
                    239: 
                    240:                /*
                    241:                 * Remove timing list from queue, creating new temporary queue.
                    242:                 */
                    243: 
                    244:                tp = timq + (lbolt % __ARRAY_LENGTH (timq));
                    245:                s  = sphi ();
                    246: 
                    247:                /*
                    248:                 * Scan timing list.
                    249:                 */
                    250: 
                    251:                for (np = tp->t_next; tp = np;) {
                    252:                        /*
                    253:                         * Remember next function in timing list.
                    254:                         * NOTE: Must be done before function is invoked,
                    255:                         *       since it may start a new timer.
                    256:                         */
                    257: 
                    258:                        np = tp->t_next;
                    259: 
                    260:                        /*
                    261:                         * Function has not timed out: leave it on timing list.
                    262:                         */
                    263: 
                    264:                        if (tp->t_lbolt != lbolt)
                    265:                                continue;
                    266: 
                    267:                        /*
                    268:                         * Remove function from timing list.
                    269:                         */
                    270: 
                    271:                        if (tp->t_last->t_next = tp->t_next)
                    272:                                tp->t_next->t_last = tp->t_last;
                    273:                        tp->t_last = NULL;
                    274: 
                    275:                        /*
                    276:                         * Invoke function.
                    277:                         */
                    278: #ifdef TRACER
                    279:                        if (tp->t_func < & stext || tp->t_func > & __end_text)
                    280:                                panic ("Bad timeout function %x in timer %x",
                    281:                                        tp->t_func, tp);
                    282: #endif
                    283: 
                    284:                        spl (s);
                    285:                        (* tp->t_func) (tp->t_farg, tp);
                    286:                        sphi ();
                    287:                }
                    288: 
                    289:                spl (s);
                    290: 
                    291:                STREAMS_TIMEOUT ();
                    292: 
                    293:        }
                    294: 
                    295:        /*
                    296:         * Timeout any devices.
                    297:         */
                    298: 
                    299:        if (outflag) {
                    300:                register int n;
                    301: 
                    302:                outflag = 0;
                    303:                for (n = 0 ; n < drvn ; n ++) {
                    304:                        if (drvl [n].d_time == 0)
                    305:                                continue;
                    306:                        s = sphi ();
                    307:                        dtime ((dev_t) makedev (n, 0));
                    308:                        spl (s);
                    309:                }
                    310:        }
                    311: 
                    312:        /*
                    313:         * Do profiling.
                    314:         */
                    315: 
                    316: #if    _I386   /* profiling */
                    317:        if (u.u_pscale & ~1) {  /* if scale is not zero or one */
                    318:                /*
                    319:                 * Treat u.u_pscale as fixed-point fraction 0xXXXX.YYYY.
                    320:                 * Increment the (short) profiling entry at
                    321:                 *      base + (pc - offset) * scale
                    322:                 */
                    323:                register caddr_t a;
                    324: 
                    325:                a = (caddr_t) ((long) (u.u_pbase + pscale(u.u_ppc-u.u_pofft,
                    326:                                                          u.u_pscale)) & ~1);
                    327:                if (a < u.u_pbend)
                    328:                        putusd(a, getusd(a)+1);
                    329:        }
                    330: #else          /* profiling */
                    331:        if (u.u_pscale) {
                    332:                register unsigned p;
                    333:                register caddr_t a;
                    334: 
                    335:                p = u.u_pscale;
                    336:                a = (int *)u.u_pbase +
                    337:                    pscale((int)(u.u_ppc-u.u_pofft), p/sizeof (int));
                    338:                if (a < u.u_pbend)
                    339:                        putuwd(a, getuwd(a)+1);
                    340:        }
                    341: #endif         /* profiling */
                    342: 
                    343:        /*
                    344:         * Check for signals and execute them; we pass in the address of the
                    345:         * user's process context rather than depend on the state of the
                    346:         * "u.u_regl" global idiocy.
                    347:         */
                    348: 
                    349:        curr_check_signals (& regset);
                    350: 
                    351: 
                    352:        /*
                    353:         * Execute deferred functions.
                    354:         */
                    355: 
                    356:        defend ();
                    357: 
                    358: 
                    359:        /*
                    360:         * Should we dispatch?
                    361:         */
                    362:        if ((SELF->p_flags & PFDISP) != 0) {
                    363:                SELF->p_flags &= ~ PFDISP;
                    364:                disflag = 1;
                    365:                if (stimer.t_last != 0)
                    366:                        wakeup ((char *)& stimer);
                    367:        }
                    368: 
                    369:        /*
                    370:         * Redispatch.
                    371:         */
                    372:        if (disflag) {
                    373:                register PROC *pp;
                    374: 
                    375:                s = sphi ();
                    376:                if ((pp = SELF) != iprocp)
                    377:                        setrun (pp);
                    378:                dispatch ();
                    379:                spl (s);
                    380:        }
                    381: 
                    382:        STREAMS_SCHEDULER ();
                    383: }
                    384: 
                    385: #ifdef TIMING
                    386: 
                    387: #define EIMAX 3
                    388: 
                    389: static int label, b_in, t_in;
                    390: static int b_pause, t_pause, e_pause, paused, timing;
                    391: 
                    392: struct H_event {
                    393:        int f; /* timing label */
                    394:        int b; /* delta ticks */
                    395:        int t; /* delta timer */
                    396:        int e; /* event count */
                    397: } Ltab[EIMAX];
                    398: 
                    399: LOGIN(lab)
                    400: {
                    401:        paused = 0;
                    402:        b_pause = t_pause = 0;
                    403:        e_pause = 1;
                    404:        label = lab;
                    405:        b_in = clocks + lbolt;
                    406:        t_in = read_t0();
                    407:        timing = 1;
                    408: }
                    409: 
                    410: LOGOUT()
                    411: {
                    412:        int i;
                    413: 
                    414:        if (!timing)
                    415:                return;
                    416:        if (!paused) {
                    417:                b_pause += clocks + lbolt - b_in;
                    418:                t_pause += (t_in - read_t0());
                    419:                if (t_pause < 0)
                    420:                        t_pause += 11932;
                    421:        }
                    422:        for (i = 0; i < EIMAX; i++) {
                    423:                if (b_pause > Ltab[i].b) {
                    424:                        Ltab[i].b = b_pause;
                    425:                        Ltab[i].t = t_pause;
                    426:                        Ltab[i].f = label;
                    427:                        Ltab[i].e = e_pause;
                    428:                        break;
                    429:                } else if (b_pause == Ltab[i].b) {
                    430:                        if (t_pause > Ltab[i].t) {
                    431:                                Ltab[i].t = t_pause;
                    432:                                Ltab[i].f = label;
                    433:                                Ltab[i].e = e_pause;
                    434:                                break;
                    435:                        } else if (t_pause == Ltab[i].t) {
                    436:                                break;
                    437:                        }
                    438:                }
                    439:        }
                    440:        timing = 0;
                    441: }
                    442: 
                    443: LOGLIST()
                    444: {
                    445:        int i, printed = 0;
                    446: 
                    447:        for (i = 0; i < EIMAX; i++)
                    448:                if (Ltab[i].t || Ltab[i].b) {
                    449:                        if (printed == 0) {
                    450:                                printf("\npsw=%x ", read_psw());
                    451:                                printed = 1;
                    452:                        }
                    453:                        printf("f=%x b=%d t=%d e=%d  ",
                    454:                          Ltab[i].f, Ltab[i].b, Ltab[i].t, Ltab[i].e);
                    455:                        Ltab[i].f = Ltab[i].b = Ltab[i].t = 0;
                    456:                } else
                    457:                        break;
                    458: }
                    459: 
                    460: LOGPAUSE()
                    461: {
                    462:        if (!timing)
                    463:                return;
                    464:        if (!paused) {
                    465:                b_pause += clocks + lbolt - b_in;
                    466:                t_pause += (t_in - read_t0());
                    467:                if (t_pause < 0)
                    468:                        t_pause += 11932;
                    469:                paused = 1;
                    470:        }
                    471: }
                    472: 
                    473: LOGRESUME()
                    474: {
                    475:        if (!timing)
                    476:                return;
                    477:        if (paused) {
                    478:                b_in = clocks + lbolt;
                    479:                t_in = read_t0();
                    480:                paused = 0;
                    481:                e_pause++;
                    482:        }
                    483: }
                    484: #endif

unix.superglobalmegacorp.com

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