void checkLwMutex(int doDispatch) { SceLwMutexWorkarea workarea; dispatchCheckpoint("sceKernelCreateLwMutex: %08x", sceKernelCreateLwMutex(&workarea, "lwmutex", 0, 1, NULL)); dispatchCheckpoint("sceKernelUnlockLwMutex: %08x", sceKernelUnlockLwMutex(&workarea, 1)); dispatchCheckpoint("sceKernelLockLwMutex: %08x", sceKernelLockLwMutex(&workarea, 1, NULL)); dispatchCheckpoint("sceKernelLockLwMutex invalid: %08x", sceKernelLockLwMutex(&workarea, -1, NULL)); dispatchCheckpoint("sceKernelDeleteLwMutex: %08x", sceKernelDeleteLwMutex(&workarea)); dispatchCheckpoint("sceKernelCreateLwMutex: %08x", sceKernelCreateLwMutex(&workarea, "lwmutex", 0, 1, NULL)); startLockThreadLwMutex(&workarea); int state; if (doDispatch) { ++ignoreResched; state = sceKernelSuspendDispatchThread(); dispatchCheckpoint("sceKernelSuspendDispatchThread: %08x", state); } SceUInt timeout = 300; dispatchCheckpoint("sceKernelLockLwMutex: %08x", sceKernelLockLwMutex(&workarea, 1, &timeout)); dispatchCheckpoint("sceKernelUnlockLwMutex: %08x", sceKernelUnlockLwMutex(&workarea, 1)); if (doDispatch) { dispatchCheckpoint("sceKernelResumeDispatchThread: %08x", sceKernelResumeDispatchThread(state)); --ignoreResched; } endLockThreadLwMutex(&workarea); dispatchCheckpoint("sceKernelTryLockLwMutex: %08x", sceKernelTryLockLwMutex_600(&workarea, 1)); dispatchCheckpoint("sceKernelDeleteLwMutex: %08x", sceKernelDeleteLwMutex(&workarea)); }
int lockThreadLwMutex(SceSize argc, void *argp) { void *mutex = *(void **)argp; dispatchCheckpoint("T sceKernelLockLwMutex: %08x", sceKernelLockLwMutex(mutex, 2, NULL)); dispatchCheckpoint("T sceKernelDelayThread: %08x", sceKernelDelayThread(3000)); dispatchCheckpoint("T sceKernelUnlockLwMutex: %08x", sceKernelUnlockLwMutex(mutex, 1)); return 0; }
static int lockFunc(SceSize argSize, void* argPointer) { SceUInt timeout = 1000; schedulingResult = sceKernelLockLwMutex(*(void**) argPointer, 1, &timeout); schedulingLogPos += sprintf(schedulingLog + schedulingLogPos, "L1 "); \ sceKernelDelayThread(1000); if (schedulingResult == 0) sceKernelUnlockLwMutex(*(void**) argPointer, 1); return 0; }
void * _sbrk_r(struct _reent *reent, ptrdiff_t incr) { if (sceKernelLockLwMutex((struct SceKernelLwMutexWork*)_newlib_sbrk_mutex, 1, 0) < 0) goto fail; if (!_newlib_heap_base || _newlib_heap_cur + incr >= _newlib_heap_end) { sceKernelUnlockLwMutex((struct SceKernelLwMutexWork*)_newlib_sbrk_mutex, 1); fail: reent->_errno = ENOMEM; return (void*)-1; } char *prev_heap_end = _newlib_heap_cur; _newlib_heap_cur += incr; sceKernelUnlockLwMutex((struct SceKernelLwMutexWork*)_newlib_sbrk_mutex, 1); return (void*) prev_heap_end; }
int main(int argc, char **argv) { LOCK_TEST("Lock 0 => 0", PSP_MUTEX_ATTR_FIFO, 0, 0); LOCK_TEST("Lock 0 => 1", PSP_MUTEX_ATTR_FIFO, 0, 1); LOCK_TEST("Lock 0 => 2", PSP_MUTEX_ATTR_FIFO, 0, 2); LOCK_TEST("Lock 0 => -1", PSP_MUTEX_ATTR_FIFO, 0, -1); LOCK_TEST("Lock 1 => 1", PSP_MUTEX_ATTR_FIFO, 1, 1); LOCK_TEST("Lock 0 => 2 (recursive)", PSP_MUTEX_ATTR_ALLOW_RECURSIVE, 0, 2); LOCK_TEST("Lock 0 => -1 (recursive)", PSP_MUTEX_ATTR_ALLOW_RECURSIVE, 0, -1); LOCK_TEST("Lock 1 => 1 (recursive)", PSP_MUTEX_ATTR_ALLOW_RECURSIVE, 1, 1); LOCK_TEST("Lock 1 => INT_MAX - 1 (recursive)", PSP_MUTEX_ATTR_ALLOW_RECURSIVE, 1, INT_MAX - 1); LOCK_TEST("Lock 1 => INT_MAX (recursive)", PSP_MUTEX_ATTR_ALLOW_RECURSIVE, 1, INT_MAX); LOCK_TEST("Lock INT_MAX => INT_MAX (recursive)", PSP_MUTEX_ATTR_ALLOW_RECURSIVE, INT_MAX, INT_MAX); LOCK_TEST_TIMEOUT("Lock 0 => 0", PSP_MUTEX_ATTR_FIFO, 0, 0, 500); LOCK_TEST_TIMEOUT("Lock 0 => 1", PSP_MUTEX_ATTR_FIFO, 0, 1, 500); LOCK_TEST_TIMEOUT("Lock 0 => 2", PSP_MUTEX_ATTR_FIFO, 0, 2, 500); LOCK_TEST_TIMEOUT("Lock 0 => -1", PSP_MUTEX_ATTR_FIFO, 0, -1, 500); LOCK_TEST_TIMEOUT("Lock 1 => 1", PSP_MUTEX_ATTR_FIFO, 1, 1, 500); LOCK_TEST_TIMEOUT("Lock 0 => 2 (recursive)", PSP_MUTEX_ATTR_ALLOW_RECURSIVE, 0, 2, 500); LOCK_TEST_TIMEOUT("Lock 0 => -1 (recursive)", PSP_MUTEX_ATTR_ALLOW_RECURSIVE, 0, -1, 500); LOCK_TEST_TIMEOUT("Lock 1 => 1 (recursive)", PSP_MUTEX_ATTR_ALLOW_RECURSIVE, 1, 1, 500); LOCK_TEST_TIMEOUT("Zero timeout", PSP_MUTEX_ATTR_FIFO, 0, 1, 0); SceUID lockThread = CREATE_SIMPLE_THREAD(lockFunc); LOCK_TEST_TIMEOUT_THREAD("Locked 1 => 1", PSP_MUTEX_ATTR_FIFO, 1, 1, 500); LOCK_TEST_TIMEOUT_THREAD("Locked 0 => 1", PSP_MUTEX_ATTR_FIFO, 0, 1, 500); LOCK_TEST_TIMEOUT_THREAD("Locked 1 => 1 (recursive)", PSP_MUTEX_ATTR_ALLOW_RECURSIVE, 1, 1, 500); LOCK_TEST_TIMEOUT_THREAD("Locked 0 => 1 (recursive)", PSP_MUTEX_ATTR_ALLOW_RECURSIVE, 0, 1, 500); LOCK_TEST_TIMEOUT_THREAD("Locked zero timeout", PSP_MUTEX_ATTR_FIFO, 0, 1, 0); SceUID deleteThread = CREATE_SIMPLE_THREAD(deleteMeFunc); SceLwMutexWorkarea workarea; void *workareaPtr = &workarea; sceKernelCreateLwMutex(&workarea, "lock", 0, 1, NULL); sceKernelStartThread(deleteThread, sizeof(void*), &workareaPtr); sceKernelDelayThread(500); sceKernelDeleteLwMutex(&workarea); // Crash. //LOCK_TEST_SIMPLE("NULL => 0", 0, 0); //LOCK_TEST_SIMPLE("NULL => 1", 0, 1); //LOCK_TEST_SIMPLE("Invalid => 1", (void*) 0xDEADBEEF, 1); LOCK_TEST_SIMPLE("Deleted => 1", &workarea, 1); BASIC_SCHED_TEST("Zero", result = sceKernelLockLwMutex(&workarea2, 0, NULL); );
static size_t psp_write_avail(void *data) { psp_audio_t* psp = (psp_audio_t*)data; #ifdef VITA size_t val; sceKernelLockLwMutex((struct SceKernelLwMutexWork*)&psp->lock, 1, 0); val = AUDIO_BUFFER_SIZE - ((uint16_t) (psp->writePos - psp->readPos) & AUDIO_BUFFER_SIZE_MASK); sceKernelUnlockLwMutex((struct SceKernelLwMutexWork*)&psp->lock, 1); return val; #else /* TODO */ return AUDIO_BUFFER_SIZE - ((uint16_t) (psp->writePos - psp->readPos) & AUDIO_BUFFER_SIZE_MASK); #endif }
static int exitFunc(SceSize argSize, void* argPointer) { int result = sceKernelLockLwMutex(*(void**) argPointer, 1, NULL); printf("Now exiting: %08X\n", result); return 0; }
static int deleteMeFunc(SceSize argSize, void* argPointer) { int result = sceKernelLockLwMutex(*(void**) argPointer, 1, NULL); printf("After delete: %08X\n", result); return 0; }
static int audioMainLoop(SceSize args, void* argp) { psp_audio_t* psp = *((psp_audio_t**)argp); #ifdef VITA int port = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_MAIN, AUDIO_OUT_COUNT, psp->rate, SCE_AUDIO_OUT_MODE_STEREO); #else sceAudioSRCChReserve(AUDIO_OUT_COUNT, psp->rate, 2); #endif while (psp->running) { #ifdef VITA //sys_event_queue_receive(id, &event, SYS_NO_TIMEOUT); sceKernelLockLwMutex((struct SceKernelLwMutexWork*)&psp->lock, 1, 0); uint16_t readPos = psp->readPos; uint16_t readPos2 = psp->readPos; bool cond = ((uint16_t)(psp->writePos - readPos) & AUDIO_BUFFER_SIZE_MASK) < (AUDIO_OUT_COUNT * 2); if (!cond) { readPos += AUDIO_OUT_COUNT; readPos &= AUDIO_BUFFER_SIZE_MASK; psp->readPos = readPos; } sceKernelUnlockLwMutex((struct SceKernelLwMutexWork*)&psp->lock, 1); sceKernelSignalLwCond(&psp->cond); sceAudioOutOutput(port, cond ? (psp->zeroBuffer) : (psp->buffer + readPos2)); #else /* Get a non-volatile copy. */ uint16_t readPos = psp->readPos; bool cond = ((uint16_t)(psp->writePos - readPos) & AUDIO_BUFFER_SIZE_MASK) < (AUDIO_OUT_COUNT * 2); sceAudioSRCOutputBlocking(PSP_AUDIO_VOLUME_MAX, cond ? (psp->zeroBuffer) : (psp->buffer + readPos)); if (!cond) { readPos += AUDIO_OUT_COUNT; readPos &= AUDIO_BUFFER_SIZE_MASK; psp->readPos = readPos; } #endif } #ifdef VITA sceAudioOutReleasePort(port); #else sceAudioSRCChRelease(); sceKernelExitThread(0); #endif return 0; }
static ssize_t psp_audio_write(void *data, const void *buf, size_t size) { psp_audio_t* psp = (psp_audio_t*)data; uint16_t sampleCount; uint16_t writePos = psp->writePos; sampleCount= size / sizeof(uint32_t); #ifdef VITA if (psp->nonblocking) { if (AUDIO_BUFFER_SIZE - ((uint16_t) (psp->writePos - psp->readPos) & AUDIO_BUFFER_SIZE_MASK) < size) return 0; } while (AUDIO_BUFFER_SIZE - ((uint16_t) (psp->writePos - psp->readPos) & AUDIO_BUFFER_SIZE_MASK) < size){ sceKernelWaitLwCond(&psp->cond, 0); } sceKernelLockLwMutex((struct SceKernelLwMutexWork*)&psp->lock, 1, 0); if((writePos + sampleCount) > AUDIO_BUFFER_SIZE) { memcpy(psp->buffer + writePos, buf, (AUDIO_BUFFER_SIZE - writePos) * sizeof(uint32_t)); memcpy(psp->buffer, (uint32_t*) buf + (AUDIO_BUFFER_SIZE - writePos), (writePos + sampleCount - AUDIO_BUFFER_SIZE) * sizeof(uint32_t)); } else memcpy(psp->buffer + writePos, buf, size); writePos += sampleCount; writePos &= AUDIO_BUFFER_SIZE_MASK; psp->writePos = writePos; sceKernelUnlockLwMutex((struct SceKernelLwMutexWork*)&psp->lock, 1); return size; #else #if 0 if (psp->nonblocking) { /* TODO */ } #endif if((writePos + sampleCount) > AUDIO_BUFFER_SIZE) { memcpy(psp->buffer + writePos, buf, (AUDIO_BUFFER_SIZE - writePos) * sizeof(uint32_t)); memcpy(psp->buffer, (uint32_t*) buf + (AUDIO_BUFFER_SIZE - writePos), (writePos + sampleCount - AUDIO_BUFFER_SIZE) * sizeof(uint32_t)); } else memcpy(psp->buffer + writePos, buf, size); writePos += sampleCount; writePos &= AUDIO_BUFFER_SIZE_MASK; psp->writePos = writePos; return sampleCount; #endif }