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

98 lines
2.0 KiB
C

// Copyright 2018 plutoo
#pragma once
#include "../kernel/mutex.h"
#include "../kernel/event.h"
#include "../kernel/thread.h"
// Implementation details.
typedef struct UsermodeEvent UsermodeEvent;
typedef struct UsermodeTimer UsermodeTimer;
typedef enum {
WaiterNodeType_Event,
WaiterNodeType_Timer
} WaiterNodeType;
typedef struct Waitable Waitable;
typedef struct WaitableNode WaitableNode;
struct WaitableNode
{
WaitableNode* prev;
WaitableNode* next;
};
typedef struct {
WaitableNode node;
WaiterNodeType type;
Handle thread;
union {
Waitable* parent;
UsermodeEvent* parent_event;
UsermodeTimer* parent_timer;
};
size_t idx;
size_t* idx_out;
} WaiterNode;
struct Waitable
{
WaitableNode list;
Mutex mutex;
};
// User-facing API starts here.
typedef enum {
WaiterType_Handle,
WaiterType_UsermodeTimer,
WaiterType_UsermodeEvent,
} WaiterType;
typedef struct {
WaiterType type;
union {
Handle handle;
UsermodeTimer* timer;
UsermodeEvent* event;
};
} Waiter;
static inline Waiter waiterForHandle(Handle h)
{
Waiter wait_obj;
wait_obj.type = WaiterType_Handle;
wait_obj.handle = h;
return wait_obj;
}
static inline Waiter waiterForUtimer(UsermodeTimer* t)
{
Waiter wait_obj;
wait_obj.type = WaiterType_UsermodeTimer;
wait_obj.timer = t;
return wait_obj;
}
static inline Waiter waiterForUevent(UsermodeEvent* e)
{
Waiter wait_obj;
wait_obj.type = WaiterType_UsermodeEvent;
wait_obj.event = e;
return wait_obj;
}
static inline Waiter waiterForEvent(Event* e) {
return waiterForHandle(e->revent);
}
static inline Waiter waiterForThreadExit(Thread* t) {
return waiterForHandle(t->handle);
}
#define waitMulti(idx_out, timeout, ...) \
waitN((idx_out), (timeout), (Waiter[]) { __VA_ARGS__ }, sizeof((Waiter[]) { __VA_ARGS__ }) / sizeof(Waiter))
Result waitN(s32* idx_out, u64 timeout, Waiter* objects, size_t num_objects);