blob: 09e485af67d7b06ef867fae810ba2c24d72cfded [file] [log] [blame]
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -07001/*
2 * Copyright (c) 2008 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <debug.h>
24#include <err.h>
25#include <kernel/event.h>
26
27#if DEBUGLEVEL > 1
28#define EVENT_CHECK 1
29#endif
30
31void event_init(event_t *e, bool initial, uint flags)
32{
33#if EVENT_CHECK
34// ASSERT(e->magic != EVENT_MAGIC);
35#endif
36
37 e->magic = EVENT_MAGIC;
38 e->signalled = initial;
39 e->flags = flags;
40 wait_queue_init(&e->wait);
41}
42
43void event_destroy(event_t *e)
44{
45 enter_critical_section();
46
47#if EVENT_CHECK
48 ASSERT(e->magic == EVENT_MAGIC);
49#endif
50
51 e->magic = 0;
52 e->signalled = false;
53 e->flags = 0;
54 wait_queue_destroy(&e->wait, true);
55
56 exit_critical_section();
57}
58
59status_t event_wait_timeout(event_t *e, time_t timeout)
60{
61 status_t ret = NO_ERROR;
62
63 enter_critical_section();
64
65#if EVENT_CHECK
66 ASSERT(e->magic == EVENT_MAGIC);
67#endif
68
69 if (e->signalled) {
70 /* signalled, we're going to fall through */
71 if (e->flags & EVENT_FLAG_AUTOUNSIGNAL) {
72 /* autounsignal flag lets one thread fall through before unsignalling */
73 e->signalled = false;
74 }
75 } else {
76 /* unsignalled, block here */
77 ret = wait_queue_block(&e->wait, timeout);
78 if (ret < 0)
79 goto err;
80 }
81
82err:
83 exit_critical_section();
84
85 return ret;
86}
87
88status_t event_wait(event_t *e)
89{
90 return event_wait_timeout(e, INFINITE_TIME);
91}
92
93status_t event_signal(event_t *e, bool reschedule)
94{
95 enter_critical_section();
96
97#if EVENT_CHECK
98 ASSERT(e->magic == EVENT_MAGIC);
99#endif
100
101 if (!e->signalled) {
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700102 if (e->flags & EVENT_FLAG_AUTOUNSIGNAL) {
Travis Geiselbrechtbb777a12009-01-20 00:24:27 -0800103 /* try to release one thread and leave unsignalled if successful */
104 if (wait_queue_wake_one(&e->wait, reschedule, NO_ERROR) <= 0) {
105 /*
106 * if we didn't actually find a thread to wake up, go to
107 * signalled state and let the next call to event_wait
108 * unsignal the event.
109 */
110 e->signalled = true;
111 }
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700112 } else {
travis geiselbrechtd98cea12008-09-18 16:01:03 +0000113 /* release all threads and remain signalled */
Travis Geiselbrechtbb777a12009-01-20 00:24:27 -0800114 e->signalled = true;
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700115 wait_queue_wake_all(&e->wait, reschedule, NO_ERROR);
116 }
117 }
118
119 exit_critical_section();
120
121 return NO_ERROR;
122}
123
124status_t event_unsignal(event_t *e)
125{
126 enter_critical_section();
127
128#if EVENT_CHECK
129 ASSERT(e->magic == EVENT_MAGIC);
130#endif
131
132 e->signalled = false;
133
134 exit_critical_section();
135
136 return NO_ERROR;
137}
138