Add support for uthreads blocking on event queues
[akaros.git] / tests / evq_block.c
1 /* Copyright (c) 2015 Google, Inc.
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Very basic test for blocking a uthread on event queues. */
6
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <parlib/event.h>
10 #include <parlib/timing.h>
11 #include <parlib/uthread.h>
12 #include <benchutil/alarm.h>
13
14 static struct event_queue *get_ectlr_evq(void)
15 {
16         struct event_queue *ev_q = get_big_event_q();
17         evq_attach_wakeup_ctlr(ev_q);
18         return ev_q;
19 }
20
21 void trampoline_handler(struct event_queue *ev_q)
22 {
23         printf("Got event on evp %p\n", ev_q);
24         evq_wakeup_handler(ev_q);
25 }
26
27 int main(int argc, char **argv)
28 {
29         uint64_t now;
30         int ctlfd1, timerfd1;
31         int ctlfd2, timerfd2;
32         /* these need to just exist somewhere.  don't free them. */
33         struct event_queue *evq1 = get_ectlr_evq();
34         struct event_queue *evq2 = get_ectlr_evq();
35         evq1->ev_flags |= EVENT_JUSTHANDLEIT | EVENT_INDIR | EVENT_SPAM_INDIR |
36                           EVENT_WAKEUP;
37         evq2->ev_flags |= EVENT_JUSTHANDLEIT | EVENT_INDIR | EVENT_SPAM_INDIR |
38                           EVENT_WAKEUP;
39         /* hack in our own handler for debugging */
40         evq1->ev_handler = trampoline_handler;
41         evq2->ev_handler = trampoline_handler;
42
43         if (devalarm_get_fds(&ctlfd1, &timerfd1, 0))
44                 return -1;
45         if (devalarm_get_fds(&ctlfd2, &timerfd2, 0))
46                 return -1;
47         if (devalarm_set_evq(ctlfd1, evq1))
48                 return -1;
49         if (devalarm_set_evq(ctlfd2, evq2))
50                 return -1;
51         now = read_tsc();
52         /* with this setup and the early sleep, two fires, then one.  but we'll
53          * process one first, since that's the first one on the list passed to
54          * blockon */
55         if (devalarm_set_time(timerfd1, now + sec2tsc(4)))
56                 return -1;
57         if (devalarm_set_time(timerfd2, now + sec2tsc(2)))
58                 return -1;
59
60         /* if we remove this, two will fire first and wake us up.  if we don't exit
61          * right away, one will eventually fire and do nothing. */
62         uthread_sleep(5);
63         /* then the actual usage: */
64         struct event_msg msg;
65         struct event_queue *which;
66         uth_blockon_evqs(&msg, &which, 2, evq1, evq2);
67         printf("Got message type %d on evq %s (%p)\n", msg.ev_type,
68                which == evq1 ? "one" : "two", which);
69         return 0;
70 }