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
12 /*******************************************************************\
15 * Information Technology Center *
16 * Carnegie-Mellon University *
20 \*******************************************************************/
23 #include <afs/param.h>
30 #ifdef AFS_LINUX20_ENV
31 /* Should now have all the possible places for picking up insque. */
42 typedef unsigned char bool;
47 #define expiration TotalTime
49 #define new_elem() ((struct TM_Elem *) malloc(sizeof(struct TM_Elem)))
51 #define MILLION 1000000
53 static globalInitDone = 0;
55 #if !defined(AFS_HPUX_ENV) && !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD_ENV)
60 static void subtract(t1, t2, t3)
61 register struct timeval *t1, *t2, *t3;
63 register int sec2, usec2, sec3, usec3;
66 usec2 = t2 -> tv_usec;
68 usec3 = t3 -> tv_usec;
70 /* Take care of the probably non-existent case where the
71 * usec field has more than 1 second in it. */
73 while (usec3 > usec2) {
78 /* Check for a negative time and use zero for the answer,
79 * since the tv_sec field is unsigned */
83 t1 -> tv_sec = (afs_uint32) 0;
85 t1 -> tv_usec = usec2 - usec3;
86 t1 -> tv_sec = sec2 - sec3;
92 static void add(t1, t2)
93 register struct timeval *t1, *t2;
95 t1 -> tv_usec += t2 -> tv_usec;
96 t1 -> tv_sec += t2 -> tv_sec;
97 if (t1->tv_usec >= MILLION) {
99 t1 -> tv_usec -= MILLION;
105 int TM_eql(struct timeval *t1, struct timeval *t2)
107 return (t1->tv_usec == t2->tv_usec) && (t1->tv_sec == t2->tv_sec);
113 obsolete, commentless procedure, all done by hand expansion now.
114 static bool geq(t1, t2)
115 register struct timeval *t1, *t2;
117 return (t1->tv_sec > t2->tv_sec) ||
118 (t1->tv_sec == t2->tv_sec && t1->tv_usec >= t2->tv_usec);
122 static bool blocking(t)
123 register struct TM_Elem *t;
125 return (t->TotalTime.tv_sec < 0 || t->TotalTime.tv_usec < 0);
131 Initializes a list -- returns -1 if failure, else 0.
135 register struct TM_Elem **list;
137 if (!globalInitDone) {
145 (*list) -> Next = *list;
146 (*list) -> Prev = *list;
147 (*list) -> TotalTime.tv_sec = 0;
148 (*list) -> TotalTime.tv_usec = 0;
149 (*list) -> TimeLeft.tv_sec = 0;
150 (*list) -> TimeLeft.tv_usec = 0;
151 (*list) -> BackPointer = NULL;
158 register struct TM_Elem **list;
160 if (list == NULL || *list == NULL)
170 Inserts elem into the timer list pointed to by *tlistPtr.
173 void TM_Insert(tlistPtr, elem)
174 struct TM_Elem *tlistPtr; /* pointer to head pointer of timer list */
175 struct TM_Elem *elem; /* element to be inserted */
177 register struct TM_Elem *next;
179 /* TimeLeft must be set for function IOMGR with infinite timeouts */
180 elem -> TimeLeft = elem -> TotalTime;
182 /* Special case -- infinite timeout */
183 if (blocking(elem)) {
184 insque(elem, tlistPtr->Prev);
188 /* Finite timeout, set expiration time */
189 FT_AGetTimeOfDay(&elem->expiration, 0);
190 add(&elem->expiration, &elem->TimeLeft);
192 FOR_ALL_ELTS(p, tlistPtr, {
193 if (blocking(p) || !(elem->TimeLeft.tv_sec > p->TimeLeft.tv_sec ||
194 (elem->TimeLeft.tv_sec == p->TimeLeft.tv_sec && elem->TimeLeft.tv_usec >= p->TimeLeft.tv_usec))
196 next = p; /* Save ptr to element that will be after this one */
201 if (next == NULL) next = tlistPtr;
202 insque(elem, next->Prev);
206 Walks through the specified list and updates the TimeLeft fields in it.
207 Returns number of expired elements in the list.
211 struct TM_Elem *tlist; /* head pointer of timer list */
214 register int expired;
216 FT_AGetTimeOfDay(&time, 0);
218 FOR_ALL_ELTS(e, tlist, {
220 subtract(&e->TimeLeft, &e->expiration, &time);
221 if (0 > e->TimeLeft.tv_sec || (0 == e->TimeLeft.tv_sec && 0 >= e->TimeLeft.tv_usec))
229 RETURNS POINTER TO earliest expired entry from tlist.
230 Returns 0 if no expired entries are present.
233 struct TM_Elem *TM_GetExpired(tlist)
234 struct TM_Elem *tlist; /* head pointer of timer list */
236 FOR_ALL_ELTS(e, tlist, {
238 (0 > e->TimeLeft.tv_sec || (0 == e->TimeLeft.tv_sec && 0 >= e->TimeLeft.tv_usec)))
245 Returns a pointer to the earliest unexpired element in tlist.
246 Its TimeLeft field will specify how much time is left.
247 Returns 0 if tlist is empty or if there are no unexpired elements.
250 struct TM_Elem *TM_GetEarliest(tlist)
251 struct TM_Elem *tlist;
253 register struct TM_Elem *e;
256 return (e == tlist ? NULL : e);
259 #if defined(AFS_HPUX_ENV) || defined(AFS_NT40_ENV) || defined(AFS_FBSD_ENV)
260 /* This used to be in hputils.c, but it's only use is in the LWP package. */
262 * Emulate the vax instructions for queue insertion and deletion, somewhat.
263 * A std_queue structure is defined here and used by these routines. These
264 * routines use caddr_ts so they can operate on any structure. The std_queue
265 * structure is used rather than proc structures so that when the proc struct
266 * changes only process management code breaks. The ideal solution would be
267 * to define a std_queue as a global type which is part of all the structures
268 * which are manipulated by these routines. This would involve considerable
272 void insque(struct TM_Elem *elementp, struct TM_Elem *quep)
274 elementp->Next = quep->Next;
275 elementp->Prev = quep;
277 quep->Next->Prev = elementp;
278 quep->Next = elementp;
281 void remque(struct TM_Elem *elementp)
283 elementp->Next->Prev = elementp->Prev;
284 elementp->Prev->Next = elementp->Next;
285 elementp->Prev = elementp->Next = (struct TM_Elem*)0;
288 #endif /* AFS_HPUX_ENV || AFS_NT40_ENV || AFS_FBSD_ENV */