[Build] Generalize POSIX platform guards

Most non-Windows code paths use standard POSIX APIs (sockets, signals,
dlopen, threading) that work on any POSIX platform. Change Linux-specific
guards to !WIN32 or #else where the code is portable. Linux-specific
APIs (SIGRTMIN, Vulkan/X11, fontconfig/GTK) remain Linux-guarded.
This commit is contained in:
Herman S.
2026-03-26 22:07:28 +09:00
parent 6c20f64e0d
commit cb12f7fa1e
10 changed files with 39 additions and 48 deletions

View File

@@ -74,7 +74,7 @@ inline void atomic_store_release(uint32_t new_value, volatile uint32_t* value) {
_InterlockedExchange(reinterpret_cast<volatile long*>(value), new_value); _InterlockedExchange(reinterpret_cast<volatile long*>(value), new_value);
} }
#elif XE_PLATFORM_LINUX || XE_PLATFORM_MAC #else
inline int32_t atomic_inc(volatile int32_t* value) { inline int32_t atomic_inc(volatile int32_t* value) {
return __sync_add_and_fetch(value, 1); return __sync_add_and_fetch(value, 1);
@@ -133,10 +133,6 @@ inline bool atomic_cas(int64_t old_value, int64_t new_value,
reinterpret_cast<volatile int64_t*>(value), old_value, new_value); reinterpret_cast<volatile int64_t*>(value), old_value, new_value);
} }
#else
#error No atomic primitives defined for this platform/cpu combination.
#endif // XE_PLATFORM #endif // XE_PLATFORM
inline uint32_t atomic_inc(volatile uint32_t* value) { inline uint32_t atomic_inc(volatile uint32_t* value) {

View File

@@ -15,7 +15,7 @@
#include "platform.h" #include "platform.h"
#if XE_PLATFORM_WIN32 #if XE_PLATFORM_WIN32
#include "platform_win.h" #include "platform_win.h"
#elif XE_PLATFORM_LINUX #else
#include <sys/types.h> #include <sys/types.h>
#endif #endif
#include "memory.h" #include "memory.h"

View File

@@ -662,7 +662,7 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
mov(rdx, qword[rsp + 8 * 2]); mov(rdx, qword[rsp + 8 * 2]);
mov(r8, qword[rsp + 8 * 3]); mov(r8, qword[rsp + 8 * 3]);
ret(); ret();
#elif XE_PLATFORM_LINUX || XE_PLATFORM_MAC #else
// System-V ABI args: // System-V ABI args:
// rdi = target // rdi = target
// rsi = arg0 (context) // rsi = arg0 (context)
@@ -704,8 +704,6 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
add(rsp, stack_size); add(rsp, stack_size);
ret(); ret();
#else
assert_always("Unknown platform ABI in host to guest thunk!");
#endif #endif
code_offsets.tail = getSize(); code_offsets.tail = getSize();
@@ -761,7 +759,7 @@ GuestToHostThunk X64HelperEmitter::EmitGuestToHostThunk() {
add(rsp, stack_size); add(rsp, stack_size);
ret(); ret();
#elif XE_PLATFORM_LINUX || XE_PLATFORM_MAC #else
// This function is being called using the Microsoft ABI from CallNative // This function is being called using the Microsoft ABI from CallNative
// rcx = target function // rcx = target function
// rdx = arg0 // rdx = arg0
@@ -812,8 +810,6 @@ GuestToHostThunk X64HelperEmitter::EmitGuestToHostThunk() {
add(rsp, stack_size); add(rsp, stack_size);
ret(); ret();
#else
assert_always("Unknown platform ABI in guest to host thunk!")
#endif #endif
code_offsets.tail = getSize(); code_offsets.tail = getSize();
@@ -867,7 +863,7 @@ ResolveFunctionThunk X64HelperEmitter::EmitResolveFunctionThunk() {
add(rsp, stack_size); add(rsp, stack_size);
jmp(rax); jmp(rax);
#elif XE_PLATFORM_LINUX || XE_PLATFORM_MAC #else
// Function is called with the following params: // Function is called with the following params:
// ebx = target PPC address // ebx = target PPC address
// rsi = context // rsi = context
@@ -906,8 +902,6 @@ ResolveFunctionThunk X64HelperEmitter::EmitResolveFunctionThunk() {
add(rsp, stack_size); add(rsp, stack_size);
jmp(rax); jmp(rax);
#else
assert_always("Unknown platform ABI in resolve function!");
#endif #endif
code_offsets.tail = getSize(); code_offsets.tail = getSize();

View File

@@ -23,10 +23,11 @@
// NOTE: must be included last as it expects windows.h to already be included. // NOTE: must be included last as it expects windows.h to already be included.
#define _WINSOCK_DEPRECATED_NO_WARNINGS // inet_addr #define _WINSOCK_DEPRECATED_NO_WARNINGS // inet_addr
#include <winsock2.h> // NOLINT(build/include_order) #include <winsock2.h> // NOLINT(build/include_order)
#elif XE_PLATFORM_LINUX #else
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/ip.h> #include <netinet/ip.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif

View File

@@ -244,7 +244,7 @@ dword_result_t NtSuspendThread_entry(dword_t handle,
} else { } else {
return X_STATUS_THREAD_IS_TERMINATING; return X_STATUS_THREAD_IS_TERMINATING;
} }
#elif XE_PLATFORM_LINUX #else
// Handle self-suspension specially to avoid deadlock. // Handle self-suspension specially to avoid deadlock.
if (!thread->guest_object<X_KTHREAD>()->terminated) { if (!thread->guest_object<X_KTHREAD>()->terminated) {
bool is_self_suspend = bool is_self_suspend =
@@ -261,8 +261,6 @@ dword_result_t NtSuspendThread_entry(dword_t handle,
} else { } else {
return X_STATUS_THREAD_IS_TERMINATING; return X_STATUS_THREAD_IS_TERMINATING;
} }
#else
#error "Unsupported platform"
#endif #endif
} else { } else {
return X_STATUS_OBJECT_TYPE_MISMATCH; return X_STATUS_OBJECT_TYPE_MISMATCH;

View File

@@ -86,7 +86,7 @@ X_STATUS XSocket::Initialize(AddressFamily af, Type type, Protocol proto) {
X_STATUS XSocket::Close() { X_STATUS XSocket::Close() {
#if XE_PLATFORM_WIN32 #if XE_PLATFORM_WIN32
int ret = closesocket(native_handle_); int ret = closesocket(native_handle_);
#elif XE_PLATFORM_LINUX #else
int ret = close(native_handle_); int ret = close(native_handle_);
#endif #endif
@@ -166,7 +166,7 @@ X_STATUS XSocket::IOControl(uint32_t cmd, uint8_t* arg_ptr) {
return X_STATUS_UNSUCCESSFUL; return X_STATUS_UNSUCCESSFUL;
} }
return X_STATUS_SUCCESS; return X_STATUS_SUCCESS;
#elif XE_PLATFORM_LINUX #else
int native_cmd = cmd; int native_cmd = cmd;
assert_false(!supported_controls.contains(cmd)); assert_false(!supported_controls.contains(cmd));

View File

@@ -9,7 +9,7 @@
#include "xenia/kernel/xthread.h" #include "xenia/kernel/xthread.h"
#if XE_PLATFORM_LINUX #if !XE_PLATFORM_WIN32
#include <signal.h> #include <signal.h>
#endif #endif
@@ -556,17 +556,19 @@ void XThread::Execute() {
// On Windows, setjmp/longjmp is used because MSVC's longjmp performs SEH // On Windows, setjmp/longjmp is used because MSVC's longjmp performs SEH
// stack unwinding which already calls destructors. // stack unwinding which already calls destructors.
uint32_t next_address; uint32_t next_address;
#if XE_PLATFORM_LINUX #if !XE_PLATFORM_WIN32
try { try {
exit_code = static_cast<int>(kernel_state()->processor()->Execute( exit_code = static_cast<int>(kernel_state()->processor()->Execute(
thread_state_, address, args.data(), args.size())); thread_state_, address, args.data(), args.size()));
next_address = 0; next_address = 0;
} catch (const FiberReentryException& e) { } catch (const FiberReentryException& e) {
#if XE_PLATFORM_LINUX
// Ensure SIGRTMIN (used for thread suspend) is not left blocked. // Ensure SIGRTMIN (used for thread suspend) is not left blocked.
sigset_t set; sigset_t set;
sigemptyset(&set); sigemptyset(&set);
sigaddset(&set, SIGRTMIN); sigaddset(&set, SIGRTMIN);
pthread_sigmask(SIG_UNBLOCK, &set, nullptr); pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
#endif
next_address = e.address; next_address = e.address;
} }
@@ -578,10 +580,12 @@ void XThread::Execute() {
exit_code = static_cast<int>(thread_state_->context()->r[3]); exit_code = static_cast<int>(thread_state_->context()->r[3]);
} }
} catch (const FiberReentryException& e) { } catch (const FiberReentryException& e) {
#if XE_PLATFORM_LINUX
sigset_t set; sigset_t set;
sigemptyset(&set); sigemptyset(&set);
sigaddset(&set, SIGRTMIN); sigaddset(&set, SIGRTMIN);
pthread_sigmask(SIG_UNBLOCK, &set, nullptr); pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
#endif
next_address = e.address; next_address = e.address;
} }
} }
@@ -616,7 +620,7 @@ void XThread::Reenter(uint32_t address) {
// Called when the game switches fiber stacks (e.g., via // Called when the game switches fiber stacks (e.g., via
// KeSetCurrentStackPointers in games like Forza Horizon 2). // KeSetCurrentStackPointers in games like Forza Horizon 2).
// Must unwind through all frames between here and Execute(). // Must unwind through all frames between here and Execute().
#if XE_PLATFORM_LINUX #if !XE_PLATFORM_WIN32
// Throw a C++ exception that unwinds through JIT frames (using DWARF // Throw a C++ exception that unwinds through JIT frames (using DWARF
// .eh_frame info) and host frames (using compiler-generated DWARF), // .eh_frame info) and host frames (using compiler-generated DWARF),
// calling destructors properly along the way. // calling destructors properly along the way.
@@ -767,7 +771,7 @@ X_STATUS XThread::Resume(uint32_t* out_suspend_count) {
} else { } else {
return X_STATUS_UNSUCCESSFUL; return X_STATUS_UNSUCCESSFUL;
} }
#elif XE_PLATFORM_LINUX #else
// Use mutex to protect suspend_count access and coordinate with SelfSuspend. // Use mutex to protect suspend_count access and coordinate with SelfSuspend.
bool should_resume_host = false; bool should_resume_host = false;
{ {
@@ -788,8 +792,6 @@ X_STATUS XThread::Resume(uint32_t* out_suspend_count) {
thread_->Resume(&unused_host_suspend_count); thread_->Resume(&unused_host_suspend_count);
} }
return X_STATUS_SUCCESS; return X_STATUS_SUCCESS;
#else
#error "Unsupported platform"
#endif #endif
} }
@@ -821,7 +823,7 @@ X_STATUS XThread::Suspend(uint32_t* out_suspend_count) {
} }
} }
#if XE_PLATFORM_LINUX #if !XE_PLATFORM_WIN32
uint32_t XThread::SelfSuspend() { uint32_t XThread::SelfSuspend() {
auto guest_thread = guest_object<X_KTHREAD>(); auto guest_thread = guest_object<X_KTHREAD>();
std::unique_lock<std::mutex> lock(suspend_mutex_); std::unique_lock<std::mutex> lock(suspend_mutex_);
@@ -831,7 +833,7 @@ uint32_t XThread::SelfSuspend() {
lock, [guest_thread]() { return guest_thread->suspend_count == 0; }); lock, [guest_thread]() { return guest_thread->suspend_count == 0; });
return previous; return previous;
} }
#endif #endif // !XE_PLATFORM_WIN32
X_STATUS XThread::Delay(uint32_t processor_mode, uint32_t alertable, X_STATUS XThread::Delay(uint32_t processor_mode, uint32_t alertable,
uint64_t interval) { uint64_t interval) {

View File

@@ -14,7 +14,7 @@
#include <string> #include <string>
#include "xenia/base/mutex.h" #include "xenia/base/mutex.h"
#if XE_PLATFORM_LINUX #if !XE_PLATFORM_WIN32
#include <condition_variable> #include <condition_variable>
#include <csignal> #include <csignal>
#include <mutex> #include <mutex>
@@ -343,7 +343,7 @@ struct X_KTHREAD {
}; };
static_assert_size(X_KTHREAD, 0xAB0); static_assert_size(X_KTHREAD, 0xAB0);
#if XE_PLATFORM_LINUX #if !XE_PLATFORM_WIN32
// Exception thrown by XThread::Reenter() to unwind through JIT frames. // Exception thrown by XThread::Reenter() to unwind through JIT frames.
// C++ exception unwinding uses DWARF .eh_frame info registered for JIT code, // C++ exception unwinding uses DWARF .eh_frame info registered for JIT code,
// ensuring destructors and RAII guards in host C++ frames are properly called. // ensuring destructors and RAII guards in host C++ frames are properly called.
@@ -442,7 +442,7 @@ class XThread : public XObject, public cpu::Thread {
X_STATUS Delay(uint32_t processor_mode, uint32_t alertable, X_STATUS Delay(uint32_t processor_mode, uint32_t alertable,
uint64_t interval); uint64_t interval);
#if XE_PLATFORM_LINUX #if !XE_PLATFORM_WIN32
// Performs self-suspension: increments suspend_count and blocks until // Performs self-suspension: increments suspend_count and blocks until
// another thread calls Resume() and suspend_count reaches 0. // another thread calls Resume() and suspend_count reaches 0.
// Returns the previous suspend_count value. // Returns the previous suspend_count value.
@@ -490,7 +490,7 @@ class XThread : public XObject, public cpu::Thread {
int32_t priority_ = 0; int32_t priority_ = 0;
#if XE_PLATFORM_LINUX #if !XE_PLATFORM_WIN32
// Condition variable for thread self-suspension. // Condition variable for thread self-suspension.
std::mutex suspend_mutex_; std::mutex suspend_mutex_;
std::condition_variable suspend_cv_; std::condition_variable suspend_cv_;

View File

@@ -12,10 +12,10 @@
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/platform.h" #include "xenia/base/platform.h"
#if XE_PLATFORM_LINUX #if XE_PLATFORM_WIN32
#include <dlfcn.h>
#elif XE_PLATFORM_WIN32
#include "xenia/base/platform_win.h" #include "xenia/base/platform_win.h"
#else
#include <dlfcn.h>
#endif #endif
namespace xe { namespace xe {
@@ -29,7 +29,14 @@ std::unique_ptr<RenderDocAPI> RenderDocAPI::CreateIfConnected() {
// The RenderDoc library should already be loaded into the process if // The RenderDoc library should already be loaded into the process if
// RenderDoc is attached - this is why RTLD_NOLOAD or GetModuleHandle instead // RenderDoc is attached - this is why RTLD_NOLOAD or GetModuleHandle instead
// of LoadLibrary. // of LoadLibrary.
#if XE_PLATFORM_LINUX #if XE_PLATFORM_WIN32
renderdoc_api->library_ = GetModuleHandleW(L"renderdoc.dll");
if (!renderdoc_api->library_) {
return nullptr;
}
get_api = pRENDERDOC_GetAPI(
GetProcAddress(renderdoc_api->library_, "RENDERDOC_GetAPI"));
#else
#if XE_PLATFORM_ANDROID #if XE_PLATFORM_ANDROID
const char* const library_name = "libVkLayer_GLES_RenderDoc.so"; const char* const library_name = "libVkLayer_GLES_RenderDoc.so";
#else #else
@@ -41,13 +48,6 @@ std::unique_ptr<RenderDocAPI> RenderDocAPI::CreateIfConnected() {
} }
get_api = get_api =
pRENDERDOC_GetAPI(dlsym(renderdoc_api->library_, "RENDERDOC_GetAPI")); pRENDERDOC_GetAPI(dlsym(renderdoc_api->library_, "RENDERDOC_GetAPI"));
#elif XE_PLATFORM_WIN32
renderdoc_api->library_ = GetModuleHandleW(L"renderdoc.dll");
if (!renderdoc_api->library_) {
return nullptr;
}
get_api = pRENDERDOC_GetAPI(
GetProcAddress(renderdoc_api->library_, "RENDERDOC_GetAPI"));
#endif #endif
// get_api will be null if RenderDoc is not connected, or the API isn't // get_api will be null if RenderDoc is not connected, or the API isn't
@@ -65,7 +65,7 @@ std::unique_ptr<RenderDocAPI> RenderDocAPI::CreateIfConnected() {
} }
RenderDocAPI::~RenderDocAPI() { RenderDocAPI::~RenderDocAPI() {
#if XE_PLATFORM_LINUX #if !XE_PLATFORM_WIN32
if (library_) { if (library_) {
dlclose(library_); dlclose(library_);
} }

View File

@@ -37,10 +37,10 @@ class RenderDocAPI {
private: private:
explicit RenderDocAPI() = default; explicit RenderDocAPI() = default;
#if XE_PLATFORM_LINUX #if XE_PLATFORM_WIN32
void* library_ = nullptr;
#elif XE_PLATFORM_WIN32
HMODULE library_ = nullptr; HMODULE library_ = nullptr;
#else
void* library_ = nullptr;
#endif #endif
const RENDERDOC_API_1_0_0* api_1_0_0_ = nullptr; const RENDERDOC_API_1_0_0* api_1_0_0_ = nullptr;