Annotation of Net2/netiso/tp_timer.c, revision 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.