Final sys_ fixes

This commit is contained in:
RipleyTom 2026-02-27 08:02:46 +01:00 committed by Elad
parent b30a20c2dc
commit 3b6afc1d9a
23 changed files with 110 additions and 114 deletions

View file

@ -174,20 +174,28 @@ bool lv2_config_service_listener::check_service(const lv2_config_service& servic
return true;
}
bool lv2_config_service_listener::notify(const shared_ptr<lv2_config_service_event>& event)
{
service_events.emplace_back(event);
return event->notify();
}
bool lv2_config_service_listener::notify(const shared_ptr<lv2_config_service>& service)
{
if (!check_service(*service))
return false;
{
std::lock_guard lock(mutex_service_events);
// Create service event and notify queue!
const auto event = lv2_config_service_event::create(handle, service, *this);
return notify(event);
if (!check_service(*service))
return false;
// Create service event and notify queue!
const auto event = lv2_config_service_event::create(handle, service, *this);
service_events.emplace_back(event);
if (!event->notify())
{
// If we fail to deliver the event to the queue just clean the event up or it'll hold the listener alive forever
g_fxo->get<lv2_config>().remove_service_event(event->id);
service_events.pop_back();
return false;
}
}
return true;
}
void lv2_config_service_listener::notify_all()
@ -267,7 +275,7 @@ void lv2_config_service_event::write(sys_config_service_event_t *dst) const
{
const auto registered = service->is_registered();
dst->service_listener_handle = listener.get_id();
dst->service_listener_handle = listener_id;
dst->registered = registered;
dst->service_id = service->id;
dst->user_id = service->user_id;
@ -346,7 +354,7 @@ error_code sys_config_get_service_event(u32 config_hdl, u32 event_id, vm::ptr<sy
// Find service_event object
const auto event = g_fxo->get<lv2_config>().find_event(event_id);
if (!event)
if (!event || event->handle != cfg)
{
return CELL_ESRCH;
}

View file

@ -296,11 +296,10 @@ private:
// The service listener owns the service events - service events will not be freed as long as their corresponding listener exists
// This has been confirmed to be the case in realhw
shared_mutex mutex_service_events;
std::vector<shared_ptr<lv2_config_service_event>> service_events;
shared_ptr<lv2_config_handle> handle;
bool notify(const shared_ptr<lv2_config_service_event>& event);
public:
const sys_config_service_id service_id;
const u64 min_verbosity;
@ -370,14 +369,14 @@ public:
// This has been confirmed to be the case in realhw
const shared_ptr<lv2_config_handle> handle;
const shared_ptr<lv2_config_service> service;
const lv2_config_service_listener& listener;
const u32 listener_id;
// Constructors (should not be used directly)
lv2_config_service_event(shared_ptr<lv2_config_handle> _handle, shared_ptr<lv2_config_service> _service, const lv2_config_service_listener& _listener) noexcept
: id(get_next_id())
, handle(std::move(_handle))
, service(std::move(_service))
, listener(_listener)
, listener_id(_listener.get_id())
{
}

View file

@ -105,7 +105,7 @@ error_code sys_dbg_write_process_memory(s32 pid, u32 address, u32 size, vm::cptr
i += op_size;
}
if (!is_exec || i >= end)
if ((!is_exec || i >= end) && exec_update_size > 0)
{
// Commit executable data update
// The read memory is also super ptr so memmove can work correctly on all implementations

View file

@ -308,6 +308,15 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
return CELL_EBUSY;
}
for (auto cpu = head; cpu; cpu = cpu->get_next_cpu())
{
if (cpu->state & cpu_flag::again)
{
ppu.state += cpu_flag::again;
return CELL_EAGAIN;
}
}
if (!queue.events.empty())
{
// Copy events for logging, does not empty
@ -320,17 +329,6 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
{
qlock.unlock();
}
else
{
for (auto cpu = head; cpu; cpu = cpu->get_next_cpu())
{
if (cpu->state & cpu_flag::again)
{
ppu.state += cpu_flag::again;
return CELL_EAGAIN;
}
}
}
return {};
});

View file

@ -382,7 +382,7 @@ lv2_fs_object::lv2_fs_object(utils::serial& ar, bool)
u64 lv2_file::op_read(const fs::file& file, vm::ptr<void> buf, u64 size, u64 opt_pos)
{
if (u64 region = buf.addr() >> 28, region_end = (buf.addr() & 0xfff'ffff) + (size & 0xfff'ffff); region == region_end && ((region >> 28) == 0 || region >= 0xC))
if (u64 region = buf.addr() >> 28, region_end = (buf.addr() + size) >> 28; region == region_end && region == 0)
{
// Optimize reads from safe memory
return (opt_pos == umax ? file.read(buf.get_ptr(), size) : file.read_at(opt_pos, buf.get_ptr(), size));
@ -1391,7 +1391,8 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32> fd)
// Add additional entries for split file candidates (while ends with .66600)
while (mp.mp != &g_mp_sys_dev_hdd1 && data.back().name.ends_with(".66600"))
{
data.emplace_back(data.back()).name.resize(data.back().name.size() - 6);
fs::dir_entry copy = data.back();
data.emplace_back(copy).name.resize(copy.name.size() - 6);
}
}
@ -2147,6 +2148,7 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
sys_fs.notice("sys_fs_fcntl(0xc0000006): %s", vpath);
// Check only mountpoint
vpath = vpath.substr(0, vpath.find_first_of('\0'));
vpath = vpath.substr(0, vpath.find_first_of("/", 1));
// Some mountpoints seem to be handled specially
@ -2635,8 +2637,6 @@ error_code sys_fs_lseek(ppu_thread& ppu, u32 fd, s64 offset, s32 whence, vm::ptr
error_code sys_fs_fdatasync(ppu_thread& ppu, u32 fd)
{
lv2_obj::sleep(ppu);
sys_fs.trace("sys_fs_fdadasync(fd=%d)", fd);
const auto file = idm::get_unlocked<lv2_fs_object, lv2_file>(fd);
@ -2661,8 +2661,6 @@ error_code sys_fs_fdatasync(ppu_thread& ppu, u32 fd)
error_code sys_fs_fsync(ppu_thread& ppu, u32 fd)
{
lv2_obj::sleep(ppu);
sys_fs.trace("sys_fs_fsync(fd=%d)", fd);
const auto file = idm::get_unlocked<lv2_fs_object, lv2_file>(fd);
@ -2903,14 +2901,6 @@ error_code sys_fs_chmod(ppu_thread&, vm::cptr<char> path, s32 mode)
{
// Try to locate split files
for (u32 i = 66601; i <= 66699; i++)
{
if (mp != &g_mp_sys_dev_hdd1 && !fs::get_stat(fmt::format("%s.%u", local_path, i), info) && !info.is_directory)
{
break;
}
}
if (fs::get_stat(local_path + ".66600", info) && !info.is_directory)
{
break;

View file

@ -333,7 +333,7 @@ error_code sys_mmapper_allocate_shared_memory_ext(ppu_thread& ppu, u64 ipc_key,
}
}
if (flags & ~SYS_MEMORY_PAGE_SIZE_MASK)
if (flags & ~SYS_MEMORY_GRANULARITY_MASK)
{
return CELL_EINVAL;
}
@ -401,6 +401,11 @@ error_code sys_mmapper_allocate_shared_memory_from_container_ext(ppu_thread& ppu
sys_mmapper.todo("sys_mmapper_allocate_shared_memory_from_container_ext(ipc_key=0x%x, size=0x%x, flags=0x%x, cid=0x%x, entries=*0x%x, entry_count=0x%x, mem_id=*0x%x)", ipc_key, size, flags, cid, entries,
entry_count, mem_id);
if (size == 0)
{
return CELL_EALIGN;
}
switch (flags & SYS_MEMORY_PAGE_SIZE_MASK)
{
case SYS_MEMORY_PAGE_SIZE_1M:
@ -546,8 +551,7 @@ error_code sys_mmapper_free_address(ppu_thread& ppu, u32 addr)
// If a memory block is freed, remove it from page notification table.
auto& pf_entries = g_fxo->get<page_fault_notification_entries>();
std::lock_guard lock(pf_entries.mutex);
std::unique_lock lock(pf_entries.mutex);
auto ind_to_remove = pf_entries.entries.begin();
for (; ind_to_remove != pf_entries.entries.end(); ++ind_to_remove)
{
@ -558,7 +562,11 @@ error_code sys_mmapper_free_address(ppu_thread& ppu, u32 addr)
}
if (ind_to_remove != pf_entries.entries.end())
{
u32 port_id = ind_to_remove->port_id;
pf_entries.entries.erase(ind_to_remove);
lock.unlock();
sys_event_port_disconnect(ppu, port_id);
sys_event_port_destroy(ppu, port_id);
}
return CELL_OK;
@ -826,7 +834,6 @@ error_code sys_mmapper_enable_page_fault_notification(ppu_thread& ppu, u32 start
vm::var<u32> port_id(0);
error_code res = sys_event_port_create(ppu, port_id, SYS_EVENT_PORT_LOCAL, SYS_MEMORY_PAGE_FAULT_EVENT_KEY);
sys_event_port_connect_local(ppu, *port_id, event_queue_id);
if (res + 0u == CELL_EAGAIN)
{
@ -834,6 +841,8 @@ error_code sys_mmapper_enable_page_fault_notification(ppu_thread& ppu, u32 start
return CELL_EAGAIN;
}
sys_event_port_connect_local(ppu, *port_id, event_queue_id);
auto& pf_entries = g_fxo->get<page_fault_notification_entries>();
std::unique_lock lock(pf_entries.mutex);

View file

@ -563,37 +563,34 @@ error_code sys_net_bnet_connect(ppu_thread& ppu, s32 s, vm::ptr<sys_net_sockaddr
return not_an_error(result);
}
if (!sock.ret)
while (auto state = ppu.state.fetch_sub(cpu_flag::signal))
{
while (auto state = ppu.state.fetch_sub(cpu_flag::signal))
if (is_stopped(state))
{
if (is_stopped(state))
{
return {};
}
if (state & cpu_flag::signal)
{
break;
}
ppu.state.wait(state);
return {};
}
if (ppu.gpr[3] == static_cast<u64>(-SYS_NET_EINTR))
if (state & cpu_flag::signal)
{
return -SYS_NET_EINTR;
break;
}
if (result)
{
if (result < 0)
{
return sys_net_error{result};
}
ppu.state.wait(state);
}
return not_an_error(result);
if (ppu.gpr[3] == static_cast<u64>(-SYS_NET_EINTR))
{
return -SYS_NET_EINTR;
}
if (result)
{
if (result < 0)
{
return sys_net_error{result};
}
return not_an_error(result);
}
return CELL_OK;
@ -1295,7 +1292,7 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr<sys_net_pollfd> fds, s32 n
if (auto sock = idm::check_unlocked<lv2_socket>(fds_buf[i].fd))
{
signaled += sock->poll(fds_buf[i], _fds[i]);
sock->poll(fds_buf[i], _fds[i]);
#ifdef _WIN32
connecting[i] = sock->is_connecting();
#endif
@ -1303,7 +1300,6 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr<sys_net_pollfd> fds, s32 n
else
{
fds_buf[i].revents |= SYS_NET_POLLNVAL;
signaled++;
}
}
@ -1536,9 +1532,9 @@ error_code sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr<sys_net_fd_set
for (s32 i = 0; i < nfds; i++)
{
bool sig = false;
if (_fds[i].revents & (POLLIN | POLLHUP | POLLERR))
if ((_fds[i].revents & (POLLIN | POLLHUP | POLLERR)) && _readfds.bit(i))
sig = true, rread.set(i);
if (_fds[i].revents & (POLLOUT | POLLERR))
if ((_fds[i].revents & (POLLOUT | POLLERR)) && _writefds.bit(i))
sig = true, rwrite.set(i);
if (sig)

View file

@ -104,7 +104,7 @@ public:
virtual void close() = 0;
virtual s32 shutdown(s32 how) = 0;
virtual s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) = 0;
virtual void poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) = 0;
virtual std::tuple<bool, bool, bool> select(bs_t<poll_t> selected, pollfd& native_pfd) = 0;
error_code abort_socket(s32 flags);

View file

@ -1147,14 +1147,14 @@ s32 lv2_socket_native::shutdown(s32 how)
return -get_last_error(false);
}
s32 lv2_socket_native::poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd)
void lv2_socket_native::poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd)
{
// Check for fake packet for dns interceptions
auto& dnshook = g_fxo->get<np::dnshook>();
if (sn_pfd.events & SYS_NET_POLLIN && dnshook.is_dns(sn_pfd.fd) && dnshook.is_dns_queue(sn_pfd.fd))
{
sn_pfd.revents |= SYS_NET_POLLIN;
return 1;
return;
}
if (sn_pfd.events & ~(SYS_NET_POLLIN | SYS_NET_POLLOUT | SYS_NET_POLLERR))
{
@ -1171,8 +1171,6 @@ s32 lv2_socket_native::poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd)
{
native_pfd.events |= POLLOUT;
}
return 0;
}
std::tuple<bool, bool, bool> lv2_socket_native::select(bs_t<lv2_socket::poll_t> selected, pollfd& native_pfd)

View file

@ -50,7 +50,7 @@ public:
std::optional<s32> sendto(s32 flags, const std::vector<u8>& buf, std::optional<sys_net_sockaddr> opt_sn_addr, bool is_lock = true) override;
std::optional<s32> sendmsg(s32 flags, const sys_net_msghdr& msg, bool is_lock = true) override;
s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override;
void poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override;
std::tuple<bool, bool, bool> select(bs_t<poll_t> selected, pollfd& native_pfd) override;
bool is_socket_connected();

View file

@ -364,7 +364,7 @@ s32 lv2_socket_p2p::shutdown([[maybe_unused]] s32 how)
return CELL_OK;
}
s32 lv2_socket_p2p::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native_pfd)
void lv2_socket_p2p::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native_pfd)
{
std::lock_guard lock(mutex);
ensure(vport);
@ -381,8 +381,6 @@ s32 lv2_socket_p2p::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native
{
sn_pfd.revents |= SYS_NET_POLLOUT;
}
return sn_pfd.revents ? 1 : 0;
}
std::tuple<bool, bool, bool> lv2_socket_p2p::select(bs_t<lv2_socket::poll_t> selected, [[maybe_unused]] pollfd& native_pfd)

View file

@ -30,7 +30,7 @@ public:
void close() override;
s32 shutdown(s32 how) override;
s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override;
void poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override;
std::tuple<bool, bool, bool> select(bs_t<poll_t> selected, pollfd& native_pfd) override;
void handle_new_data(sys_net_sockaddr_in_p2p p2p_addr, std::vector<u8> p2p_data);

View file

@ -985,7 +985,7 @@ s32 lv2_socket_p2ps::shutdown([[maybe_unused]] s32 how)
return CELL_OK;
}
s32 lv2_socket_p2ps::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native_pfd)
void lv2_socket_p2ps::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native_pfd)
{
std::lock_guard lock(mutex);
sys_net.trace("[P2PS] poll checking for 0x%X", sn_pfd.events);
@ -1002,14 +1002,7 @@ s32 lv2_socket_p2ps::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& nativ
{
sn_pfd.revents |= SYS_NET_POLLOUT;
}
if (sn_pfd.revents)
{
return 1;
}
}
return 0;
}
std::tuple<bool, bool, bool> lv2_socket_p2ps::select(bs_t<lv2_socket::poll_t> selected, [[maybe_unused]] pollfd& native_pfd)

View file

@ -89,7 +89,7 @@ public:
void close() override;
s32 shutdown(s32 how) override;
s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override;
void poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override;
std::tuple<bool, bool, bool> select(bs_t<poll_t> selected, pollfd& native_pfd) override;
private:

View file

@ -134,10 +134,9 @@ s32 lv2_socket_raw::shutdown([[maybe_unused]] s32 how)
return {};
}
s32 lv2_socket_raw::poll([[maybe_unused]] sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native_pfd)
void lv2_socket_raw::poll([[maybe_unused]] sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native_pfd)
{
LOG_ONCE(raw_poll, "lv2_socket_raw::poll");
return {};
}
std::tuple<bool, bool, bool> lv2_socket_raw::select([[maybe_unused]] bs_t<lv2_socket::poll_t> selected, [[maybe_unused]] pollfd& native_pfd)

View file

@ -32,6 +32,6 @@ public:
void close() override;
s32 shutdown(s32 how) override;
s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override;
void poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override;
std::tuple<bool, bool, bool> select(bs_t<poll_t> selected, pollfd& native_pfd) override;
};

View file

@ -305,6 +305,7 @@ error_code sys_ppu_thread_detach(ppu_thread& ppu, u32 thread_id)
{
// Join and notify thread (it is detached from IDM now so it must be done explicitly now)
*ptr = thread_state::finished;
return CELL_OK;
}
return result;

View file

@ -899,7 +899,7 @@ error_code _sys_prx_register_library(ppu_thread& ppu, vm::ptr<void> library)
{
for (u32 lib_addr = prx.exports_start, index = 0; lib_addr < prx.exports_end; index++, lib_addr += vm::read8(lib_addr) ? vm::read8(lib_addr) : sizeof_lib)
{
if (std::memcpy(vm::base(lib_addr), mem_copy.data(), sizeof_lib) == 0)
if (std::memcmp(vm::base(lib_addr), mem_copy.data(), sizeof_lib) == 0)
{
atomic_storage<char>::release(prx.m_external_loaded_flags[index], true);
return true;

View file

@ -46,14 +46,14 @@ namespace rsxaudio_ringbuf_reader
static void set_timestamp(rsxaudio_shmem::ringbuf_t& ring_buf, u64 timestamp)
{
const s32 entry_idx_raw = (ring_buf.read_idx + ring_buf.rw_max_idx - (ring_buf.rw_max_idx > 2) - 1) % ring_buf.rw_max_idx;
const s32 entry_idx = std::clamp<s32>(entry_idx_raw, 0, SYS_RSXAUDIO_RINGBUF_SZ);
const s32 entry_idx = std::clamp<s32>(entry_idx_raw, 0, SYS_RSXAUDIO_RINGBUF_SZ - 1);
ring_buf.entries[entry_idx].timestamp = convert_to_timebased_time(timestamp);
}
static std::tuple<bool /*notify*/, u64 /*blk_idx*/, u64 /*timestamp*/> update_status(rsxaudio_shmem::ringbuf_t& ring_buf)
{
const s32 read_idx = std::clamp<s32>(ring_buf.read_idx, 0, SYS_RSXAUDIO_RINGBUF_SZ);
const s32 read_idx = std::clamp<s32>(ring_buf.read_idx, 0, SYS_RSXAUDIO_RINGBUF_SZ - 1);
if ((ring_buf.entries[read_idx].valid & 1) == 0U)
{
@ -61,7 +61,7 @@ namespace rsxaudio_ringbuf_reader
}
const s32 entry_idx_raw = (ring_buf.read_idx + ring_buf.rw_max_idx - (ring_buf.rw_max_idx > 2)) % ring_buf.rw_max_idx;
const s32 entry_idx = std::clamp<s32>(entry_idx_raw, 0, SYS_RSXAUDIO_RINGBUF_SZ);
const s32 entry_idx = std::clamp<s32>(entry_idx_raw, 0, SYS_RSXAUDIO_RINGBUF_SZ - 1);
ring_buf.entries[read_idx].valid = 0;
ring_buf.queue_notify_idx = (ring_buf.queue_notify_idx + 1) % ring_buf.queue_notify_step;
@ -72,7 +72,7 @@ namespace rsxaudio_ringbuf_reader
static std::pair<bool /*entry_valid*/, u32 /*addr*/> get_addr(const rsxaudio_shmem::ringbuf_t& ring_buf)
{
const s32 read_idx = std::clamp<s32>(ring_buf.read_idx, 0, SYS_RSXAUDIO_RINGBUF_SZ);
const s32 read_idx = std::clamp<s32>(ring_buf.read_idx, 0, SYS_RSXAUDIO_RINGBUF_SZ - 1);
if (ring_buf.entries[read_idx].valid & 1)
{
@ -1392,9 +1392,9 @@ void rsxaudio_backend_thread::operator()()
return;
}
static rsxaudio_state ra_state{};
static emu_audio_cfg emu_cfg{};
static bool backend_failed = false;
rsxaudio_state ra_state{};
emu_audio_cfg emu_cfg{};
bool backend_failed = false;
for (;;)
{
@ -2018,7 +2018,7 @@ void rsxaudio_periodic_tmr::cancel_timer_unlocked()
{
const u64 flag = 1;
const auto wr_res = write(cancel_event, &flag, sizeof(flag));
ensure(wr_res == sizeof(flag) || wr_res == -EAGAIN);
ensure(wr_res == sizeof(flag) || errno == EAGAIN);
}
#elif defined(BSD) || defined(__APPLE__)
handle[TIMER_ID].flags = (handle[TIMER_ID].flags & ~EV_ENABLE) | EV_DISABLE;

View file

@ -24,7 +24,7 @@ struct lv2_update_manager
// For example, 4.90 should be converted to 0x4900000000000
std::erase(version_str, '.');
if (std::from_chars(version_str.data(), version_str.data() + version_str.size(), system_sw_version, 16).ec != std::errc{})
if (std::from_chars(version_str.data(), version_str.data() + version_str.size(), system_sw_version, 16).ec == std::errc{})
system_sw_version <<= 40;
else
system_sw_version = 0;
@ -79,6 +79,7 @@ struct lv2_update_manager
if (malloc_set.count(addr))
{
malloc_set.erase(addr);
return vm::dealloc(addr, vm::main);
}

View file

@ -1531,9 +1531,11 @@ private:
}
}();
if (sce_idx == umax)
return PS3AV_STATUS_INVALID_VIDEO_PARAM;
const video_sce_param &sce_param = sce_param_arr[sce_idx];
if (sce_idx == umax ||
video_head_cfg.video_head > PS3AV_HEAD_B_ANALOG ||
if (video_head_cfg.video_head > PS3AV_HEAD_B_ANALOG ||
video_head_cfg.video_order > 1 ||
video_head_cfg.video_format > 16 ||
video_head_cfg.video_out_format > 16 ||

View file

@ -1173,11 +1173,15 @@ error_code sys_usbd_get_device_list(ppu_thread& ppu, u32 handle, vm::ptr<UsbInte
return CELL_EINVAL;
// TODO: was std::min<s32>
u32 i_tocopy = std::min<u32>(max_devices, ::size32(usbh.handled_devices));
const u32 i_tocopy = std::min<u32>(max_devices, ::size32(usbh.handled_devices));
u32 index = 0;
for (u32 index = 0; index < i_tocopy; index++)
for (const auto& [_, device] : usbh.handled_devices)
{
device_list[index] = usbh.handled_devices[index].first;
if (index == i_tocopy)
break;
device_list[index++] = device.first;
}
return not_an_error(i_tocopy);
@ -1409,7 +1413,7 @@ error_code sys_usbd_receive_event(ppu_thread& ppu, u32 handle, vm::ptr<u64> arg1
if (is_stopped(state))
{
std::lock_guard lock(usbh.mutex);
std::lock_guard lock(usbh.mutex_sq);
for (auto cpu = +usbh.sq; cpu; cpu = cpu->next_cpu)
{
@ -1587,7 +1591,7 @@ error_code sys_usbd_get_transfer_status(ppu_thread& ppu, u32 handle, u32 id_tran
std::lock_guard lock(usbh.mutex);
if (!usbh.is_init)
if (!usbh.is_init || id_transfer >= MAX_SYS_USBD_TRANSFERS)
return CELL_EINVAL;
const auto status = usbh.get_transfer_status(id_transfer);
@ -1607,7 +1611,7 @@ error_code sys_usbd_get_isochronous_transfer_status(ppu_thread& ppu, u32 handle,
std::lock_guard lock(usbh.mutex);
if (!usbh.is_init)
if (!usbh.is_init || id_transfer >= MAX_SYS_USBD_TRANSFERS)
return CELL_EINVAL;
const auto status = usbh.get_isochronous_transfer_status(id_transfer);

View file

@ -97,7 +97,7 @@ error_code sys_vm_memory_map(ppu_thread& ppu, u64 vsize, u64 psize, u32 cid, u64
// Look for unmapped space
if (const auto area = vm::find_map(0x10000000, 0x10000000, 2 | (flag & SYS_MEMORY_PAGE_SIZE_MASK)))
{
sys_vm.warning("sys_vm_memory_map(): Found VM 0x%x area (vsize=0x%x)", addr, vsize);
sys_vm.warning("sys_vm_memory_map(): Found VM 0x%x area (vsize=0x%x)", area->addr, vsize);
// Alloc all memory (shall not fail)
ensure(area->alloc(static_cast<u32>(vsize)));