From 194f7375da7098be93b97e32200d878fb78b481c Mon Sep 17 00:00:00 2001 From: Eladash Date: Sun, 18 Sep 2022 21:19:34 +0300 Subject: [PATCH] SPU/LV2: Fix tiny race conditions --- rpcs3/Emu/CPU/CPUThread.cpp | 5 ++- rpcs3/Emu/Cell/lv2/sys_cond.cpp | 1 + rpcs3/Emu/Cell/lv2/sys_event.cpp | 12 +++++-- rpcs3/Emu/Cell/lv2/sys_event_flag.cpp | 6 ++++ rpcs3/Emu/Cell/lv2/sys_fs.cpp | 33 +++++++++++++++---- rpcs3/Emu/Cell/lv2/sys_interrupt.cpp | 1 + rpcs3/Emu/Cell/lv2/sys_lwcond.cpp | 1 + rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp | 1 + rpcs3/Emu/Cell/lv2/sys_memory.cpp | 27 ++++++++++----- rpcs3/Emu/Cell/lv2/sys_mmapper.cpp | 8 +++++ rpcs3/Emu/Cell/lv2/sys_mutex.cpp | 1 + rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp | 4 ++- rpcs3/Emu/Cell/lv2/sys_prx.cpp | 3 ++ rpcs3/Emu/Cell/lv2/sys_rwlock.cpp | 1 + rpcs3/Emu/Cell/lv2/sys_spu.cpp | 47 ++++++++++++++++++++------- rpcs3/Emu/Cell/lv2/sys_timer.cpp | 2 ++ rpcs3/Emu/Cell/lv2/sys_usbd.cpp | 10 ++++-- rpcs3/Emu/Cell/lv2/sys_vm.cpp | 3 ++ 18 files changed, 130 insertions(+), 36 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index a246fb3600..675fcb36ca 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -695,7 +695,6 @@ bool cpu_thread::check_state() noexcept { // Sticky flag, indicates check_state() is not allowed to return true flags -= cpu_flag::temp; - flags -= cpu_flag::wait; cpu_can_stop = false; store = true; } @@ -766,9 +765,9 @@ bool cpu_thread::check_state() noexcept } else { - if (cpu_can_stop && !(flags & cpu_flag::wait)) + if (flags & cpu_flag::wait) { - flags += cpu_flag::wait; + flags -= cpu_flag::wait; store = true; } diff --git a/rpcs3/Emu/Cell/lv2/sys_cond.cpp b/rpcs3/Emu/Cell/lv2/sys_cond.cpp index 9ddbdba868..8db28a9328 100644 --- a/rpcs3/Emu/Cell/lv2/sys_cond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_cond.cpp @@ -99,6 +99,7 @@ error_code sys_cond_create(ppu_thread& ppu, vm::ptr cond_id, u32 mutex_id, return error; } + ppu.check_state(); *cond_id = idm::last_id(); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_event.cpp b/rpcs3/Emu/Cell/lv2/sys_event.cpp index 8ba38e586c..aed56f207d 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event.cpp @@ -220,6 +220,7 @@ error_code sys_event_queue_create(cpu_thread& cpu, vm::ptr equeue_id, vm::p return error; } + cpu.check_state(); *equeue_id = idm::last_id(); return CELL_OK; } @@ -381,7 +382,9 @@ error_code sys_event_queue_tryreceive(ppu_thread& ppu, u32 equeue_id, vm::ptrmutex); + std::array events; + + std::unique_lock lock(queue->mutex); if (!queue->exists) { @@ -392,13 +395,17 @@ error_code sys_event_queue_tryreceive(ppu_thread& ppu, u32 equeue_id, vm::ptrevents.empty()) { - auto& dest = event_array[count++]; + auto& dest = events[count++]; const auto event = queue->events.front(); queue->events.pop_front(); std::tie(dest.source, dest.data1, dest.data2, dest.data3) = event; } + lock.unlock(); + ppu.check_state(); + + std::copy_n(event_array.get_ptr(), count, events.begin()); *number = count; return CELL_OK; @@ -559,6 +566,7 @@ error_code sys_event_port_create(cpu_thread& cpu, vm::ptr eport_id, s32 por if (const u32 id = idm::make(port_type, name)) { + cpu.check_state(); *eport_id = id; return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp b/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp index 1a489638e8..0a70d03dc6 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp @@ -77,6 +77,7 @@ error_code sys_event_flag_create(ppu_thread& ppu, vm::ptr id, vm::ptr flags) return +flag.pattern; }); + ppu.check_state(); + if (!flag) { if (flags) *flags = 0; diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index b8412c8e39..6409c7ef3d 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -839,6 +839,7 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr path, s32 flags, vm::ptr< return result; })) { + ppu.check_state(); *fd = id; return CELL_OK; } @@ -962,7 +963,7 @@ error_code sys_fs_write(ppu_thread& ppu, u32 fd, vm::cptr buf, u64 nbytes, return CELL_EROFS; } - std::lock_guard lock(file->mp->mutex); + std::unique_lock lock(file->mp->mutex); if (!file->file) { @@ -986,8 +987,11 @@ error_code sys_fs_write(ppu_thread& ppu, u32 fd, vm::cptr buf, u64 nbytes, file->file.seek(0, fs::seek_end); } - *nwrite = file->op_write(buf, nbytes); + const u64 written = file->op_write(buf, nbytes); + lock.unlock(); + ppu.check_state(); + *nwrite = written; return CELL_OK; } @@ -1102,7 +1106,7 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr path, vm::ptr fd) return {CELL_ENOTDIR, path}; } - std::lock_guard lock(mp->mutex); + std::unique_lock lock(mp->mutex); const fs::dir dir(local_path); @@ -1177,6 +1181,9 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr path, vm::ptr fd) if (const u32 id = idm::make(processed_path, std::move(data))) { + lock.unlock(); + ppu.check_state(); + *fd = id; return CELL_OK; } @@ -1199,6 +1206,8 @@ error_code sys_fs_readdir(ppu_thread& ppu, u32 fd, vm::ptr dir, vm return CELL_EBADF; } + ppu.check_state(); + if (auto* info = directory->dir_read()) { dir->d_type = info->is_directory ? CELL_FS_TYPE_DIRECTORY : CELL_FS_TYPE_REGULAR; @@ -1265,7 +1274,7 @@ error_code sys_fs_stat(ppu_thread& ppu, vm::cptr path, vm::ptr return {CELL_ENOTMOUNTED, path}; } - std::lock_guard lock(mp->mutex); + std::unique_lock lock(mp->mutex); fs::stat_t info{}; @@ -1308,6 +1317,9 @@ error_code sys_fs_stat(ppu_thread& ppu, vm::cptr path, vm::ptr } } + lock.unlock(); + ppu.check_state(); + sb->mode = info.is_directory ? CELL_FS_S_IFDIR | 0777 : CELL_FS_S_IFREG | 0666; sb->uid = mp->flags & lv2_mp_flag::no_uid_gid ? -1 : 0; sb->gid = mp->flags & lv2_mp_flag::no_uid_gid ? -1 : 0; @@ -1340,7 +1352,7 @@ error_code sys_fs_fstat(ppu_thread& ppu, u32 fd, vm::ptr sb) return CELL_EBADF; } - std::lock_guard lock(file->mp->mutex); + std::unique_lock lock(file->mp->mutex); if (!file->file) { @@ -1352,7 +1364,9 @@ error_code sys_fs_fstat(ppu_thread& ppu, u32 fd, vm::ptr sb) return CELL_EIO; } - const fs::stat_t& info = file->file.stat(); + const fs::stat_t info = file->file.stat(); + lock.unlock(); + ppu.check_state(); sb->mode = info.is_directory ? CELL_FS_S_IFDIR | 0777 : CELL_FS_S_IFREG | 0666; sb->uid = file->mp->flags & lv2_mp_flag::no_uid_gid ? -1 : 0; @@ -2342,7 +2356,7 @@ error_code sys_fs_lseek(ppu_thread& ppu, u32 fd, s64 offset, s32 whence, vm::ptr return CELL_EBADF; } - std::lock_guard lock(file->mp->mutex); + std::unique_lock lock(file->mp->mutex); if (!file->file) { @@ -2367,6 +2381,9 @@ error_code sys_fs_lseek(ppu_thread& ppu, u32 fd, s64 offset, s32 whence, vm::ptr return CELL_EIO; // ??? } + lock.unlock(); + ppu.check_state(); + *pos = result; return CELL_OK; } @@ -2662,6 +2679,8 @@ error_code sys_fs_disk_free(ppu_thread& ppu, vm::cptr path, vm::ptr t return {CELL_ENOTSUP, path}; } + ppu.check_state(); + if (mp->flags & lv2_mp_flag::read_only) { // TODO: check /dev_bdvd diff --git a/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp b/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp index 00dd50f98e..1fd8f8b79a 100644 --- a/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp @@ -190,6 +190,7 @@ error_code _sys_interrupt_thread_establish(ppu_thread& ppu, vm::ptr ih, u32 if (id) { + ppu.check_state(); *ih = id; return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp b/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp index 7494499844..21e19912e3 100644 --- a/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp @@ -50,6 +50,7 @@ error_code _sys_lwcond_create(ppu_thread& ppu, vm::ptr lwcond_id, u32 lwmut if (const u32 id = idm::make(name, lwmutex_id, protocol, control)) { + ppu.check_state(); *lwcond_id = id; return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp b/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp index 3ef086ae86..252fd9e839 100644 --- a/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp @@ -42,6 +42,7 @@ error_code _sys_lwmutex_create(ppu_thread& ppu, vm::ptr lwmutex_id, u32 pro if (const u32 id = idm::make(protocol, control, name)) { + ppu.check_state(); *lwmutex_id = id; return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_memory.cpp b/rpcs3/Emu/Cell/lv2/sys_memory.cpp index ca4240ff12..5c11a04f0e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_memory.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_memory.cpp @@ -132,6 +132,7 @@ error_code sys_memory_allocate(cpu_thread& cpu, u32 size, u64 flags, vm::ptrget(); - ::reader_lock lock(s_memstats_mtx); - - mem_info->total_user_memory = dct.size; - mem_info->available_user_memory = dct.size - dct.used; - - // Scan other memory containers - idm::select([&](u32, lv2_memory_container& ct) + sys_memory_info_t out{}; { - mem_info->total_user_memory -= ct.size; - }); + ::reader_lock lock(s_memstats_mtx); + out.total_user_memory = dct.size; + out.available_user_memory = dct.size - dct.used; + + // Scan other memory containers + idm::select([&](u32, lv2_memory_container& ct) + { + out.total_user_memory -= ct.size; + }); + } + + cpu.check_state(); + *mem_info = out; return CELL_OK; } @@ -332,6 +339,7 @@ error_code sys_memory_container_create(cpu_thread& cpu, vm::ptr cid, u32 si // Create the memory container if (const u32 id = idm::make(size, true)) { + cpu.check_state(); *cid = id; return CELL_OK; } @@ -388,6 +396,7 @@ error_code sys_memory_container_get_size(cpu_thread& cpu, vm::ptrtotal_user_memory = ct->size; // Total container memory mem_info->available_user_memory = ct->size - ct->used; // Available container memory diff --git a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp index b992a42be3..2cf5e3bf8b 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp @@ -174,6 +174,7 @@ error_code sys_mmapper_allocate_address(ppu_thread& ppu, u64 size, u64 flags, u6 { if (const auto area = vm::find_map(static_cast(size), static_cast(alignment), flags & SYS_MEMORY_PAGE_SIZE_MASK)) { + ppu.check_state(); *alloc_addr = area->addr; return CELL_OK; } @@ -246,6 +247,7 @@ error_code sys_mmapper_allocate_shared_memory(ppu_thread& ppu, u64 ipc_key, u64 return error; } + ppu.check_state(); *mem_id = idm::last_id(); return CELL_OK; } @@ -301,6 +303,7 @@ error_code sys_mmapper_allocate_shared_memory_from_container(ppu_thread& ppu, u6 return error; } + ppu.check_state(); *mem_id = idm::last_id(); return CELL_OK; } @@ -399,6 +402,7 @@ error_code sys_mmapper_allocate_shared_memory_ext(ppu_thread& ppu, u64 ipc_key, return error; } + ppu.check_state(); *mem_id = idm::last_id(); return CELL_OK; } @@ -496,6 +500,7 @@ error_code sys_mmapper_allocate_shared_memory_from_container_ext(ppu_thread& ppu return error; } + ppu.check_state(); *mem_id = idm::last_id(); return CELL_OK; } @@ -718,6 +723,8 @@ error_code sys_mmapper_search_and_map(ppu_thread& ppu, u32 start_addr, u32 mem_i } vm::lock_sudo(addr, mem->size); + + ppu.check_state(); *alloc_addr = addr; return CELL_OK; } @@ -763,6 +770,7 @@ error_code sys_mmapper_unmap_shared_memory(ppu_thread& ppu, u32 addr, vm::ptr mutex_id, vm::ptr thread_id, vm::p return CELL_EAGAIN; } - *thread_id = tid; sys_ppu_thread.warning(u8"_sys_ppu_thread_create(): Thread “%s” created (id=0x%x, func=*0x%x, rtoc=0x%x, user-tls=0x%x)", ppu_name, tid, entry.addr, entry.rtoc, tls); + + ppu.check_state(); + *thread_id = tid; return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_prx.cpp b/rpcs3/Emu/Cell/lv2/sys_prx.cpp index 1ed9d7c61a..99202051cf 100644 --- a/rpcs3/Emu/Cell/lv2/sys_prx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_prx.cpp @@ -542,6 +542,7 @@ error_code _sys_prx_start_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptrentry.set(prx->start ? prx->start.addr() : ~0ull); // This check is probably for older fw @@ -594,6 +595,7 @@ error_code _sys_prx_stop_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptrentry.set(prx->stop ? prx->stop.addr() : ~0ull); set_entry2(prx->epilogue ? prx->epilogue.addr() : ~0ull); return CELL_OK; @@ -633,6 +635,7 @@ error_code _sys_prx_stop_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptrcmd == 4u) { + ppu.check_state(); pOpt->entry.set(prx->stop ? prx->stop.addr() : ~0ull); set_entry2(prx->epilogue ? prx->epilogue.addr() : ~0ull); } diff --git a/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp b/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp index b7f37d99e0..7147ac1388 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp @@ -62,6 +62,7 @@ error_code sys_rwlock_create(ppu_thread& ppu, vm::ptr rw_lock_id, vm::ptre_entry; *nsegs = image->nsegs; return CELL_OK; @@ -540,6 +541,7 @@ error_code _sys_spu_image_get_segments(ppu_thread& ppu, vm::ptr i } // TODO: apply SPU patches + ppu.check_state(); std::memcpy(segments.get_ptr(), handle->segs.get_ptr(), sizeof(sys_spu_segment) * std::min(nseg, handle->nsegs)); return CELL_OK; } @@ -674,7 +676,7 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr thread, u32 g return CELL_EINVAL; } - std::lock_guard lock(group->mutex); + std::unique_lock lock(group->mutex); if (auto state = +group->run_state; state != SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED) { @@ -713,8 +715,6 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr thread, u32 g ensure(vm::get(vm::spu)->falloc(spu->vm_offset(), SPU_LS_SIZE, &spu->shm, static_cast(vm::page_size_64k) | static_cast(vm::alloc_hidden))); spu->map_ls(*spu->shm, spu->ls); - *thread = tid; - group->args[inited] = {arg->arg1, arg->arg2, arg->arg3, arg->arg4}; group->imgs[inited].first = image.entry_point; group->imgs[inited].second = std::move(spu_segs); @@ -740,7 +740,11 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr thread, u32 g } } + lock.unlock(); sys_spu.warning(u8"sys_spu_thread_initialize(): Thread “%s” created (id=0x%x)", thread_name, tid); + + ppu.check_state(); + *thread = tid; return CELL_OK; } @@ -781,6 +785,7 @@ error_code sys_spu_thread_get_exit_status(ppu_thread& ppu, u32 id, vm::ptr if (thread->exit_status.try_read(data)) { + ppu.check_state(); *status = static_cast(data); return CELL_OK; } @@ -924,7 +929,7 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr id, u32 num auto& limits = g_fxo->get(); - std::lock_guard lock(limits.mutex); + std::unique_lock lock(limits.mutex); if (!limits.check(use_scheduler ? limits_data{.controllable = num} : limits_data{.physical = num})) { @@ -940,8 +945,11 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr id, u32 num return CELL_EAGAIN; } - *id = idm::last_id(); + lock.unlock(); sys_spu.warning(u8"sys_spu_thread_group_create(): Thread group “%s” created (id=0x%x)", group->name, idm::last_id()); + + ppu.check_state(); + *id = idm::last_id(); return CELL_OK; } @@ -1490,6 +1498,8 @@ error_code sys_spu_thread_group_join(ppu_thread& ppu, u32 id, vm::ptr cause } while (false); + ppu.check_state(); + if (!cause) { if (status) @@ -1548,6 +1558,8 @@ error_code sys_spu_thread_group_get_priority(ppu_thread& ppu, u32 id, vm::ptrhas_scheduler_context) { *priority = 0; @@ -1608,6 +1620,7 @@ error_code sys_spu_thread_group_syscall_253(ppu_thread& ppu, u32 id, vm::ptrdeadlineMissCounter = 0; info->deadlineMeetCounter = 0; info->timestamp = get_timebased_time(); @@ -1675,7 +1688,7 @@ error_code sys_spu_thread_read_ls(ppu_thread& ppu, u32 id, u32 lsa, vm::ptr return CELL_ESRCH; } - std::lock_guard lock(group->mutex); + std::unique_lock lock(group->mutex); if (auto state = +group->run_state; state < SPU_THREAD_GROUP_STATUS_WAITING || state > SPU_THREAD_GROUP_STATUS_RUNNING) @@ -1688,15 +1701,21 @@ error_code sys_spu_thread_read_ls(ppu_thread& ppu, u32 id, u32 lsa, vm::ptr return CELL_ESTAT; } + u64 _value{}; + switch (type) { - case 1: *value = thread->_ref(lsa); break; - case 2: *value = thread->_ref(lsa); break; - case 4: *value = thread->_ref(lsa); break; - case 8: *value = thread->_ref(lsa); break; + case 1: _value = thread->_ref(lsa); break; + case 2: _value = thread->_ref(lsa); break; + case 4: _value = thread->_ref(lsa); break; + case 8: _value = thread->_ref(lsa); break; default: fmt::throw_exception("Unreachable"); } + lock.unlock(); + ppu.check_state(); + + *value = _value; return CELL_OK; } @@ -1756,6 +1775,7 @@ error_code sys_spu_thread_get_spu_cfg(ppu_thread& ppu, u32 id, vm::ptr valu return CELL_ESRCH; } + ppu.check_state(); *value = thread->snr_config; return CELL_OK; @@ -2041,7 +2061,7 @@ error_code sys_spu_thread_group_connect_event_all_threads(ppu_thread& ppu, u32 i return CELL_EINVAL; } - std::lock_guard lock(group->mutex); + std::unique_lock lock(group->mutex); if (auto state = +group->run_state; state < SPU_THREAD_GROUP_STATUS_INITIALIZED || state == SPU_THREAD_GROUP_STATUS_DESTROYED) @@ -2096,6 +2116,9 @@ error_code sys_spu_thread_group_connect_event_all_threads(ppu_thread& ppu, u32 i } } + lock.unlock(); + ppu.check_state(); + *spup = port; return CELL_OK; @@ -2154,6 +2177,7 @@ error_code sys_spu_thread_group_log(ppu_thread& ppu, s32 command, vm::ptr s return CELL_EFAULT; } + ppu.check_state(); *stat = state.state; break; } @@ -2559,6 +2583,7 @@ error_code raw_spu_get_int_control(u32 id, u32 class_id, vm::ptr value, ato return CELL_ESRCH; } + cpu_thread::get_current()->check_state(); *value = thread->int_ctrl[class_id].*control; return CELL_OK; diff --git a/rpcs3/Emu/Cell/lv2/sys_timer.cpp b/rpcs3/Emu/Cell/lv2/sys_timer.cpp index 6c196f0a1d..2c3712ba65 100644 --- a/rpcs3/Emu/Cell/lv2/sys_timer.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_timer.cpp @@ -163,6 +163,7 @@ error_code sys_timer_create(ppu_thread& ppu, vm::ptr timer_id) } } + ppu.check_state(); *timer_id = idm::last_id(); return CELL_OK; } @@ -226,6 +227,7 @@ error_code sys_timer_get_information(ppu_thread& ppu, u32 timer_id, vm::ptr handle) auto& usbh = g_fxo->get>(); - std::lock_guard lock(usbh.mutex); + { + std::lock_guard lock(usbh.mutex); - // Must not occur (lv2 allows multiple handles, cellUsbd does not) - ensure(!usbh.is_init.exchange(true)); + // Must not occur (lv2 allows multiple handles, cellUsbd does not) + ensure(!usbh.is_init.exchange(true)); + } + ppu.check_state(); *handle = 0x115B; // TODO @@ -891,6 +894,7 @@ error_code sys_usbd_receive_event(ppu_thread& ppu, u32 handle, vm::ptr arg1 thread_ctrl::wait_on(ppu.state, state); } + ppu.check_state(); *arg1 = ppu.gpr[4]; *arg2 = ppu.gpr[5]; *arg3 = ppu.gpr[6]; diff --git a/rpcs3/Emu/Cell/lv2/sys_vm.cpp b/rpcs3/Emu/Cell/lv2/sys_vm.cpp index 46c2b00b81..8f0470b1e9 100644 --- a/rpcs3/Emu/Cell/lv2/sys_vm.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_vm.cpp @@ -98,6 +98,7 @@ error_code sys_vm_memory_map(ppu_thread& ppu, u32 vsize, u32 psize, u32 cid, u64 idm::make(area->addr, vsize, ct, psize); // Write a pointer for the allocated memory + ppu.check_state(); *addr = area->addr; return CELL_OK; } @@ -399,6 +400,7 @@ error_code sys_vm_test(ppu_thread& ppu, u32 addr, u32 size, vm::ptr result) return CELL_EINVAL; } + ppu.check_state(); *result = SYS_VM_STATE_ON_MEMORY; return CELL_OK; @@ -417,6 +419,7 @@ error_code sys_vm_get_statistics(ppu_thread& ppu, u32 addr, vm::ptrpage_fault_ppu = 0; stat->page_fault_spu = 0; stat->page_in = 0;