BSD 4_4 release
[unix-history] / usr / src / sys / netiso / tp_timer.c
index f898df5..b3a0be3 100644 (file)
@@ -1,3 +1,38 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)tp_timer.c  8.1 (Berkeley) 6/10/93
+ */
+
 /***********************************************************
                Copyright IBM Corporation 1987
 
 /***********************************************************
                Copyright IBM Corporation 1987
 
@@ -29,47 +64,30 @@ SOFTWARE.
  *
  * $Header: tp_timer.c,v 5.2 88/11/18 17:29:07 nhall Exp $
  * $Source: /usr/argo/sys/netiso/RCS/tp_timer.c,v $
  *
  * $Header: tp_timer.c,v 5.2 88/11/18 17:29:07 nhall Exp $
  * $Source: /usr/argo/sys/netiso/RCS/tp_timer.c,v $
- *     @(#)tp_timer.c  7.3 (Berkeley) 8/29/89 *
- *
- * Contains all the timer code.  
- * There are two sources of calls to these routines:
- * the clock, and tp.trans. (ok, and tp_pcb.c calls it at init time)
  *
  *
- * Timers come in two flavors - those that generally get
- * cancelled (tp_ctimeout, tp_cuntimeout)
- * and those that either usually expire (tp_etimeout, 
- * tp_euntimeout, tp_slowtimo) or may require more than one instance
- * of the timer active at a time.
- *
- * The C timers are stored in the tp_ref structure. Their "going off"
- * is manifested by a driver event of the TM_xxx form.
- *
- * The E timers are handled like the generic kernel callouts.
- * Their "going off" is manifested by a function call w/ 3 arguments.
  */
 
  */
 
-#ifndef lint
-static char *rcsid = "$Header: tp_timer.c,v 5.2 88/11/18 17:29:07 nhall Exp $";
-#endif lint
-
-#include "param.h"
-#include "types.h"
-#include "time.h"
-#include "malloc.h"
-
-#include "tp_param.h"
-#include "tp_timer.h"
-#include "tp_stat.h"
-#include "tp_pcb.h"
-#include "tp_tpdu.h"
-#include "argo_debug.h"
-#include "tp_trace.h"
-#include "tp_seq.h"
-
-static  struct Ecallout *TP_callfree;
-static  struct Ecallout TP_callout[N_TPREF*2]; 
-
-extern int tp_maxrefopen;  /* highest ref # of an open tp connection */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/malloc.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/kernel.h>
+
+#include <netiso/argo_debug.h>
+#include <netiso/tp_param.h>
+#include <netiso/tp_timer.h>
+#include <netiso/tp_stat.h>
+#include <netiso/tp_pcb.h>
+#include <netiso/tp_tpdu.h>
+#include <netiso/tp_trace.h>
+#include <netiso/tp_seq.h>
+
+struct tp_ref *tp_ref;
+int    tp_rttdiv, tp_rttadd, N_TPREF = 127;
+struct tp_refinfo tp_refinfo;
+struct tp_pcb *tp_ftimeolist = (struct tp_pcb *)&tp_ftimeolist;
 
 /*
  * CALLED FROM:
 
 /*
  * CALLED FROM:
@@ -81,146 +99,53 @@ extern int tp_maxrefopen;  /* highest ref # of an open tp connection */
 void
 tp_timerinit()
 {
 void
 tp_timerinit()
 {
-       register int i;
+       register int s;
        /*
        /*
-        * Initialize callouts
+        * Initialize storage
         */
         */
-       TP_callfree = TP_callout;
-       for (i = 1; i < N_TPREF*2; i++)
-               TP_callout[i-1].c_next = &TP_callout[i];
-
-       bzero( (caddr_t)tp_ref, N_TPREF * sizeof(struct tp_ref) );
-
-       /* hate to do this but we really don't want zero to be a legit ref */
-       tp_maxrefopen = 1;
-       tp_ref[0].tpr_state = REF_FROZEN;  /* white lie -- no ref timer, don't
-               * want this one to be allocated- ever
-               * unless, of course, you make refs and address instead of an
-               * index - then 0 can be allocated
-               */
-
+       if (tp_refinfo.tpr_base)
+               return;
+       tp_refinfo.tpr_size = N_TPREF + 1;  /* Need to start somewhere */
+       s = sizeof(*tp_ref) * tp_refinfo.tpr_size;
+       if ((tp_ref = (struct tp_ref *) malloc(s, M_PCB, M_NOWAIT)) == 0)
+               panic("tp_timerinit");
+       bzero((caddr_t)tp_ref, (unsigned) s);
+       tp_refinfo.tpr_base = tp_ref;
+       tp_rttdiv = hz / PR_SLOWHZ;
+       tp_rttadd = (2 * tp_rttdiv) - 1;
 }
 }
-
+#ifdef TP_DEBUG_TIMERS
 /**********************  e timers *************************/
 
 /**********************  e timers *************************/
 
-/*
- * CALLED FROM:
- *  tp_slowtimo() every 1/2 second, for each open reference
- * FUNCTION and ARGUMENTS:
- *  (refp) indicates a reference structure that is in use.
- *  This ref structure may contain active E-type timers.
- *  Update the timers and if any expire, create an event and
- *  call the driver.
- */
-static void
-tp_Eclock(refp)
-       struct tp_ref   *refp; /* the reference structure */
-{
-       register struct Ecallout *p1; /* to drift through the list of callouts */
-       struct tp_event                  E; /* event to pass to tp_driver() */
-       int                                              tp_driver(); /* drives the FSM */
-
-       /*
-        * Update real-time timeout queue.
-        * At front of queue are some number of events which are ``due''.
-        * The time to these is <= 0 and if negative represents the
-        * number of ticks which have passed since it was supposed to happen.
-        * The rest of the q elements (times > 0) are events yet to happen,
-        * where the time for each is given as a delta from the previous.
-        * Decrementing just the first of these serves to decrement the time
-        * to all events.
-        * 
-        * This version, which calls the driver directly, doesn't pass
-        * along the ticks - may want to add the ticks if there's any use
-        * for them.
-        */
-       IncStat(ts_Eticks);
-       p1 = refp->tpr_calltodo.c_next;
-       while (p1) {
-               if (--p1->c_time > 0)
-                       break;
-               if (p1->c_time == 0)
-                       break;
-               p1 = p1->c_next;
-       }
-
-       for (;;) {
-               struct tp_pcb *tpcb;
-               if ((p1 = refp->tpr_calltodo.c_next) == 0 || p1->c_time > 0) {
-                       break;
-               }
-               refp->tpr_calltodo.c_next = p1->c_next;
-               p1->c_next = TP_callfree;
-
-#ifndef lint
-               E.ev_number = p1->c_func;
-               E.ATTR(TM_data_retrans).e_low = (SeqNum) p1->c_arg1;
-               E.ATTR(TM_data_retrans).e_high = (SeqNum) p1->c_arg2;
-               E.ATTR(TM_data_retrans).e_retrans =  p1->c_arg3;
-#endif lint
-               IFDEBUG(D_TIMER)
-                       printf("E expired! event 0x%x (0x%x,0x%x), pcb 0x%x ref %d\n",
-                               p1->c_func, p1->c_arg1, p1->c_arg2, refp->tpr_pcb,
-                               refp-tp_ref);
-               ENDDEBUG
-
-               TP_callfree = p1;
-               IncStat(ts_Eexpired);
-               (void) tp_driver( tpcb = refp->tpr_pcb, &E);
-               if (p1->c_func == TM_reference && tpcb->tp_state == TP_CLOSED)
-                       free((caddr_t)tpcb, M_PCB); /* XXX wart; where else to do it? */
-       }
-}
-
 /*
  * CALLED FROM:
  *  tp.trans all over
  * FUNCTION and ARGUMENTS:
 /*
  * CALLED FROM:
  *  tp.trans all over
  * FUNCTION and ARGUMENTS:
- * Set an E type timer.  (refp) is the ref structure.
- * Causes  fun(arg1,arg2,arg3) to be called after time t.
+ * Set an E type timer.
  */
 void
  */
 void
-tp_etimeout(refp, fun, arg1, arg2, arg3, ticks)
-       struct tp_ref   *refp;          
-       int                     fun;    /* function to be called */
-       u_int                   arg1, arg2; 
-       int                             arg3;
-       register int    ticks;
+tp_etimeout(tpcb, fun, ticks)
+       register struct tp_pcb  *tpcb;
+       int                                     fun;    /* function to be called */
+       int                                             ticks;
 {
 {
-       register struct Ecallout *p1, *p2, *pnew;
-               /* p1 and p2 drift through the list of timeout callout structures,
-                * pnew points to the newly created callout structure
-                */
 
 
+       register u_int *callp;
        IFDEBUG(D_TIMER)
        IFDEBUG(D_TIMER)
-               printf("etimeout pcb 0x%x state 0x%x\n", refp->tpr_pcb,
-               refp->tpr_pcb->tp_state);
+               printf("etimeout pcb 0x%x state 0x%x\n", tpcb, tpcb->tp_state);
        ENDDEBUG
        IFTRACE(D_TIMER)
        ENDDEBUG
        IFTRACE(D_TIMER)
-               tptrace(TPPTmisc, "tp_etimeout ref refstate tks Etick", refp-tp_ref,
-               refp->tpr_state, ticks, tp_stat.ts_Eticks);
+               tptrace(TPPTmisc, "tp_etimeout ref refstate tks Etick", tpcb->tp_lref,
+               tpcb->tp_state, ticks, tp_stat.ts_Eticks);
        ENDTRACE
        ENDTRACE
-
+       if (tpcb == 0)
+               return;
        IncStat(ts_Eset);
        if (ticks == 0)
                ticks = 1;
        IncStat(ts_Eset);
        if (ticks == 0)
                ticks = 1;
-       pnew = TP_callfree;
-       if (pnew == (struct Ecallout *)0)
-               panic("tp timeout table overflow");
-       TP_callfree = pnew->c_next;
-       pnew->c_arg1 = arg1;
-       pnew->c_arg2 = arg2;
-       pnew->c_arg3 = arg3;
-       pnew->c_func = fun;
-       for (p1 = &(refp->tpr_calltodo); 
-                                                       (p2 = p1->c_next) && p2->c_time < ticks; p1 = p2)
-               if (p2->c_time > 0)
-                       ticks -= p2->c_time;
-       p1->c_next = pnew;
-       pnew->c_next = p2;
-       pnew->c_time = ticks;
-       if (p2)
-               p2->c_time -= ticks;
+       callp = tpcb->tp_timer + fun;
+       if (*callp == 0 || *callp > ticks)
+               *callp = ticks;
 }
 
 /*
 }
 
 /*
@@ -230,64 +155,16 @@ tp_etimeout(refp, fun, arg1, arg2, arg3, ticks)
  *  Cancel all occurrences of E-timer function (fun) for reference (refp)
  */
 void
  *  Cancel all occurrences of E-timer function (fun) for reference (refp)
  */
 void
-tp_euntimeout(refp, fun)
-       struct tp_ref *refp;
-       int                       fun;
-{
-       register struct Ecallout *p1, *p2; /* ptrs to drift through the list */
-
-       IFTRACE(D_TIMER)
-               tptrace(TPPTmisc, "tp_euntimeout ref", refp-tp_ref, 0, 0, 0);
-       ENDTRACE
-
-       p1 = &refp->tpr_calltodo; 
-       while ( (p2 = p1->c_next) != 0) {
-               if (p2->c_func == fun)  {
-                       if (p2->c_next && p2->c_time > 0) 
-                               p2->c_next->c_time += p2->c_time;
-                       p1->c_next = p2->c_next;
-                       p2->c_next = TP_callfree;
-                       TP_callfree = p2;
-                       IncStat(ts_Ecan_act);
-                       continue;
-               }
-               p1 = p2;
-       }
-}
-
-/*
- * CALLED FROM:
- *  tp.trans, when an incoming ACK causes things to be dropped
- *  from the retransmission queue, and we want their associated
- *  timers to be cancelled.
- * FUNCTION and ARGUMENTS:
- *  cancel all occurrences of function (fun) where (arg2) < (seq)
- */
-void
-tp_euntimeout_lss(refp, fun, seq)
-       struct tp_ref *refp;
+tp_euntimeout(tpcb, fun)
+       register struct tp_pcb  *tpcb;
        int                       fun;
        int                       fun;
-       SeqNum            seq;
 {
 {
-       register struct Ecallout *p1, *p2;
-
        IFTRACE(D_TIMER)
        IFTRACE(D_TIMER)
-               tptrace(TPPTmisc, "tp_euntimeoutLSS ref", refp-tp_ref, seq, 0, 0);
+               tptrace(TPPTmisc, "tp_euntimeout ref", tpcb->tp_lref, 0, 0, 0);
        ENDTRACE
 
        ENDTRACE
 
-       p1 = &refp->tpr_calltodo; 
-       while ( (p2 = p1->c_next) != 0) {
-               if ((p2->c_func == fun) && SEQ_LT(refp->tpr_pcb, p2->c_arg2, seq))  {
-                       if (p2->c_next && p2->c_time > 0) 
-                               p2->c_next->c_time += p2->c_time;
-                       p1->c_next = p2->c_next;
-                       p2->c_next = TP_callfree;
-                       TP_callfree = p2;
-                       IncStat(ts_Ecan_act);
-                       continue;
-               }
-               p1 = p2;
-       }
+       if (tpcb)
+               tpcb->tp_timer[fun] = 0;
 }
 
 /****************  c timers **********************
 }
 
 /****************  c timers **********************
@@ -297,7 +174,7 @@ tp_euntimeout_lss(refp, fun, seq)
  * are typically cancelled so it's faster not to
  * mess with the chains
  */
  * are typically cancelled so it's faster not to
  * mess with the chains
  */
-
+#endif
 /*
  * CALLED FROM:
  *  the clock, every 500 ms
 /*
  * CALLED FROM:
  *  the clock, every 500 ms
@@ -305,47 +182,123 @@ tp_euntimeout_lss(refp, fun, seq)
  *  Look for open references with active timers.
  *  If they exist, call the appropriate timer routines to update
  *  the timers and possibly generate events.
  *  Look for open references with active timers.
  *  If they exist, call the appropriate timer routines to update
  *  the timers and possibly generate events.
- *  (The E timers are done in other procedures; the C timers are
- *  updated here, and events for them are generated here.)
  */
 ProtoHook
 tp_slowtimo()
 {
  */
 ProtoHook
 tp_slowtimo()
 {
-       register int            r,t;
-       struct Ccallout         *cp;
-       struct tp_ref           *rp = tp_ref;
+       register u_int  *cp;
+       register struct tp_ref          *rp;
+       struct tp_pcb           *tpcb;
        struct tp_event         E;
        struct tp_event         E;
-       int                             s = splnet();
+       int                             s = splnet(), t;
 
        /* check only open reference structures */
        IncStat(ts_Cticks);
 
        /* check only open reference structures */
        IncStat(ts_Cticks);
-       rp++;   /* tp_ref[0] is never used */
-       for(  r=1 ; (r <= tp_maxrefopen) ; r++,rp++ ) {
-               if (rp->tpr_state < REF_OPEN) 
+       /* tp_ref[0] is never used */
+       for (rp = tp_ref + tp_refinfo.tpr_maxopen; rp > tp_ref; rp--) {
+               if ((tpcb = rp->tpr_pcb) == 0 || tpcb->tp_refstate < REF_OPEN) 
                        continue;
                        continue;
-
-               /* check the C-type timers */
-               cp = rp->tpr_callout;
-               for (t=0 ; t < N_CTIMERS; t++,cp++) {
-                       if( cp->c_active ) {
-                               if( --cp->c_time <= 0 ) {
-                                       cp->c_active = FALSE;
-                                       E.ev_number = t;
-                                       IFDEBUG(D_TIMER)
-                                               printf("C expired! type 0x%x\n", t);
-                                       ENDDEBUG
-                                       IncStat(ts_Cexpired);
-                                       tp_driver( rp->tpr_pcb, &E);
+               /* check the timers */
+               for (t = 0; t < TM_NTIMERS; t++) {
+                       cp = tpcb->tp_timer + t;
+                       if (*cp && --(*cp) <= 0 ) {
+                               *cp = 0;
+                               E.ev_number = t;
+                               IFDEBUG(D_TIMER)
+                                       printf("tp_slowtimo: pcb 0x%x t %d\n",
+                                                       tpcb, t);
+                               ENDDEBUG
+                               IncStat(ts_Cexpired);
+                               tp_driver(tpcb, &E);
+                               if (t == TM_reference && tpcb->tp_state == TP_CLOSED) {
+                                       if (tpcb->tp_notdetached) {
+                                               IFDEBUG(D_CONN)
+                                                       printf("PRU_DETACH: not detached\n");
+                                               ENDDEBUG
+                                               tp_detach(tpcb);
+                                       }
+                                       /* XXX wart; where else to do it? */
+                                       free((caddr_t)tpcb, M_PCB);
                                }
                        }
                }
                                }
                        }
                }
-               /* now update the list */
-               tp_Eclock(rp);
        }
        splx(s);
        return 0;
 }
 
        }
        splx(s);
        return 0;
 }
 
+/*
+ * Called From: tp.trans from tp_slowtimo() -- retransmission timer went off.
+ */
+tp_data_retrans(tpcb)
+register struct tp_pcb *tpcb;
+{
+       int rexmt, win;
+       tpcb->tp_rttemit = 0;   /* cancel current round trip time */
+       tpcb->tp_dupacks = 0;
+       tpcb->tp_sndnxt = tpcb->tp_snduna;
+       if (tpcb->tp_fcredit == 0) {
+               /*
+                * We transmitted new data, started timing it and the window
+                * got shrunk under us.  This can only happen if all data
+                * that they wanted us to send got acked, so don't
+                * bother shrinking the congestion windows, et. al.
+                * The retransmission timer should have been reset in goodack()
+                */
+               IFDEBUG(D_ACKRECV)
+                       printf("tp_data_retrans: 0 window tpcb 0x%x una 0x%x\n",
+                               tpcb, tpcb->tp_snduna);
+               ENDDEBUG
+               tpcb->tp_rxtshift = 0;
+               tpcb->tp_timer[TM_data_retrans] = 0;
+               tpcb->tp_timer[TM_sendack] = tpcb->tp_dt_ticks;
+               return;
+       }
+       rexmt = tpcb->tp_dt_ticks << min(tpcb->tp_rxtshift, TP_MAXRXTSHIFT);
+       win = min(tpcb->tp_fcredit, (tpcb->tp_cong_win / tpcb->tp_l_tpdusize / 2));
+       win = max(win, 2);
+       tpcb->tp_cong_win = tpcb->tp_l_tpdusize;        /* slow start again. */
+       tpcb->tp_ssthresh = win * tpcb->tp_l_tpdusize;
+       /* We're losing; our srtt estimate is probably bogus.
+        * Clobber it so we'll take the next rtt measurement as our srtt;
+        * Maintain current rxt times until then.
+        */
+       if (++tpcb->tp_rxtshift > TP_NRETRANS / 4) {
+               /* tpcb->tp_nlprotosw->nlp_losing(tpcb->tp_npcb) someday */
+               tpcb->tp_rtt = 0;
+       }
+       TP_RANGESET(tpcb->tp_rxtcur, rexmt, tpcb->tp_peer_acktime, 128);
+       tpcb->tp_timer[TM_data_retrans] = tpcb->tp_rxtcur;
+       tp_send(tpcb);
+}
+
+int
+tp_fasttimo()
+{
+       register struct tp_pcb *t;
+       int s = splnet();
+       struct tp_event         E;
+
+       E.ev_number = TM_sendack;
+       while ((t = tp_ftimeolist) != (struct tp_pcb *)&tp_ftimeolist) {
+               if (t == 0) {
+                       printf("tp_fasttimeo: should panic");
+                       tp_ftimeolist = (struct tp_pcb *)&tp_ftimeolist;
+               } else {
+                       if (t->tp_flags & TPF_DELACK) {
+                               IncStat(ts_Fdelack);
+                               tp_driver(t, &E);
+                               t->tp_flags &= ~TPF_DELACK;
+                       } else
+                               IncStat(ts_Fpruned);
+                       tp_ftimeolist = t->tp_fasttimeo;
+                       t->tp_fasttimeo = 0;
+               }
+       }
+       splx(s);
+}
+
+#ifdef TP_DEBUG_TIMERS
 /*
  * CALLED FROM:
  *  tp.trans, tp_emit()
 /*
  * CALLED FROM:
  *  tp.trans, tp_emit()
@@ -353,21 +306,21 @@ tp_slowtimo()
  *     Set a C type timer of type (which) to go off after (ticks) time.
  */
 void
  *     Set a C type timer of type (which) to go off after (ticks) time.
  */
 void
-tp_ctimeout(refp, which, ticks)
-       register struct tp_ref  *refp;
+tp_ctimeout(tpcb, which, ticks)
+       register struct tp_pcb  *tpcb;
        int                                     which, ticks; 
 {
        int                                     which, ticks; 
 {
-       register struct Ccallout *cp = &(refp->tpr_callout[which]);
 
        IFTRACE(D_TIMER)
                tptrace(TPPTmisc, "tp_ctimeout ref which tpcb active", 
 
        IFTRACE(D_TIMER)
                tptrace(TPPTmisc, "tp_ctimeout ref which tpcb active", 
-                       (int)(refp - tp_ref), which, refp->tpr_pcb, cp->c_active);
+                       tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]);
        ENDTRACE
        ENDTRACE
-       if(cp->c_active)
+       if(tpcb->tp_timer[which])
                IncStat(ts_Ccan_act);
        IncStat(ts_Cset);
                IncStat(ts_Ccan_act);
        IncStat(ts_Cset);
-       cp->c_time = ticks;
-       cp->c_active = TRUE;
+       if (ticks <= 0)
+               ticks = 1;
+       tpcb->tp_timer[which] = ticks;
 }
 
 /*
 }
 
 /*
@@ -378,25 +331,20 @@ tp_ctimeout(refp, which, ticks)
  *     parameter (ticks) is > the current value of the timer.
  */
 void
  *     parameter (ticks) is > the current value of the timer.
  */
 void
-tp_ctimeout_MIN(refp, which, ticks)
-       register struct tp_ref  *refp;
+tp_ctimeout_MIN(tpcb, which, ticks)
+       register struct tp_pcb  *tpcb;
        int                                             which, ticks; 
 {
        int                                             which, ticks; 
 {
-       register struct Ccallout *cp = &(refp->tpr_callout[which]);
-
        IFTRACE(D_TIMER)
                tptrace(TPPTmisc, "tp_ctimeout_MIN ref which tpcb active", 
        IFTRACE(D_TIMER)
                tptrace(TPPTmisc, "tp_ctimeout_MIN ref which tpcb active", 
-                       (int)(refp - tp_ref), which, refp->tpr_pcb, cp->c_active);
+                       tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]);
        ENDTRACE
        ENDTRACE
-       if(cp->c_active)
-               IncStat(ts_Ccan_act);
        IncStat(ts_Cset);
        IncStat(ts_Cset);
-       if( cp->c_active ) 
-               cp->c_time = MIN(ticks, cp->c_time);
-       else  {
-               cp->c_time = ticks;
-               cp->c_active = TRUE;
-       }
+       if (tpcb->tp_timer[which])  {
+               tpcb->tp_timer[which] = min(ticks, tpcb->tp_timer[which]);
+               IncStat(ts_Ccan_act);
+       } else
+               tpcb->tp_timer[which] = ticks;
 }
 
 /*
 }
 
 /*
@@ -406,26 +354,24 @@ tp_ctimeout_MIN(refp, which, ticks)
  *  Cancel the (which) timer in the ref structure indicated by (refp).
  */
 void
  *  Cancel the (which) timer in the ref structure indicated by (refp).
  */
 void
-tp_cuntimeout(refp, which)
+tp_cuntimeout(tpcb, which)
+       register struct tp_pcb  *tpcb;
        int                                             which;
        int                                             which;
-       register struct tp_ref  *refp;
 {
 {
-       register struct Ccallout *cp;
-
-       cp = &(refp->tpr_callout[which]);
-
        IFDEBUG(D_TIMER)
        IFDEBUG(D_TIMER)
-               printf("tp_cuntimeout(0x%x, %d) active %d\n", refp, which, cp->c_active);
+               printf("tp_cuntimeout(0x%x, %d) active %d\n",
+                               tpcb, which, tpcb->tp_timer[which]);
        ENDDEBUG
 
        IFTRACE(D_TIMER)
                tptrace(TPPTmisc, "tp_cuntimeout ref which, active", refp-tp_ref, 
        ENDDEBUG
 
        IFTRACE(D_TIMER)
                tptrace(TPPTmisc, "tp_cuntimeout ref which, active", refp-tp_ref, 
-                       which, cp->c_active, 0);
+                       which, tpcb->tp_timer[which], 0);
        ENDTRACE
 
        ENDTRACE
 
-       if(cp->c_active)
+       if (tpcb->tp_timer[which])
                IncStat(ts_Ccan_act);
        else
                IncStat(ts_Ccan_inact);
                IncStat(ts_Ccan_act);
        else
                IncStat(ts_Ccan_inact);
-       cp->c_active = FALSE;
+       tpcb->tp_timer[which] = 0;
 }
 }
+#endif