Annotation of 43BSDReno/sys/netiso/tp_timer.c, revision 1.1

1.1     ! root        1: /***********************************************************
        !             2:                Copyright IBM Corporation 1987
        !             3: 
        !             4:                       All Rights Reserved
        !             5: 
        !             6: Permission to use, copy, modify, and distribute this software and its 
        !             7: documentation for any purpose and without fee is hereby granted, 
        !             8: provided that the above copyright notice appear in all copies and that
        !             9: both that copyright notice and this permission notice appear in 
        !            10: supporting documentation, and that the name of IBM not be
        !            11: used in advertising or publicity pertaining to distribution of the
        !            12: software without specific, written prior permission.  
        !            13: 
        !            14: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
        !            15: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
        !            16: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
        !            17: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
        !            18: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
        !            19: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
        !            20: SOFTWARE.
        !            21: 
        !            22: ******************************************************************/
        !            23: 
        !            24: /*
        !            25:  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
        !            26:  */
        !            27: /* 
        !            28:  * ARGO TP
        !            29:  *
        !            30:  * $Header: tp_timer.c,v 5.2 88/11/18 17:29:07 nhall Exp $
        !            31:  * $Source: /usr/argo/sys/netiso/RCS/tp_timer.c,v $
        !            32:  *     @(#)tp_timer.c  7.3 (Berkeley) 8/29/89 *
        !            33:  *
        !            34:  * Contains all the timer code.  
        !            35:  * There are two sources of calls to these routines:
        !            36:  * the clock, and tp.trans. (ok, and tp_pcb.c calls it at init time)
        !            37:  *
        !            38:  * Timers come in two flavors - those that generally get
        !            39:  * cancelled (tp_ctimeout, tp_cuntimeout)
        !            40:  * and those that either usually expire (tp_etimeout, 
        !            41:  * tp_euntimeout, tp_slowtimo) or may require more than one instance
        !            42:  * of the timer active at a time.
        !            43:  *
        !            44:  * The C timers are stored in the tp_ref structure. Their "going off"
        !            45:  * is manifested by a driver event of the TM_xxx form.
        !            46:  *
        !            47:  * The E timers are handled like the generic kernel callouts.
        !            48:  * Their "going off" is manifested by a function call w/ 3 arguments.
        !            49:  */
        !            50: 
        !            51: #ifndef lint
        !            52: static char *rcsid = "$Header: tp_timer.c,v 5.2 88/11/18 17:29:07 nhall Exp $";
        !            53: #endif lint
        !            54: 
        !            55: #include "param.h"
        !            56: #include "types.h"
        !            57: #include "time.h"
        !            58: #include "malloc.h"
        !            59: 
        !            60: #include "tp_param.h"
        !            61: #include "tp_timer.h"
        !            62: #include "tp_stat.h"
        !            63: #include "tp_pcb.h"
        !            64: #include "tp_tpdu.h"
        !            65: #include "argo_debug.h"
        !            66: #include "tp_trace.h"
        !            67: #include "tp_seq.h"
        !            68: 
        !            69: static  struct Ecallout *TP_callfree;
        !            70: static  struct Ecallout TP_callout[N_TPREF*2]; 
        !            71: 
        !            72: extern int tp_maxrefopen;  /* highest ref # of an open tp connection */
        !            73: 
        !            74: /*
        !            75:  * CALLED FROM:
        !            76:  *  at autoconfig time from tp_init() 
        !            77:  *     a combo of event, state, predicate
        !            78:  * FUNCTION and ARGUMENTS:
        !            79:  *  initialize data structures for the timers
        !            80:  */
        !            81: void
        !            82: tp_timerinit()
        !            83: {
        !            84:        register int i;
        !            85:        /*
        !            86:         * Initialize callouts
        !            87:         */
        !            88:        TP_callfree = TP_callout;
        !            89:        for (i = 1; i < N_TPREF*2; i++)
        !            90:                TP_callout[i-1].c_next = &TP_callout[i];
        !            91: 
        !            92:        bzero( (caddr_t)tp_ref, N_TPREF * sizeof(struct tp_ref) );
        !            93: 
        !            94:        /* hate to do this but we really don't want zero to be a legit ref */
        !            95:        tp_maxrefopen = 1;
        !            96:        tp_ref[0].tpr_state = REF_FROZEN;  /* white lie -- no ref timer, don't
        !            97:                * want this one to be allocated- ever
        !            98:                * unless, of course, you make refs and address instead of an
        !            99:                * index - then 0 can be allocated
        !           100:                */
        !           101: 
        !           102: }
        !           103: 
        !           104: /**********************  e timers *************************/
        !           105: 
        !           106: /*
        !           107:  * CALLED FROM:
        !           108:  *  tp_slowtimo() every 1/2 second, for each open reference
        !           109:  * FUNCTION and ARGUMENTS:
        !           110:  *  (refp) indicates a reference structure that is in use.
        !           111:  *  This ref structure may contain active E-type timers.
        !           112:  *  Update the timers and if any expire, create an event and
        !           113:  *  call the driver.
        !           114:  */
        !           115: static void
        !           116: tp_Eclock(refp)
        !           117:        struct tp_ref   *refp; /* the reference structure */
        !           118: {
        !           119:        register struct Ecallout *p1; /* to drift through the list of callouts */
        !           120:        struct tp_event                  E; /* event to pass to tp_driver() */
        !           121:        int                                              tp_driver(); /* drives the FSM */
        !           122: 
        !           123:        /*
        !           124:         * Update real-time timeout queue.
        !           125:         * At front of queue are some number of events which are ``due''.
        !           126:         * The time to these is <= 0 and if negative represents the
        !           127:         * number of ticks which have passed since it was supposed to happen.
        !           128:         * The rest of the q elements (times > 0) are events yet to happen,
        !           129:         * where the time for each is given as a delta from the previous.
        !           130:         * Decrementing just the first of these serves to decrement the time
        !           131:         * to all events.
        !           132:         * 
        !           133:         * This version, which calls the driver directly, doesn't pass
        !           134:         * along the ticks - may want to add the ticks if there's any use
        !           135:         * for them.
        !           136:         */
        !           137:        IncStat(ts_Eticks);
        !           138:        p1 = refp->tpr_calltodo.c_next;
        !           139:        while (p1) {
        !           140:                if (--p1->c_time > 0)
        !           141:                        break;
        !           142:                if (p1->c_time == 0)
        !           143:                        break;
        !           144:                p1 = p1->c_next;
        !           145:        }
        !           146: 
        !           147:        for (;;) {
        !           148:                struct tp_pcb *tpcb;
        !           149:                if ((p1 = refp->tpr_calltodo.c_next) == 0 || p1->c_time > 0) {
        !           150:                        break;
        !           151:                }
        !           152:                refp->tpr_calltodo.c_next = p1->c_next;
        !           153:                p1->c_next = TP_callfree;
        !           154: 
        !           155: #ifndef lint
        !           156:                E.ev_number = p1->c_func;
        !           157:                E.ATTR(TM_data_retrans).e_low = (SeqNum) p1->c_arg1;
        !           158:                E.ATTR(TM_data_retrans).e_high = (SeqNum) p1->c_arg2;
        !           159:                E.ATTR(TM_data_retrans).e_retrans =  p1->c_arg3;
        !           160: #endif lint
        !           161:                IFDEBUG(D_TIMER)
        !           162:                        printf("E expired! event 0x%x (0x%x,0x%x), pcb 0x%x ref %d\n",
        !           163:                                p1->c_func, p1->c_arg1, p1->c_arg2, refp->tpr_pcb,
        !           164:                                refp-tp_ref);
        !           165:                ENDDEBUG
        !           166: 
        !           167:                TP_callfree = p1;
        !           168:                IncStat(ts_Eexpired);
        !           169:                (void) tp_driver( tpcb = refp->tpr_pcb, &E);
        !           170:                if (p1->c_func == TM_reference && tpcb->tp_state == TP_CLOSED)
        !           171:                        free((caddr_t)tpcb, M_PCB); /* XXX wart; where else to do it? */
        !           172:        }
        !           173: }
        !           174: 
        !           175: /*
        !           176:  * CALLED FROM:
        !           177:  *  tp.trans all over
        !           178:  * FUNCTION and ARGUMENTS:
        !           179:  * Set an E type timer.  (refp) is the ref structure.
        !           180:  * Causes  fun(arg1,arg2,arg3) to be called after time t.
        !           181:  */
        !           182: void
        !           183: tp_etimeout(refp, fun, arg1, arg2, arg3, ticks)
        !           184:        struct tp_ref   *refp;          
        !           185:        int                     fun;    /* function to be called */
        !           186:        u_int                   arg1, arg2; 
        !           187:        int                             arg3;
        !           188:        register int    ticks;
        !           189: {
        !           190:        register struct Ecallout *p1, *p2, *pnew;
        !           191:                /* p1 and p2 drift through the list of timeout callout structures,
        !           192:                 * pnew points to the newly created callout structure
        !           193:                 */
        !           194: 
        !           195:        IFDEBUG(D_TIMER)
        !           196:                printf("etimeout pcb 0x%x state 0x%x\n", refp->tpr_pcb,
        !           197:                refp->tpr_pcb->tp_state);
        !           198:        ENDDEBUG
        !           199:        IFTRACE(D_TIMER)
        !           200:                tptrace(TPPTmisc, "tp_etimeout ref refstate tks Etick", refp-tp_ref,
        !           201:                refp->tpr_state, ticks, tp_stat.ts_Eticks);
        !           202:        ENDTRACE
        !           203: 
        !           204:        IncStat(ts_Eset);
        !           205:        if (ticks == 0)
        !           206:                ticks = 1;
        !           207:        pnew = TP_callfree;
        !           208:        if (pnew == (struct Ecallout *)0)
        !           209:                panic("tp timeout table overflow");
        !           210:        TP_callfree = pnew->c_next;
        !           211:        pnew->c_arg1 = arg1;
        !           212:        pnew->c_arg2 = arg2;
        !           213:        pnew->c_arg3 = arg3;
        !           214:        pnew->c_func = fun;
        !           215:        for (p1 = &(refp->tpr_calltodo); 
        !           216:                                                        (p2 = p1->c_next) && p2->c_time < ticks; p1 = p2)
        !           217:                if (p2->c_time > 0)
        !           218:                        ticks -= p2->c_time;
        !           219:        p1->c_next = pnew;
        !           220:        pnew->c_next = p2;
        !           221:        pnew->c_time = ticks;
        !           222:        if (p2)
        !           223:                p2->c_time -= ticks;
        !           224: }
        !           225: 
        !           226: /*
        !           227:  * CALLED FROM:
        !           228:  *  tp.trans all over
        !           229:  * FUNCTION and ARGUMENTS:
        !           230:  *  Cancel all occurrences of E-timer function (fun) for reference (refp)
        !           231:  */
        !           232: void
        !           233: tp_euntimeout(refp, fun)
        !           234:        struct tp_ref *refp;
        !           235:        int                       fun;
        !           236: {
        !           237:        register struct Ecallout *p1, *p2; /* ptrs to drift through the list */
        !           238: 
        !           239:        IFTRACE(D_TIMER)
        !           240:                tptrace(TPPTmisc, "tp_euntimeout ref", refp-tp_ref, 0, 0, 0);
        !           241:        ENDTRACE
        !           242: 
        !           243:        p1 = &refp->tpr_calltodo; 
        !           244:        while ( (p2 = p1->c_next) != 0) {
        !           245:                if (p2->c_func == fun)  {
        !           246:                        if (p2->c_next && p2->c_time > 0) 
        !           247:                                p2->c_next->c_time += p2->c_time;
        !           248:                        p1->c_next = p2->c_next;
        !           249:                        p2->c_next = TP_callfree;
        !           250:                        TP_callfree = p2;
        !           251:                        IncStat(ts_Ecan_act);
        !           252:                        continue;
        !           253:                }
        !           254:                p1 = p2;
        !           255:        }
        !           256: }
        !           257: 
        !           258: /*
        !           259:  * CALLED FROM:
        !           260:  *  tp.trans, when an incoming ACK causes things to be dropped
        !           261:  *  from the retransmission queue, and we want their associated
        !           262:  *  timers to be cancelled.
        !           263:  * FUNCTION and ARGUMENTS:
        !           264:  *  cancel all occurrences of function (fun) where (arg2) < (seq)
        !           265:  */
        !           266: void
        !           267: tp_euntimeout_lss(refp, fun, seq)
        !           268:        struct tp_ref *refp;
        !           269:        int                       fun;
        !           270:        SeqNum            seq;
        !           271: {
        !           272:        register struct Ecallout *p1, *p2;
        !           273: 
        !           274:        IFTRACE(D_TIMER)
        !           275:                tptrace(TPPTmisc, "tp_euntimeoutLSS ref", refp-tp_ref, seq, 0, 0);
        !           276:        ENDTRACE
        !           277: 
        !           278:        p1 = &refp->tpr_calltodo; 
        !           279:        while ( (p2 = p1->c_next) != 0) {
        !           280:                if ((p2->c_func == fun) && SEQ_LT(refp->tpr_pcb, p2->c_arg2, seq))  {
        !           281:                        if (p2->c_next && p2->c_time > 0) 
        !           282:                                p2->c_next->c_time += p2->c_time;
        !           283:                        p1->c_next = p2->c_next;
        !           284:                        p2->c_next = TP_callfree;
        !           285:                        TP_callfree = p2;
        !           286:                        IncStat(ts_Ecan_act);
        !           287:                        continue;
        !           288:                }
        !           289:                p1 = p2;
        !           290:        }
        !           291: }
        !           292: 
        !           293: /****************  c timers **********************
        !           294:  *
        !           295:  * These are not chained together; they sit
        !           296:  * in the tp_ref structure. they are the kind that
        !           297:  * are typically cancelled so it's faster not to
        !           298:  * mess with the chains
        !           299:  */
        !           300: 
        !           301: /*
        !           302:  * CALLED FROM:
        !           303:  *  the clock, every 500 ms
        !           304:  * FUNCTION and ARGUMENTS:
        !           305:  *  Look for open references with active timers.
        !           306:  *  If they exist, call the appropriate timer routines to update
        !           307:  *  the timers and possibly generate events.
        !           308:  *  (The E timers are done in other procedures; the C timers are
        !           309:  *  updated here, and events for them are generated here.)
        !           310:  */
        !           311: ProtoHook
        !           312: tp_slowtimo()
        !           313: {
        !           314:        register int            r,t;
        !           315:        struct Ccallout         *cp;
        !           316:        struct tp_ref           *rp = tp_ref;
        !           317:        struct tp_event         E;
        !           318:        int                             s = splnet();
        !           319: 
        !           320:        /* check only open reference structures */
        !           321:        IncStat(ts_Cticks);
        !           322:        rp++;   /* tp_ref[0] is never used */
        !           323:        for(  r=1 ; (r <= tp_maxrefopen) ; r++,rp++ ) {
        !           324:                if (rp->tpr_state < REF_OPEN) 
        !           325:                        continue;
        !           326: 
        !           327:                /* check the C-type timers */
        !           328:                cp = rp->tpr_callout;
        !           329:                for (t=0 ; t < N_CTIMERS; t++,cp++) {
        !           330:                        if( cp->c_active ) {
        !           331:                                if( --cp->c_time <= 0 ) {
        !           332:                                        cp->c_active = FALSE;
        !           333:                                        E.ev_number = t;
        !           334:                                        IFDEBUG(D_TIMER)
        !           335:                                                printf("C expired! type 0x%x\n", t);
        !           336:                                        ENDDEBUG
        !           337:                                        IncStat(ts_Cexpired);
        !           338:                                        tp_driver( rp->tpr_pcb, &E);
        !           339:                                }
        !           340:                        }
        !           341:                }
        !           342:                /* now update the list */
        !           343:                tp_Eclock(rp);
        !           344:        }
        !           345:        splx(s);
        !           346:        return 0;
        !           347: }
        !           348: 
        !           349: /*
        !           350:  * CALLED FROM:
        !           351:  *  tp.trans, tp_emit()
        !           352:  * FUNCTION and ARGUMENTS:
        !           353:  *     Set a C type timer of type (which) to go off after (ticks) time.
        !           354:  */
        !           355: void
        !           356: tp_ctimeout(refp, which, ticks)
        !           357:        register struct tp_ref  *refp;
        !           358:        int                                     which, ticks; 
        !           359: {
        !           360:        register struct Ccallout *cp = &(refp->tpr_callout[which]);
        !           361: 
        !           362:        IFTRACE(D_TIMER)
        !           363:                tptrace(TPPTmisc, "tp_ctimeout ref which tpcb active", 
        !           364:                        (int)(refp - tp_ref), which, refp->tpr_pcb, cp->c_active);
        !           365:        ENDTRACE
        !           366:        if(cp->c_active)
        !           367:                IncStat(ts_Ccan_act);
        !           368:        IncStat(ts_Cset);
        !           369:        cp->c_time = ticks;
        !           370:        cp->c_active = TRUE;
        !           371: }
        !           372: 
        !           373: /*
        !           374:  * CALLED FROM:
        !           375:  *  tp.trans 
        !           376:  * FUNCTION and ARGUMENTS:
        !           377:  *     Version of tp_ctimeout that resets the C-type time if the 
        !           378:  *     parameter (ticks) is > the current value of the timer.
        !           379:  */
        !           380: void
        !           381: tp_ctimeout_MIN(refp, which, ticks)
        !           382:        register struct tp_ref  *refp;
        !           383:        int                                             which, ticks; 
        !           384: {
        !           385:        register struct Ccallout *cp = &(refp->tpr_callout[which]);
        !           386: 
        !           387:        IFTRACE(D_TIMER)
        !           388:                tptrace(TPPTmisc, "tp_ctimeout_MIN ref which tpcb active", 
        !           389:                        (int)(refp - tp_ref), which, refp->tpr_pcb, cp->c_active);
        !           390:        ENDTRACE
        !           391:        if(cp->c_active)
        !           392:                IncStat(ts_Ccan_act);
        !           393:        IncStat(ts_Cset);
        !           394:        if( cp->c_active ) 
        !           395:                cp->c_time = MIN(ticks, cp->c_time);
        !           396:        else  {
        !           397:                cp->c_time = ticks;
        !           398:                cp->c_active = TRUE;
        !           399:        }
        !           400: }
        !           401: 
        !           402: /*
        !           403:  * CALLED FROM:
        !           404:  *  tp.trans
        !           405:  * FUNCTION and ARGUMENTS:
        !           406:  *  Cancel the (which) timer in the ref structure indicated by (refp).
        !           407:  */
        !           408: void
        !           409: tp_cuntimeout(refp, which)
        !           410:        int                                             which;
        !           411:        register struct tp_ref  *refp;
        !           412: {
        !           413:        register struct Ccallout *cp;
        !           414: 
        !           415:        cp = &(refp->tpr_callout[which]);
        !           416: 
        !           417:        IFDEBUG(D_TIMER)
        !           418:                printf("tp_cuntimeout(0x%x, %d) active %d\n", refp, which, cp->c_active);
        !           419:        ENDDEBUG
        !           420: 
        !           421:        IFTRACE(D_TIMER)
        !           422:                tptrace(TPPTmisc, "tp_cuntimeout ref which, active", refp-tp_ref, 
        !           423:                        which, cp->c_active, 0);
        !           424:        ENDTRACE
        !           425: 
        !           426:        if(cp->c_active)
        !           427:                IncStat(ts_Ccan_act);
        !           428:        else
        !           429:                IncStat(ts_Ccan_inact);
        !           430:        cp->c_active = FALSE;
        !           431: }

unix.superglobalmegacorp.com

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