libnx  v4.2.0
wait.h
Go to the documentation of this file.
1 /**
2  * @file wait.h
3  * @brief User mode synchronization primitive waiting operations.
4  * @author plutoo
5  * @copyright libnx Authors
6  */
7 #pragma once
8 #include "mutex.h"
9 
10 // Implementation details.
11 
12 typedef struct Waitable Waitable;
13 typedef struct WaitableMethods WaitableMethods;
14 typedef struct WaitableNode WaitableNode;
15 
16 struct WaitableNode {
17  WaitableNode* prev;
18  WaitableNode* next;
19 };
20 
21 struct Waitable {
22  const WaitableMethods* vt;
23  WaitableNode list;
24  Mutex mutex;
25 };
26 
27 typedef enum {
28  WaiterType_Handle,
29  WaiterType_HandleWithClear,
30  WaiterType_Waitable,
31 } WaiterType;
32 
33 // User-facing API starts here.
34 
35 /// Waiter structure, representing any generic waitable synchronization object; both kernel-mode and user-mode.
36 typedef struct {
37  WaiterType type;
38 
39  union {
40  Handle handle;
41  Waitable* waitable;
42  };
43 } Waiter;
44 
45 /// Creates a \ref Waiter for a kernel-mode \ref Handle.
46 static inline Waiter waiterForHandle(Handle h)
47 {
48  Waiter wait_obj;
49  wait_obj.type = WaiterType_Handle;
50  wait_obj.handle = h;
51  return wait_obj;
52 }
53 
54 /**
55  * @brief Waits for an arbitrary number of generic waitable synchronization objects, optionally with a timeout.
56  * @param[out] idx_out Variable that will received the index of the signalled object.
57  * @param[in] objects Array containing \ref Waiter structures.
58  * @param[in] num_objects Number of objects in the array.
59  * @param[in] timeout Timeout (in nanoseconds).
60  * @return Result code.
61  * @note The number of objects must not be greater than \ref MAX_WAIT_OBJECTS. This is a Horizon kernel limitation.
62  */
63 Result waitObjects(s32* idx_out, const Waiter* objects, s32 num_objects, u64 timeout);
64 
65 /**
66  * @brief Waits for an arbitrary number of kernel synchronization objects, optionally with a timeout. This function replaces \ref svcWaitSynchronization.
67  * @param[out] idx_out Variable that will received the index of the signalled object.
68  * @param[in] handles Array containing handles.
69  * @param[in] num_handles Number of handles in the array.
70  * @param[in] timeout Timeout (in nanoseconds).
71  * @return Result code.
72  * @note The number of objects must not be greater than \ref MAX_WAIT_OBJECTS. This is a Horizon kernel limitation.
73  */
74 Result waitHandles(s32* idx_out, const Handle* handles, s32 num_handles, u64 timeout);
75 
76 /**
77  * @brief Helper macro for \ref waitObjects that accepts \ref Waiter structures as variadic arguments instead of as an array.
78  * @param[out] idx_out The index of the signalled waiter.
79  * @param[in] timeout Timeout (in nanoseconds).
80  * @note The number of objects must not be greater than \ref MAX_WAIT_OBJECTS. This is a Horizon kernel limitation.
81  */
82 #define waitMulti(idx_out, timeout, ...) ({ \
83  Waiter __objects[] = { __VA_ARGS__ }; \
84  waitObjects((idx_out), __objects, sizeof(__objects) / sizeof(Waiter), (timeout)); \
85 })
86 
87 /**
88  * @brief Helper macro for \ref waitHandles that accepts handles as variadic arguments instead of as an array.
89  * @param[out] idx_out The index of the signalled handle.
90  * @param[in] timeout Timeout (in nanoseconds).
91  * @note The number of objects must not be greater than \ref MAX_WAIT_OBJECTS. This is a Horizon kernel limitation.
92  */
93 #define waitMultiHandle(idx_out, timeout, ...) ({ \
94  Handle __handles[] = { __VA_ARGS__ }; \
95  waitHandles((idx_out), __handles, sizeof(__handles) / sizeof(Handle), (timeout)); \
96 })
97 
98 /**
99  * @brief Waits on a single generic waitable synchronization object, optionally with a timeout.
100  * @param[in] w \ref Waiter structure.
101  * @param[in] timeout Timeout (in nanoseconds).
102  */
103 static inline Result waitSingle(Waiter w, u64 timeout)
104 {
105  s32 idx;
106  return waitObjects(&idx, &w, 1, timeout);
107 }
108 
109 /**
110  * @brief Waits for a single kernel synchronization object, optionally with a timeout.
111  * @param[in] h \ref Handle of the object.
112  * @param[in] timeout Timeout (in nanoseconds).
113  */
114 static inline Result waitSingleHandle(Handle h, u64 timeout)
115 {
116  s32 idx;
117  return waitHandles(&idx, &h, 1, timeout);
118 }
waitObjects
Result waitObjects(s32 *idx_out, const Waiter *objects, s32 num_objects, u64 timeout)
Waits for an arbitrary number of generic waitable synchronization objects, optionally with a timeout.
waitSingle
static Result waitSingle(Waiter w, u64 timeout)
Waits on a single generic waitable synchronization object, optionally with a timeout.
Definition: wait.h:103
s32
int32_t s32
32-bit signed integer.
Definition: types.h:27
waitSingleHandle
static Result waitSingleHandle(Handle h, u64 timeout)
Waits for a single kernel synchronization object, optionally with a timeout.
Definition: wait.h:114
Waitable
Definition: wait.h:21
waitHandles
Result waitHandles(s32 *idx_out, const Handle *handles, s32 num_handles, u64 timeout)
Waits for an arbitrary number of kernel synchronization objects, optionally with a timeout.
Waiter
Waiter structure, representing any generic waitable synchronization object; both kernel-mode and user...
Definition: wait.h:36
u64
uint64_t u64
64-bit unsigned integer.
Definition: types.h:22
Mutex
_LOCK_T Mutex
Mutex datatype, defined in newlib.
Definition: mutex.h:12
WaitableNode
Definition: wait.h:16
Result
u32 Result
Function error code result type.
Definition: types.h:44
waiterForHandle
static Waiter waiterForHandle(Handle h)
Creates a Waiter for a kernel-mode Handle.
Definition: wait.h:46
mutex.h
Mutex synchronization primitive.
Handle
u32 Handle
Kernel object handle.
Definition: types.h:43