// Copyright 2018 plutoo #include "result.h" #include "kernel/svc.h" #include "kernel/mutex.h" #include "kernel/uevent.h" #include "wait.h" static bool _ueventBeginWait(Waitable* ww, WaiterNode* w, u64 cur_tick, u64* next_tick); static Result _ueventOnTimeout(Waitable* ww, u64 old_tick); static Result _ueventOnSignal(Waitable* ww); static const WaitableMethods g_ueventVt = { .beginWait = _ueventBeginWait, .onTimeout = _ueventOnTimeout, .onSignal = _ueventOnSignal, }; void ueventCreate(UEvent* e, bool auto_clear) { _waitableInitialize(&e->waitable, &g_ueventVt); e->signal = false; e->auto_clear = auto_clear; } void ueventClear(UEvent* e) { mutexLock(&e->waitable.mutex); e->signal = false; mutexUnlock(&e->waitable.mutex); } void ueventSignal(UEvent* e) { mutexLock(&e->waitable.mutex); e->signal = true; _waitableSignalAllListeners(&e->waitable); mutexUnlock(&e->waitable.mutex); } Result _ueventOnSignal(Waitable* ww) { UEvent* e = (UEvent*)ww; Result rc = 0; mutexLock(&e->waitable.mutex); // Try to auto-clear the event. If auto-clear is enabled but // the event is not signalled, that means the state of the // event has changed and thus we need to retry the wait. if (e->auto_clear) { if (e->signal) e->signal = false; else rc = KERNELRESULT(Cancelled); } mutexUnlock(&e->waitable.mutex); return rc; } bool _ueventBeginWait(Waitable* ww, WaiterNode* w, u64 cur_tick, u64* next_tick) { UEvent* e = (UEvent*)ww; mutexLock(&e->waitable.mutex); bool can_add = !e->signal; if (can_add) _waiterNodeAdd(w); else if (e->auto_clear) e->signal = false; mutexUnlock(&e->waitable.mutex); return can_add; } Result _ueventOnTimeout(Waitable* ww, u64 old_tick) { // This is not supposed to happen. return KERNELRESULT(Cancelled); }