Skip to content

Commit e013bea

Browse files
committed
revive the Windows port
The `DISPATCH_EXPORT` macro added an extraneous `extern` on the declaration. This was pointed out by a newer clang. Adjust the declaration accordingly. Add build rules to improve Windows builds. These additions help cross-compile to Windows with both clang-cl as well as the GNU clang driver. Use the newer Windows APIs to detect the windows CPU state. This allows us to collect all of the CPU configuration information to properly affinitise work to the preferred CPU. Use the FLS API to create thread local data storage for libdispatch's queues.
1 parent 79ca48b commit e013bea

37 files changed

+899
-131
lines changed

CMakeLists.txt

+11-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ project(dispatch
88
LANGUAGES C CXX)
99
enable_testing()
1010

11+
if("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC")
12+
include(ClangClCompileRules)
13+
endif()
14+
1115
set(CMAKE_C_STANDARD 11)
1216
set(CMAKE_C_STANDARD_REQUIRED YES)
1317

@@ -262,10 +266,6 @@ if (HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME)
262266
endif()
263267
check_symbol_exists(__printflike "bsd/sys/cdefs.h" HAVE_PRINTFLIKE)
264268

265-
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
266-
add_definitions(-DTARGET_OS_WIN32)
267-
endif()
268-
269269
if(CMAKE_SYSTEM_NAME STREQUAL Android)
270270
set(ENABLE_DTRACE_DEFAULT OFF)
271271
endif()
@@ -321,6 +321,13 @@ configure_file("${CMAKE_SOURCE_DIR}/cmake/config.h.in"
321321
"${CMAKE_BINARY_DIR}/config/config_ac.h")
322322
add_definitions(-DHAVE_CONFIG_H)
323323

324+
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
325+
include(DispatchWindowsSupport)
326+
dispatch_windows_arch_spelling(${CMAKE_SYSTEM_PROCESSOR} DISPATCH_MSVC_ARCH)
327+
dispatch_windows_include_for_arch(${DISPATCH_MSVC_ARCH} DISPATCH_INCLUDES)
328+
include_directories(BEFORE SYSTEM ${DISPATCH_INCLUDES})
329+
endif()
330+
324331
add_subdirectory(dispatch)
325332
add_subdirectory(man)
326333
add_subdirectory(os)
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
# clang-cl interprets paths starting with /U as macro undefines, so we need to
3+
# put a -- before the input file path to force it to be treated as a path.
4+
string(REPLACE "-c <SOURCE>" "-c -- <SOURCE>" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
5+
string(REPLACE "-c <SOURCE>" "-c -- <SOURCE>" CMAKE_CXX_COMPILE_OBJECT "${CMAKE_CXX_COMPILE_OBJECT}")
6+
7+
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
8+
+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
2+
function(dispatch_windows_arch_spelling arch var)
3+
if(${arch} STREQUAL i686)
4+
set(${var} x86 PARENT_SCOPE)
5+
elseif(${arch} STREQUAL x86_64)
6+
set(${var} x64 PARENT_SCOPE)
7+
elseif(${arch} STREQUAL armv7)
8+
set(${var} arm PARENT_SCOPE)
9+
elseif(${arch} STREQUAL aarch64)
10+
set(${var} arm64 PARENT_SCOPE)
11+
else()
12+
message(FATAL_ERROR "do not know MSVC spelling for ARCH: `${arch}`")
13+
endif()
14+
endfunction()
15+
16+
function(dispatch_verify_windows_environment_variables)
17+
set(VCToolsInstallDir $ENV{VCToolsInstallDir})
18+
set(UniversalCRTSdkDir $ENV{UniversalCRTSdkDir})
19+
set(UCRTVersion $ENV{UCRTVersion})
20+
21+
if("${VCToolsInstallDir}" STREQUAL "")
22+
message(SEND_ERROR "VCToolsInstallDir environment variable must be set")
23+
endif()
24+
if("${UniversalCRTSdkDir}" STREQUAL "")
25+
message(SEND_ERROR "UniversalCRTSdkDir environment variable must be set")
26+
endif()
27+
if("${UCRTVersion}" STREQUAL "")
28+
message(SEND_ERROR "UCRTVersion environment variable must be set")
29+
endif()
30+
endfunction()
31+
32+
function(dispatch_windows_include_for_arch arch var)
33+
dispatch_verify_windows_environment_variables()
34+
35+
set(paths
36+
"$ENV{VCToolsInstallDir}/include"
37+
"$ENV{UniversalCRTSdkDir}/Include/$ENV{UCRTVersion}/ucrt"
38+
"$ENV{UniversalCRTSdkDir}/Include/$ENV{UCRTVersion}/shared"
39+
"$ENV{UniversalCRTSdkDir}/Include/$ENV{UCRTVersion}/um")
40+
set(${var} ${paths} PARENT_SCOPE)
41+
endfunction()
42+
43+
function(dispatch_windows_lib_for_arch arch var)
44+
dispatch_verify_windows_environment_variables()
45+
dispatch_windows_arch_spelling(${arch} ARCH)
46+
47+
set(paths)
48+
if(${ARCH} STREQUAL x86)
49+
list(APPEND paths "$ENV{VCToolsInstallDir}/Lib")
50+
else()
51+
list(APPEND paths "$ENV{VCToolsInstallDir}/Lib/${ARCH}")
52+
endif()
53+
list(APPEND paths
54+
"$ENV{UniversalCRTSdkDir}/Lib/$ENV{UCRTVersion}/ucrt/${ARCH}"
55+
"$ENV{UniversalCRTSdkDir}/Lib/$ENV{UCRTVersion}/um/${ARCH}")
56+
set(${var} ${paths} PARENT_SCOPE)
57+
endfunction()
58+
59+
function(dispatch_windows_generate_sdk_vfs_overlay flags)
60+
dispatch_verify_windows_environment_variables()
61+
62+
get_filename_component(VCToolsInstallDir $ENV{VCToolsInstallDir} ABSOLUTE)
63+
get_filename_component(UniversalCRTSdkDir $ENV{UniversalCRTSdkDir} ABSOLUTE)
64+
set(UCRTVersion $ENV{UCRTVersion})
65+
66+
# TODO(compnerd) use a target to avoid re-creating this file all the time
67+
configure_file("${CMAKE_SOURCE_DIR}/utils/WindowsSDKVFSOverlay.yaml.in"
68+
"${CMAKE_BINARY_DIR}/windows-sdk-vfs-overlay.yaml"
69+
@ONLY)
70+
71+
set(${flags}
72+
-ivfsoverlay;"${CMAKE_BINARY_DIR}/windows-sdk-vfs-overlay.yaml"
73+
PARENT_SCOPE)
74+
endfunction()

dispatch/base.h

+12-7
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,20 @@
128128
#endif
129129
#endif
130130

131-
#if TARGET_OS_WIN32 && defined(__DISPATCH_BUILDING_DISPATCH__) && \
132-
defined(__cplusplus)
133-
#define DISPATCH_EXPORT extern "C" extern __declspec(dllexport)
134-
#elif TARGET_OS_WIN32 && defined(__DISPATCH_BUILDING_DISPATCH__)
131+
#if defined(_WIN32)
132+
#if defined(__DISPATCH_BUILDING_DISPATCH__)
133+
#if defined(__cplusplus)
134+
#define DISPATCH_EXPORT extern "C" __declspec(dllexport)
135+
#else
135136
#define DISPATCH_EXPORT extern __declspec(dllexport)
136-
#elif TARGET_OS_WIN32 && defined(__cplusplus)
137-
#define DISPATCH_EXPORT extern "C" extern __declspec(dllimport)
138-
#elif TARGET_OS_WIN32
137+
#endif
138+
#else
139+
#if defined(__cplusplus)
140+
#define DISPATCH_EXPORT extern "C" __declspec(dllimport)
141+
#else
139142
#define DISPATCH_EXPORT extern __declspec(dllimport)
143+
#endif
144+
#endif
140145
#elif __GNUC__
141146
#define DISPATCH_EXPORT extern __attribute__((visibility("default")))
142147
#else

dispatch/data.h

-5
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,10 @@ DISPATCH_EXPORT struct dispatch_data_s _dispatch_data_empty;
6262
#define DISPATCH_DATA_DESTRUCTOR_DEFAULT NULL
6363

6464
#ifdef __BLOCKS__
65-
#if !TARGET_OS_WIN32
6665
/*! @parseOnly */
6766
#define DISPATCH_DATA_DESTRUCTOR_TYPE_DECL(name) \
6867
DISPATCH_EXPORT const dispatch_block_t _dispatch_data_destructor_##name
6968
#else
70-
#define DISPATCH_DATA_DESTRUCTOR_TYPE_DECL(name) \
71-
DISPATCH_EXPORT dispatch_block_t _dispatch_data_destructor_##name
72-
#endif
73-
#else
7469
#define DISPATCH_DATA_DESTRUCTOR_TYPE_DECL(name) \
7570
DISPATCH_EXPORT const dispatch_function_t \
7671
_dispatch_data_destructor_##name

dispatch/dispatch.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
#include <os/availability.h>
2727
#include <TargetConditionals.h>
2828
#include <os/base.h>
29-
#elif defined(__linux__) || defined(__FreeBSD__)
29+
#elif defined(_WIN32)
30+
#include <os/generic_win_base.h>
31+
#elif defined(__unix__)
3032
#include <os/generic_unix_base.h>
3133
#endif
3234

dispatch/io.h

+4
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ __BEGIN_DECLS
5050
* @typedef dispatch_fd_t
5151
* Native file descriptor type for the platform.
5252
*/
53+
#if defined(_WIN32)
54+
typedef intptr_t dispatch_fd_t;
55+
#else
5356
typedef int dispatch_fd_t;
57+
#endif
5458

5559
/*!
5660
* @functiongroup Dispatch I/O Convenience API

dispatch/object.h

+1-7
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ typedef union {
121121
#ifndef DISPATCH_DATA_DECL
122122
#define DISPATCH_DATA_DECL(name) OS_OBJECT_DECL_SWIFT(name)
123123
#endif // DISPATCH_DATA_DECL
124-
#elif !TARGET_OS_WIN32
124+
#else
125125
/*! @parseOnly */
126126
#define DISPATCH_SOURCE_DECL(name) \
127127
DISPATCH_DECL(name);
@@ -131,12 +131,6 @@ typedef union {
131131
#define DISPATCH_SOURCE_TYPE_DECL(name) \
132132
DISPATCH_EXPORT const struct dispatch_source_type_s \
133133
_dispatch_source_type_##name
134-
#else
135-
#define DISPATCH_SOURCE_DECL(name) \
136-
DISPATCH_DECL(name);
137-
#define DISPATCH_SOURCE_TYPE_DECL(name) \
138-
DISPATCH_EXPORT struct dispatch_source_type_s _dispatch_source_type_##name
139-
#define DISPATCH_DATA_DECL(name) DISPATCH_DECL(name)
140134
#endif
141135

142136
#ifdef __BLOCKS__

dispatch/source.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#include <mach/message.h>
3232
#endif
3333

34-
#if !TARGET_OS_WIN32
34+
#if !defined(_WIN32)
3535
#include <sys/signal.h>
3636
#endif
3737

os/generic_win_base.h

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* This source file is part of the Swift.org open source project
3+
*
4+
* Copyright (c) 2015 Apple Inc. and the Swift project authors
5+
*
6+
* Licensed under Apache License v2.0 with Runtime Library Exception
7+
*
8+
* See http://swift.org/LICENSE.txt for license information
9+
* See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
*
11+
*/
12+
13+
#ifndef __OS_GENERIC_WIN_BASE__
14+
#define __OS_GENERIC_WIN_BASE__
15+
16+
// Unices provide `roundup` via sys/param.h
17+
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
18+
// Unices provide `MAX` via sys/param.h
19+
#define MAX(a,b) (((a)>(b))?(a):(b))
20+
// Unices provide `MIN` via sys/param.h
21+
#define MIN(a,b) (((a)<(b))?(a):(b))
22+
// Unices provide `howmany` via sys/param.h
23+
#define howmany(x, y) (((x) + ((y) - 1)) / (y))
24+
25+
typedef int mode_t;
26+
typedef void pthread_attr_t;
27+
28+
#if defined(__cplusplus)
29+
#define __BEGIN_DECLS extern "C" {
30+
#define __END_DECLS }
31+
#else
32+
#define __BEGIN_DECLS
33+
#define __END_DECLS
34+
#endif
35+
36+
#ifndef API_AVAILABLE
37+
#define API_AVAILABLE(...)
38+
#endif
39+
#ifndef API_DEPRECATED
40+
#define API_DEPRECATED(...)
41+
#endif
42+
#ifndef API_UNAVAILABLE
43+
#define API_UNAVAILABLE(...)
44+
#endif
45+
#ifndef API_DEPRECATED_WITH_REPLACEMENT
46+
#define API_DEPRECATED_WITH_REPLACEMENT(...)
47+
#endif
48+
49+
#if !defined(__has_attribute)
50+
#define __has_attribute(attibute) 0
51+
#endif
52+
53+
#if !defined(__has_builtin)
54+
#define __has_builtin(builtin) 0
55+
#endif
56+
57+
#if !defined(__has_feature)
58+
#define __has_feature(feature) 0
59+
#endif
60+
61+
#if __has_builtin(__builtin_expect)
62+
#define OS_EXPECT(expression, value) __builtin_expect((expression), (value))
63+
#else
64+
#define OS_EXPECT(expression, value) (expression)
65+
#endif
66+
67+
#if __has_attribute(__unused__)
68+
#define OS_UNUSED __attribute__((__unused__))
69+
#else
70+
#define OS_UNUSED
71+
#endif
72+
73+
#ifndef os_likely
74+
#define os_likely(expression) OS_EXPECT(!!(expression), 1)
75+
#endif
76+
#ifndef os_unlikely
77+
#define os_unlikely(expression) OS_EXPECT(!!(expression), 0)
78+
#endif
79+
80+
#if __has_feature(assume_nonnull)
81+
#define OS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
82+
#define OS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
83+
#else
84+
#define OS_ASSUME_NONNULL_BEGIN
85+
#define OS_ASSUME_NONNULL_END
86+
#endif
87+
88+
#if __has_builtin(__builtin_assume)
89+
#define OS_COMPILER_CAN_ASSUME(expr) __builtin_assume(expr)
90+
#else
91+
#define OS_COMPILER_CAN_ASSUME(expr) ((void)(expr))
92+
#endif
93+
94+
#if __has_feature(attribute_availability_swift)
95+
// equivalent to __SWIFT_UNAVAILABLE from Availability.h
96+
#define OS_SWIFT_UNAVAILABLE(msg) \
97+
__attribute__((__availability__(swift, unavailable, message = msg)))
98+
#else
99+
#define OS_SWIFT_UNAVAILABLE(msg)
100+
#endif
101+
102+
#define __OS_STRINGIFY(s) #s
103+
#define OS_STRINGIFY(s) __OS_STRINGIFY(s)
104+
105+
#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums)
106+
#define OS_ENUM(name, type, ...) typedef enum : type { __VA_ARGS__ } name##_t
107+
#else
108+
#define OS_ENUM(name, type, ...) \
109+
enum { __VA_ARGS__ }; \
110+
typedef type name##_t
111+
#endif
112+
113+
#ifdef OS_EXPORT
114+
#undef OS_EXPORT
115+
#endif
116+
#define OS_EXPORT __declspec(dllexport)
117+
118+
#ifdef OS_WARN_RESULT_NEEDS_RELEASE
119+
#undef OS_WARN_RESULT_NEEDS_RELEASE
120+
#endif
121+
122+
#ifdef OS_WARN_RESULT
123+
#undef OS_WARN_RESULT
124+
#endif
125+
#define OS_WARN_RESULT
126+
127+
#ifdef OS_NOTHROW
128+
#undef OS_NOTHROW
129+
#endif
130+
#define OS_NOTHROW
131+
132+
#endif

os/object.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
#include <os/availability.h>
2727
#include <TargetConditionals.h>
2828
#include <os/base.h>
29-
#elif defined(__linux__) || defined(__FreeBSD__)
29+
#elif defined(_WIN32)
30+
#include <os/generic_win_base.h>
31+
#elif defined(__unix__)
3032
#include <os/generic_unix_base.h>
3133
#endif
3234

private/data_private.h

-6
Original file line numberDiff line numberDiff line change
@@ -182,15 +182,9 @@ dispatch_data_make_memory_entry(dispatch_data_t data);
182182
*/
183183
typedef const struct dispatch_data_format_type_s *dispatch_data_format_type_t;
184184

185-
#if !TARGET_OS_WIN32
186185
#define DISPATCH_DATA_FORMAT_TYPE_DECL(name) \
187186
DISPATCH_EXPORT const struct dispatch_data_format_type_s \
188187
_dispatch_data_format_type_##name
189-
#else
190-
#define DISPATCH_DATA_FORMAT_TYPE_DECL(name) \
191-
DISPATCH_EXPORT struct dispatch_data_format_type_s \
192-
_dispatch_data_format_type_##name
193-
#endif
194188

195189
/*!
196190
* @const DISPATCH_DATA_FORMAT_TYPE_NONE

private/layout_private.h

-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
__BEGIN_DECLS
3030

31-
#if !TARGET_OS_WIN32
3231
API_AVAILABLE(macos(10.6), ios(4.0))
3332
DISPATCH_EXPORT const struct dispatch_queue_offsets_s {
3433
// always add new fields at the end
@@ -51,7 +50,6 @@ DISPATCH_EXPORT const struct dispatch_queue_offsets_s {
5150
const uint16_t dqo_priority;
5251
const uint16_t dqo_priority_size;
5352
} dispatch_queue_offsets;
54-
#endif
5553

5654
#if DISPATCH_LAYOUT_SPI
5755

0 commit comments

Comments
 (0)