void psp_init(void) { SceUID thid; char buff[128], *r; /* fw 1.5 sometimes returns 8002032c, although getcwd works */ r = getcwd(buff, sizeof(buff)); if (r) sceIoChdir(buff); main_thread_id = sceKernelGetThreadId(); lprintf("running on %08x kernel\n", sceKernelDevkitVersion()), lprintf("entered psp_init, threadId %08x, priority %i\n", main_thread_id, sceKernelGetThreadCurrentPriority()); thid = sceKernelCreateThread("update_thread", callback_thread, 0x11, 0xFA0, 0, NULL); if (thid >= 0) { sceKernelStartThread(thid, 0, 0); } /* video */ sceDisplaySetMode(0, 480, 272); sceDisplaySetFrameBuf(VRAM_FB1, 512, PSP_DISPLAY_PIXEL_FORMAT_565, PSP_DISPLAY_SETBUF_NEXTFRAME); current_screen = 1; psp_screen = VRAM_FB0; /* gu */ sceGuInit(); sceGuStart(GU_DIRECT, guCmdList); sceGuDrawBuffer(GU_PSM_5650, (void *)VRAMOFFS_FB0, 512); sceGuDispBuffer(480, 272, (void *)VRAMOFFS_FB1, 512); // don't care sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT); sceGuDepthBuffer((void *)VRAMOFFS_DEPTH, 512); sceGuOffset(2048 - (480 / 2), 2048 - (272 / 2)); sceGuViewport(2048, 2048, 480, 272); sceGuDepthRange(0xc350, 0x2710); sceGuScissor(0, 0, 480, 272); sceGuEnable(GU_SCISSOR_TEST); sceGuDepthMask(0xffff); sceGuDisable(GU_DEPTH_TEST); sceGuFrontFace(GU_CW); sceGuEnable(GU_TEXTURE_2D); sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB); sceGuAmbientColor(0xffffffff); sceGuColor(0xffffffff); sceGuFinish(); sceGuSync(0, 0); sceDisplayWaitVblankStart(); sceGuDisplay(GU_TRUE); /* input */ sceCtrlSetSamplingCycle(0); sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); }
// 222: 4-5us void PspSpeedTests::getPrioritySpeed() { uint32 time1 = PspRtc::instance().getMicros(); int priority = sceKernelGetThreadCurrentPriority(); uint32 time2 = PspRtc::instance().getMicros(); PSP_INFO_PRINT("Getting thread priority %d took %dus\n", priority, time2-time1); }
int main(int argc, char *argv[]) { reschedThread = sceKernelCreateThread("resched", &reschedFunc, sceKernelGetThreadCurrentPriority(), 0x1000, 0, NULL); checkDispatchCases("Semas", &checkSema); didResched = 0; schedf("\n\n"); checkDispatchCases("Mutexes", &checkMutex); didResched = 0; schedf("\n\n"); checkDispatchCases("LwMutexes", &checkLwMutex); didResched = 0; schedf("\n\n"); checkDispatchCases("EventFlags", &checkEventFlag); didResched = 0; schedf("\n\n"); checkDispatchCases("Io", &checkIo); didResched = 0; schedf("\n\n"); checkDispatchInterrupt(); return 0; }
/** * display_end_frame: End processing for the current frame, then swap the * displayed buffer and work buffer. The current frame will not actually * be shown until the next vertical blank. * * [Parameters] * None * [Return value] * None */ void display_end_frame(void) { guFinish(); swap_pending = 1; /* Give the new thread a slightly higher priority than us, or else it * won't actually get a chance to run. */ if (sys_start_thread("YabauseBufferSwapThread", buffer_swap_thread, sceKernelGetThreadCurrentPriority() - 1, 0x1000, 0, NULL) < 0) { DMSG("Failed to start buffer swap thread"); swap_pending = 0; do_buffer_swap(); // Do it ourselves } }
/* Callback thread */ static int callback_thread(SceSize args, void *argp) { int cbid; lprintf("callback_thread started with id %08x, priority %i\n", sceKernelGetThreadId(), sceKernelGetThreadCurrentPriority()); cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL); sceKernelRegisterExitCallback(cbid); cbid = sceKernelCreateCallback("Power Callback", power_callback, NULL); scePowerRegisterCallback(0, cbid); sceKernelSleepThreadCB(); return 0; }
int main(int argc, char *argv[]) { int result, data; SceCtrlData pad_data[128]; SceCtrlLatch latch; schedulingLogPos = schedulingLog; SceUID thread = sceKernelCreateThread("preempt", &testThread, sceKernelGetThreadCurrentPriority() - 1, 0x500, 0, NULL); sceKernelStartThread(thread, 0, 0); schedulingLogPos += sprintf(schedulingLogPos, "BEFORE sceCtrlSetSamplingMode 1\n"); didPreempt = 0; result = sceCtrlSetSamplingMode(1); schedulingLogPos += sprintf(schedulingLogPos, "AFTER sceCtrlSetSamplingMode 1: %08x preempt:%d\n", result, didPreempt); sceKernelDelayThread(300); schedulingLogPos += sprintf(schedulingLogPos, "BEFORE sceCtrlSetSamplingMode 0\n"); didPreempt = 0; result = sceCtrlSetSamplingMode(0); schedulingLogPos += sprintf(schedulingLogPos, "AFTER sceCtrlSetSamplingMode 0: %08x preempt:%d\n", result, didPreempt); sceKernelDelayThread(300); schedulingLogPos += sprintf(schedulingLogPos, "BEFORE sceCtrlSetSamplingCycle 0\n"); didPreempt = 0; result = sceCtrlSetSamplingCycle(0); schedulingLogPos += sprintf(schedulingLogPos, "AFTER sceCtrlSetSamplingCycle 0: %08x preempt:%d\n", result, didPreempt); sceKernelDelayThread(300); schedulingLogPos += sprintf(schedulingLogPos, "BEFORE sceCtrlGetSamplingMode\n"); didPreempt = 0; result = sceCtrlGetSamplingMode(&data); schedulingLogPos += sprintf(schedulingLogPos, "VALUE: %08x\n", data); schedulingLogPos += sprintf(schedulingLogPos, "AFTER sceCtrlGetSamplingMode: %08x preempt:%d\n", result, didPreempt); sceKernelDelayThread(300); schedulingLogPos += sprintf(schedulingLogPos, "BEFORE sceCtrlReadBufferPositive 1\n"); didPreempt = 0; result = sceCtrlReadBufferPositive(&pad_data[0], 1); outputPadData(result, &pad_data[0]); schedulingLogPos += sprintf(schedulingLogPos, "AFTER sceCtrlReadBufferPositive 1: %08x preempt:%d\n", result, didPreempt); sceKernelDelayThread(300); schedulingLogPos += sprintf(schedulingLogPos, "BEFORE sceCtrlReadBufferPositive 64\n"); didPreempt = 0; result = sceCtrlReadBufferPositive(&pad_data[0], 64); outputPadData(result, &pad_data[0]); schedulingLogPos += sprintf(schedulingLogPos, "AFTER sceCtrlReadBufferPositive 64: %08x preempt:%d\n", result, didPreempt); sceKernelDelayThread(300); schedulingLogPos += sprintf(schedulingLogPos, "BEFORE sceCtrlPeekBufferPositive 64\n"); didPreempt = 0; result = sceCtrlPeekBufferPositive(&pad_data[0], 64); outputPadData(result, &pad_data[0]); schedulingLogPos += sprintf(schedulingLogPos, "AFTER sceCtrlPeekBufferPositive 64: %08x preempt:%d\n", result, didPreempt); sceKernelDelayThread(300); schedulingLogPos += sprintf(schedulingLogPos, "BEFORE sceCtrlReadBufferPositive 96\n"); didPreempt = 0; result = sceCtrlReadBufferPositive(&pad_data[0], 96); outputPadData(result, &pad_data[0]); schedulingLogPos += sprintf(schedulingLogPos, "AFTER sceCtrlReadBufferPositive 96: %08x preempt:%d\n", result, didPreempt); sceKernelDelayThread(300); schedulingLogPos += sprintf(schedulingLogPos, "BEFORE sceCtrlPeekLatch\n"); didPreempt = 0; result = sceCtrlPeekLatch(&latch); // Result is # of reads, which won't match headless. result = result >= 1 ? 1 : 0; outputLatchData(result, &latch); schedulingLogPos += sprintf(schedulingLogPos, "AFTER sceCtrlPeekLatch: %08x preempt:%d\n", result, didPreempt); sceKernelDelayThread(300); schedulingLogPos += sprintf(schedulingLogPos, "BEFORE sceCtrlReadLatch\n"); didPreempt = 0; result = sceCtrlReadLatch(&latch); // Result is # of reads, which won't match headless. result = result >= 1 ? 1 : 0; outputLatchData(result, &latch); schedulingLogPos += sprintf(schedulingLogPos, "AFTER sceCtrlReadLatch: %08x preempt:%d\n", result, didPreempt); sceKernelDelayThread(300); schedulingLogPos += sprintf(schedulingLogPos, "BEFORE sceCtrlPeekLatch\n"); didPreempt = 0; result = sceCtrlPeekLatch(&latch); outputLatchData(result, &latch); schedulingLogPos += sprintf(schedulingLogPos, "AFTER sceCtrlPeekLatch: %08x preempt:%d\n", result, didPreempt); sceKernelDelayThread(300); sceKernelTerminateDeleteThread(thread); sceKernelDelayThread(300); printf("%s", schedulingLog); return 0; }
void runReferTests() { SceKernelThreadInfo2 info; int i; SceUID delayThread = sceKernelCreateThread("delay", &delayFunc, sceKernelGetThreadCurrentPriority(), 0x1000, PSP_THREAD_ATTR_VFPU, NULL); SceUID deletedThread = sceKernelCreateThread("deleted", &delayFunc, sceKernelGetThreadCurrentPriority(), 0x1000, 0, NULL); sceKernelDeleteThread(deletedThread); info.size = sizeof(info); checkpointNext("Thread IDs:"); checkpoint(" NULL: %08x", sceKernelReferThreadStatus(0, &info)); checkpoint(" Current: %08x", sceKernelReferThreadStatus(sceKernelGetThreadId(), &info)); checkpoint(" Deleted: %08x", sceKernelReferThreadStatus(deletedThread, &info)); checkpoint(" Invalid: %08x", sceKernelReferThreadStatus(0xDEADBEEF, &info)); // Crashes. //checkpointNext("sceKernelReferThreadStatus info ptr:"); //checkpoint(" NULL info: %08x", sceKernelReferThreadStatus(0, NULL)); checkpointNext("Sizes:"); int sizes[] = {-1, 0, 1, 2, 3, 4, 5, 8, 16, 32, 64, 80, 82, 108, 128, 1024}; for (i = 0; i < ARRAY_SIZE(sizes); ++i) { memset(&info, 0xff, sizeof(info)); info.size = sizes[i]; int result = sceKernelReferThreadStatus(0, &info); checkpoint(" %d: %08x => %d (exit: %x)", sizes[i], result, info.size, info.exitStatus); } info.size = sizeof(info); sceKernelStartThread(delayThread, 0, NULL); sceKernelReferThreadStatus(delayThread, &info); checkpointNext("Values:"); schedfThreadInfo(&info, &delayFunc); SceUID slumberThread = sceKernelCreateThread("slumber", &slumberFunc, sceKernelGetThreadCurrentPriority() - 1, 0x1000, 0, NULL); checkpoint(" slumber before start:"); sceKernelReferThreadStatus(slumberThread, &info); schedfThreadInfo(&info, &slumberFunc); sceKernelStartThread(slumberThread, 0, NULL); checkpoint(" started slumber"); checkpoint(" slumber after start:"); sceKernelReferThreadStatus(slumberThread, &info); schedfThreadInfo(&info, &slumberFunc); sceKernelTerminateThread(slumberThread); checkpoint(" terminated slumber"); checkpoint(" slumber after terminate:"); sceKernelReferThreadStatus(slumberThread, &info); schedfThreadInfo(&info, &slumberFunc); sceKernelStartThread(slumberThread, 0, NULL); checkpoint(" started slumber"); checkpoint(" slumber after start:"); sceKernelReferThreadStatus(slumberThread, &info); schedfThreadInfo(&info, &slumberFunc); checkpoint(" woke slumber: %08x", sceKernelWakeupThread(slumberThread)); checkpoint(" slumber after wake:"); sceKernelReferThreadStatus(slumberThread, &info); schedfThreadInfo(&info, &slumberFunc); sceKernelTerminateDeleteThread(slumberThread); checkpoint(" terminated and deleted slumber"); // TODO: Test more cases. flushschedf(); }
int main(int argc, char *argv[]) { int i; char temp[128]; setup(); testAlloc("Normal", PSP_MEMORY_PARTITION_USER, "test", 0, 0x10, NULL); printf("\nNames:\n"); testAlloc(" NULL name", PSP_MEMORY_PARTITION_USER, NULL, 0, 0x1000, NULL); testAlloc(" Blank name", PSP_MEMORY_PARTITION_USER, "", 0, 0x1000, NULL); testAlloc(" Long name", PSP_MEMORY_PARTITION_USER, "1234567890123456789012345678901234567890123456789012345678901234", 0, 0x1000, NULL); printf("\nPartitions:\n"); int parts[] = {-5, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; for (i = 0; i < sizeof(parts) / sizeof(parts[0]); ++i) { sprintf(temp, " Partition %d", parts[i]); testAlloc(temp, parts[i], "part", 0, 0x1000, NULL); } printf("\nTypes:\n"); unsigned int types[] = {-5, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; for (i = 0; i < sizeof(types) / sizeof(types[0]); ++i) { sprintf(temp, " Type %d", types[i]); testAlloc(temp, PSP_MEMORY_PARTITION_USER, "type", types[i], 0x1000, NULL); } printf("\nSizes:\n"); unsigned int sizes[] = { -1, 0, 1, 0x10, 0x20, 0x2F, 0x30, 0x31, 0x32, 0x36, 0x38, 0x39, 0x3A, 0x131, 0x136, 0x139, 0x1000, 0x10000, 0x100000, 0x1000000, 0x10000000, 0x1800000, 0x2000000, }; for (i = 0; i < sizeof(sizes) / sizeof(sizes[0]); ++i) { sprintf(temp, " Size 0x%08X", sizes[i]); testAlloc(temp, PSP_MEMORY_PARTITION_USER, "size", 0, sizes[i], NULL); } printf("\nPositions:\n"); testAlloc(" Wrong type", PSP_MEMORY_PARTITION_USER, "pos", 0, 0x1000, high - 0x1000); testAlloc(" Below low", PSP_MEMORY_PARTITION_USER, "pos", 2, 0x1000, low - 0x1000); testAlloc(" At low", PSP_MEMORY_PARTITION_USER, "pos", 2, 0x1000, low); testAlloc(" Above low", PSP_MEMORY_PARTITION_USER, "pos", 2, 0x1000, low + 0x1000); testAlloc(" Near high", PSP_MEMORY_PARTITION_USER, "pos", 2, 0x1000, high - 0x1000); testAlloc(" At high", PSP_MEMORY_PARTITION_USER, "pos", 2, 0x1000, high); testAlloc(" Above high", PSP_MEMORY_PARTITION_USER, "pos", 2, 0x1000, high + 0x1000); SceUID posPart1 = sceKernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, "part1", 2, 0x1000, low); char *pos1 = (char *)sceKernelGetBlockHeadAddr(posPart1); testAlloc(" Second at low", PSP_MEMORY_PARTITION_USER, "part2", 2, 0x1000, low); char *pos2 = testAlloc(" Second type low", PSP_MEMORY_PARTITION_USER, "part2", 0, 0x1000, low); printf(" Difference: %X\n", pos2 - pos1); sceKernelFreePartitionMemory(posPart1); printf("\nAlignment:\n"); SceUID alignbase[0x1000]; int alignbaseCount; for (alignbaseCount = 0; alignbaseCount < 0x1000; ++alignbaseCount) { alignbase[alignbaseCount] = sceKernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, "alignbase", 0, 0x1, NULL); char *base = (char *)sceKernelGetBlockHeadAddr(alignbase[alignbaseCount]); if (((u32)base & 0xFFF) == 0xF00) break; } SceUID alignLowID = sceKernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, "part1", 3, 0x1000, (void *)0x1000); SceUID alignHighID = sceKernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, "part2", 4, 0x1000, (void *)0x1000); char *alignLow = (char *)sceKernelGetBlockHeadAddr(alignLowID); char *alignHigh = (char *)sceKernelGetBlockHeadAddr(alignHighID); unsigned int aligns[] = { -5, -1, 0, 1, 2, 3, 4, 7, 8, 0x10, 0x11, 0x20, 0x2F, 0x40, 0x60, 0x80, 0x100, 0x1000, 0x2000, 0x1000000, 0x4000000, 0x40000000, 0x80000000, }; for (i = 0; i < sizeof(aligns) / sizeof(aligns[0]); ++i) { sprintf(temp, " Align 0x%08X low", aligns[i]); testAllocDiff(temp, PSP_MEMORY_PARTITION_USER, "part2", 3, 0x1000, (char *)aligns[i], 0, alignLow); sprintf(temp, " Align 0x%08X high", aligns[i]); testAllocDiff(temp, PSP_MEMORY_PARTITION_USER, "part2", 4, 0x1000, (char *)aligns[i], 1, alignHigh); } sceKernelFreePartitionMemory(alignLowID); while (alignbaseCount >= 0) { sceKernelFreePartitionMemory(alignbase[alignbaseCount--]); } sceKernelFreePartitionMemory(alignHighID); printf("\n"); SceUID part1 = sceKernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, "part1", 0, 0x1, NULL); SceUID part2 = sceKernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, "part2", 0, 0x1, NULL); if (part1 > 0 && part2 > 0) { printf("Two with same name: OK\n"); } else { printf("Two with same name: Failed (%08X, %08X)\n", part1, part2); } char *part1Pos = (char *)sceKernelGetBlockHeadAddr(part1); char *part2Pos = (char *)sceKernelGetBlockHeadAddr(part2); printf("Minimum difference: %x\n", part2Pos - part1Pos); sceKernelFreePartitionMemory(part1); sceKernelFreePartitionMemory(part2); part1 = sceKernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, "part1", 3, 0x101, (void *)1); part2 = sceKernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, "part2", 3, 0x101, (void *)1); part1Pos = (char *)sceKernelGetBlockHeadAddr(part1); part2Pos = (char *)sceKernelGetBlockHeadAddr(part2); printf("Offset difference: %x\n", part2Pos - part1Pos); sceKernelFreePartitionMemory(part1); sceKernelFreePartitionMemory(part2); SceUID reschedThread = sceKernelCreateThread("resched", &reschedFunc, sceKernelGetThreadCurrentPriority(), 0x1000, 0, NULL); sceKernelStartThread(reschedThread, 0, NULL); SceUID reschedPart = sceKernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, "part", 0, 0x1000, NULL); sceKernelGetBlockHeadAddr(reschedPart); sceKernelFreePartitionMemory(reschedPart); sceKernelTerminateDeleteThread(reschedThread); printf("Reschedule: %s\n", didResched ? "yes" : "no"); SceUID allocs[1024]; int result = 0; for (i = 0; i < 1024; i++) { allocs[i] = sceKernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, "create", 0, 0x100, NULL); if (allocs[i] < 0) { result = allocs[i]; break; } } if (result != 0) printf("Create 1024: Failed at %d (%08X)\n", i, result); else printf("Create 1024: OK\n"); while (--i >= 0) sceKernelFreePartitionMemory(allocs[i]); printf("Get deleted: %08X\n", (unsigned int)sceKernelGetBlockHeadAddr(reschedPart)); printf("Get NULL: %08X\n", (unsigned int)sceKernelGetBlockHeadAddr(0)); printf("Get invalid: %08X\n", (unsigned int)sceKernelGetBlockHeadAddr(0xDEADBEEF)); printf("Free deleted: %08X\n", sceKernelFreePartitionMemory(reschedPart)); printf("Free NULL: %08X\n", sceKernelFreePartitionMemory(0)); printf("Free invalid: %08X\n", sceKernelFreePartitionMemory(0xDEADBEEF)); return 0; }
int main(int argc, char *argv[]) { SceCtrlData pad; int oldButtons = 0; #define SECOND 1000000 #define REPEAT_START (1 * SECOND) #define REPEAT_DELAY (SECOND / 5) struct timeval repeatStart; struct timeval repeatDelay; repeatStart.tv_sec = 0; repeatStart.tv_usec = 0; repeatDelay.tv_sec = 0; repeatDelay.tv_usec = 0; pspDebugScreenInit(); pspDebugScreenPrintf("Press Cross to start the Task Scheduler Test\n"); pspDebugScreenPrintf("Press Circle to start the CpuSuspendIntr/CpuResumeIntr Test\n"); pspDebugScreenPrintf("Press Square to start the Task with thread of same priority\n"); pspDebugScreenPrintf("Press Left to start the Task Dispatcher Test\n"); pspDebugScreenPrintf("Press Triangle to Exit\n"); while(!done) { sceCtrlReadBufferPositive(&pad, 1); int buttonDown = (oldButtons ^ pad.Buttons) & pad.Buttons; if (pad.Buttons == oldButtons) { struct timeval now; gettimeofday(&now, NULL); if (repeatStart.tv_sec == 0) { repeatStart.tv_sec = now.tv_sec; repeatStart.tv_usec = now.tv_usec; repeatDelay.tv_sec = 0; repeatDelay.tv_usec = 0; } else { long usec = (now.tv_sec - repeatStart.tv_sec) * SECOND; usec += (now.tv_usec - repeatStart.tv_usec); if (usec >= REPEAT_START) { if (repeatDelay.tv_sec != 0) { usec = (now.tv_sec - repeatDelay.tv_sec) * SECOND; usec += (now.tv_usec - repeatDelay.tv_usec); if (usec >= REPEAT_DELAY) { repeatDelay.tv_sec = 0; } } if (repeatDelay.tv_sec == 0) { buttonDown = pad.Buttons; repeatDelay.tv_sec = now.tv_sec; repeatDelay.tv_usec = now.tv_usec; } } } } else { repeatStart.tv_sec = 0; } if (buttonDown & PSP_CTRL_CROSS) { SceUID lowThid = sceKernelCreateThread("Low Prio Thread", threadLowPrio, 0x70, 0x1000, 0, 0); SceUID mediumThid = sceKernelCreateThread("Medium Prio Thread", threadMediumPrio, 0x30, 0x1000, 0, 0); SceUID highThid = sceKernelCreateThread("High Prio Thread", threadHighPrio, 0x10, 0x1000, 0, 0); SceUID busyThid = sceKernelCreateThread("Busy Thread", threadBusy, 0x30, 0x1000, 0, 0); testDone = 0; highPrioCounter = 0; mediumPrioCounter = 0; lowPrioCounter = 0; sceKernelStartThread(lowThid, 0, 0); sceKernelStartThread(mediumThid, 0, 0); sceKernelStartThread(busyThid, 0, 0); sceKernelStartThread(highThid, 0, 0); int totalDelay = 5000000; sceKernelDelayThread(totalDelay); testDone = 1; sceKernelWaitThreadEnd(busyThid, NULL); sceKernelWaitThreadEnd(mediumThid, NULL); sceKernelWaitThreadEnd(highThid, NULL); sceKernelWaitThreadEnd(lowThid, NULL); pspDebugScreenPrintf("Counters: high=%d (%d us), medium=%d, low=%d\n", highPrioCounter, (totalDelay / highPrioCounter), mediumPrioCounter, lowPrioCounter); } if (buttonDown & PSP_CTRL_CIRCLE) { msg = buffer; strcpy(msg, ""); SceUID sleepingThid = sceKernelCreateThread("Sleeping Thread", sleepingThread, 0x10, 0x1000, 0, 0); sceKernelStartThread(sleepingThid, 0, 0); sceKernelDelayThread(100000); int intr = sceKernelCpuSuspendIntr(); sceKernelWakeupThread(sleepingThid); strcat(msg, "Main Thread with disabled interrupts\n"); sceKernelCpuResumeIntr(intr); strcat(msg, "Main Thread with enabled interrupts\n"); pspDebugScreenPrintf("%s", msg); } if (buttonDown & PSP_CTRL_SQUARE) { msg = buffer; strcpy(msg, ""); // Two threads having the same priority SceUID thread1 = sceKernelCreateThread("Thread 1", threadPrio_1, sceKernelGetThreadCurrentPriority(), 0x1000, 0, 0); SceUID thread2 = sceKernelCreateThread("Thread 2", threadPrio_2, sceKernelGetThreadCurrentPriority(), 0x1000, 0, 0); // Test that thread1 will be scheduled before thread2 sceKernelStartThread(thread1, 0, 0); sceKernelStartThread(thread2, 0, 0); strcat(msg, "1 "); sceKernelDelayThread(10000); strcat(msg, "4"); sceKernelWaitThreadEnd(thread1, NULL); sceKernelWaitThreadEnd(thread2, NULL); pspDebugScreenPrintf("Starting 2 threads at same priority: %s\n", msg); // Now with a different order for create & start strcpy(msg, ""); SceUID thread3 = sceKernelCreateThread("Thread 3", threadPrio_3, sceKernelGetThreadCurrentPriority(), 0x1000, 0, 0); SceUID thread4 = sceKernelCreateThread("Thread 4", threadPrio_4, sceKernelGetThreadCurrentPriority(), 0x1000, 0, 0); // Test that thread4 will be scheduled before thread3 sceKernelStartThread(thread4, 0, 0); sceKernelStartThread(thread3, 0, 0); strcat(msg, "1 "); sceKernelDelayThread(10000); strcat(msg, "4"); sceKernelWaitThreadEnd(thread3, NULL); sceKernelWaitThreadEnd(thread4, NULL); pspDebugScreenPrintf("Starting 2 threads with a different order create/start: %s\n", msg); } if (buttonDown & PSP_CTRL_LEFT) { msg = buffer; strcpy(msg, ""); int state = sceKernelSuspendDispatchThread(); // High priority thread SceUID thread = sceKernelCreateThread("Thread 1", threadHello, 0x10, 0x1000, 0, 0); strcat(msg, "1 "); // sceKernelStartThread resumes the thread dispatcher sceKernelStartThread(thread, 0, 0); strcat(msg, "2 "); sceKernelDelayThread(10000); strcat(msg, "3 "); sceKernelResumeDispatchThread(state); sceKernelWaitThreadEnd(thread, NULL); pspDebugScreenPrintf("Starting high prio thread with a disabled dispatcher (state=0x%X): %s\n", state, msg); msg = buffer; strcpy(msg, ""); state = sceKernelSuspendDispatchThread(); // Low priority thread thread = sceKernelCreateThread("Thread 1", threadHello, 0x70, 0x1000, 0, 0); strcat(msg, "1 "); // sceKernelStartThread resumes the thread dispatcher sceKernelStartThread(thread, 0, 0); strcat(msg, "2 "); sceKernelDelayThread(10000); strcat(msg, "3 "); sceKernelResumeDispatchThread(state); sceKernelWaitThreadEnd(thread, NULL); pspDebugScreenPrintf("Starting low prio thread with a disabled dispatcher (state=0x%X): %s\n", state, msg); } if (buttonDown & PSP_CTRL_TRIANGLE) { done = 1; } oldButtons = pad.Buttons; } sceGuTerm(); sceKernelExitGame(); return 0; }
int main(int argc, char *argv[]) { int i, result; SceKernelThreadInfo info; SceUID testThread = sceKernelCreateThread("test", &testFunc, sceKernelGetThreadCurrentPriority(), 0x1000, 0, NULL); SceUID deletedThread = sceKernelCreateThread("deleted", &testFunc, sceKernelGetThreadCurrentPriority(), 0x1000, 0, NULL); sceKernelDeleteThread(deletedThread); checkpointNext("Thread IDs:"); checkpoint(" Normal: %08x", sceKernelStartThread(testThread, 0, NULL)); checkpoint(" Twice: %08x", sceKernelStartThread(testThread, 0, NULL)); checkpoint(" NULL: %08x", sceKernelStartThread(0, 0, NULL)); checkpoint(" Current: %08x", sceKernelStartThread(sceKernelGetThreadId(), 0, NULL)); checkpoint(" Deleted: %08x", sceKernelStartThread(deletedThread, 0, NULL)); checkpoint(" Invalid: %08x", sceKernelStartThread(0xDEADBEEF, 0, NULL)); checkpointNext("Argument length:"); SceUID argLengthThread = sceKernelCreateThread("argLength", &argLengthFunc, sceKernelGetThreadCurrentPriority() - 1, 0x800, 0, NULL); char argLengthTemp[0x1000]; void *argLengthStack; info.size = sizeof(info); sceKernelReferThreadStatus(argLengthThread, &info); argLengthStack = info.stack; result = sceKernelStartThread(argLengthThread, 8, NULL); sceKernelWaitThreadEnd(argLengthThread, NULL); char temp[256]; if (argLengthArgv == 0) sprintf(temp, "NULL"); else if (argLengthArgv == argLengthTemp) sprintf(temp, "original"); else sprintf(temp, "stack+0x%x", (char *)argLengthArgv - (char *)argLengthStack); checkpoint(" With NULL ptr: %08x (%d, %s)", result, argLengthArgc, temp); // Note: larger than stack seems to crash the PSP... static int lengths[] = {-1, 0x80000000, 0, 1, 2, 3, 4, 5, 6, 7, 8, 80, 90, 0x600}; for (i = 0; i < ARRAY_SIZE(lengths); ++i) { argLengthArgc = -1; argLengthArgv = NULL; result = sceKernelStartThread(argLengthThread, lengths[i], argLengthTemp); sceKernelWaitThreadEnd(argLengthThread, NULL); if (argLengthArgv == 0) sprintf(temp, "NULL"); else if (argLengthArgv == argLengthTemp) sprintf(temp, "original"); else sprintf(temp, "stack+0x%x", (char *)argLengthArgv - (char *)argLengthStack); checkpoint(" %d arg length: %08x (%d, %s)", lengths[i], result, argLengthArgc, temp); } // NULL crashes it, though... checkpointNext("Argument pointers:"); void *argptrs[] = {argLengthTemp, (void *)0xDEADBEEF, (void *)0x80000000}; for (i = 0; i < ARRAY_SIZE(argptrs); ++i) { argLengthArgc = -1; argLengthArgv = NULL; result = sceKernelStartThread(argLengthThread, 4, argptrs[i]); sceKernelWaitThreadEnd(argLengthThread, NULL); if (argLengthArgv == 0) sprintf(temp, "NULL"); else if (argLengthArgv == argLengthTemp) sprintf(temp, "original"); else sprintf(temp, "stack+0x%x", (char *)argLengthArgv - (char *)argLengthStack); checkpoint(" arg ptr #%d: %08x (%d, %s)", i, result, argLengthArgc, temp); } checkpointNext("Priorities:"); static int priorities[] = {0x8, 0x1F, 0x20, 0x21, 0x40}; for (i = 0; i < ARRAY_SIZE(priorities); ++i) { argLengthArgc = -1; sceKernelDeleteThread(argLengthThread); argLengthThread = sceKernelCreateThread("argLength", &argLengthFunc, priorities[i], 0x800, 0, NULL); result = sceKernelStartThread(argLengthThread, priorities[i], argLengthTemp); int afterStart = argLengthArgc; sceKernelWaitThreadEnd(argLengthThread, NULL); int priorityDiff = priorities[i] - sceKernelGetThreadCurrentPriority(); checkpoint(" priority 0x%02x: %08x (current%s0x%02x, %s)", priorities[i], result, priorityDiff < 0 ? "-" : "+", priorityDiff < 0 ? -priorityDiff : priorityDiff, afterStart == priorities[i] ? "resched" : (argLengthArgc == priorities[i] ? "deferred" : "never")); } checkpointNext("Stack:"); testCheckStackLayout(" No arg", 0, 0); testCheckStackLayout(" Odd arg", 1, 0); testCheckStackLayout(" Large arg", 0x600, 0); testCheckStackLayout(" Low stack", 0, 0x00400000); testCheckStackLayout(" Without fill", 0, 0x00100000); testCheckStackLayout(" Clear stack", 0, 0x00200000); return 0; }
static int music_thread(SceSize arg, void *argp) { u32 key = 0; u32 oldkey = 0; u64 start, end; double interval = 0; g_thread_actived = 1; g_thread_exited = 0; sceRtcGetCurrentTick(&start); sceRtcGetCurrentTick(&end); while (g_thread_actived) { music_lock(); if (g_list.is_list_playing) { if (musicdrv_has_stop()) { if (g_list.first_time) { int ret; ret = music_play(g_list.curr_pos); if (ret == 0) g_list.first_time = false; } else { get_next_music(); if (!g_list.is_list_playing) { music_unlock(); music_load(g_list.curr_pos); music_stop(); continue; } music_play(g_list.curr_pos); } } music_unlock(); sceKernelDelayThread(100000); } else { music_unlock(); sceKernelDelayThread(500000); } if (g_music_hprm_enable) { key = ctrl_hprm_raw(); sceRtcGetCurrentTick(&end); interval = pspDiffTime(&end, &start); if (key == PSP_HPRM_FORWARD || key == PSP_HPRM_BACK || key == PSP_HPRM_PLAYPAUSE) { if (key != oldkey) { sceRtcGetCurrentTick(&start); sceRtcGetCurrentTick(&end); interval = pspDiffTime(&end, &start); } if (interval >= 0.5) { if (key == PSP_HPRM_FORWARD) { musicdrv_fforward(5); sceKernelDelayThread(200000); } else if (key == PSP_HPRM_BACK) { musicdrv_fbackward(5); sceKernelDelayThread(200000); } } oldkey = key; if (key == PSP_HPRM_PLAYPAUSE && interval >= 4.0) { power_down(); scePowerRequestSuspend(); } } else { if ((oldkey == PSP_HPRM_FORWARD || oldkey == PSP_HPRM_BACK || oldkey == PSP_HPRM_PLAYPAUSE)) { if (interval < 0.5) { if (oldkey == PSP_HPRM_FORWARD) music_next(); else if (oldkey == PSP_HPRM_BACK) music_prev(); } if (interval < 4.0) { if (oldkey == PSP_HPRM_PLAYPAUSE) music_list_playorpause(); } } oldkey = key; sceRtcGetCurrentTick(&start); } } { int thid = sceKernelGetThreadId(); int oldpri = sceKernelGetThreadCurrentPriority(); sceKernelChangeThreadPriority(thid, 90); cache_routine(); sceKernelChangeThreadPriority(thid, oldpri); } } g_thread_actived = 0; g_thread_exited = 1; return 0; }
void startLockThreadSema(SceUID sema) { lockThread = sceKernelCreateThread("sema lock", &lockThreadSema, sceKernelGetThreadCurrentPriority() - 1, 0x1000, 0, NULL); dispatchCheckpoint("S sceKernelCreateThread: %08x", lockThread >= 0 ? 1 : lockThread); dispatchCheckpoint("S sceKernelStartThread: %08x", sceKernelStartThread(lockThread, 4, &sema)); }
void startLockThreadEventFlag(SceUID flag) { lockThread = sceKernelCreateThread("eventflag lock", &lockThreadEventFlag, sceKernelGetThreadCurrentPriority() - 1, 0x1000, 0, NULL); dispatchCheckpoint("S sceKernelCreateThread: %08x", lockThread >= 0 ? 1 : lockThread); dispatchCheckpoint("S sceKernelStartThread: %08x", sceKernelStartThread(lockThread, 4, &flag)); }
void startLockThreadLwMutex(void *mutex) { lockThread = sceKernelCreateThread("lwmutex lock", &lockThreadLwMutex, sceKernelGetThreadCurrentPriority() - 1, 0x1000, 0, NULL); dispatchCheckpoint("S sceKernelCreateThread: %08x", lockThread >= 0 ? 1 : lockThread); dispatchCheckpoint("S sceKernelStartThread: %08x", sceKernelStartThread(lockThread, 4, &mutex)); }