2 ****************************************************************************
3 * Copyright IBM Corporation 1988, 1989 - All Rights Reserved *
5 * Permission to use, copy, modify, and distribute this software and its *
6 * documentation for any purpose and without fee is hereby granted, *
7 * provided that the above copyright notice appear in all copies and *
8 * that both that copyright notice and this permission notice appear in *
9 * supporting documentation, and that the name of IBM not be used in *
10 * advertising or publicity pertaining to distribution of the software *
11 * without specific, written prior permission. *
13 * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL *
14 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL IBM *
15 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY *
16 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER *
17 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING *
18 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *
19 ****************************************************************************
27 * All event processing is relative to the apparent current time
28 * given by clock_GetTime
31 /* This should be static, but event_test wants to look at the free list... */
32 struct rx_queue rxevent_free
; /* It's somewhat bogus to use a
33 * doubly-linked queue for the free
35 static struct rx_queue rxevent_queue
; /* The list of waiting events */
36 static int rxevent_allocUnit
= 10; /* Allocation unit (number of event
37 * records to allocate at one time) */
38 int rxevent_nFree
; /* Number of free event records */
39 int rxevent_nPosted
; /* Current number of posted events */
40 static void (*rxevent_ScheduledEarlierEvent
) ();/* Proc to call when an event
41 * is scheduled that is
42 * earlier than all other
44 static struct xfreelist
{
45 struct xfreelist
*next
;
46 } *xfreemallocs
= 0, *xsp
= 0;
49 FILE *rxevent_debugFile
; /* Set to an stdio descriptor for
50 * event logging to that file */
53 /* Pass in the number of events to allocate at a time */
54 static int initialized
= 0;
57 rxevent_Init(int nEvents
, void (*scheduler
) ())
63 rxevent_allocUnit
= nEvents
;
64 queue_Init(&rxevent_free
);
65 queue_Init(&rxevent_queue
);
66 rxevent_nFree
= rxevent_nPosted
= 0;
67 rxevent_ScheduledEarlierEvent
= scheduler
;
71 /* Add the indicated event (function, arg) at the specified clock time */
73 rxevent_Post(struct clock
* when
, void (*func
)(), void *arg
, void *arg1
)
74 /* when - When event should happen, in clock (clock.h) units */
76 struct rxevent
*ev
, *qe
, *qpr
;
83 fprintf(Log
, "%ld.%ld: rxevent_Post(%ld.%ld, %p, %p)\n",
84 now
.sec
, now
.usec
, when
->sec
, when
->usec
, func
, arg
);
87 #if defined(AFS_SGIMP_ENV)
88 ASSERT(osi_rxislocked());
92 * If we're short on free event entries, create a block of new ones and
93 * add them to the free queue
95 if (queue_IsEmpty(&rxevent_free
)) {
98 #if defined(AFS_AIX32_ENV) && defined(KERNEL)
99 ev
= (struct rxevent
*) rxi_Alloc(sizeof(struct rxevent
));
100 queue_Append(&rxevent_free
, &ev
[0]), rxevent_nFree
++;
102 ev
= (struct rxevent
*) osi_Alloc(sizeof(struct rxevent
) *
105 xfreemallocs
= (struct xfreelist
*) ev
;
106 xfreemallocs
->next
= xsp
;
107 for (i
= 0; i
< rxevent_allocUnit
; i
++)
108 queue_Append(&rxevent_free
, &ev
[i
]), rxevent_nFree
++;
111 /* Grab and initialize a new rxevent structure */
112 ev
= queue_First(&rxevent_free
, rxevent
);
116 /* Record user defined event state */
117 ev
->eventTime
= *when
;
121 rxevent_nPosted
+= 1; /* Rather than ++, to shut high-C up
122 * regarding never-set variables */
125 * Locate a slot for the new entry. The queue is ordered by time, and we
126 * assume that a new entry is likely to be greater than a majority of the
127 * entries already on the queue (unless there's very few entries on the
128 * queue), so we scan it backwards
130 for (queue_ScanBackwards(&rxevent_queue
, qe
, qpr
, rxevent
)) {
131 if (clock_Ge(when
, &qe
->eventTime
)) {
132 queue_InsertAfter(qe
, ev
);
136 /* The event is to expire earlier than any existing events */
137 queue_Prepend(&rxevent_queue
, ev
);
138 if (rxevent_ScheduledEarlierEvent
)
139 (*rxevent_ScheduledEarlierEvent
) (); /* Notify our external
145 * Cancel an event by moving it from the event queue to the free list.
146 * Warning, the event must be on the event queue! If not, this should core
147 * dump (reference through 0). This routine should be called using the macro
148 * event_Cancel, which checks for a null event and also nulls the caller's
149 * event pointer after cancelling the event.
152 rxevent_Cancel_1(struct rxevent
* ev
)
159 fprintf(Log
, "%ld.%ld: rxevent_Cancel_1(%ld.%ld, %p, %p)\n",
160 now
.sec
, now
.usec
, ev
->eventTime
.sec
, ev
->eventTime
.usec
,
165 * Append it to the free list (rather than prepending) to keep
166 * the free list hot so nothing pages out
168 #if defined(AFS_SGIMP_ENV)
169 ASSERT(osi_rxislocked());
171 queue_MoveAppend(&rxevent_free
, ev
);
177 * Process all events that have expired relative to the current clock time
178 * (which is not re-evaluated unless clock_NewTime has been called).
179 * The relative time to the next event is returned in the output parameter
180 * next and the function returns 1. If there are is no next event,
181 * the function returns 0.
184 rxevent_RaiseEvents(struct clock
* next
)
191 fprintf(Log
, "rxevent_RaiseEvents(%ld.%ld)\n", now
.sec
, now
.usec
);
195 * Events are sorted by time, so only scan until an event is found that
196 * has not yet timed out
198 while (queue_IsNotEmpty(&rxevent_queue
)) {
200 qe
= queue_First(&rxevent_queue
, rxevent
);
201 if (clock_Lt(&now
, &qe
->eventTime
)) {
202 *next
= qe
->eventTime
;
203 clock_Sub(next
, &now
);
208 qe
->func(qe
, qe
->arg
, qe
->arg1
);
209 queue_Append(&rxevent_free
, qe
);
217 shutdown_rxevent(void)
219 struct xfreelist
*xp
, *nxp
;
222 #if defined(AFS_AIX32_ENV) && defined(KERNEL)
223 /* Everything is freed in afs_osinet.c */
225 while ((xp
= xfreemallocs
) != NULL
) {
227 osi_Free((char *) xp
, sizeof(struct rxevent
) * rxevent_allocUnit
);