History

win32: define arm64 Interlocked helpers in winnt.h

Move the TinyCC/Windows ARM64 Interlocked workaround from the semlock call site into the bundled WinAPI header. This keeps tcc.h using the normal Interlocked API while avoiding unresolved Interlocked imports when tcc -run self-compiles on Windows ARM64. Update lib/bt-exe.c as well so its ARM64 runtime object does not define a second InterlockedExchange fallback now provided by winnt.h.

Mounir IDRASSI committed 5 months ago

Commit 3b1fe971 parent 904e95c7 files · +122 −47Browse files

Unified · Split

7 files
  1. lib/bt-exe.c +0 −10
  2. tcc.h +3 −37
  3. tests/tests2/145_winarm64_interlocked.c +35 −0
  4. tests/tests2/145_winarm64_interlocked.expect +8 −0
  5. tests/tests2/Makefile +5 −0
  6. win32/include/winapi/winbase.h +8 −0
  7. win32/include/winapi/winnt.h +63 −0
lib/bt-exe.c+0−10
@@ -85,13 +85,3 @@ ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s) · 84 unmodified lines
85 buf[l] = 0;85 buf[l] = 0;
86 return buf;86 return buf;
87}87}
88
89#if defined(_WIN64) && defined(__aarch64__)
90/* The bt-only Windows ARM64 build should not rely on importing this helper. */
91LONG InterlockedExchange(LONG volatile *Target, LONG Value)
92{
93 LONG Old = *Target;
94 *Target = Value;
95 return Old;
96}
97#endif
tcc.h+3−37
@@ -1930,46 +1930,12 @@ dwarf_read_sleb128(unsigned char **ln, unsigned char *end) · 1929 unmodified lines
1930#if CONFIG_TCC_SEMLOCK1930#if CONFIG_TCC_SEMLOCK
1931#if defined _WIN321931#if defined _WIN32
1932typedef struct { volatile LONG init; CRITICAL_SECTION cs; } TCCSem;1932typedef struct { volatile LONG init; CRITICAL_SECTION cs; } TCCSem;
1933#if defined __TINYC__ && (defined __aarch64__ || defined __arm64__)
1934/* Windows/arm64 Interlocked* names are compiler intrinsics, not
1935 kernel32 exports, so tcc -run must not emit calls to them. */
1936# define TCC_SEM_USE_ATOMICS 1
1937enum { TCC_SEM_ATOMIC_SEQ_CST = 5 };
1938#endif
1939static inline LONG tcc_sem_cmpxchg(volatile LONG *ptr, LONG val, LONG cmp) {
1940#ifdef TCC_SEM_USE_ATOMICS
1941 LONG old = cmp;
1942 __atomic_compare_exchange((LONG *)ptr, &old, &val, 0,
1943 TCC_SEM_ATOMIC_SEQ_CST,
1944 TCC_SEM_ATOMIC_SEQ_CST);
1945 return old;
1946#else
1947 return InterlockedCompareExchange(ptr, val, cmp);
1948#endif
1949}
1950static inline void tcc_sem_store(volatile LONG *ptr, LONG val) {
1951#ifdef TCC_SEM_USE_ATOMICS
1952 __atomic_store((LONG *)ptr, &val, TCC_SEM_ATOMIC_SEQ_CST);
1953#else
1954 InterlockedExchange(ptr, val);
1955#endif
1956}
1957static inline LONG tcc_sem_load(volatile LONG *ptr) {
1958#ifdef TCC_SEM_USE_ATOMICS
1959 LONG val;
1960 __atomic_load((LONG *)ptr, &val, TCC_SEM_ATOMIC_SEQ_CST);
1961 return val;
1962#else
1963 return InterlockedCompareExchange(ptr, 0, 0);
1964#endif
1965}
1966static inline void wait_sem(TCCSem *p) {1933static inline void wait_sem(TCCSem *p) {
1967 if (tcc_sem_cmpxchg(&p->init, 1, 0) == 0) {1934 if (InterlockedCompareExchange(&p->init, 1, 0) == 0) {
1968 InitializeCriticalSection(&p->cs);1935 InitializeCriticalSection(&p->cs);
1969 tcc_sem_store(&p->init, 2);1936 InterlockedExchange(&p->init, 2);
1970 } else {1937 } else {
1971 /* On tcc/arm64, __atomic_load maps to the acquire helper path. */1938 while (InterlockedCompareExchange(&p->init, 2, 2) != 2)
1972 while (tcc_sem_load(&p->init) != 2)
1973 Sleep(0);1939 Sleep(0);
1974 }1940 }
1975 EnterCriticalSection(&p->cs);1941 EnterCriticalSection(&p->cs);
tests/tests2/145_winarm64_interlocked.c+35−0
@@ -0,0 +1,35 @@
1#include <stdio.h>
2#include <windows.h>
3
4#define PTR(x) ((PVOID)(ULONG_PTR)(x))
5#define CHECK(name, expr) printf("%s: %s\n", name, (expr) ? "yes" : "no")
6
7int main(void)
8{
9 PVOID volatile slot = PTR(0x1111222233334444ULL);
10 PVOID old;
11
12 old = InterlockedExchangePointer(&slot, PTR(0x5555666677778888ULL));
13 CHECK("exchange old", old == PTR(0x1111222233334444ULL));
14 CHECK("exchange stored", slot == PTR(0x5555666677778888ULL));
15
16 old = InterlockedCompareExchangePointer(&slot,
17 PTR(0x9999aaaabbbbccccULL),
18 PTR(0x5555666677778888ULL));
19 CHECK("compare old", old == PTR(0x5555666677778888ULL));
20 CHECK("compare stored", slot == PTR(0x9999aaaabbbbccccULL));
21
22 old = InterlockedCompareExchangePointerAcquire(&slot,
23 PTR(0xdddd111122223333ULL),
24 PTR(0x0123456789abcdefULL));
25 CHECK("acquire old", old == PTR(0x9999aaaabbbbccccULL));
26 CHECK("acquire stored", slot == PTR(0x9999aaaabbbbccccULL));
27
28 old = InterlockedCompareExchangePointerRelease(&slot,
29 PTR(0xdddd111122223333ULL),
30 PTR(0x9999aaaabbbbccccULL));
31 CHECK("release old", old == PTR(0x9999aaaabbbbccccULL));
32 CHECK("release stored", slot == PTR(0xdddd111122223333ULL));
33
34 return 0;
35}
tests/tests2/145_winarm64_interlocked.expect+8−0
@@ -0,0 +1,8 @@
1exchange old: yes
2exchange stored: yes
3compare old: yes
4compare stored: yes
5acquire old: yes
6acquire stored: yes
7release old: yes
8release stored: yes
tests/tests2/Makefile+5−0
@@ -65,6 +65,11 @@ ifeq (,$(filter arm64 aarch64,$(ARCH))) · 64 unmodified lines
65 SKIP += 139_arm64_errors.test65 SKIP += 139_arm64_errors.test
66 SKIP += 140_arm64_extasm.test66 SKIP += 140_arm64_extasm.test
67endif67endif
68ifneq ($(CONFIG_WIN32),yes)
69 SKIP += 145_winarm64_interlocked.test
70else ifeq (,$(filter arm64 aarch64,$(ARCH)))
71 SKIP += 145_winarm64_interlocked.test
72endif
68ifeq (,$(filter riscv64,$(ARCH)))73ifeq (,$(filter riscv64,$(ARCH)))
69 SKIP += 141_riscv_asm.test # riscv64 asm74 SKIP += 141_riscv_asm.test # riscv64 asm
70endif75endif
win32/include/winapi/winbase.h+8−0
@@ -972,7 +972,9 @@ extern "C" { · 971 unmodified lines
972 LONG WINAPI InterlockedDecrement(LONG volatile *lpAddend);972 LONG WINAPI InterlockedDecrement(LONG volatile *lpAddend);
973 LONG WINAPI InterlockedExchange(LONG volatile *Target,LONG Value);973 LONG WINAPI InterlockedExchange(LONG volatile *Target,LONG Value);
974 974
975#ifndef InterlockedExchangePointer
975#define InterlockedExchangePointer(Target,Value) (PVOID)InterlockedExchange((PLONG)(Target),(LONG)(Value))976#define InterlockedExchangePointer(Target,Value) (PVOID)InterlockedExchange((PLONG)(Target),(LONG)(Value))
977#endif
976 978
977 LONG WINAPI InterlockedExchangeAdd(LONG volatile *Addend,LONG Value);979 LONG WINAPI InterlockedExchangeAdd(LONG volatile *Addend,LONG Value);
978 LONG WINAPI InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand);980 LONG WINAPI InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand);
@@ -1035,6 +1037,7 @@ extern "C" { · 56 unmodified lines
1035 return Old;1037 return Old;
1036 }1038 }
1037 1039
1040#ifndef InterlockedCompareExchangePointer
1038#ifdef __cplusplus1041#ifdef __cplusplus
1039 __CRT_INLINE PVOID __cdecl __InlineInterlockedCompareExchangePointer(PVOID volatile *Destination,PVOID ExChange,PVOID Comperand) {1042 __CRT_INLINE PVOID __cdecl __InlineInterlockedCompareExchangePointer(PVOID volatile *Destination,PVOID ExChange,PVOID Comperand) {
1040 return((PVOID)(LONG_PTR)InterlockedCompareExchange((LONG volatile *)Destination,(LONG)(LONG_PTR)ExChange,(LONG)(LONG_PTR)Comperand));1043 return((PVOID)(LONG_PTR)InterlockedCompareExchange((LONG volatile *)Destination,(LONG)(LONG_PTR)ExChange,(LONG)(LONG_PTR)Comperand));
@@ -1043,6 +1046,7 @@ extern "C" { · 2 unmodified lines
1043#else1046#else
1044#define InterlockedCompareExchangePointer(Destination,ExChange,Comperand)(PVOID)(LONG_PTR)InterlockedCompareExchange((LONG volatile *)(Destination),(LONG)(LONG_PTR)(ExChange),(LONG)(LONG_PTR)(Comperand))1047#define InterlockedCompareExchangePointer(Destination,ExChange,Comperand)(PVOID)(LONG_PTR)InterlockedCompareExchange((LONG volatile *)(Destination),(LONG)(LONG_PTR)(ExChange),(LONG)(LONG_PTR)(Comperand))
1045#endif1048#endif
1049#endif
1046 1050
1047#define InterlockedIncrementAcquire InterlockedIncrement1051#define InterlockedIncrementAcquire InterlockedIncrement
1048#define InterlockedIncrementRelease InterlockedIncrement1052#define InterlockedIncrementRelease InterlockedIncrement
@@ -1054,9 +1058,13 @@ extern "C" { · 5 unmodified lines
1054#define InterlockedCompareExchangeRelease InterlockedCompareExchange1058#define InterlockedCompareExchangeRelease InterlockedCompareExchange
1055#define InterlockedCompareExchangeAcquire64 InterlockedCompareExchange641059#define InterlockedCompareExchangeAcquire64 InterlockedCompareExchange64
1056#define InterlockedCompareExchangeRelease64 InterlockedCompareExchange641060#define InterlockedCompareExchangeRelease64 InterlockedCompareExchange64
1061#ifndef InterlockedCompareExchangePointerAcquire
1057#define InterlockedCompareExchangePointerAcquire InterlockedCompareExchangePointer1062#define InterlockedCompareExchangePointerAcquire InterlockedCompareExchangePointer
1063#endif
1064#ifndef InterlockedCompareExchangePointerRelease
1058#define InterlockedCompareExchangePointerRelease InterlockedCompareExchangePointer1065#define InterlockedCompareExchangePointerRelease InterlockedCompareExchangePointer
1059#endif1066#endif
1067#endif
1060 1068
1061#if defined(_SLIST_HEADER_) && !defined(_NTOSP_)1069#if defined(_SLIST_HEADER_) && !defined(_NTOSP_)
1062 WINBASEAPI VOID WINAPI InitializeSListHead(PSLIST_HEADER ListHead);1070 WINBASEAPI VOID WINAPI InitializeSListHead(PSLIST_HEADER ListHead);
win32/include/winapi/winnt.h+63−0
@@ -1419,6 +1419,69 @@ typedef DWORD LCID; · 1418 unmodified lines
1419#define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME "OutOfProcessFunctionTableCallback"1419#define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME "OutOfProcessFunctionTableCallback"
1420#endif /* defined(__x86_64) && !defined(RC_INVOKED) */1420#endif /* defined(__x86_64) && !defined(RC_INVOKED) */
1421 1421
1422#if defined(__TINYC__) && (defined(__aarch64__) || defined(__arm64__)) && !defined(RC_INVOKED)
1423
1424#define __TCC_WINNT_ATOMIC_SEQ_CST 5
1425/* TCC lowers __atomic_compare_exchange's fourth argument as weak, but the
1426 ARM64 helper reads it as success_memorder. Strong CAS passes weak == 0,
1427 so keep Interlocked's barriers explicit here. */
1428#define __TCC_WINNT_MEMORY_BARRIER() __asm__ __volatile__("dmb ish" : : : "memory")
1429
1430/* This covers the LONG operations needed by TCC's semaphore code and the
1431 pointer helpers that winbase.h exposes through Interlocked pointer macros.
1432 Add local helpers before relying on increment/decrement, add/exchange-add,
1433 bitwise, or 64-bit Interlocked forms on Windows ARM64 with TCC. */
1434
1435 __CRT_INLINE LONG InterlockedExchange(LONG volatile *Target,LONG Value) {
1436 LONG Old;
1437 __atomic_load(Target,&Old,__TCC_WINNT_ATOMIC_SEQ_CST);
1438 __TCC_WINNT_MEMORY_BARRIER();
1439 while (!__atomic_compare_exchange(Target,&Old,&Value,0,
1440 __TCC_WINNT_ATOMIC_SEQ_CST,__TCC_WINNT_ATOMIC_SEQ_CST))
1441 ;
1442 __TCC_WINNT_MEMORY_BARRIER();
1443 return Old;
1444 }
1445 __CRT_INLINE LONG InterlockedCompareExchange(LONG volatile *Destination,LONG ExChange,LONG Comperand) {
1446 LONG Old = Comperand;
1447 __TCC_WINNT_MEMORY_BARRIER();
1448 __atomic_compare_exchange(Destination,&Old,&ExChange,0,
1449 __TCC_WINNT_ATOMIC_SEQ_CST,__TCC_WINNT_ATOMIC_SEQ_CST);
1450 __TCC_WINNT_MEMORY_BARRIER();
1451 return Old;
1452 }
1453 __CRT_INLINE PVOID __TCC_WINNT_InterlockedExchangePointer(PVOID volatile *Target,PVOID Value) {
1454 PVOID Old;
1455 __atomic_load(Target,&Old,__TCC_WINNT_ATOMIC_SEQ_CST);
1456 __TCC_WINNT_MEMORY_BARRIER();
1457 while (!__atomic_compare_exchange(Target,&Old,&Value,0,
1458 __TCC_WINNT_ATOMIC_SEQ_CST,__TCC_WINNT_ATOMIC_SEQ_CST))
1459 ;
1460 __TCC_WINNT_MEMORY_BARRIER();
1461 return Old;
1462 }
1463 __CRT_INLINE PVOID __TCC_WINNT_InterlockedCompareExchangePointer(PVOID volatile *Destination,PVOID ExChange,PVOID Comperand) {
1464 PVOID Old = Comperand;
1465 __TCC_WINNT_MEMORY_BARRIER();
1466 __atomic_compare_exchange(Destination,&Old,&ExChange,0,
1467 __TCC_WINNT_ATOMIC_SEQ_CST,__TCC_WINNT_ATOMIC_SEQ_CST);
1468 __TCC_WINNT_MEMORY_BARRIER();
1469 return Old;
1470 }
1471
1472#define InterlockedExchangePointer __TCC_WINNT_InterlockedExchangePointer
1473#define InterlockedCompareExchangePointer __TCC_WINNT_InterlockedCompareExchangePointer
1474#define InterlockedCompareExchangePointerAcquire InterlockedCompareExchangePointer
1475#define InterlockedCompareExchangePointerRelease InterlockedCompareExchangePointer
1476
1477#define InterlockedCompareExchangeAcquire InterlockedCompareExchange
1478#define InterlockedCompareExchangeRelease InterlockedCompareExchange
1479
1480#undef __TCC_WINNT_MEMORY_BARRIER
1481#undef __TCC_WINNT_ATOMIC_SEQ_CST
1482
1483#endif /* defined(__TINYC__) && (defined(__aarch64__) || defined(__arm64__)) && !defined(RC_INVOKED) */
1484
1422#if defined(_ARM64_)1485#if defined(_ARM64_)
1423 1486
1424/* ARM64 Context Definition */1487/* ARM64 Context Definition */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t