*** empty log message ***
[arla.git] / rx / rx_event.c
blobe431733ef45d8506edc2ccc0609937704a8a4031
1 /*
2 ****************************************************************************
3 * Copyright IBM Corporation 1988, 1989 - All Rights Reserved *
4 * *
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. *
12 * *
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 ****************************************************************************
22 #include "rx_locl.h"
24 RCSID("$Id$");
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
34 * list */
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
43 * events */
44 static struct xfreelist {
45 struct xfreelist *next;
46 } *xfreemallocs = 0, *xsp = 0;
48 #ifdef RXDEBUG
49 FILE *rxevent_debugFile; /* Set to an stdio descriptor for
50 * event logging to that file */
51 #endif
53 /* Pass in the number of events to allocate at a time */
54 static int initialized = 0;
56 void
57 rxevent_Init(int nEvents, void (*scheduler) ())
59 if (initialized)
60 return;
61 clock_Init();
62 if (nEvents)
63 rxevent_allocUnit = nEvents;
64 queue_Init(&rxevent_free);
65 queue_Init(&rxevent_queue);
66 rxevent_nFree = rxevent_nPosted = 0;
67 rxevent_ScheduledEarlierEvent = scheduler;
68 initialized = 1;
71 /* Add the indicated event (function, arg) at the specified clock time */
72 struct rxevent *
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;
78 #ifdef RXDEBUG
79 if (Log) {
80 struct clock now;
82 clock_GetTime(&now);
83 fprintf(Log, "%ld.%ld: rxevent_Post(%ld.%ld, %p, %p)\n",
84 now.sec, now.usec, when->sec, when->usec, func, arg);
86 #endif
87 #if defined(AFS_SGIMP_ENV)
88 ASSERT(osi_rxislocked());
89 #endif
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)) {
96 int i;
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++;
101 #else
102 ev = (struct rxevent *) osi_Alloc(sizeof(struct rxevent) *
103 rxevent_allocUnit);
104 xsp = xfreemallocs;
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++;
109 #endif
111 /* Grab and initialize a new rxevent structure */
112 ev = queue_First(&rxevent_free, rxevent);
113 queue_Remove(ev);
114 rxevent_nFree--;
116 /* Record user defined event state */
117 ev->eventTime = *when;
118 ev->func = func;
119 ev->arg = arg;
120 ev->arg1 = arg1;
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);
133 return 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
140 * scheduler */
141 return ev;
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.
151 void
152 rxevent_Cancel_1(struct rxevent * ev)
154 #ifdef RXDEBUG
155 if (Log) {
156 struct clock now;
158 clock_GetTime(&now);
159 fprintf(Log, "%ld.%ld: rxevent_Cancel_1(%ld.%ld, %p, %p)\n",
160 now.sec, now.usec, ev->eventTime.sec, ev->eventTime.usec,
161 ev->func, ev->arg);
163 #endif
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());
170 #endif
171 queue_MoveAppend(&rxevent_free, ev);
172 rxevent_nPosted--;
173 rxevent_nFree++;
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)
186 struct rxevent *qe;
187 struct clock now;
189 #ifdef RXDEBUG
190 if (Log)
191 fprintf(Log, "rxevent_RaiseEvents(%ld.%ld)\n", now.sec, now.usec);
192 #endif
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)) {
199 clock_GetTime(&now);
200 qe = queue_First(&rxevent_queue, rxevent);
201 if (clock_Lt(&now, &qe->eventTime)) {
202 *next = qe->eventTime;
203 clock_Sub(next, &now);
204 return 1;
206 queue_Remove(qe);
207 rxevent_nPosted--;
208 qe->func(qe, qe->arg, qe->arg1);
209 queue_Append(&rxevent_free, qe);
210 rxevent_nFree++;
212 return 0;
215 #if 0
216 static void
217 shutdown_rxevent(void)
219 struct xfreelist *xp, *nxp;
221 initialized = 0;
222 #if defined(AFS_AIX32_ENV) && defined(KERNEL)
223 /* Everything is freed in afs_osinet.c */
224 #else
225 while ((xp = xfreemallocs) != NULL) {
226 nxp = xp->next;
227 osi_Free((char *) xp, sizeof(struct rxevent) * rxevent_allocUnit);
229 #endif
231 #endif