2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 /*******************************************************************\
13 * Information Technology Center *
14 * Carnegie-Mellon University *
18 \*******************************************************************/
21 #include <afsconfig.h>
22 #include <afs/param.h>
32 #ifdef AFS_LINUX20_ENV
33 /* Should now have all the possible places for picking up insque. */
44 typedef unsigned char bool;
49 #define expiration TotalTime
51 #define new_elem() ((struct TM_Elem *) malloc(sizeof(struct TM_Elem)))
53 #define MILLION 1000000
55 static globalInitDone = 0;
57 #if !defined(AFS_HPUX_ENV) && !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD_ENV)
62 static void subtract(t1, t2, t3)
63 register struct timeval *t1, *t2, *t3;
65 register int sec2, usec2, sec3, usec3;
68 usec2 = t2 -> tv_usec;
70 usec3 = t3 -> tv_usec;
72 /* Take care of the probably non-existent case where the
73 * usec field has more than 1 second in it. */
75 while (usec3 > usec2) {
80 /* Check for a negative time and use zero for the answer,
81 * since the tv_sec field is unsigned */
85 t1 -> tv_sec = (afs_uint32) 0;
87 t1 -> tv_usec = usec2 - usec3;
88 t1 -> tv_sec = sec2 - sec3;
94 static void add(t1, t2)
95 register struct timeval *t1, *t2;
97 t1 -> tv_usec += t2 -> tv_usec;
98 t1 -> tv_sec += t2 -> tv_sec;
99 if (t1->tv_usec >= MILLION) {
101 t1 -> tv_usec -= MILLION;
107 int TM_eql(struct timeval *t1, struct timeval *t2)
109 return (t1->tv_usec == t2->tv_usec) && (t1->tv_sec == t2->tv_sec);
115 obsolete, commentless procedure, all done by hand expansion now.
116 static bool geq(t1, t2)
117 register struct timeval *t1, *t2;
119 return (t1->tv_sec > t2->tv_sec) ||
120 (t1->tv_sec == t2->tv_sec && t1->tv_usec >= t2->tv_usec);
124 static bool blocking(t)
125 register struct TM_Elem *t;
127 return (t->TotalTime.tv_sec < 0 || t->TotalTime.tv_usec < 0);
133 Initializes a list -- returns -1 if failure, else 0.
137 register struct TM_Elem **list;
139 if (!globalInitDone) {
147 (*list) -> Next = *list;
148 (*list) -> Prev = *list;
149 (*list) -> TotalTime.tv_sec = 0;
150 (*list) -> TotalTime.tv_usec = 0;
151 (*list) -> TimeLeft.tv_sec = 0;
152 (*list) -> TimeLeft.tv_usec = 0;
153 (*list) -> BackPointer = NULL;
160 register struct TM_Elem **list;
162 if (list == NULL || *list == NULL)
172 Inserts elem into the timer list pointed to by *tlistPtr.
175 void TM_Insert(tlistPtr, elem)
176 struct TM_Elem *tlistPtr; /* pointer to head pointer of timer list */
177 struct TM_Elem *elem; /* element to be inserted */
179 register struct TM_Elem *next;
181 /* TimeLeft must be set for function IOMGR with infinite timeouts */
182 elem -> TimeLeft = elem -> TotalTime;
184 /* Special case -- infinite timeout */
185 if (blocking(elem)) {
186 insque(elem, tlistPtr->Prev);
190 /* Finite timeout, set expiration time */
191 FT_AGetTimeOfDay(&elem->expiration, 0);
192 add(&elem->expiration, &elem->TimeLeft);
194 FOR_ALL_ELTS(p, tlistPtr, {
195 if (blocking(p) || !(elem->TimeLeft.tv_sec > p->TimeLeft.tv_sec ||
196 (elem->TimeLeft.tv_sec == p->TimeLeft.tv_sec && elem->TimeLeft.tv_usec >= p->TimeLeft.tv_usec))
198 next = p; /* Save ptr to element that will be after this one */
203 if (next == NULL) next = tlistPtr;
204 insque(elem, next->Prev);
208 Walks through the specified list and updates the TimeLeft fields in it.
209 Returns number of expired elements in the list.
213 struct TM_Elem *tlist; /* head pointer of timer list */
216 register int expired;
218 #ifndef AFS_DJGPP_ENV
219 FT_AGetTimeOfDay(&time, 0);
221 FT_GetTimeOfDay(&time, 0); /* we need a real time value */
224 FOR_ALL_ELTS(e, tlist, {
226 subtract(&e->TimeLeft, &e->expiration, &time);
227 if (0 > e->TimeLeft.tv_sec || (0 == e->TimeLeft.tv_sec && 0 >= e->TimeLeft.tv_usec))
235 RETURNS POINTER TO earliest expired entry from tlist.
236 Returns 0 if no expired entries are present.
239 struct TM_Elem *TM_GetExpired(tlist)
240 struct TM_Elem *tlist; /* head pointer of timer list */
242 FOR_ALL_ELTS(e, tlist, {
244 (0 > e->TimeLeft.tv_sec || (0 == e->TimeLeft.tv_sec && 0 >= e->TimeLeft.tv_usec)))
251 Returns a pointer to the earliest unexpired element in tlist.
252 Its TimeLeft field will specify how much time is left.
253 Returns 0 if tlist is empty or if there are no unexpired elements.
256 struct TM_Elem *TM_GetEarliest(tlist)
257 struct TM_Elem *tlist;
259 register struct TM_Elem *e;
262 return (e == tlist ? NULL : e);
265 #if defined(AFS_HPUX_ENV) || defined(AFS_NT40_ENV) || defined(AFS_FBSD_ENV)
266 /* This used to be in hputils.c, but it's only use is in the LWP package. */
268 * Emulate the vax instructions for queue insertion and deletion, somewhat.
269 * A std_queue structure is defined here and used by these routines. These
270 * routines use caddr_ts so they can operate on any structure. The std_queue
271 * structure is used rather than proc structures so that when the proc struct
272 * changes only process management code breaks. The ideal solution would be
273 * to define a std_queue as a global type which is part of all the structures
274 * which are manipulated by these routines. This would involve considerable
278 void insque(struct TM_Elem *elementp, struct TM_Elem *quep)
280 elementp->Next = quep->Next;
281 elementp->Prev = quep;
283 quep->Next->Prev = elementp;
284 quep->Next = elementp;
287 void remque(struct TM_Elem *elementp)
289 elementp->Next->Prev = elementp->Prev;
290 elementp->Prev->Next = elementp->Next;
291 elementp->Prev = elementp->Next = (struct TM_Elem*)0;
294 #endif /* AFS_HPUX_ENV || AFS_NT40_ENV || AFS_FBSD_ENV */