Skip to content

Commit b718432

Browse files
committed
[Threading][Windows] Don't include <windows.h>
We can't safely include <windows.h> because it defines a large number of macros, some of which clash with things in the Swift source tree, and others of which clash with things in the LLVM source tree. Sadly we *also* can't just include the Windows headers we need, because they pull in some of the problematic macros. In this instance, the best thing seems to be to grab the definitions for the types and functions we are going to use and put them in their own header file. If we define them correctly, then #including <windows.h> before or after this header won't have any adverse effects. rdar://90776105
1 parent 848b6b5 commit b718432

File tree

2 files changed

+90
-25
lines changed

2 files changed

+90
-25
lines changed

include/swift/Threading/Impl/Win32.h

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,7 @@
1717
#ifndef SWIFT_THREADING_IMPL_WIN32_H
1818
#define SWIFT_THREADING_IMPL_WIN32_H
1919

20-
#define WIN32_LEAN_AND_MEAN
21-
#define NOMINMAX
22-
#include <windows.h>
23-
24-
// <windows.h> defines some unhelpful macros
25-
#undef Yield
26-
#undef ERROR
20+
#include "Win32/Win32Defs.h"
2721

2822
#include <atomic>
2923

@@ -32,7 +26,7 @@ namespace threading_impl {
3226

3327
// .. Thread related things ..................................................
3428

35-
using thread_id = DWORD;
29+
using thread_id = ::DWORD;
3630

3731
inline thread_id thread_get_current() { return ::GetCurrentThreadId(); }
3832
thread_id thread_get_main();
@@ -41,31 +35,31 @@ inline bool threads_same(thread_id a, thread_id b) { return a == b; }
4135

4236
// .. Mutex support ..........................................................
4337

44-
using mutex_handle = SRWLOCK;
38+
using mutex_handle = ::SRWLOCK;
4539

4640
inline void mutex_init(mutex_handle &handle, bool checked=false) {
4741
handle = SRWLOCK_INIT;
4842
}
4943
inline void mutex_destroy(mutex_handle &handle) { }
5044

5145
inline void mutex_lock(mutex_handle &handle) {
52-
AcquireSRWLockExclusive(&handle);
46+
::AcquireSRWLockExclusive(&handle);
5347
}
5448
inline void mutex_unlock(mutex_handle &handle) {
55-
ReleaseSRWLockExclusive(&handle);
49+
::ReleaseSRWLockExclusive(&handle);
5650
}
5751
inline bool mutex_try_lock(mutex_handle &handle) {
58-
return !!TryAcquireSRWLockExclusive(&handle);
52+
return !!::TryAcquireSRWLockExclusive(&handle);
5953
}
6054

6155
inline void mutex_unsafe_lock(mutex_handle &handle) {
62-
AcquireSRWLockExclusive(&handle);
56+
::AcquireSRWLockExclusive(&handle);
6357
}
6458
inline void mutex_unsafe_unlock(mutex_handle &handle) {
65-
ReleaseSRWLockExclusive(&handle);
59+
::ReleaseSRWLockExclusive(&handle);
6660
}
6761

68-
using lazy_mutex_handle = SRWLOCK;
62+
using lazy_mutex_handle = ::SRWLOCK;
6963

7064
// We don't need to be lazy here because Win32 has SRWLOCK_INIT.
7165
inline constexpr lazy_mutex_handle lazy_mutex_initializer() {
@@ -74,20 +68,20 @@ inline constexpr lazy_mutex_handle lazy_mutex_initializer() {
7468
inline void lazy_mutex_destroy(lazy_mutex_handle &handle) { }
7569

7670
inline void lazy_mutex_lock(lazy_mutex_handle &handle) {
77-
AcquireSRWLockExclusive(&handle);
71+
::AcquireSRWLockExclusive(&handle);
7872
}
7973
inline void lazy_mutex_unlock(lazy_mutex_handle &handle) {
80-
ReleaseSRWLockExclusive(&handle);
74+
::ReleaseSRWLockExclusive(&handle);
8175
}
8276
inline bool lazy_mutex_try_lock(lazy_mutex_handle &handle) {
83-
return !!TryAcquireSRWLockExclusive(&handle);
77+
return !!::TryAcquireSRWLockExclusive(&handle);
8478
}
8579

8680
inline void lazy_mutex_unsafe_lock(lazy_mutex_handle &handle) {
87-
AcquireSRWLockExclusive(&handle);
81+
::AcquireSRWLockExclusive(&handle);
8882
}
8983
inline void lazy_mutex_unsafe_unlock(lazy_mutex_handle &handle) {
90-
ReleaseSRWLockExclusive(&handle);
84+
::ReleaseSRWLockExclusive(&handle);
9185
}
9286

9387
// .. Once ...................................................................
@@ -116,20 +110,20 @@ inline void once_impl(once_t &predicate, void (*fn)(void *), void *context) {
116110

117111
#define SWIFT_TLS_DECLARE_DTOR(name) void NTAPI name(void *)
118112

119-
using tls_key = DWORD;
120-
using tls_dtor = PFLS_CALLBACK_FUNCTION;
113+
using tls_key = ::DWORD;
114+
using tls_dtor = ::PFLS_CALLBACK_FUNCTION;
121115

122116
inline bool tls_alloc(tls_key &key, tls_dtor dtor) {
123-
key = FlsAlloc(dtor);
117+
key = ::FlsAlloc(dtor);
124118
return key != FLS_OUT_OF_INDEXES;
125119
}
126120

127121
inline void *tls_get(tls_key key) {
128-
return FlsGetValue(key);
122+
return ::FlsGetValue(key);
129123
}
130124

131125
inline void tls_set(tls_key key, void *value) {
132-
FlsSetValue(key, value);
126+
::FlsSetValue(key, value);
133127
}
134128

135129
} // namespace threading_impl
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//==--- Win32Defs.h - Windows API definitions ------------------ -*-C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// We cannot include <windows.h> from the Threading headers because they get
14+
// included all over the place and <windows.h> defines a large number of
15+
// obnoxious macros. Instead, this header declares *just* what we need.
16+
//
17+
// If you need <windows.h> in a file, please make sure to include it *before*
18+
// this file, or you'll get errors about RTL_SRWLOCK.
19+
//
20+
//===----------------------------------------------------------------------===//
21+
22+
#ifndef SWIFT_THREADING_IMPL_WIN32_DEFS_H
23+
#define SWIFT_THREADING_IMPL_WIN32_DEFS_H
24+
25+
#define DECLSPEC_IMPORT __declspec(dllimport)
26+
#define WINBASEAPI DECLSPEC_IMPORT
27+
#define WINAPI __stdcall
28+
#define NTAPI __stdcall
29+
30+
// <windows.h> #defines VOID rather than typedefing it(!) Changing that
31+
// to use a typedef instead isn't problematic later on, so let's do that.
32+
#undef VOID
33+
34+
typedef void VOID, *PVOID;
35+
typedef unsigned char BYTE;
36+
typedef BYTE BOOLEAN;
37+
typedef int BOOL;
38+
typedef unsigned long DWORD;
39+
40+
typedef VOID (NTAPI* PFLS_CALLBACK_FUNCTION)(PVOID lpFlsData);
41+
42+
// We can't define this struct if <winnt.h> already did so
43+
#ifndef _WINNT_
44+
struct _RTL_SRWLOCK {
45+
PVOID Ptr;
46+
};
47+
#endif // _WINNT_
48+
49+
typedef struct _RTL_SRWLOCK RTL_SRWLOCK, *PRTL_SRWLOCK;
50+
typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
51+
52+
// These have to be #defines, to avoid problems with <windows.h>
53+
#define RTL_SRWLOCK_INIT {0}
54+
#define SRWLOCK_INIT RTL_SRWLOCK_INIT
55+
#define FLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
56+
57+
extern "C" {
58+
WINBASEAPI DWORD WINAPI GetCurrentThreadId(VOID);
59+
60+
WINBASEAPI VOID WINAPI InitializeSRWLock(PSRWLOCK SRWLock);
61+
WINBASEAPI VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK SRWLock);
62+
WINBASEAPI VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK SRWLock);
63+
WINBASEAPI BOOLEAN WINAPI TryAcquireSRWLockExclusive(PSRWLOCK SRWLock);
64+
65+
WINBASEAPI DWORD WINAPI FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback);
66+
WINBASEAPI PVOID WINAPI FlsGetValue(DWORD dwFlsIndex);
67+
WINBASEAPI BOOL WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData);
68+
WINBASEAPI BOOL WINAPI FlsFree(DWORD dwFlsIndex);
69+
}
70+
71+
#endif // SWIFT_THREADING_IMPL_WIN32_DEFS_H

0 commit comments

Comments
 (0)