-
-
Save Subv/fe6d4abdb69fb349c22f69204e3e6529 to your computer and use it in GitHub Desktop.
Thread starvation 3DS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <3ds.h> | |
#include <inttypes.h> | |
#include <cstdio> | |
#define NUM_THREADS 2 | |
u32 threadA_stack[0x400]; | |
u32 threadB_stack[0x400]; | |
volatile bool outputs[] = { false, false }; | |
volatile bool exit = false; | |
Handle thread[NUM_THREADS]; | |
Handle event1, event2; | |
volatile s32 thread1_prio = 62; | |
volatile u64 thread1_runticks = 0; | |
void cmd_thread_func2(void* input) { | |
if (!exit) { | |
thread1_runticks = svcGetSystemTick(); | |
outputs[(u32)input] = true; | |
if ((u32)input == 1) { | |
svcOutputDebugString("RAN\n", 0); | |
} | |
} | |
exit = true; | |
svcExitThread(); | |
} | |
void cmd_thread_func(void* input) { | |
if (!exit) { | |
outputs[(u32)input] = true; | |
while (!exit) { | |
s32 prio; | |
svcGetThreadPriority(&prio, thread[1]); | |
if (prio != 62) | |
thread1_prio = prio; | |
svcWaitSynchronization(event1, -1); | |
svcSignalEvent(event2); | |
} | |
} | |
svcExitThread(); | |
} | |
int main() | |
{ | |
// Initialize services | |
gfxInitDefault(); | |
consoleInit(GFX_TOP, NULL); | |
printf("\n\nHello Top Screen!\n\n\n"); | |
printf("Starting\n"); | |
svcCreateEvent(&event1, RESET_ONESHOT); | |
svcCreateEvent(&event2, RESET_ONESHOT); | |
svcSetThreadPriority(0xFFFF8000, 27); | |
Result thread_results[NUM_THREADS]; | |
thread_results[0] = svcCreateThread(&thread[0], cmd_thread_func, 0, threadA_stack + 0x400, 27, 0xFFFFFFFE); | |
thread_results[1] = svcCreateThread(&thread[1], cmd_thread_func2, 1, threadB_stack + 0x400, 62, 0xFFFFFFFE); | |
s64 start_ticks = svcGetSystemTick(); | |
while (!exit) { | |
hidScanInput(); | |
u32 kDown = hidKeysDown(); | |
if (kDown & KEY_A) | |
break; | |
s32 prio; | |
svcGetThreadPriority(&prio, thread[1]); | |
if (prio != 62 || thread1_prio != 62) | |
printf("Thread1 changed priority: %d %d\n", prio, thread1_prio); | |
svcSignalEvent(event1); | |
svcWaitSynchronization(event2, -1); | |
} | |
exit = true; | |
svcSignalEvent(event1); | |
printf("Waiting for thread0 to finish\n"); | |
svcWaitSynchronization(thread[0], U64_MAX); | |
printf("Waiting for thread1 to finish\n"); | |
svcWaitSynchronization(thread[1], U64_MAX); | |
printf("All threads finished\n"); | |
for (int i = 0; i < NUM_THREADS; ++i) { | |
s32 prio; | |
svcGetThreadPriority(&prio, thread[i]); | |
if (outputs[i]) | |
printf("Thread %d ran prio: %d %d\n", i, prio, thread1_prio); | |
else | |
printf("Thread %d did not run prio: %d\n", i, prio); | |
} | |
printf("Tick difference: %" PRIX64 "\n", (u64)(thread1_runticks - start_ticks)); | |
gfxFlushBuffers(); | |
gfxSwapBuffers(); | |
// Main loop | |
while (aptMainLoop()) | |
{ | |
gspWaitForVBlank(); | |
hidScanInput(); | |
u32 kDown = hidKeysDown(); | |
if (kDown & KEY_START) | |
break; // break in order to return to hbmenu | |
} | |
svcCloseHandle(event1); | |
svcCloseHandle(event2); | |
svcCloseHandle(thread[0]); | |
svcCloseHandle(thread[1]); | |
// Exit services | |
gfxExit(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment