Annotation of 43BSDReno/sys/netiso/tp_timer.c, revision 1.1.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.