1 // Copyright (c) 2008-2014 Travis Geiselbrecht
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6 #pragma once
7
8 #include <kernel/thread.h>
9 #include <lk/compiler.h>
10 #include <stdbool.h>
11 #include <sys/types.h>
12 #include <stdint.h>
13
14 // This file defines the kernel event, which is a synchronization primitive
15 // that allows threads to wait for an event to be signaled. It is primarily used
16 // for inter-thread communication and synchronization.
17
18 __BEGIN_CDECLS
19
20 // Rules for Events:
21 // - Events may be signaled from interrupt context *but* the reschedule
22 // parameter must be false in that case.
23 // - Events may not be waited upon from interrupt context.
24 // - Events without FLAG_AUTOUNSIGNAL:
25 // - Wake up any waiting threads when signaled.
26 // - Continue to do so (no threads will wait) until unsignaled.
27 // - Events with FLAG_AUTOUNSIGNAL:
28 // - If one or more threads are waiting when signaled, one thread will
29 // be woken up and return. The signaled state will not be set.
30 // - If no threads are waiting when signaled, the Event will remain
31 // in the signaled state until a thread attempts to wait (at which
32 // time it will unsignal atomicly and return immediately) or
33 // event_unsignal() is called.
34
35 #define EVENT_MAGIC (0x65766E74) // "evnt"
36
37 typedef struct event {
38 uint32_t magic;
39 bool signaled;
40 uint flags;
41 wait_queue_t wait;
42 } event_t;
43
44 #define EVENT_FLAG_AUTOUNSIGNAL 1
45
46 // Initializer for an event structure. Events may be initialized with a
47 // non-signaled state, or a signaled state. The flags parameter can be used
48 // to specify additional behavior, such as FLAG_AUTOUNSIGNAL.
49 #define EVENT_INITIAL_VALUE(e, initial, _flags) \
50 { \
51 .magic = EVENT_MAGIC, \
52 .signaled = (initial), \
53 .flags = (_flags), \
54 .wait = WAIT_QUEUE_INITIAL_VALUE((e).wait), \
55 }
56
57 // Dynamically initialize an event structure.
58 void event_init(event_t *, bool initial, uint flags);
59
60 // Check if an event is initialized.
event_initialized(event_t * e)61 static inline bool event_initialized(event_t *e) {
62 return e->magic == EVENT_MAGIC;
63 }
64
65 // Destroy an event. Any threads waiting on the event will be woken up
66 // with an error status.
67 void event_destroy(event_t *);
68
69 // Wait on the event until it is signaled or a timeout occurs.
70 // If timeout is INFINITE_TIME, it will wait indefinitely.
71 // If timeout is 0, it will return immediately if it is unable to acquire the event.
72 // Returns an error status if the event is not signaled within the timeout period.
73 // If the event is signaled, it will return NO_ERROR.
74 status_t event_wait_timeout(event_t *, lk_time_t);
75
76 // Signal the event, waking up any threads waiting on it.
77 // If reschedule is true, it will reschedule the thread that was waiting.
78 // May be called during interrupt context, but in that case reschedule must be false.
79 status_t event_signal(event_t *, bool reschedule);
80
81 // Unsignal the event, clearing its signaled state.
82 status_t event_unsignal(event_t *);
83
84 // Shortcut for waiting for an event indefinitely.
event_wait(event_t * e)85 static inline status_t event_wait(event_t *e) {
86 return event_wait_timeout(e, INFINITE_TIME);
87 }
88
89 __END_CDECLS
90