Skip to content

Commit

Permalink
fwd,thread,c11,gthr,libcxx: Add some basic support for MSVC
Browse files Browse the repository at this point in the history
  • Loading branch information
lhmouse committed Jan 17, 2024
1 parent c9a96bf commit 508c74b
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 52 deletions.
35 changes: 22 additions & 13 deletions mcfgthread/c11.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ enum __MCF_thrd_error
/* 7.26.2.1 The call_once function */
__MCF_C11_INLINE
void
__MCF_c11_call_once(once_flag* __flag, __MCF_once_callback* __init_func);
__MCF_c11_call_once(once_flag* __once, __MCF_once_callback* __init_proc);

#ifndef __MCF_C11_NO_ALIASES
__MCF_ALWAYS_INLINE void call_once(once_flag* __flag, __MCF_once_callback* __init_func) __MCF_ASM_CALL(__MCF_c11_call_once);
__MCF_ALWAYS_INLINE void call_once(once_flag* __once, __MCF_once_callback* __init_proc) __MCF_ASM_CALL(__MCF_c11_call_once);
# ifndef __clang__
__MCF_ALWAYS_INLINE void call_once(once_flag* __flag, __MCF_once_callback* __init_func) { __MCF_c11_call_once(__flag, __init_func); }
__MCF_ALWAYS_INLINE void call_once(once_flag* __once, __MCF_once_callback* __init_proc) { __MCF_c11_call_once(__once, __init_proc); }
# endif /* __clang__ */
#endif

Expand Down Expand Up @@ -397,17 +397,26 @@ __MCF_ALWAYS_INLINE int tss_set(tss_t __key, void* __val_opt) __MCF_NOEXCEPT { r
* this file. */
__MCF_C11_INLINE
void
__MCF_c11_call_once(once_flag* __flag, __MCF_once_callback* __init_func)
__MCF_c11_call_once(once_flag* __once, __MCF_once_callback* __init_proc)
{
_MCF_once* __cleanup __attribute__((__cleanup__(__MCF_gthr_unonce))) = NULL;

if(_MCF_once_wait(__flag, NULL) == 0)
return;

__cleanup = __flag;
__init_func();
__cleanup = NULL;
_MCF_once_release(__flag);
#ifdef _MSC_VER
_MCF_once* __once_g = NULL;
__try
#else
_MCF_once* __once_g __attribute__((__cleanup__(__MCF_gthr_unonce))) = NULL;
#endif
{
if(_MCF_once_wait(__once, NULL) == 0)
return;

__once_g = __once;
__init_proc();
__once_g = NULL;
_MCF_once_release(__once);
}
#ifdef _MSC_VER
__finally { __MCF_gthr_unonce(&__once_g); }
#endif
}

__MCF_C11_INLINE
Expand Down
29 changes: 21 additions & 8 deletions mcfgthread/fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,30 @@
#endif

/* Compiler-specific stuff */
#define __MCF_GNU_INLINE extern __inline__ __attribute__((__gnu_inline__))
#define __MCF_ALWAYS_INLINE __MCF_GNU_INLINE __attribute__((__always_inline__, __artificial__))
#define __MCF_NEVER_INLINE __attribute__((__noinline__))
#define __MCF_NEVER_RETURN __attribute__((__noreturn__))
#define __MCF_FN_CONST __attribute__((__const__))
#define __MCF_FN_PURE __attribute__((__pure__))
#define __MCF_ASM_CALL(x) __asm__(__MCF_S(__USER_LABEL_PREFIX__) #x)
#define __MCF_ALIGNED(x) __attribute__((__aligned__(x)))
#ifdef _MSC_VER
# define __MCF_GNU_INLINE __inline
# define __MCF_ALWAYS_INLINE __forceinline
# define __MCF_NEVER_INLINE __declspec(noinline)
# define __MCF_NEVER_RETURN __declspec(noreturn)
# define __MCF_FN_CONST /* unsupported */
# define __MCF_FN_PURE /* unsupported */
# define __MCF_ASM_CALL(x) /* unnecessary */
# define __MCF_ALIGNED(x) __declspec(align(x))
#else
# define __MCF_GNU_INLINE extern __inline__ __attribute__((__gnu_inline__))
# define __MCF_ALWAYS_INLINE __MCF_GNU_INLINE __attribute__((__always_inline__, __artificial__))
# define __MCF_NEVER_INLINE __attribute__((__noinline__))
# define __MCF_NEVER_RETURN __attribute__((__noreturn__))
# define __MCF_FN_CONST __attribute__((__const__))
# define __MCF_FN_PURE __attribute__((__pure__))
# define __MCF_ASM_CALL(x) __asm__(__MCF_S(__USER_LABEL_PREFIX__) #x)
# define __MCF_ALIGNED(x) __attribute__((__aligned__(x)))
#endif

#ifdef __MCF_DEBUG
# define __MCF_UNREACHABLE __MCF_runtime_failure(__func__)
#elif defined _MSC_VER
# define __MCF_UNREACHABLE __assume(0)
#else
# define __MCF_UNREACHABLE __builtin_unreachable()
#endif
Expand Down
28 changes: 18 additions & 10 deletions mcfgthread/gthr.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,17 +345,25 @@ __MCF_GTHR_INLINE
int
__MCF_gthr_once(__gthread_once_t* __once, __MCF_once_callback* __init_proc)
{
_MCF_once* __cleanup __attribute__((__cleanup__(__MCF_gthr_unonce))) = NULL;

if(_MCF_once_wait(__once, NULL) == 0)
#ifdef _MSC_VER
_MCF_once* __once_g = NULL;
__try
#else
_MCF_once* __once_g __attribute__((__cleanup__(__MCF_gthr_unonce))) = NULL;
#endif
{
if(_MCF_once_wait(__once, NULL) == 0)
return 0;

__once_g = __once;
__init_proc();
__once_g = NULL;
_MCF_once_release(__once);
return 0;

__cleanup = __once;
__init_proc();
__cleanup = NULL;

_MCF_once_release(__once);
return 0;
}
#ifdef _MSC_VER
__finally { __MCF_gthr_unonce(&__once_g); }
#endif
}

__MCF_GTHR_INLINE
Expand Down
28 changes: 18 additions & 10 deletions mcfgthread/libcxx.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,17 +341,25 @@ __MCF_LIBCXX_INLINE
int
__MCF_libcxx_execute_once(__libcpp_exec_once_flag* __once, __MCF_once_callback* __init_proc)
{
_MCF_once* __cleanup __attribute__((__cleanup__(__MCF_gthr_unonce))) = NULL;

if(_MCF_once_wait(__once, NULL) == 0)
#ifdef _MSC_VER
_MCF_once* __once_g = NULL;
__try
#else
_MCF_once* __once_g __attribute__((__cleanup__(__MCF_gthr_unonce))) = NULL;
#endif
{
if(_MCF_once_wait(__once, NULL) == 0)
return 0;

__once_g = __once;
__init_proc();
__once_g = NULL;
_MCF_once_release(__once);
return 0;

__cleanup = __once;
__init_proc();
__cleanup = NULL;

_MCF_once_release(__once);
return 0;
}
#ifdef _MSC_VER
__finally { __MCF_gthr_unonce(&__once_g); }
#endif
}

__MCF_LIBCXX_INLINE
Expand Down
87 changes: 76 additions & 11 deletions mcfgthread/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,30 +303,95 @@ _MCF_thread_get_handle(const _MCF_thread* __thrd) __MCF_NOEXCEPT
return __thrd->__handle;
}

#if defined _MSC_VER && (defined _M_X64 && !defined _M_ARM64EC)
/* x86-64, MSVC */
unsigned long __readgsdword(unsigned long) __MCF_NOEXCEPT;
#pragma intrinsic(__readgsdword)
__MCF_THREAD_INLINE
uint32_t
_MCF_thread_self_tid(void) __MCF_NOEXCEPT
{
return __readgsdword(0x48);
}
#elif defined __amd64__
/* x86-64, GCC or Clang */
__MCF_THREAD_INLINE
uint32_t
_MCF_thread_self_tid(void) __MCF_NOEXCEPT
{
uint32_t __tid;
#if defined __amd64__
/* Current TEB starts at `gs:0`. */
__asm__ ("{ movl %%gs:0x48, %0 | mov %0, dword ptr gs:[0x48] }" : "=r"(__tid));
return __tid;
}
#endif

#if defined _MSC_VER && defined _M_IX86
/* x86, MSVC */
unsigned long __readfsdword(unsigned long) __MCF_NOEXCEPT;
#pragma intrinsic(__readfsdword)
__MCF_THREAD_INLINE
uint32_t
_MCF_thread_self_tid(void) __MCF_NOEXCEPT
{
return __readfsdword(0x24);
}
#elif defined __i386__
/* Current TEB starts at `fs:0`. */
/* x86, GCC or Clang */
__MCF_THREAD_INLINE
uint32_t
_MCF_thread_self_tid(void) __MCF_NOEXCEPT
{
uint32_t __tid;
__asm__ ("{ movl %%fs:0x24, %0 | mov %0, dword ptr fs:[0x24] }" : "=r"(__tid));
return __tid;
}
#endif

#if defined _MSC_VER && (defined _M_ARM64 || defined _M_ARM64EC)
/* ARM64, MSVC */
unsigned long __readx18dword(unsigned long) __MCF_NOEXCEPT;
#pragma intrinsic(__readx18dword)
__MCF_THREAD_INLINE
uint32_t
_MCF_thread_self_tid(void) __MCF_NOEXCEPT
{
return __readx18dword(0x48);
}
#elif defined __aarch64__
/* Current TEB base is `x18`. */
/* ARM64, GCC or Clang */
__MCF_THREAD_INLINE
uint32_t
_MCF_thread_self_tid(void) __MCF_NOEXCEPT
{
uint32_t __tid;
__asm__ ("ldr %w0, [x18, #0x48]" : "=r"(__tid));
#elif defined __arm__
/* Current TEB base is moved from co-processor p15. */
return __tid;
}
#endif

#if defined _MSC_VER && defined _M_ARM
/* ARM32, MSVC */
int _MoveFromCoprocessor(unsigned, unsigned, unsigned, unsigned) __MCF_NOEXCEPT;
#pragma intrinsic(_MoveFromCoprocessor)
__MCF_THREAD_INLINE
uint32_t
_MCF_thread_self_tid(void) __MCF_NOEXCEPT
{
char* __teb;
__teb = (char*) _MoveFromCoprocessor(15, 0, 13, 0, 2);
return *(uint32_t*) (__teb + 0x24);
}
#elif defined __aarch64__
/* ARM32, GCC or Clang */
__MCF_THREAD_INLINE
uint32_t
_MCF_thread_self_tid(void) __MCF_NOEXCEPT
{
char* __teb;
__asm__ ("mrc p15, #0, %0, c13, c0, #2" : "=r"(__teb));
__tid = *(uint32_t*) (__teb + 0x24);
#else
# error TODO: CPU not supported
#endif
return __tid;
return *(uint32_t*) (__teb + 0x24);
}
#endif

__MCF_THREAD_INLINE
void*
Expand Down

0 comments on commit 508c74b

Please sign in to comment.