[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:
@@ -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) {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|||||||
@@ -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_);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user