From da7ecc255b146b66a493e18011a6617d435129e1 Mon Sep 17 00:00:00 2001 From: fincs Date: Tue, 5 Jul 2016 22:38:44 +0200 Subject: [PATCH] Take advantage of light events in NDSP and GSPGPU code --- libctru/source/ndsp/ndsp.c | 32 ++++++++------- libctru/source/services/gspgpu.c | 69 +++++++++++++++++--------------- 2 files changed, 54 insertions(+), 47 deletions(-) diff --git a/libctru/source/ndsp/ndsp.c b/libctru/source/ndsp/ndsp.c index 70c914c..00b3cdc 100644 --- a/libctru/source/ndsp/ndsp.c +++ b/libctru/source/ndsp/ndsp.c @@ -9,7 +9,7 @@ u16 ndspFrameId, ndspBufferCurId, ndspBufferId; void* ndspVars[16][2]; -static bool bComponentLoaded = false, bDspReady = false, bSleeping = false, bNeedsSync = false; +static bool bComponentLoaded = false, bDspReady = false, bSleeping = false, bActuallySleeping = false, bNeedsSync = false; static u32 droppedFrames, frameCount; static const void* componentBin; @@ -19,7 +19,8 @@ static bool componentFree; static aptHookCookie aptCookie; -static Handle irqEvent, dspSem, sleepEvent; +static Handle irqEvent, dspSem; +static LightEvent sleepEvent; static LightLock ndspMutex; static u8 dspVar5Backup[0x1080]; @@ -305,7 +306,11 @@ static void ndspAptHook(APT_HookType hook, void* param) case APTHOOK_ONWAKEUP: bSleeping = false; ndspInitialize(true); - svcSignalEvent(sleepEvent); + if (bActuallySleeping) + { + bActuallySleeping = false; + LightEvent_Signal(&sleepEvent); + } break; case APTHOOK_ONSUSPEND: @@ -323,8 +328,8 @@ static void ndspSync(void) { if (bSleeping) { - svcWaitSynchronization(sleepEvent, U64_MAX); - svcClearEvent(sleepEvent); + bActuallySleeping = true; + LightEvent_Wait(&sleepEvent); } ndspWaitForIrq(); @@ -455,7 +460,7 @@ Result ndspInit(void) if (!componentBin && !ndspFindAndLoadComponent()) { - rc = MAKERESULT(RL_PERMANENT, RS_NOTFOUND, 41, RD_NOT_FOUND); + rc = MAKERESULT(RL_PERMANENT, RS_NOTFOUND, RM_DSP, RD_NOT_FOUND); goto _fail0; } @@ -479,17 +484,14 @@ Result ndspInit(void) rc = ndspInitialize(false); if (R_FAILED(rc)) goto _fail1; - rc = svcCreateEvent(&sleepEvent, RESET_STICKY); - if (R_FAILED(rc)) goto _fail2; + LightEvent_Init(&sleepEvent, RESET_ONESHOT); ndspThread = threadCreate(ndspThreadMain, 0x0, NDSP_THREAD_STACK_SIZE, 0x18, -2, true); - if (!ndspThread) goto _fail3; + if (!ndspThread) goto _fail2; aptHook(&aptCookie, ndspAptHook, NULL); return 0; -_fail3: - svcCloseHandle(sleepEvent); _fail2: ndspFinalize(false); _fail1: @@ -509,10 +511,12 @@ void ndspExit(void) if (AtomicDecrement(&ndspRefCount)) return; if (!bDspReady) return; ndspThreadRun = false; - if (bSleeping) - svcSignalEvent(sleepEvent); + if (bActuallySleeping) + { + bActuallySleeping = false; + LightEvent_Signal(&sleepEvent); + } threadJoin(ndspThread, U64_MAX); - svcCloseHandle(sleepEvent); aptUnhook(&aptCookie); if (!bSleeping) ndspFinalize(false); diff --git a/libctru/source/services/gspgpu.c b/libctru/source/services/gspgpu.c index 46278dc..af602d8 100644 --- a/libctru/source/services/gspgpu.c +++ b/libctru/source/services/gspgpu.c @@ -14,19 +14,22 @@ Handle gspGpuHandle; static int gspRefCount; -Handle gspEvents[GSPGPU_EVENT_MAX]; -vu32 gspEventCounts[GSPGPU_EVENT_MAX]; -ThreadFunc gspEventCb[GSPGPU_EVENT_MAX]; -void* gspEventCbData[GSPGPU_EVENT_MAX]; -bool gspEventCbOneShot[GSPGPU_EVENT_MAX]; -volatile bool gspRunEvents; -Thread gspEventThread; +static s32 gspLastEvent = -1; +static LightEvent gspEvents[GSPGPU_EVENT_MAX]; +static vu32 gspEventCounts[GSPGPU_EVENT_MAX]; +static ThreadFunc gspEventCb[GSPGPU_EVENT_MAX]; +static void* gspEventCbData[GSPGPU_EVENT_MAX]; +static bool gspEventCbOneShot[GSPGPU_EVENT_MAX]; +static volatile bool gspRunEvents; +static Thread gspEventThread; static Handle gspEvent; static vu8* gspEventData; static void gspEventThreadMain(void *arg); +Handle __sync_get_arbiter(void); + Result gspInit(void) { Result res=0; @@ -53,20 +56,10 @@ void gspSetEventCallback(GSPGPU_Event id, ThreadFunc cb, void* data, bool oneSho Result gspInitEventHandler(Handle _gspEvent, vu8* _gspSharedMem, u8 gspThreadId) { - // Create events + // Initialize events int i; for (i = 0; i < GSPGPU_EVENT_MAX; i ++) - { - Result rc = svcCreateEvent(&gspEvents[i], RESET_STICKY); - if (rc != 0) - { - // Destroy already created events due to failure - int j; - for (j = 0; j < i; j ++) - svcCloseHandle(gspEvents[j]); - return rc; - } - } + LightEvent_Init(&gspEvents[i], RESET_STICKY); // Start event thread gspEvent = _gspEvent; @@ -82,11 +75,6 @@ void gspExitEventHandler(void) gspRunEvents = false; svcSignalEvent(gspEvent); threadJoin(gspEventThread, U64_MAX); - - // Free events - int i; - for (i = 0; i < GSPGPU_EVENT_MAX; i ++) - svcCloseHandle(gspEvents[i]); } void gspWaitForEvent(GSPGPU_Event id, bool nextEvent) @@ -94,19 +82,30 @@ void gspWaitForEvent(GSPGPU_Event id, bool nextEvent) if(id>= GSPGPU_EVENT_MAX)return; if (nextEvent) - svcClearEvent(gspEvents[id]); - svcWaitSynchronization(gspEvents[id], U64_MAX); + LightEvent_Clear(&gspEvents[id]); + LightEvent_Wait(&gspEvents[id]); if (!nextEvent) - svcClearEvent(gspEvents[id]); + LightEvent_Clear(&gspEvents[id]); } GSPGPU_Event gspWaitForAnyEvent(void) { - s32 which = 0; - Result rc = svcWaitSynchronizationN(&which, gspEvents, GSPGPU_EVENT_MAX, false, U64_MAX); - if (R_FAILED(rc)) return -1; - svcClearEvent(gspEvents[which]); - return which; + 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; } static int popInterrupt() @@ -168,7 +167,11 @@ void gspEventThreadMain(void *arg) gspEventCb[curEvt] = NULL; func(gspEventCbData[curEvt]); } - svcSignalEvent(gspEvents[curEvt]); + LightEvent_Signal(&gspEvents[curEvt]); + do + __ldrex(&gspLastEvent); + while (__strex(&gspLastEvent, curEvt)); + svcArbitrateAddress(__sync_get_arbiter(), (u32)&gspLastEvent, ARBITRATION_SIGNAL, 1, 0); gspEventCounts[curEvt]++; } }