libnx/nx/include/switch/kernel/wait.h
2018-12-17 16:06:23 +01:00

100 lines
2.6 KiB
C

/**
* @file wait.h
* @brief User mode synchronization primitive waiting operations.
* @author plutoo
* @copyright libnx Authors
*/
#pragma once
#include "mutex.h"
// Implementation details.
typedef struct Waitable Waitable;
typedef struct WaitableMethods WaitableMethods;
typedef struct WaitableNode WaitableNode;
struct WaitableNode {
WaitableNode* prev;
WaitableNode* next;
};
struct Waitable {
const WaitableMethods* vt;
WaitableNode list;
Mutex mutex;
};
typedef enum {
WaiterType_Handle,
WaiterType_HandleWithClear,
WaiterType_Waitable,
} WaiterType;
// User-facing API starts here.
/// Waiter structure.
typedef struct {
WaiterType type;
union {
Handle handle;
Waitable* waitable;
};
} Waiter;
/// Creates a \ref Waiter for a kernel-mode \ref Handle.
static inline Waiter waiterForHandle(Handle h)
{
Waiter wait_obj;
wait_obj.type = WaiterType_Handle;
wait_obj.handle = h;
return wait_obj;
}
Result waitN(s32* idx_out, Waiter* objects, size_t num_objects, u64 timeout);
Result waitNHandle(s32* idx_out, Handle* handles, size_t num_handles, u64 timeout);
/**
* @brief Waits for an arbitrary number of waiters. This is a macro that uses var-args.
* @param[out] idx_out The index of the signalled waiter.
* @param[in] timeout Timeout (in nanoseconds).
* @note The number of objects must not be greater than \ref MAX_WAIT_OBJECTS. This is a Horizon kernel limitation.
*/
#define waitMulti(idx_out, timeout, ...) ({ \
Waiter __objects[] = { __VA_ARGS__ }; \
waitN((idx_out), __objects, sizeof(__objects) / sizeof(Waiter), (timeout)); \
})
/**
* @brief Waits for an arbitrary number of handles. This is a macro that uses var-args.
* @param[out] idx_out The index of the signalled handle.
* @param[in] timeout Timeout (in nanoseconds).
* @note The number of objects must not be greater than \ref MAX_WAIT_OBJECTS. This is a Horizon kernel limitation.
*/
#define waitMultiHandle(idx_out, timeout, ...) ({ \
Handle __handles[] = { __VA_ARGS__ }; \
waitNHandle((idx_out), __handles, sizeof(__handles) / sizeof(Handle), (timeout)); \
})
/**
* @brief Waits for a single waiter.
* @param[in] w The waiter to wait for.
* @param[in] timeout Timeout (in nanoseconds).
*/
static inline Result waitSingle(Waiter w, u64 timeout)
{
s32 idx;
return waitMulti(&idx, timeout, w);
}
/**
* @brief Waits for a single handle.
* @param[in] h The handle to wait for.
* @param[in] timeout Timeout (in nanoseconds).
*/
static inline Result waitSingleHandle(Handle h, u64 timeout)
{
s32 idx;
return waitMultiHandle(&idx, timeout, h);
}