diff --git a/rpcs3/Emu/Cell/lv2/sys_net.cpp b/rpcs3/Emu/Cell/lv2/sys_net.cpp index 9b4428686a..efac7556d1 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net.cpp @@ -54,7 +54,7 @@ void fmt_class_string::format(std::string& out, u64 arg) { format_enum(out, arg, [](auto error) { - switch (s32 _error = error) + switch (static_cast(error)) { #define SYS_NET_ERROR_CASE(x) \ case -x: return "-" #x; \ @@ -1413,6 +1413,7 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr fds, s32 n } has_timedout = network_clear_queue(ppu); + clear_ppu_to_awake(ppu); ppu.state -= cpu_flag::signal; break; } @@ -1646,6 +1647,7 @@ error_code sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptrget_name(), ppu->current_function, ppu->gpr[3], ppu->gpr[4], ppu->gpr[5], ppu->gpr[6]); ppu->gpr[3] = static_cast(-SYS_NET_EINTR); lv2_obj::append(ppu.get()); diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp index d5d53b6c70..02f5b2c697 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp @@ -165,11 +165,11 @@ void lv2_socket::queue_wake(ppu_thread* ppu) { case SYS_NET_SOCK_STREAM: case SYS_NET_SOCK_DGRAM: - g_fxo->get().ppu_to_awake.emplace_back(ppu); + g_fxo->get().add_ppu_to_awake(ppu); break; case SYS_NET_SOCK_DGRAM_P2P: case SYS_NET_SOCK_STREAM_P2P: - g_fxo->get().ppu_to_awake.emplace_back(ppu); + g_fxo->get().add_ppu_to_awake(ppu); break; default: break; diff --git a/rpcs3/Emu/Cell/lv2/sys_net/network_context.cpp b/rpcs3/Emu/Cell/lv2/sys_net/network_context.cpp index 72356c54e1..aaf79d4f41 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/network_context.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/network_context.cpp @@ -85,8 +85,32 @@ namespace np void init_np_handler_dependencies(); } +void base_network_thread::add_ppu_to_awake(ppu_thread* ppu) +{ + std::lock_guard lock(mutex_ppu_to_awake); + ppu_to_awake.emplace_back(ppu); +} + +void base_network_thread::del_ppu_to_awake(ppu_thread* ppu) +{ + std::lock_guard lock(mutex_ppu_to_awake); + + for (auto it = ppu_to_awake.begin(); it != ppu_to_awake.end();) + { + if (*it == ppu) + { + it = ppu_to_awake.erase(it); + continue; + } + + it++; + } +} + void base_network_thread::wake_threads() { + std::lock_guard lock(mutex_ppu_to_awake); + ppu_to_awake.erase(std::unique(ppu_to_awake.begin(), ppu_to_awake.end()), ppu_to_awake.end()); for (ppu_thread* ppu : ppu_to_awake) { @@ -117,7 +141,10 @@ void network_thread::operator()() std::vector> socklist; socklist.reserve(lv2_socket::id_count); - ppu_to_awake.clear(); + { + std::lock_guard lock(mutex_ppu_to_awake); + ppu_to_awake.clear(); + } std::vector<::pollfd> fds(lv2_socket::id_count); #ifdef _WIN32 diff --git a/rpcs3/Emu/Cell/lv2/sys_net/network_context.h b/rpcs3/Emu/Cell/lv2/sys_net/network_context.h index 5cb846bd88..658196c4b4 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/network_context.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/network_context.h @@ -9,6 +9,10 @@ struct base_network_thread { + void add_ppu_to_awake(ppu_thread* ppu); + void del_ppu_to_awake(ppu_thread* ppu); + + shared_mutex mutex_ppu_to_awake; std::vector ppu_to_awake; void wake_threads(); diff --git a/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.cpp b/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.cpp index 8eb13bc168..0fabc61cae 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.cpp @@ -6,6 +6,8 @@ #include "lv2_socket.h" #include "sys_net_helpers.h" +#include "network_context.h" + LOG_CHANNEL(sys_net); int get_native_error() @@ -194,6 +196,12 @@ u32 network_clear_queue(ppu_thread& ppu) return cleared; } +void clear_ppu_to_awake(ppu_thread& ppu) +{ + g_fxo->get().del_ppu_to_awake(&ppu); + g_fxo->get().del_ppu_to_awake(&ppu); +} + #ifdef _WIN32 // Workaround function for WSAPoll not reporting failed connections void windows_poll(std::vector& fds, unsigned long nfds, int timeout, std::vector& connecting) diff --git a/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.h b/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.h index 1243ec1933..1cd9e136ca 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.h @@ -24,6 +24,7 @@ sys_net_sockaddr native_addr_to_sys_net_addr(const ::sockaddr_storage& native_ad ::sockaddr_in sys_net_addr_to_native_addr(const sys_net_sockaddr& sn_addr); bool is_ip_public_address(const ::sockaddr_in& addr); u32 network_clear_queue(ppu_thread& ppu); +void clear_ppu_to_awake(ppu_thread& ppu); #ifdef _WIN32 void windows_poll(std::vector& fds, unsigned long nfds, int timeout, std::vector& connecting);