wait: Doxygen

This commit is contained in:
plutooo 2018-12-13 00:48:51 +01:00 committed by fincs
parent 6a6f654526
commit eb01ccd097
4 changed files with 49 additions and 6 deletions

View File

@ -1,6 +1,5 @@
// Copyright 2018 plutoo // Copyright 2018 plutoo
#pragma once #pragma once
#include "../kernel/mutex.h"
#include "../kernel/wait.h" #include "../kernel/wait.h"
typedef struct UsermodeEvent UsermodeEvent; typedef struct UsermodeEvent UsermodeEvent;
@ -12,6 +11,21 @@ struct UsermodeEvent
bool auto_clear; bool auto_clear;
}; };
/**
* @brief Creates a usermode event.
* @param[out] e UsermodeEvent object.
* @param[in] bool auto_clear Whether to automatically clear the event.
* @note It is safe to wait on this event with several threads simultaneously.
* @note If more than one thread is listening on it, at least one thread will get the signal. No other guarantees.
*/
void ueventCreate(UsermodeEvent* e, bool auto_clear); void ueventCreate(UsermodeEvent* e, bool auto_clear);
/**
* @brief Clears the event signal.
* @param[in] e UsermodeEvent object.
*/
void ueventClear(UsermodeEvent* e); void ueventClear(UsermodeEvent* e);
/**
* @brief Signals the event.
* @param[in] e UsermodeEvent object.
*/
void ueventSignal(UsermodeEvent* e); void ueventSignal(UsermodeEvent* e);

View File

@ -1,6 +1,5 @@
// Copyright 2018 plutoo // Copyright 2018 plutoo
#pragma once #pragma once
#include "../kernel/mutex.h"
#include "../kernel/wait.h" #include "../kernel/wait.h"
typedef struct UsermodeTimer UsermodeTimer; typedef struct UsermodeTimer UsermodeTimer;
@ -12,6 +11,23 @@ struct UsermodeTimer
u64 interval; u64 interval;
}; };
/**
* @brief Creates a usermode timer.
* @param[out] t UsermodeTimer object.
* @param[in] interval Interval (in nanoseconds).
* @param[in] start Whether to start the timer right away.
* @note It is safe to wait on this timer with several threads simultaneously.
* @note If more than one thread is listening on it, at least one thread will get the signal. No other guarantees.
* @note If the timer triggers twice before you wait on it, you will only get one signal.
*/
void utimerCreate(UsermodeTimer* t, u64 interval, bool start); void utimerCreate(UsermodeTimer* t, u64 interval, bool start);
/**
* @brief Starts the timer.
* @param[in] t UsermodeTimer object.
*/
void utimerStart(UsermodeTimer* t); void utimerStart(UsermodeTimer* t);
/**
* @brief Stops the timer.
* @param[in] t UsermodeTimer object.
*/
void utimerStop(UsermodeTimer* t); void utimerStop(UsermodeTimer* t);

View File

@ -58,6 +58,7 @@ typedef struct {
}; };
} Waiter; } Waiter;
/// Creates a waiter for a kernelmode handle.
static inline Waiter waiterForHandle(Handle h) static inline Waiter waiterForHandle(Handle h)
{ {
Waiter wait_obj; Waiter wait_obj;
@ -66,6 +67,7 @@ static inline Waiter waiterForHandle(Handle h)
return wait_obj; return wait_obj;
} }
/// Creates a waiter for a usermode timer.
static inline Waiter waiterForUtimer(UsermodeTimer* t) static inline Waiter waiterForUtimer(UsermodeTimer* t)
{ {
Waiter wait_obj; Waiter wait_obj;
@ -74,6 +76,7 @@ static inline Waiter waiterForUtimer(UsermodeTimer* t)
return wait_obj; return wait_obj;
} }
/// Creates a waiter for a usermode event.
static inline Waiter waiterForUevent(UsermodeEvent* e) static inline Waiter waiterForUevent(UsermodeEvent* e)
{ {
Waiter wait_obj; Waiter wait_obj;
@ -82,16 +85,23 @@ static inline Waiter waiterForUevent(UsermodeEvent* e)
return wait_obj; return wait_obj;
} }
/// Creates a waiter for a kernelmode event.
static inline Waiter waiterForEvent(Event* e) { static inline Waiter waiterForEvent(Event* e) {
return waiterForHandle(e->revent); return waiterForHandle(e->revent);
} }
/// Creates a waiter for a thread exit.
static inline Waiter waiterForThreadExit(Thread* t) { static inline Waiter waiterForThreadExit(Thread* t) {
return waiterForHandle(t->handle); return waiterForHandle(t->handle);
} }
/**
* @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 waiters must be less than 64. This is a Horizon kernel limitation.
*/
#define waitMulti(idx_out, timeout, ...) \ #define waitMulti(idx_out, timeout, ...) \
waitN((idx_out), (timeout), (Waiter[]) { __VA_ARGS__ }, sizeof((Waiter[]) { __VA_ARGS__ }) / sizeof(Waiter)) 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); Result waitN(s32* idx_out, u64 timeout, Waiter* objects, size_t num_objects);

View File

@ -69,7 +69,7 @@ static Result waitImpl(s32* idx_out, u64 timeout, Waiter* objects, size_t num_ob
} }
// Always add a listener on the timer, // Always add a listener on the timer,
// So that we can detect another thread were to stopping/starting it during our waiting. // If the timer is started/stopped we want to detect that.
_utimerAddListener( _utimerAddListener(
obj->timer, &waiters[num_waiters], num_waiters, &triggered_idx, obj->timer, &waiters[num_waiters], num_waiters, &triggered_idx,
own_thread_handle); own_thread_handle);
@ -111,8 +111,9 @@ static Result waitImpl(s32* idx_out, u64 timeout, Waiter* objects, size_t num_ob
if (rc == KernelError_Timeout) if (rc == KernelError_Timeout)
{ {
// If we hit the user-supplied timeout, we return the timeout error back to caller. // If we hit the user-supplied timeout, we return the timeout error back to caller.
if (end_tick_idx == -1) if (end_tick_idx == -1) {
goto clean_up; goto clean_up;
}
// If not, it means a timer triggered the timeout. // If not, it means a timer triggered the timeout.
_utimerRecalculate(objects[end_tick_idx].timer, end_tick + cur_tick); _utimerRecalculate(objects[end_tick_idx].timer, end_tick + cur_tick);
@ -134,6 +135,7 @@ static Result waitImpl(s32* idx_out, u64 timeout, Waiter* objects, size_t num_ob
{ {
case WaiterNodeType_Event: case WaiterNodeType_Event:
_ueventTryAutoClear(waiters[triggered_idx].parent_event); _ueventTryAutoClear(waiters[triggered_idx].parent_event);
*idx_out = triggered_idx; *idx_out = triggered_idx;
rc = 0; rc = 0;
break; break;
@ -171,8 +173,9 @@ Result waitN(s32* idx_out, u64 timeout, Waiter* objects, size_t num_objects)
{ {
u64 time_spent = armTicksToNs(armGetSystemTick() - cur_tick); u64 time_spent = armTicksToNs(armGetSystemTick() - cur_tick);
if (time_spent >= timeout) if (time_spent >= timeout) {
return KernelError_Timeout; return KernelError_Timeout;
}
timeout -= time_spent; timeout -= time_spent;
} }