1 /* A simple test of the rx event layer */
9 #include <tests/tap/basic.h>
11 #include "rx/rx_event.h"
12 #include "rx/rx_clock.h"
14 #define NUMEVENTS 10000
16 /* Mutexes and condvars for the scheduler */
17 static int rescheduled
= 0;
18 static pthread_mutex_t eventMutex
;
19 static pthread_cond_t eventCond
;
21 /* Mutexes and condvars for the event list */
23 static pthread_mutex_t eventListMutex
;
25 struct rxevent
*event
;
30 static struct testEvent events
[NUMEVENTS
];
35 pthread_mutex_lock(&eventMutex
);
36 pthread_cond_signal(&eventCond
);
38 pthread_mutex_unlock(&eventMutex
);
43 eventSub(struct rxevent
*event
, void *arg
, void *arg1
, int arg2
)
45 struct testEvent
*evrecord
= arg
;
47 pthread_mutex_lock(&eventListMutex
);
48 rxevent_Put(&evrecord
->event
);
49 evrecord
->event
= NULL
;
51 pthread_mutex_unlock(&eventListMutex
);
56 reportSub(struct rxevent
*event
, void *arg
, void *arg1
, int arg2
)
58 printf("Event fired\n");
62 eventHandler(void *dummy
) {
63 struct timespec nextEvent
;
67 pthread_mutex_lock(&eventMutex
);
69 pthread_mutex_unlock(&eventMutex
);
74 rxevent_RaiseEvents(&next
);
76 pthread_mutex_lock(&eventMutex
);
78 /* If we were rescheduled whilst running the event queue,
79 * process the queue again */
85 clock_Add(&cv
, &next
);
86 nextEvent
.tv_sec
= cv
.sec
;
87 nextEvent
.tv_nsec
= cv
.usec
* 1000;
88 pthread_cond_timedwait(&eventCond
, &eventMutex
, &nextEvent
);
90 pthread_mutex_unlock(&eventMutex
);
98 int when
, counter
, fail
, fired
, cancelled
;
99 struct clock now
, eventTime
;
100 struct rxevent
*event
;
105 pthread_mutex_init(&eventMutex
, NULL
);
106 pthread_cond_init(&eventCond
, NULL
);
108 memset(events
, 0, sizeof(events
));
109 pthread_mutex_init(&eventListMutex
, NULL
);
111 /* Start up the event system */
112 rxevent_Init(20, reschedule
);
113 ok(1, "Started event subsystem");
116 /* Test for a problem when there is only a single event in the tree */
117 event
= rxevent_Post(&now
, &now
, reportSub
, NULL
, NULL
, 0);
118 ok(event
!= NULL
, "Created a single event");
119 rxevent_Cancel(&event
);
120 ok(1, "Cancelled a single event");
121 rxevent_RaiseEvents(&now
);
122 ok(1, "RaiseEvents happened without error");
124 ok(pthread_create(&handler
, NULL
, eventHandler
, NULL
) == 0,
125 "Created handler thread");
127 /* Add 1000 random events to fire over the next 3 seconds, but front-loaded
128 * a bit so that we can exercise the cancel/fire race path. */
130 for (counter
= 0; counter
< NUMEVENTS
; counter
++) {
131 when
= random() % 4000;
132 /* Put 1/4 of events "right away" so we cancel them as they fire */
137 clock_Addmsec(&eventTime
, when
);
138 pthread_mutex_lock(&eventListMutex
);
139 events
[counter
].event
140 = rxevent_Post(&eventTime
, &now
, eventSub
, &events
[counter
], NULL
, 0);
142 /* A 10% chance that we will schedule another event at the same time */
143 if (counter
!=999 && random() % 10 == 0) {
145 events
[counter
].event
146 = rxevent_Post(&eventTime
, &now
, eventSub
, &events
[counter
],
150 /* A 25% chance that we will cancel a random event */
151 if (random() % 4 == 0) {
152 int victim
= random() % counter
;
154 if (events
[victim
].event
!= NULL
) {
155 rxevent_Cancel(&events
[victim
].event
);
156 events
[victim
].cancelled
= 1;
159 pthread_mutex_unlock(&eventListMutex
);
162 ok(1, "Added %d events", NUMEVENTS
);
169 for (counter
= 0; counter
< NUMEVENTS
; counter
++) {
170 if (events
[counter
].fired
)
172 if (events
[counter
].cancelled
)
174 if (events
[counter
].cancelled
&& events
[counter
].fired
)
177 ok(!fail
, "Didn't fire any cancelled events");
178 ok(fired
+cancelled
== NUMEVENTS
,
179 "Number of fired and cancelled events sum to correct total");