Skip to content

Instantly share code, notes, and snippets.

@Subv
Last active December 11, 2017 14:49
Show Gist options
  • Save Subv/fe6d4abdb69fb349c22f69204e3e6529 to your computer and use it in GitHub Desktop.
Save Subv/fe6d4abdb69fb349c22f69204e3e6529 to your computer and use it in GitHub Desktop.
Thread starvation 3DS
#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