I must have misinterpreted your response as I took it as my thread example shouldn't work. I was just going by your suggestion to @Badda to use svcSleepThread(1) but I see that isn't sufficient in my case. I've just tried setting both threads to sleep for 100000000 and the Home button works!
I'll see if I can augment this into my code and if not I'll fallback on your suggestion to put it in a common function. I could probably just write a wrapper for hidScanInput to manage that for me since I know that's called everywhere regardless if a frame is rendered.
Thanks for taking the time to help me out!
Trust me, do the wrapper.
--------------------- MERGED ---------------------------
Okay, I got it working to the point where it will not request another update if it's already busy.
However, one thing I don't understand is that as a test I cannot block until it finishes.
Code:#include <stdio.h> #include <stdarg.h> #include <stdlib.h> #include <3ds.h> int ShowError( const char* ErrorText, ... ); void RenderThread( void* Pram ); void Cleanup( void ); Handle RenderThreadReadyEvent = 0; Handle RenderThreadUpdateEvent = 0; Handle RenderThreadBusyMutex = 0; Thread RenderThreadHandle = NULL; volatile bool RenderThreadRun = false; int ShowError( const char* ErrorText, ... ) { static char Buffer[ 1024 ]; errorConf Err; va_list Argp; va_start( Argp, ErrorText ); vsnprintf( Buffer, sizeof( Buffer ), ErrorText, Argp ); va_end( Argp ); errorInit( &Err, ERROR_TEXT_WORD_WRAP, CFG_LANGUAGE_EN ); errorText( &Err, Buffer ); errorDisp( &Err ); return 1; } void RenderThread( void* Pram ) { gfxInitDefault( ); consoleInit( GFX_BOTTOM, NULL ); svcSignalEvent( RenderThreadReadyEvent ); while ( RenderThreadRun ) { svcWaitSynchronization( RenderThreadUpdateEvent, INT64_MAX ); svcClearEvent( RenderThreadUpdateEvent ); svcWaitSynchronization( RenderThreadBusyMutex, INT64_MAX ); svcSleepThread( 1 * ( 1e+9 ) ); svcReleaseMutex( RenderThreadBusyMutex ); } gfxExit( ); threadExit( 0 ); } void Cleanup( void ) { if ( RenderThreadHandle ) { RenderThreadRun = false; threadJoin( RenderThreadHandle, UINT64_MAX ); threadFree( RenderThreadHandle ); } svcCloseHandle( RenderThreadReadyEvent ); svcCloseHandle( RenderThreadUpdateEvent ); svcCloseHandle( RenderThreadBusyMutex ); } int main( void ) { uint32_t Keys_Down = 0; uint64_t a, b = 0; atexit( Cleanup ); svcCreateEvent( &RenderThreadReadyEvent, RESET_ONESHOT ); svcCreateEvent( &RenderThreadUpdateEvent, RESET_ONESHOT ); svcCreateMutex( &RenderThreadBusyMutex, false ); RenderThreadRun = true; RenderThreadHandle = threadCreate( RenderThread, NULL, 4096, 0x20, 1, false ); if ( RenderThreadHandle == NULL ) { return ShowError( "Failed to create rendering thread" ); } // Wait for render thread to complete init svcWaitSynchronization( RenderThreadReadyEvent, INT64_MAX ); svcClearEvent( RenderThreadReadyEvent ); printf( "Render thread ready.\n" ); while ( aptMainLoop( ) ) { gspWaitForVBlank( ); gfxSwapBuffers( ); hidScanInput( ); Keys_Down = hidKeysDown( ); if ( Keys_Down & KEY_A ) { if ( svcWaitSynchronization( RenderThreadBusyMutex, 0 ) != 0 ) { printf( "Render thread busy, try again later.\n" ); } else { // Clear mutex in case we locked it while peeking at it svcReleaseMutex( RenderThreadBusyMutex ); a = svcGetSystemTick( ); // Tell the render thread to do the thing svcSignalEvent( RenderThreadUpdateEvent ); // Wait for render thread to finish svcWaitSynchronization( RenderThreadBusyMutex, INT64_MAX ); svcReleaseMutex( RenderThreadBusyMutex ); b = svcGetSystemTick( ); svcReleaseMutex( RenderThreadBusyMutex ); printf( "Operation took %.2fms\n", ( ( float ) ( b - a ) ) / ( float ) CPU_TICKS_PER_MSEC ); } } if ( Keys_Down & KEY_START ) { break; } } return 0; }
I would have thought that between the calls to svcGetSystemTick() it would signal the event and block until the render thread clears the busy mutex.
Shouldn't even work without APT_SetAppCpuTimeLimit, but otherwise seems ok.