diff --git a/libctru/include/3ds/synchronization.h b/libctru/include/3ds/synchronization.h index 0f5f327..d8edfdc 100755 --- a/libctru/include/3ds/synchronization.h +++ b/libctru/include/3ds/synchronization.h @@ -305,6 +305,14 @@ int LightEvent_TryWait(LightEvent* event); */ void LightEvent_Wait(LightEvent* event); +/** + * @brief Waits on a light event until either the event is signaled or the timeout is reached. + * @param event Pointer to the event. + * @param timeout_ns Timeout in nanoseconds. + * @return Non-zero on timeout, zero otherwise. + */ +int LightEvent_WaitTimeout(LightEvent* event, s64 timeout_ns); + /** * @brief Initializes a light semaphore. * @param event Pointer to the semaphore. diff --git a/libctru/source/synchronization.c b/libctru/source/synchronization.c index dee0cfa..79de968 100644 --- a/libctru/source/synchronization.c +++ b/libctru/source/synchronization.c @@ -318,6 +318,34 @@ void LightEvent_Wait(LightEvent* event) } } +int LightEvent_WaitTimeout(LightEvent* event, s64 timeout_ns) +{ + Result timeoutRes = 0x09401BFE; + Result res = 0; + + while (res != timeoutRes) + { + if (event->state == -2) + { + res = syncArbitrateAddressWithTimeout(&event->state, ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT, 0, timeout_ns); + return res == timeoutRes; + } + + if (event->state != -1) + { + if (event->state == 1) + return 0; + + if (event->state == 0 && LightEvent_TryReset(event)) + return 0; + } + + res = syncArbitrateAddressWithTimeout(&event->state, ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT, 0, timeout_ns); + } + + return res == timeoutRes; +} + void LightSemaphore_Init(LightSemaphore* semaphore, s16 initial_count, s16 max_count) { semaphore->current_count = (s32)initial_count;