mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-09 03:01:28 -06:00
Feat: Further refinemets
This commit is contained in:
parent
e763e90c2a
commit
c576aefa9f
@ -727,13 +727,13 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
||||
}
|
||||
|
||||
// P2P dgram sockets only support EPOLLIN (matches PS4 kernel behavior)
|
||||
auto epoll_events_mod = event->events;
|
||||
auto epoll_events = event->events;
|
||||
if (file->socket->socket_type == ORBIS_NET_SOCK_DGRAM_P2P) {
|
||||
epoll_events_mod &= ORBIS_NET_EPOLLIN;
|
||||
epoll_events &= ORBIS_NET_EPOLLIN;
|
||||
}
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
epoll_event native_event = {.events = ConvertEpollEventsIn(epoll_events_mod),
|
||||
epoll_event native_event = {.events = ConvertEpollEventsIn(epoll_events),
|
||||
.data = {.fd = id}};
|
||||
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_MOD, *native_handle, &native_event) == 0);
|
||||
#endif
|
||||
@ -893,6 +893,9 @@ int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events,
|
||||
LOG_TRACE(Lib_Net, "timed out");
|
||||
} else {
|
||||
for (int j = 0; j < result; ++j) {
|
||||
if (i >= maxevents) {
|
||||
break;
|
||||
}
|
||||
const auto& current_event = native_events[j];
|
||||
// Skip the abort fd event (registered with data.fd = -1)
|
||||
if (current_event.data.fd == -1) {
|
||||
@ -1734,8 +1737,7 @@ int PS4_SYSV_ABI sceNetSysctl() {
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceNetTerm() {
|
||||
LOG_DEBUG(Lib_Net, "called");
|
||||
g_isNetInitialized = false;
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -6,8 +6,13 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "common/types.h"
|
||||
#include "net_epoll.h"
|
||||
#ifdef __linux__
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#elif defined(__linux__)
|
||||
#include <sys/eventfd.h>
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
namespace Libraries::Net {
|
||||
@ -54,30 +59,85 @@ Epoll::Epoll(const char* name_) : name(name_ ? name_ : "anon"), epoll_fd(epoll_c
|
||||
#else
|
||||
ASSERT(epoll_fd != -1);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
|
||||
// Set up the abort wake mechanism and register it in epoll with sentinel data.fd = -1.
|
||||
// Linux: eventfd, macOS/BSD: self-pipe, Windows: loopback UDP socket.
|
||||
#ifdef _WIN32
|
||||
abort_sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
ASSERT(abort_sock != INVALID_SOCKET);
|
||||
sockaddr_in addr{};
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
addr.sin_port = 0; // OS picks an ephemeral port
|
||||
ASSERT(::bind(abort_sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == 0);
|
||||
// Connect to self so we can use send() in Abort()
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
ASSERT(::getsockname(abort_sock, reinterpret_cast<sockaddr*>(&addr), &addrlen) == 0);
|
||||
ASSERT(::connect(abort_sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == 0);
|
||||
u_long nonblocking = 1;
|
||||
ASSERT(::ioctlsocket(abort_sock, FIONBIO, &nonblocking) == 0);
|
||||
epoll_event ev = {.events = EPOLLIN, .data = {.fd = -1}};
|
||||
ASSERT(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, abort_sock, &ev) == 0);
|
||||
#elif defined(__linux__)
|
||||
abort_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
|
||||
ASSERT(abort_fd != -1);
|
||||
epoll_event ev = {.events = EPOLLIN, .data = {.fd = -1}};
|
||||
ASSERT(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, abort_fd, &ev) == 0);
|
||||
#else
|
||||
// Self-pipe for macOS/BSD
|
||||
int r = ::pipe(abort_pipe);
|
||||
ASSERT(r == 0);
|
||||
// Set both ends non-blocking
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
int flags = ::fcntl(abort_pipe[i], F_GETFL);
|
||||
::fcntl(abort_pipe[i], F_SETFL, flags | O_NONBLOCK);
|
||||
::fcntl(abort_pipe[i], F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
epoll_event ev = {.events = EPOLLIN, .data = {.fd = -1}};
|
||||
ASSERT(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, abort_pipe[0], &ev) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Epoll::Abort() {
|
||||
aborted.store(true, std::memory_order_release);
|
||||
#ifdef __linux__
|
||||
#ifdef _WIN32
|
||||
if (abort_sock != INVALID_SOCKET) {
|
||||
char byte = 1;
|
||||
(void)::send(abort_sock, &byte, 1, 0);
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
if (abort_fd != -1) {
|
||||
uint64_t val = 1;
|
||||
::write(abort_fd, &val, sizeof(val));
|
||||
(void)::write(abort_fd, &val, sizeof(val));
|
||||
}
|
||||
#else
|
||||
if (abort_pipe[1] != -1) {
|
||||
char byte = 1;
|
||||
(void)::write(abort_pipe[1], &byte, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Epoll::ClearAbort() {
|
||||
aborted.store(false, std::memory_order_release);
|
||||
#ifdef __linux__
|
||||
#ifdef _WIN32
|
||||
if (abort_sock != INVALID_SOCKET) {
|
||||
char buf[64];
|
||||
// Drain any pending data
|
||||
while (::recv(abort_sock, buf, sizeof(buf), 0) > 0) {
|
||||
}
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
if (abort_fd != -1) {
|
||||
uint64_t val;
|
||||
::read(abort_fd, &val, sizeof(val));
|
||||
(void)::read(abort_fd, &val, sizeof(val));
|
||||
}
|
||||
#else
|
||||
if (abort_pipe[0] != -1) {
|
||||
char buf[64];
|
||||
// Drain the pipe
|
||||
while (::read(abort_pipe[0], buf, sizeof(buf)) > 0) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -85,17 +145,29 @@ void Epoll::ClearAbort() {
|
||||
void Epoll::Destroy() noexcept {
|
||||
events.clear();
|
||||
#ifdef _WIN32
|
||||
if (abort_sock != INVALID_SOCKET) {
|
||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, abort_sock, nullptr);
|
||||
::closesocket(abort_sock);
|
||||
abort_sock = INVALID_SOCKET;
|
||||
}
|
||||
epoll_close(epoll_fd);
|
||||
epoll_fd = nullptr;
|
||||
#else
|
||||
close(epoll_fd);
|
||||
epoll_fd = -1;
|
||||
#ifdef __linux__
|
||||
if (abort_fd != -1) {
|
||||
close(abort_fd);
|
||||
abort_fd = -1;
|
||||
}
|
||||
#else
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (abort_pipe[i] != -1) {
|
||||
close(abort_pipe[i]);
|
||||
abort_pipe[i] = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
close(epoll_fd);
|
||||
epoll_fd = -1;
|
||||
#endif
|
||||
name = "";
|
||||
destroyed = true;
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <wepoll.h>
|
||||
#endif
|
||||
|
||||
// TODO: FreeBSD requires libepoll-shim for epoll support
|
||||
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#include <sys/epoll.h>
|
||||
#include <unistd.h>
|
||||
@ -35,8 +36,12 @@ struct Epoll {
|
||||
epoll_handle epoll_fd;
|
||||
std::deque<u32> async_resolutions{};
|
||||
std::atomic<bool> aborted{false};
|
||||
#ifdef __linux__
|
||||
int abort_fd = -1;
|
||||
#ifdef _WIN32
|
||||
SOCKET abort_sock = INVALID_SOCKET; // loopback UDP socket for abort wake
|
||||
#elif defined(__linux__)
|
||||
int abort_fd = -1; // eventfd for abort wake
|
||||
#else
|
||||
int abort_pipe[2] = {-1, -1}; // self-pipe for abort wake (macOS/BSD)
|
||||
#endif
|
||||
|
||||
explicit Epoll(const char* name_);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user