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>
33 typedef unsigned char bool;
38 #define expiration TotalTime
40 #define new_elem() (malloc(sizeof(struct TM_Elem)))
42 #define MILLION 1000000
44 static int globalInitDone
= 0;
48 subtract(struct timeval
*t1
, struct timeval
*t2
,
51 int sec2
, usec2
, sec3
, usec3
;
58 /* Take care of the probably non-existent case where the
59 * usec field has more than 1 second in it. */
61 while (usec3
> usec2
) {
66 /* Check for a negative time and use zero for the answer,
67 * since the tv_sec field is unsigned */
71 t1
->tv_sec
= (afs_uint32
) 0;
73 t1
->tv_usec
= usec2
- usec3
;
74 t1
->tv_sec
= sec2
- sec3
;
81 add(struct timeval
*t1
, struct timeval
*t2
)
83 t1
->tv_usec
+= t2
->tv_usec
;
84 t1
->tv_sec
+= t2
->tv_sec
;
85 if (t1
->tv_usec
>= MILLION
) {
87 t1
->tv_usec
-= MILLION
;
94 TM_eql(struct timeval
*t1
, struct timeval
*t2
)
96 return (t1
->tv_usec
== t2
->tv_usec
) && (t1
->tv_sec
== t2
->tv_sec
);
102 obsolete, commentless procedure, all done by hand expansion now.
103 static bool geq(struct timeval *t1, struct timeval *t2)
105 return (t1->tv_sec > t2->tv_sec) ||
106 (t1->tv_sec == t2->tv_sec && t1->tv_usec >= t2->tv_usec);
111 blocking(struct TM_Elem
*t
)
113 return (t
->TotalTime
.tv_sec
< 0 || t
->TotalTime
.tv_usec
< 0);
119 Initializes a list -- returns -1 if failure, else 0.
123 TM_Init(struct TM_Elem
**list
)
125 if (!globalInitDone
) {
133 (*list
)->Next
= *list
;
134 (*list
)->Prev
= *list
;
135 (*list
)->TotalTime
.tv_sec
= 0;
136 (*list
)->TotalTime
.tv_usec
= 0;
137 (*list
)->TimeLeft
.tv_sec
= 0;
138 (*list
)->TimeLeft
.tv_usec
= 0;
139 (*list
)->BackPointer
= NULL
;
146 TM_Final(struct TM_Elem
**list
)
148 if (list
== NULL
|| *list
== NULL
)
158 Inserts elem into the timer list pointed to by *tlistPtr.
162 TM_Insert(struct TM_Elem
*tlistPtr
, struct TM_Elem
*elem
)
164 struct TM_Elem
*next
;
166 /* TimeLeft must be set for function IOMGR with infinite timeouts */
167 elem
->TimeLeft
= elem
->TotalTime
;
169 /* Special case -- infinite timeout */
170 if (blocking(elem
)) {
171 openafs_insque(elem
, tlistPtr
->Prev
);
175 /* Finite timeout, set expiration time */
176 FT_AGetTimeOfDay(&elem
->expiration
, 0);
177 add(&elem
->expiration
, &elem
->TimeLeft
);
179 FOR_ALL_ELTS(p
, tlistPtr
, {
181 || !(elem
->TimeLeft
.tv_sec
> p
->TimeLeft
.tv_sec
182 || (elem
->TimeLeft
.tv_sec
== p
->TimeLeft
.tv_sec
183 && elem
->TimeLeft
.tv_usec
>=
184 p
->TimeLeft
.tv_usec
))
186 next
= p
; /* Save ptr to element that will be after this one */
193 openafs_insque(elem
, next
->Prev
);
197 Walks through the specified list and updates the TimeLeft fields in it.
198 Returns number of expired elements in the list.
202 TM_Rescan(struct TM_Elem
*tlist
) /* head pointer of timer list */
207 FT_AGetTimeOfDay(&time
, 0);
209 FOR_ALL_ELTS(e
, tlist
, {
211 subtract(&e
->TimeLeft
, &e
->expiration
, &time
);
212 if (0 > e
->TimeLeft
.tv_sec
213 || (0 == e
->TimeLeft
.tv_sec
&& 0 >= e
->TimeLeft
.tv_usec
))
221 RETURNS POINTER TO earliest expired entry from tlist.
222 Returns 0 if no expired entries are present.
226 TM_GetExpired(struct TM_Elem
*tlist
) /* head pointer of timer list */
228 FOR_ALL_ELTS(e
, tlist
, {
230 && (0 > e
->TimeLeft
.tv_sec
231 || (0 == e
->TimeLeft
.tv_sec
232 && 0 >= e
->TimeLeft
.tv_usec
)))
239 Returns a pointer to the earliest unexpired element in tlist.
240 Its TimeLeft field will specify how much time is left.
241 Returns 0 if tlist is empty or if there are no unexpired elements.
245 TM_GetEarliest(struct TM_Elem
*tlist
)
250 return (e
== tlist
? NULL
: e
);
253 /* This used to be in hputils.c, but it's only use is in the LWP package. */
255 * Emulate the vax instructions for queue insertion and deletion, somewhat.
256 * A std_queue structure is defined here and used by these routines. These
257 * routines use caddr_ts so they can operate on any structure. The std_queue
258 * structure is used rather than proc structures so that when the proc struct
259 * changes only process management code breaks. The ideal solution would be
260 * to define a std_queue as a global type which is part of all the structures
261 * which are manipulated by these routines. This would involve considerable
266 openafs_insque(struct TM_Elem
*elementp
, struct TM_Elem
*quep
)
268 elementp
->Next
= quep
->Next
;
269 elementp
->Prev
= quep
;
271 quep
->Next
->Prev
= elementp
;
272 quep
->Next
= elementp
;
276 openafs_remque(struct TM_Elem
*elementp
)
278 elementp
->Next
->Prev
= elementp
->Prev
;
279 elementp
->Prev
->Next
= elementp
->Next
;
280 elementp
->Prev
= elementp
->Next
= NULL
;