void LightEvent_Pulse(LightEvent* event) { if (event->state == -2) svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_SIGNAL, -1, 0); else if (event->state == -1) svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_SIGNAL, 1, 0); else LightEvent_Clear(event); }
void LightEvent_Signal(LightEvent* event) { if (event->state == -1) { LightEvent_SetState(event, 0); svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_SIGNAL, 1, 0); } else if (event->state == -2) { LightLock_Lock(&event->lock); LightEvent_SetState(event, 1); svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_SIGNAL, -1, 0); LightLock_Unlock(&event->lock); } }
void LightLock_Lock(LightLock* lock) { s32 val; _begin: do { val = __ldrex(lock); if (val < 0) { // Add ourselves to the list of threads blocked on this lock if (__strex(lock, val-1)) goto _begin; // strex failed, try to lock again _wait: // Wait for a thread to wake us up svcArbitrateAddress(arbiter, (u32)lock, ARBITRATION_WAIT_IF_LESS_THAN, 0, 0); // Try to lock again do { val = __ldrex(lock); if (val < 0) { // Lock is still locked - keep waiting __clrex(); goto _wait; } } while (__strex(lock, -(val-1))); return; } } while (__strex(lock, -val)); }
void LightSemaphore_Acquire(LightSemaphore* semaphore, s32 count) { s32 old_count; s16 num_threads_acq; do { for (;;) { old_count = __ldrex(&semaphore->current_count); if (old_count > 0) break; __clrex(); do num_threads_acq = (s16)__ldrexh((u16 *)&semaphore->num_threads_acq); while (__strexh((u16 *)&semaphore->num_threads_acq, num_threads_acq + 1)); svcArbitrateAddress(arbiter, (u32)semaphore, ARBITRATION_WAIT_IF_LESS_THAN, count, 0); do num_threads_acq = (s16)__ldrexh((u16 *)&semaphore->num_threads_acq); while (__strexh((u16 *)&semaphore->num_threads_acq, num_threads_acq - 1)); } } while (__strex(&semaphore->current_count, old_count - count)); }
void gspEventThreadMain(void *arg) { while (gspRunEvents) { svcWaitSynchronization(gspEvent, U64_MAX); svcClearEvent(gspEvent); while (true) { int curEvt = popInterrupt(); if (curEvt == -1) break; if (curEvt < GSPGPU_EVENT_MAX) { if (gspEventCb[curEvt]) { ThreadFunc func = gspEventCb[curEvt]; if (gspEventCbOneShot[curEvt]) gspEventCb[curEvt] = NULL; func(gspEventCbData[curEvt]); } LightEvent_Signal(&gspEvents[curEvt]); do __ldrex(&gspLastEvent); while (__strex(&gspLastEvent, curEvt)); svcArbitrateAddress(__sync_get_arbiter(), (u32)&gspLastEvent, ARBITRATION_SIGNAL, 1, 0); gspEventCounts[curEvt]++; } } } }
void LightEvent_Wait(LightEvent* event) { for (;;) { if (event->state == -2) { svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_WAIT_IF_LESS_THAN, 0, 0); return; } if (event->state != -1) { if (event->state == 1) return; if (event->state == 0 && LightEvent_TryReset(event)) return; } svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_WAIT_IF_LESS_THAN, 0, 0); } }
void LightLock_Unlock(LightLock* lock) { s32 val; do val = -__ldrex(lock); while (__strex(lock, val)); if (val > 1) // Wake up exactly one thread svcArbitrateAddress(arbiter, (u32)lock, ARBITRATION_SIGNAL, 1, 0); }
void LightSemaphore_Release(LightSemaphore* semaphore, s32 count) { s32 old_count, new_count; do { old_count = __ldrex(&semaphore->current_count); new_count = old_count + count; if (new_count >= semaphore->max_count) new_count = semaphore->max_count; } while (__strex(&semaphore->current_count, new_count)); if(old_count <= 0 || semaphore->num_threads_acq > 0) svcArbitrateAddress(arbiter, (u32)semaphore, ARBITRATION_SIGNAL, count, 0); }
static void poll_thread(void* arg) { while ((u32) svcArbitrateAddress(arbiter, alloc_address, ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT, 0, 0) == 0xD9001814) svcSleepThread(10000); __asm__ volatile("cpsid aif \n\t"); memcpy(flush_buffer, flush_buffer + 0x8000, 0x8000); memcpy(flush_buffer, flush_buffer + 0x8000, 0x8000); memcpy(flush_buffer, flush_buffer + 0x8000, 0x8000); memcpy(flush_buffer, flush_buffer + 0x8000, 0x8000); memcpy(flush_buffer, flush_buffer + 0x8000, 0x8000); while (lock_thread); __asm__ volatile("cpsie aif \n\t"); svcExitThread(); }
GSPGPU_Event gspWaitForAnyEvent(void) { s32 x; do { do { x = __ldrex(&gspLastEvent); if (x < 0) { __clrex(); break; } } while (__strex(&gspLastEvent, -1)); if (x < 0) svcArbitrateAddress(__sync_get_arbiter(), (u32)&gspLastEvent, ARBITRATION_WAIT_IF_LESS_THAN, 0, 0); } while (x < 0); return (GSPGPU_Event)x; }