blob: 188b5d33f8b291e11c69a52c6c93d52b7591b462 [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) {
102 e->signalled = true;
103 if (e->flags & EVENT_FLAG_AUTOUNSIGNAL) {
travis geiselbrechtd98cea12008-09-18 16:01:03 +0000104 /* try to release one thread and unsignal again if successful */
105 if (wait_queue_wake_one(&e->wait, reschedule, NO_ERROR) > 0)
106 e->signalled = false;
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700107 } else {
travis geiselbrechtd98cea12008-09-18 16:01:03 +0000108 /* release all threads and remain signalled */
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700109 wait_queue_wake_all(&e->wait, reschedule, NO_ERROR);
110 }
111 }
112
113 exit_critical_section();
114
115 return NO_ERROR;
116}
117
118status_t event_unsignal(event_t *e)
119{
120 enter_critical_section();
121
122#if EVENT_CHECK
123 ASSERT(e->magic == EVENT_MAGIC);
124#endif
125
126 e->signalled = false;
127
128 exit_critical_section();
129
130 return NO_ERROR;
131}
132