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

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

unix.superglobalmegacorp.com

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