Annotation of Net2/netiso/tp_timer.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

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