mirror of
https://github.com/libretro/bsnes-libretro.git
synced 2024-11-23 08:59:40 +00:00
138 lines
5.2 KiB
C
138 lines
5.2 KiB
C
#if defined(LIBCO_C)
|
|
|
|
/*[amd64, arm, ppc, x86]:
|
|
by default, co_swap_function is marked as a text (code) section
|
|
if not supported, uncomment the below line to use mprotect instead */
|
|
/* #define LIBCO_MPROTECT */
|
|
|
|
/*[amd64]:
|
|
Win64 only: provides a substantial speed-up, but will thrash XMM regs
|
|
do not use this unless you are certain your application won't use SSE */
|
|
/* #define LIBCO_NO_SSE */
|
|
|
|
#if !defined(thread_local) /* User can override thread_local for obscure compilers */
|
|
#if !defined(LIBCO_MP) /* Running in single-threaded environment */
|
|
#define thread_local
|
|
#else /* Running in multi-threaded environment */
|
|
#if defined(__STDC__) /* Compiling as C Language */
|
|
#if defined(_MSC_VER) /* Don't rely on MSVC's C11 support */
|
|
#define thread_local __declspec(thread)
|
|
#elif __STDC_VERSION__ < 201112L /* If we are on C90/99 */
|
|
#if defined(__clang__) || defined(__GNUC__) /* Clang and GCC */
|
|
#define thread_local __thread
|
|
#else /* Otherwise, we ignore the directive (unless user provides their own) */
|
|
#define thread_local
|
|
#endif
|
|
#else /* C11 and newer define thread_local in threads.h */
|
|
#include <threads.h>
|
|
#endif
|
|
#elif defined(__cplusplus) /* Compiling as C++ Language */
|
|
#if __cplusplus < 201103L /* thread_local is a C++11 feature */
|
|
#if defined(_MSC_VER)
|
|
#define thread_local __declspec(thread)
|
|
#elif defined(__clang__) || defined(__GNUC__)
|
|
#define thread_local __thread
|
|
#else /* Otherwise, we ignore the directive (unless user provides their own) */
|
|
#define thread_local
|
|
#endif
|
|
#else /* In C++ >= 11, thread_local in a builtin keyword */
|
|
/* Don't do anything */
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
/* In alignas(a), 'a' should be a power of two that is at least the type's
|
|
alignment and at most the implementation's alignment limit. This limit is
|
|
2**13 on MSVC. To be portable to MSVC through at least version 10.0,
|
|
'a' should be an integer constant, as MSVC does not support expressions
|
|
such as 1 << 3.
|
|
|
|
The following C11 requirements are NOT supported on MSVC:
|
|
|
|
- If 'a' is zero, alignas has no effect.
|
|
- alignas can be used multiple times; the strictest one wins.
|
|
- alignas (TYPE) is equivalent to alignas (alignof (TYPE)).
|
|
*/
|
|
#if !defined(alignas)
|
|
#if defined(__STDC__) /* C Language */
|
|
#if defined(_MSC_VER) /* Don't rely on MSVC's C11 support */
|
|
#define alignas(bytes) __declspec(align(bytes))
|
|
#elif __STDC_VERSION__ >= 201112L /* C11 and above */
|
|
#include <stdalign.h>
|
|
#elif defined(__clang__) || defined(__GNUC__) /* C90/99 on Clang/GCC */
|
|
#define alignas(bytes) __attribute__ ((aligned (bytes)))
|
|
#else /* Otherwise, we ignore the directive (user should provide their own) */
|
|
#define alignas(bytes)
|
|
#endif
|
|
#elif defined(__cplusplus) /* C++ Language */
|
|
#if __cplusplus < 201103L
|
|
#if defined(_MSC_VER)
|
|
#define alignas(bytes) __declspec(align(bytes))
|
|
#elif defined(__clang__) || defined(__GNUC__) /* C++98/03 on Clang/GCC */
|
|
#define alignas(bytes) __attribute__ ((aligned (bytes)))
|
|
#else /* Otherwise, we ignore the directive (unless user provides their own) */
|
|
#define alignas(bytes)
|
|
#endif
|
|
#else /* C++ >= 11 has alignas keyword */
|
|
/* Do nothing */
|
|
#endif
|
|
#endif /* = !defined(__STDC_VERSION__) && !defined(__cplusplus) */
|
|
#endif
|
|
|
|
#if !defined(LIBCO_ASSERT)
|
|
#include <assert.h>
|
|
#define LIBCO_ASSERT assert
|
|
#endif
|
|
|
|
#if defined (__OpenBSD__)
|
|
#if !defined(LIBCO_MALLOC) || !defined(LIBCO_FREE)
|
|
#include <unistd.h>
|
|
#include <sys/mman.h>
|
|
|
|
static void* malloc_obsd(size_t size) {
|
|
long pagesize = sysconf(_SC_PAGESIZE);
|
|
char* memory = (char*)mmap(NULL, size + pagesize, PROT_READ|PROT_WRITE, MAP_STACK|MAP_PRIVATE|MAP_ANON, -1, 0);
|
|
if (memory == MAP_FAILED) return NULL;
|
|
*(size_t*)memory = size + pagesize;
|
|
memory += pagesize;
|
|
return (void*)memory;
|
|
}
|
|
|
|
static void free_obsd(void *ptr) {
|
|
char* memory = (char*)ptr - sysconf(_SC_PAGESIZE);
|
|
munmap(memory, *(size_t*)memory);
|
|
}
|
|
|
|
#define LIBCO_MALLOC malloc_obsd
|
|
#define LIBCO_FREE free_obsd
|
|
#endif
|
|
#endif
|
|
|
|
#if !defined(LIBCO_MALLOC) || !defined(LIBCO_FREE)
|
|
#include <stdlib.h>
|
|
#define LIBCO_MALLOC malloc
|
|
#define LIBCO_FREE free
|
|
#endif
|
|
|
|
#if defined(_MSC_VER)
|
|
#define section(name) __declspec(allocate("." #name))
|
|
#elif defined(__APPLE__)
|
|
#define section(name) __attribute__((section("__TEXT,__" #name)))
|
|
#elif defined(__SWITCH__)
|
|
/*
|
|
This is basically the same as the last case, however the "#" suffix will create a secondary .text section.
|
|
Because of that, the toolchain will treat the section as non-executable. This might be related to the linker scripts
|
|
used for libnx homebrew. The reason that this is a seperate ifdef, is purely to silence a cosmetic warn
|
|
about ignoring the +w attribute on .text which would happen on other platforms under some conditions (said warning is by design
|
|
when data is being merged like this into .text).
|
|
*/
|
|
#define section(name) __attribute__((section("." #name)))
|
|
#else
|
|
#define section(name) __attribute__((section("." #name "#")))
|
|
#endif
|
|
|
|
|
|
/* if defined(LIBCO_C) */
|
|
#endif
|