Merge pull request #346 from ikesyo/optional-map-over-flatmap
[gardening] Use `Optional.map` over `flatMap` where appropriate
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ead4696..b0adcb5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,6 +8,10 @@
LANGUAGES C CXX)
enable_testing()
+if("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC")
+ include(ClangClCompileRules)
+endif()
+
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED YES)
@@ -262,10 +266,6 @@
endif()
check_symbol_exists(__printflike "bsd/sys/cdefs.h" HAVE_PRINTFLIKE)
-if(CMAKE_SYSTEM_NAME STREQUAL Windows)
- add_definitions(-DTARGET_OS_WIN32)
-endif()
-
if(CMAKE_SYSTEM_NAME STREQUAL Android)
set(ENABLE_DTRACE_DEFAULT OFF)
endif()
@@ -321,6 +321,13 @@
"${CMAKE_BINARY_DIR}/config/config_ac.h")
add_definitions(-DHAVE_CONFIG_H)
+if(CMAKE_SYSTEM_NAME STREQUAL Windows)
+ include(DispatchWindowsSupport)
+ dispatch_windows_arch_spelling(${CMAKE_SYSTEM_PROCESSOR} DISPATCH_MSVC_ARCH)
+ dispatch_windows_include_for_arch(${DISPATCH_MSVC_ARCH} DISPATCH_INCLUDES)
+ include_directories(BEFORE SYSTEM ${DISPATCH_INCLUDES})
+endif()
+
add_subdirectory(dispatch)
add_subdirectory(man)
add_subdirectory(os)
diff --git a/cmake/modules/ClangClCompileRules.cmake b/cmake/modules/ClangClCompileRules.cmake
new file mode 100644
index 0000000..9c2a4cd
--- /dev/null
+++ b/cmake/modules/ClangClCompileRules.cmake
@@ -0,0 +1,8 @@
+
+# clang-cl interprets paths starting with /U as macro undefines, so we need to
+# put a -- before the input file path to force it to be treated as a path.
+string(REPLACE "-c <SOURCE>" "-c -- <SOURCE>" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
+string(REPLACE "-c <SOURCE>" "-c -- <SOURCE>" CMAKE_CXX_COMPILE_OBJECT "${CMAKE_CXX_COMPILE_OBJECT}")
+
+set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
+
diff --git a/cmake/modules/DispatchCompilerWarnings.cmake b/cmake/modules/DispatchCompilerWarnings.cmake
index fa3b2b5..a7b31c8 100644
--- a/cmake/modules/DispatchCompilerWarnings.cmake
+++ b/cmake/modules/DispatchCompilerWarnings.cmake
@@ -74,5 +74,6 @@
add_compile_options(-Wno-int-conversion)
add_compile_options(-Wno-shorten-64-to-32)
endif()
+ add_compile_options(-Wno-error=assign-enum)
endmacro()
endif()
diff --git a/cmake/modules/DispatchWindowsSupport.cmake b/cmake/modules/DispatchWindowsSupport.cmake
new file mode 100644
index 0000000..eed28a2
--- /dev/null
+++ b/cmake/modules/DispatchWindowsSupport.cmake
@@ -0,0 +1,74 @@
+
+function(dispatch_windows_arch_spelling arch var)
+ if(${arch} STREQUAL i686)
+ set(${var} x86 PARENT_SCOPE)
+ elseif(${arch} STREQUAL x86_64)
+ set(${var} x64 PARENT_SCOPE)
+ elseif(${arch} STREQUAL armv7)
+ set(${var} arm PARENT_SCOPE)
+ elseif(${arch} STREQUAL aarch64)
+ set(${var} arm64 PARENT_SCOPE)
+ else()
+ message(FATAL_ERROR "do not know MSVC spelling for ARCH: `${arch}`")
+ endif()
+endfunction()
+
+function(dispatch_verify_windows_environment_variables)
+ set(VCToolsInstallDir $ENV{VCToolsInstallDir})
+ set(UniversalCRTSdkDir $ENV{UniversalCRTSdkDir})
+ set(UCRTVersion $ENV{UCRTVersion})
+
+ if("${VCToolsInstallDir}" STREQUAL "")
+ message(SEND_ERROR "VCToolsInstallDir environment variable must be set")
+ endif()
+ if("${UniversalCRTSdkDir}" STREQUAL "")
+ message(SEND_ERROR "UniversalCRTSdkDir environment variable must be set")
+ endif()
+ if("${UCRTVersion}" STREQUAL "")
+ message(SEND_ERROR "UCRTVersion environment variable must be set")
+ endif()
+endfunction()
+
+function(dispatch_windows_include_for_arch arch var)
+ dispatch_verify_windows_environment_variables()
+
+ set(paths
+ "$ENV{VCToolsInstallDir}/include"
+ "$ENV{UniversalCRTSdkDir}/Include/$ENV{UCRTVersion}/ucrt"
+ "$ENV{UniversalCRTSdkDir}/Include/$ENV{UCRTVersion}/shared"
+ "$ENV{UniversalCRTSdkDir}/Include/$ENV{UCRTVersion}/um")
+ set(${var} ${paths} PARENT_SCOPE)
+endfunction()
+
+function(dispatch_windows_lib_for_arch arch var)
+ dispatch_verify_windows_environment_variables()
+ dispatch_windows_arch_spelling(${arch} ARCH)
+
+ set(paths)
+ if(${ARCH} STREQUAL x86)
+ list(APPEND paths "$ENV{VCToolsInstallDir}/Lib")
+ else()
+ list(APPEND paths "$ENV{VCToolsInstallDir}/Lib/${ARCH}")
+ endif()
+ list(APPEND paths
+ "$ENV{UniversalCRTSdkDir}/Lib/$ENV{UCRTVersion}/ucrt/${ARCH}"
+ "$ENV{UniversalCRTSdkDir}/Lib/$ENV{UCRTVersion}/um/${ARCH}")
+ set(${var} ${paths} PARENT_SCOPE)
+endfunction()
+
+function(dispatch_windows_generate_sdk_vfs_overlay flags)
+ dispatch_verify_windows_environment_variables()
+
+ get_filename_component(VCToolsInstallDir $ENV{VCToolsInstallDir} ABSOLUTE)
+ get_filename_component(UniversalCRTSdkDir $ENV{UniversalCRTSdkDir} ABSOLUTE)
+ set(UCRTVersion $ENV{UCRTVersion})
+
+ # TODO(compnerd) use a target to avoid re-creating this file all the time
+ configure_file("${CMAKE_SOURCE_DIR}/utils/WindowsSDKVFSOverlay.yaml.in"
+ "${CMAKE_BINARY_DIR}/windows-sdk-vfs-overlay.yaml"
+ @ONLY)
+
+ set(${flags}
+ -ivfsoverlay;"${CMAKE_BINARY_DIR}/windows-sdk-vfs-overlay.yaml"
+ PARENT_SCOPE)
+endfunction()
diff --git a/dispatch/base.h b/dispatch/base.h
index 0c5f8c9..bd01f48 100644
--- a/dispatch/base.h
+++ b/dispatch/base.h
@@ -128,15 +128,20 @@
#endif
#endif
-#if TARGET_OS_WIN32 && defined(__DISPATCH_BUILDING_DISPATCH__) && \
- defined(__cplusplus)
-#define DISPATCH_EXPORT extern "C" extern __declspec(dllexport)
-#elif TARGET_OS_WIN32 && defined(__DISPATCH_BUILDING_DISPATCH__)
+#if defined(_WIN32)
+#if defined(__DISPATCH_BUILDING_DISPATCH__)
+#if defined(__cplusplus)
+#define DISPATCH_EXPORT extern "C" __declspec(dllexport)
+#else
#define DISPATCH_EXPORT extern __declspec(dllexport)
-#elif TARGET_OS_WIN32 && defined(__cplusplus)
-#define DISPATCH_EXPORT extern "C" extern __declspec(dllimport)
-#elif TARGET_OS_WIN32
+#endif
+#else
+#if defined(__cplusplus)
+#define DISPATCH_EXPORT extern "C" __declspec(dllimport)
+#else
#define DISPATCH_EXPORT extern __declspec(dllimport)
+#endif
+#endif
#elif __GNUC__
#define DISPATCH_EXPORT extern __attribute__((visibility("default")))
#else
@@ -203,7 +208,7 @@
#endif
#endif
-#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums)
+#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums) || defined(_WIN32)
#define DISPATCH_ENUM(name, type, ...) \
typedef enum : type { __VA_ARGS__ } name##_t
#else
diff --git a/dispatch/data.h b/dispatch/data.h
index 33a0c9d..8250669 100644
--- a/dispatch/data.h
+++ b/dispatch/data.h
@@ -62,16 +62,11 @@
#define DISPATCH_DATA_DESTRUCTOR_DEFAULT NULL
#ifdef __BLOCKS__
-#if !TARGET_OS_WIN32
/*! @parseOnly */
#define DISPATCH_DATA_DESTRUCTOR_TYPE_DECL(name) \
DISPATCH_EXPORT const dispatch_block_t _dispatch_data_destructor_##name
#else
#define DISPATCH_DATA_DESTRUCTOR_TYPE_DECL(name) \
- DISPATCH_EXPORT dispatch_block_t _dispatch_data_destructor_##name
-#endif
-#else
-#define DISPATCH_DATA_DESTRUCTOR_TYPE_DECL(name) \
DISPATCH_EXPORT const dispatch_function_t \
_dispatch_data_destructor_##name
#endif /* __BLOCKS__ */
diff --git a/dispatch/dispatch.h b/dispatch/dispatch.h
index d36259c..1901226 100644
--- a/dispatch/dispatch.h
+++ b/dispatch/dispatch.h
@@ -26,7 +26,9 @@
#include <os/availability.h>
#include <TargetConditionals.h>
#include <os/base.h>
-#elif defined(__linux__) || defined(__FreeBSD__)
+#elif defined(_WIN32)
+#include <os/generic_win_base.h>
+#elif defined(__unix__)
#include <os/generic_unix_base.h>
#endif
diff --git a/dispatch/io.h b/dispatch/io.h
index a9e6892..db9733d 100644
--- a/dispatch/io.h
+++ b/dispatch/io.h
@@ -50,7 +50,11 @@
* @typedef dispatch_fd_t
* Native file descriptor type for the platform.
*/
+#if defined(_WIN32)
+typedef intptr_t dispatch_fd_t;
+#else
typedef int dispatch_fd_t;
+#endif
/*!
* @functiongroup Dispatch I/O Convenience API
diff --git a/dispatch/object.h b/dispatch/object.h
index 3ff36c2..3a31b10 100644
--- a/dispatch/object.h
+++ b/dispatch/object.h
@@ -121,7 +121,7 @@
#ifndef DISPATCH_DATA_DECL
#define DISPATCH_DATA_DECL(name) OS_OBJECT_DECL_SWIFT(name)
#endif // DISPATCH_DATA_DECL
-#elif !TARGET_OS_WIN32
+#else
/*! @parseOnly */
#define DISPATCH_SOURCE_DECL(name) \
DISPATCH_DECL(name);
@@ -131,12 +131,6 @@
#define DISPATCH_SOURCE_TYPE_DECL(name) \
DISPATCH_EXPORT const struct dispatch_source_type_s \
_dispatch_source_type_##name
-#else
-#define DISPATCH_SOURCE_DECL(name) \
- DISPATCH_DECL(name);
-#define DISPATCH_SOURCE_TYPE_DECL(name) \
- DISPATCH_EXPORT struct dispatch_source_type_s _dispatch_source_type_##name
-#define DISPATCH_DATA_DECL(name) DISPATCH_DECL(name)
#endif
#ifdef __BLOCKS__
diff --git a/dispatch/source.h b/dispatch/source.h
index 6992d42..35bb03f 100644
--- a/dispatch/source.h
+++ b/dispatch/source.h
@@ -31,7 +31,7 @@
#include <mach/message.h>
#endif
-#if !TARGET_OS_WIN32
+#if !defined(_WIN32)
#include <sys/signal.h>
#endif
diff --git a/os/generic_win_base.h b/os/generic_win_base.h
new file mode 100644
index 0000000..8b4c613
--- /dev/null
+++ b/os/generic_win_base.h
@@ -0,0 +1,132 @@
+/*
+ * This source file is part of the Swift.org open source project
+ *
+ * Copyright (c) 2015 Apple Inc. and the Swift project authors
+ *
+ * Licensed under Apache License v2.0 with Runtime Library Exception
+ *
+ * See http://swift.org/LICENSE.txt for license information
+ * See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+ *
+ */
+
+#ifndef __OS_GENERIC_WIN_BASE__
+#define __OS_GENERIC_WIN_BASE__
+
+// Unices provide `roundup` via sys/param.h
+#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+// Unices provide `MAX` via sys/param.h
+#define MAX(a,b) (((a)>(b))?(a):(b))
+// Unices provide `MIN` via sys/param.h
+#define MIN(a,b) (((a)<(b))?(a):(b))
+// Unices provide `howmany` via sys/param.h
+#define howmany(x, y) (((x) + ((y) - 1)) / (y))
+
+typedef int mode_t;
+typedef void pthread_attr_t;
+
+#if defined(__cplusplus)
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+
+#ifndef API_AVAILABLE
+#define API_AVAILABLE(...)
+#endif
+#ifndef API_DEPRECATED
+#define API_DEPRECATED(...)
+#endif
+#ifndef API_UNAVAILABLE
+#define API_UNAVAILABLE(...)
+#endif
+#ifndef API_DEPRECATED_WITH_REPLACEMENT
+#define API_DEPRECATED_WITH_REPLACEMENT(...)
+#endif
+
+#if !defined(__has_attribute)
+#define __has_attribute(attibute) 0
+#endif
+
+#if !defined(__has_builtin)
+#define __has_builtin(builtin) 0
+#endif
+
+#if !defined(__has_feature)
+#define __has_feature(feature) 0
+#endif
+
+#if __has_builtin(__builtin_expect)
+#define OS_EXPECT(expression, value) __builtin_expect((expression), (value))
+#else
+#define OS_EXPECT(expression, value) (expression)
+#endif
+
+#if __has_attribute(__unused__)
+#define OS_UNUSED __attribute__((__unused__))
+#else
+#define OS_UNUSED
+#endif
+
+#ifndef os_likely
+#define os_likely(expression) OS_EXPECT(!!(expression), 1)
+#endif
+#ifndef os_unlikely
+#define os_unlikely(expression) OS_EXPECT(!!(expression), 0)
+#endif
+
+#if __has_feature(assume_nonnull)
+#define OS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
+#define OS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
+#else
+#define OS_ASSUME_NONNULL_BEGIN
+#define OS_ASSUME_NONNULL_END
+#endif
+
+#if __has_builtin(__builtin_assume)
+#define OS_COMPILER_CAN_ASSUME(expr) __builtin_assume(expr)
+#else
+#define OS_COMPILER_CAN_ASSUME(expr) ((void)(expr))
+#endif
+
+#if __has_feature(attribute_availability_swift)
+// equivalent to __SWIFT_UNAVAILABLE from Availability.h
+#define OS_SWIFT_UNAVAILABLE(msg) \
+ __attribute__((__availability__(swift, unavailable, message = msg)))
+#else
+#define OS_SWIFT_UNAVAILABLE(msg)
+#endif
+
+#define __OS_STRINGIFY(s) #s
+#define OS_STRINGIFY(s) __OS_STRINGIFY(s)
+
+#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums)
+#define OS_ENUM(name, type, ...) typedef enum : type { __VA_ARGS__ } name##_t
+#else
+#define OS_ENUM(name, type, ...) \
+ enum { __VA_ARGS__ }; \
+ typedef type name##_t
+#endif
+
+#ifdef OS_EXPORT
+#undef OS_EXPORT
+#endif
+#define OS_EXPORT __declspec(dllexport)
+
+#ifdef OS_WARN_RESULT_NEEDS_RELEASE
+#undef OS_WARN_RESULT_NEEDS_RELEASE
+#endif
+
+#ifdef OS_WARN_RESULT
+#undef OS_WARN_RESULT
+#endif
+#define OS_WARN_RESULT
+
+#ifdef OS_NOTHROW
+#undef OS_NOTHROW
+#endif
+#define OS_NOTHROW
+
+#endif
diff --git a/os/object.h b/os/object.h
index 3666c33..1ad1158 100644
--- a/os/object.h
+++ b/os/object.h
@@ -26,7 +26,9 @@
#include <os/availability.h>
#include <TargetConditionals.h>
#include <os/base.h>
-#elif defined(__linux__) || defined(__FreeBSD__)
+#elif defined(_WIN32)
+#include <os/generic_win_base.h>
+#elif defined(__unix__)
#include <os/generic_unix_base.h>
#endif
diff --git a/private/data_private.h b/private/data_private.h
index 364a8ff..a922157 100644
--- a/private/data_private.h
+++ b/private/data_private.h
@@ -182,15 +182,9 @@
*/
typedef const struct dispatch_data_format_type_s *dispatch_data_format_type_t;
-#if !TARGET_OS_WIN32
#define DISPATCH_DATA_FORMAT_TYPE_DECL(name) \
DISPATCH_EXPORT const struct dispatch_data_format_type_s \
_dispatch_data_format_type_##name
-#else
-#define DISPATCH_DATA_FORMAT_TYPE_DECL(name) \
- DISPATCH_EXPORT struct dispatch_data_format_type_s \
- _dispatch_data_format_type_##name
-#endif
/*!
* @const DISPATCH_DATA_FORMAT_TYPE_NONE
diff --git a/private/layout_private.h b/private/layout_private.h
index 0c0cd94..81bcabd 100644
--- a/private/layout_private.h
+++ b/private/layout_private.h
@@ -28,7 +28,6 @@
__BEGIN_DECLS
-#if !TARGET_OS_WIN32
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT const struct dispatch_queue_offsets_s {
// always add new fields at the end
@@ -51,7 +50,6 @@
const uint16_t dqo_priority;
const uint16_t dqo_priority_size;
} dispatch_queue_offsets;
-#endif
#if DISPATCH_LAYOUT_SPI
diff --git a/private/private.h b/private/private.h
index ee2b26e..7fba396 100644
--- a/private/private.h
+++ b/private/private.h
@@ -32,7 +32,9 @@
#include <os/availability.h>
#include <TargetConditionals.h>
#include <os/base.h>
-#elif defined(__linux__) || defined(__FreeBSD__)
+#elif defined(_WIN32)
+#include <os/generic_win_base.h>
+#elif defined(__unix__)
#include <os/generic_unix_base.h>
#endif
@@ -44,7 +46,9 @@
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#endif
+#if !defined(_WIN32)
#include <pthread.h>
+#endif
#if TARGET_OS_MAC
#include <pthread/qos.h>
#endif
diff --git a/src/BlocksRuntime/runtime.c b/src/BlocksRuntime/runtime.c
index da85f71..b8c4b33 100644
--- a/src/BlocksRuntime/runtime.c
+++ b/src/BlocksRuntime/runtime.c
@@ -172,7 +172,7 @@
}
static void _Block_assign_weak_default(const void *ptr, void *dest) {
-#if !TARGET_OS_WIN32
+#if !defined(_WIN32)
*(long *)dest = (long)ptr;
#else
*(void **)dest = (void *)ptr;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c9c55b5..a7cd89b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -47,14 +47,23 @@
shims/atomic_sfb.h
shims/getprogname.h
shims/hw_config.h
- shims/generic_unix_stubs.c
- shims/generic_unix_stubs.h
shims/lock.c
shims/lock.h
shims/perfmon.h
shims/time.h
shims/tsd.h
shims/yield.h)
+if(UNIX)
+ target_sources(dispatch
+ PRIVATE
+ shims/generic_unix_stubs.c
+ shims/generic_unix_stubs.h)
+elseif(WIN32)
+ target_sources(dispatch
+ PRIVATE
+ shims/generic_win_stubs.c
+ shims/generic_win_stubs.h)
+endif()
if(DISPATCH_USE_INTERNAL_WORKQUEUE)
target_sources(dispatch
PRIVATE
@@ -130,6 +139,11 @@
SYSTEM BEFORE PRIVATE
"${WITH_BLOCKS_RUNTIME}")
endif()
+if(WIN32)
+ target_compile_definitions(dispatch
+ PRIVATE
+ _CRT_NONSTDC_NO_WARNINGS)
+endif()
if("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC")
target_compile_options(dispatch PRIVATE /EHsc-)
else()
diff --git a/src/block.cpp b/src/block.cpp
index 8f8113a..a46b551 100644
--- a/src/block.cpp
+++ b/src/block.cpp
@@ -69,7 +69,9 @@
{
// copy constructor, create copy with retained references
if (dbpd_voucher) voucher_retain(dbpd_voucher);
- if (o.dbpd_block) dbpd_block = _dispatch_Block_copy(o.dbpd_block);
+ if (o.dbpd_block) {
+ dbpd_block = reinterpret_cast<dispatch_block_t>(_dispatch_Block_copy(o.dbpd_block));
+ }
_dispatch_block_private_data_debug("copy from %p, block: %p from %p",
&o, dbpd_block, o.dbpd_block);
if (!o.dbpd_magic) return; // No group in initial copy of stack object
@@ -98,11 +100,11 @@
pthread_priority_t pri, dispatch_block_t block)
{
struct dispatch_block_private_data_s dbpds(flags, voucher, pri, block);
- return _dispatch_Block_copy(^{
+ return reinterpret_cast<dispatch_block_t>(_dispatch_Block_copy(^{
// Capture stack object: invokes copy constructor (17094902)
(void)dbpds;
_dispatch_block_invoke_direct(&dbpds);
- });
+ }));
}
extern "C" {
diff --git a/src/event/event_config.h b/src/event/event_config.h
index 871a3e0..fda5d22 100644
--- a/src/event/event_config.h
+++ b/src/event/event_config.h
@@ -29,6 +29,9 @@
# include <sys/event.h>
# define DISPATCH_EVENT_BACKEND_EPOLL 0
# define DISPATCH_EVENT_BACKEND_KEVENT 1
+#elif defined(_WIN32)
+# define DISPATCH_EVENT_BACKEND_EPOLL 0
+# define DISPATCH_EVENT_BACKEND_KEVENT 0
#else
# error unsupported event loop
#endif
diff --git a/src/init.c b/src/init.c
index 4ef733d..00a04d3 100644
--- a/src/init.c
+++ b/src/init.c
@@ -37,7 +37,7 @@
void
_libdispatch_init(void);
-DISPATCH_EXPORT DISPATCH_NOTHROW
+DISPATCH_NOTHROW
void
_libdispatch_init(void)
{
@@ -45,6 +45,7 @@
}
#endif
+#if !defined(_WIN32)
DISPATCH_EXPORT DISPATCH_NOTHROW
void
dispatch_atfork_prepare(void)
@@ -96,6 +97,7 @@
r |= pthread_sigmask(SIG_BLOCK, &mask, NULL);
return dispatch_assume_zero(r);
}
+#endif
#pragma mark -
#pragma mark dispatch_globals
@@ -111,7 +113,11 @@
#if DISPATCH_USE_THREAD_LOCAL_STORAGE
__thread struct dispatch_tsd __dispatch_tsd;
+#if defined(_WIN32)
+DWORD __dispatch_tsd_key;
+#else
pthread_key_t __dispatch_tsd_key;
+#endif
#elif !DISPATCH_USE_DIRECT_TSD
pthread_key_t dispatch_queue_key;
pthread_key_t dispatch_frame_key;
@@ -690,26 +696,57 @@
log_to_file = true;
} else if (strcmp(e, "stderr") == 0) {
log_to_file = true;
+#if defined(_WIN32)
+ dispatch_logfile = _fileno(stderr);
+#else
dispatch_logfile = STDERR_FILENO;
+#endif
}
}
if (!dispatch_log_disabled) {
if (log_to_file && dispatch_logfile == -1) {
+#if defined(_WIN32)
+ char path[MAX_PATH + 1] = {0};
+ DWORD dwLength = GetTempPathA(MAX_PATH, path);
+ dispatch_assert(dwLength <= MAX_PATH + 1);
+ snprintf(&path[dwLength], MAX_PATH - dwLength, "libdispatch.%d.log",
+ GetCurrentProcessId());
+ dispatch_logfile = _open(path, O_WRONLY | O_APPEND | O_CREAT, 0666);
+#else
char path[PATH_MAX];
snprintf(path, sizeof(path), "/var/tmp/libdispatch.%d.log",
getpid());
dispatch_logfile = open(path, O_WRONLY | O_APPEND | O_CREAT |
O_NOFOLLOW | O_CLOEXEC, 0666);
+#endif
}
if (dispatch_logfile != -1) {
struct timeval tv;
+#if defined(_WIN32)
+ DWORD dwTime = GetTickCount();
+ tv.tv_sec = dwTime / 1000;
+ tv.tv_usec = 1000 * (dwTime % 1000);
+#else
gettimeofday(&tv, NULL);
+#endif
#if DISPATCH_DEBUG
dispatch_log_basetime = _dispatch_absolute_time();
#endif
+#if defined(_WIN32)
+ FILE *pLogFile = _fdopen(dispatch_logfile, "w");
+
+ char szProgramName[MAX_PATH + 1] = {0};
+ GetModuleFileNameA(NULL, szProgramName, MAX_PATH);
+
+ fprintf(pLogFile, "=== log file opened for %s[%lu] at "
+ "%ld.%06u ===\n", szProgramName, GetCurrentProcessId(),
+ tv.tv_sec, (int)tv.tv_usec);
+ fclose(pLogFile);
+#else
dprintf(dispatch_logfile, "=== log file opened for %s[%u] at "
"%ld.%06u ===\n", getprogname() ?: "", getpid(),
tv.tv_sec, (int)tv.tv_usec);
+#endif
}
}
}
@@ -721,7 +758,12 @@
buf[len++] = '\n';
retry:
+#if defined(_WIN32)
+ dispatch_assert(len <= UINT_MAX);
+ r = _write(dispatch_logfile, buf, (unsigned int)len);
+#else
r = write(dispatch_logfile, buf, len);
+#endif
if (slowpath(r == -1) && errno == EINTR) {
goto retry;
}
@@ -765,6 +807,36 @@
free(str);
}
}
+#elif defined(_WIN32)
+static inline void
+_dispatch_syslog(const char *msg)
+{
+ OutputDebugStringA(msg);
+}
+
+static inline void
+_dispatch_vsyslog(const char *msg, va_list ap)
+{
+ va_list argp;
+
+ va_copy(argp, ap);
+
+ int length = _vscprintf(msg, ap);
+ if (length == -1)
+ return;
+
+ char *buffer = malloc((size_t)length + 1);
+ if (buffer == NULL)
+ return;
+
+ _vsnprintf(buffer, (size_t)length + 1, msg, argp);
+
+ va_end(argp);
+
+ _dispatch_syslog(buffer);
+
+ free(buffer);
+}
#else // DISPATCH_USE_SIMPLE_ASL
static inline void
_dispatch_syslog(const char *msg)
diff --git a/src/internal.h b/src/internal.h
index 84505e5..126f4c6 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -148,9 +148,7 @@
#include <dispatch/semaphore.h>
#include <dispatch/once.h>
#include <dispatch/data.h>
-#if !TARGET_OS_WIN32
#include <dispatch/io.h>
-#endif
#if defined(__OBJC__) || defined(__cplusplus)
#define DISPATCH_PURE_C 0
@@ -159,7 +157,9 @@
#endif
/* private.h must be included last to avoid picking up installed headers. */
+#if !defined(_WIN32)
#include <pthread.h>
+#endif
#include "os/object_private.h"
#include "queue_private.h"
#include "source_private.h"
@@ -167,16 +167,14 @@
#include "data_private.h"
#include "os/voucher_private.h"
#include "os/voucher_activity_private.h"
-#if !TARGET_OS_WIN32
#include "io_private.h"
-#endif
#include "layout_private.h"
#include "benchmark.h"
#include "private.h"
/* SPI for Libsystem-internal use */
DISPATCH_EXPORT DISPATCH_NOTHROW void libdispatch_init(void);
-#if !TARGET_OS_WIN32
+#if !defined(_WIN32)
DISPATCH_EXPORT DISPATCH_NOTHROW void dispatch_atfork_prepare(void);
DISPATCH_EXPORT DISPATCH_NOTHROW void dispatch_atfork_parent(void);
DISPATCH_EXPORT DISPATCH_NOTHROW void dispatch_atfork_child(void);
@@ -244,10 +242,12 @@
#endif
#include <sys/stat.h>
-
-#if !TARGET_OS_WIN32
-#include <sys/mount.h>
#include <sys/queue.h>
+
+#if defined(_WIN32)
+#include <time.h>
+#else
+#include <sys/mount.h>
#ifdef __ANDROID__
#include <linux/sysctl.h>
#else
@@ -283,13 +283,19 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
+#if defined(_WIN32)
+#define _CRT_RAND_S
+#endif
#include <stdlib.h>
#include <string.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#endif
+#if defined(_WIN32)
+#include <io.h>
+#endif
-#if __GNUC__
+#if defined(__GNUC__) || defined(__clang__)
#define DISPATCH_NOINLINE __attribute__((__noinline__))
#define DISPATCH_USED __attribute__((__used__))
#define DISPATCH_UNUSED __attribute__((__unused__))
@@ -420,7 +426,7 @@
#endif
#endif // DISPATCH_USE_SIMPLE_ASL
-#if !DISPATCH_USE_SIMPLE_ASL && !DISPATCH_USE_OS_DEBUG_LOG && !TARGET_OS_WIN32
+#if !DISPATCH_USE_SIMPLE_ASL && !DISPATCH_USE_OS_DEBUG_LOG && !defined(_WIN32)
#include <syslog.h>
#endif
@@ -513,7 +519,7 @@
})
#else
static inline long
-_dispatch_assume(long e, long line)
+_dispatch_assume(long e, unsigned long line)
{
if (!e) _dispatch_bug(line, e);
return e;
@@ -538,7 +544,7 @@
})
#else
static inline long
-_dispatch_assume_zero(long e, long line)
+_dispatch_assume_zero(long e, unsigned long line)
{
if (e) _dispatch_bug(line, e);
return e;
@@ -604,7 +610,9 @@
const char *_dispatch_strdup_if_mutable(const char *str);
void _dispatch_vtable_init(void);
char *_dispatch_get_build(void);
+#if !defined(_WIN32)
int _dispatch_sigmask(void);
+#endif
uint64_t _dispatch_timeout(dispatch_time_t when);
uint64_t _dispatch_time_nanoseconds_since_epoch(dispatch_time_t when);
@@ -913,6 +921,18 @@
_dispatch_hardware_crash(); \
} while (0)
+#if defined(_WIN32)
+#define _dispatch_client_assert_fail(fmt, ...) do { \
+ char *_msg = NULL; \
+ int _length = _scprintf("%s" fmt, DISPATCH_ASSERTION_FAILED_MESSAGE, ##__VA_ARGS__); \
+ dispatch_assert(_length != -1); \
+ _msg = (char *)malloc((unsigned)_length + 1); \
+ dispatch_assert(_msg); \
+ _snprintf(_msg, (unsigned)_length, "%s" fmt, DISPATCH_ASSERTION_FAILED_MESSAGE, ##__VA_ARGS__); \
+ _dispatch_assert_crash(_msg); \
+ free(_msg); \
+ } while (0)
+#else
#define _dispatch_client_assert_fail(fmt, ...) do { \
char *_msg = NULL; \
asprintf(&_msg, "%s" fmt, DISPATCH_ASSERTION_FAILED_MESSAGE, \
@@ -920,6 +940,7 @@
_dispatch_assert_crash(_msg); \
free(_msg); \
} while (0)
+#endif
#define DISPATCH_NO_VOUCHER ((voucher_t)(void*)~0ul)
#define DISPATCH_NO_PRIORITY ((pthread_priority_t)~0ul)
@@ -967,9 +988,7 @@
#include "mach_internal.h"
#include "voucher_internal.h"
#include "data_internal.h"
-#if !TARGET_OS_WIN32
#include "io_internal.h"
-#endif
#include "inline_internal.h"
#include "firehose/firehose_internal.h"
diff --git a/src/introspection.c b/src/introspection.c
index 1332adf..1bb095d 100644
--- a/src/introspection.c
+++ b/src/introspection.c
@@ -137,7 +137,7 @@
_dispatch_unfair_lock_unlock(&_dispatch_introspection.threads_lock);
}
-static void
+static DISPATCH_TSD_DTOR_CC void
_dispatch_introspection_thread_remove(void *ctxt)
{
dispatch_introspection_thread_t dit = ctxt;
diff --git a/src/io.c b/src/io.c
index 6ec45d8..fbb0373 100644
--- a/src/io.c
+++ b/src/io.c
@@ -30,6 +30,15 @@
#endif
#ifndef PAGE_SIZE
+#if defined(_WIN32)
+static DWORD
+getpagesize(void)
+{
+ SYSTEM_INFO siInfo;
+ GetSystemInfo(&siInfo);
+ return siInfo.dwPageSize;
+}
+#endif
#define PAGE_SIZE ((size_t)getpagesize())
#endif
@@ -366,12 +375,23 @@
err = _dispatch_io_validate_type(channel, fd_entry->stat.mode);
}
if (!err && type == DISPATCH_IO_RANDOM) {
+#if defined(_WIN32)
+ LARGE_INTEGER liPosition;
+ LARGE_INTEGER liDistance = {};
+ if (!SetFilePointerEx((HANDLE)fd_entry->fd, liDistance, &liPosition, FILE_CURRENT)) {
+ err = (int)GetLastError();
+ } else {
+ err = 0;
+ channel->f_ptr = liPosition.QuadPart;
+ }
+#else
off_t f_ptr;
_dispatch_io_syscall_switch_noerr(err,
f_ptr = lseek(fd_entry->fd, 0, SEEK_CUR),
case 0: channel->f_ptr = f_ptr; break;
default: (void)dispatch_assume_zero(err); break;
);
+#endif
}
channel->err = err;
_dispatch_fd_entry_retain(fd_entry);
@@ -423,11 +443,15 @@
int err = 0;
struct stat st;
_dispatch_io_syscall_switch_noerr(err,
+#if defined(_WIN32)
+ stat(path_data->path, &st),
+#else
(path_data->oflag & O_NOFOLLOW) == O_NOFOLLOW
#if __APPLE__
|| (path_data->oflag & O_SYMLINK) == O_SYMLINK
#endif
? lstat(path_data->path, &st) : stat(path_data->path, &st),
+#endif
case 0:
err = _dispatch_io_validate_type(channel, st.st_mode);
break;
@@ -528,12 +552,23 @@
in_channel->fd_entry->stat.mode);
}
if (!err && type == DISPATCH_IO_RANDOM && in_channel->fd != -1) {
+#if defined(_WIN32)
+ LARGE_INTEGER liPosition;
+ LARGE_INTEGER liDistance = {};
+ if (!SetFilePointerEx((HANDLE)in_channel->fd_entry->fd, liDistance, &liPosition, FILE_CURRENT)) {
+ err = (int)GetLastError();
+ } else {
+ err = 0;
+ channel->f_ptr = liPosition.QuadPart;
+ }
+#else
off_t f_ptr;
_dispatch_io_syscall_switch_noerr(err,
f_ptr = lseek(in_channel->fd_entry->fd, 0, SEEK_CUR),
case 0: channel->f_ptr = f_ptr; break;
default: (void)dispatch_assume_zero(err); break;
);
+#endif
}
channel->err = err;
if (err) {
@@ -1075,7 +1110,11 @@
}
// For write operations, op->buf is owned by op->buf_data
if (op->buf && op->direction == DOP_DIR_READ) {
+#if defined(_WIN32)
+ _aligned_free(op->buf);
+#else
free(op->buf);
+#endif
}
if (op->buf_data) {
_dispatch_io_data_release(op->buf_data);
@@ -1226,13 +1265,15 @@
);
}
#else
+#if !defined(_WIN32)
static inline void
_dispatch_fd_entry_guard(dispatch_fd_entry_t fd_entry) { (void)fd_entry; }
+#endif
static inline void
_dispatch_fd_entry_unguard(dispatch_fd_entry_t fd_entry) { (void)fd_entry; }
#endif // DISPATCH_USE_GUARDED_FD
-static inline int
+static inline dispatch_fd_t
_dispatch_fd_entry_guarded_open(dispatch_fd_entry_t fd_entry, const char *path,
int oflag, mode_t mode) {
#if DISPATCH_USE_GUARDED_FD
@@ -1249,11 +1290,28 @@
#else
(void)fd_entry;
#endif
+#if defined(_WIN32)
+ (void)mode;
+ DWORD dwDesiredAccess = 0;
+ if (oflag & _O_RDWR)
+ dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
+ else if (oflag & _O_RDONLY)
+ dwDesiredAccess = GENERIC_READ;
+ else if (oflag & _O_WRONLY)
+ dwDesiredAccess = GENERIC_WRITE;
+ DWORD dwCreationDisposition = OPEN_EXISTING;
+ if (oflag & _O_CREAT)
+ dwCreationDisposition = OPEN_ALWAYS;
+ if (oflag & _O_TRUNC)
+ dwCreationDisposition = CREATE_ALWAYS;
+ return (dispatch_fd_t)CreateFile(path, dwDesiredAccess, 0, NULL, dwCreationDisposition, 0, NULL);
+#else
return open(path, oflag, mode);
+#endif
}
static inline int
-_dispatch_fd_entry_guarded_close(dispatch_fd_entry_t fd_entry, int fd) {
+_dispatch_fd_entry_guarded_close(dispatch_fd_entry_t fd_entry, dispatch_fd_t fd) {
#if DISPATCH_USE_GUARDED_FD
if (fd_entry->guard_flags) {
guardid_t guard = (uintptr_t)fd_entry;
@@ -1263,7 +1321,11 @@
(void)fd_entry;
#endif
{
+#if defined(_WIN32)
+ return CloseHandle((HANDLE)fd);
+#else
return close(fd);
+#endif
}
}
@@ -1337,6 +1399,24 @@
"com.apple.libdispatch-io.barrierq", NULL);
fd_entry->barrier_group = dispatch_group_create();
dispatch_async(fd_entry->barrier_queue, ^{
+#if defined(_WIN32)
+ DWORD dwType = GetFileType((HANDLE)fd);
+ if (dwType == FILE_TYPE_PIPE) {
+ unsigned long value = 1;
+ int result = ioctlsocket((SOCKET)fd, (long)FIONBIO, &value);
+ (void)dispatch_assume_zero(result);
+ _dispatch_stream_init(fd_entry,
+ _dispatch_get_root_queue(DISPATCH_QOS_DEFAULT, false));
+ } else {
+ dispatch_suspend(fd_entry->barrier_queue);
+ dispatch_once_f(&_dispatch_io_devs_lockq_pred, NULL,
+ _dispatch_io_devs_lockq_init);
+ dispatch_async(_dispatch_io_devs_lockq, ^{
+ _dispatch_disk_init(fd_entry, 0);
+ dispatch_resume(fd_entry->barrier_queue);
+ });
+ }
+#else
_dispatch_fd_entry_debug("stat", fd_entry);
int err, orig_flags, orig_nosigpipe = -1;
struct stat st;
@@ -1404,6 +1484,7 @@
}
fd_entry->orig_flags = orig_flags;
fd_entry->orig_nosigpipe = orig_nosigpipe;
+#endif
});
// This is the first item run when the close queue is resumed, indicating
// that all channels associated with this entry have been closed and that
@@ -1434,6 +1515,7 @@
dispatch_release(fd_entry->barrier_queue);
_dispatch_fd_entry_debug("barrier group release", fd_entry);
dispatch_release(fd_entry->barrier_group);
+#if !defined(_WIN32)
if (fd_entry->orig_flags != -1) {
_dispatch_io_syscall(
fcntl(fd, F_SETFL, fd_entry->orig_flags)
@@ -1446,6 +1528,7 @@
);
}
#endif
+#endif
_dispatch_fd_entry_unguard(fd_entry);
if (fd_entry->convenience_channel) {
fd_entry->convenience_channel->fd_entry = NULL;
@@ -1465,7 +1548,11 @@
path_data->channel->queue);
_dispatch_fd_entry_debug("create: path %s", fd_entry, path_data->path);
if (S_ISREG(mode)) {
+#if defined(_WIN32)
+ _dispatch_disk_init(fd_entry, 0);
+#else
_dispatch_disk_init(fd_entry, (dev_t)major(dev));
+#endif
} else {
_dispatch_stream_init(fd_entry,
_dispatch_get_root_queue(DISPATCH_QOS_DEFAULT, false));
@@ -1520,7 +1607,7 @@
if (fd_entry->err) {
return fd_entry->err;
}
- int fd = -1;
+ dispatch_fd_t fd = -1;
int oflag = fd_entry->disk ? fd_entry->path_data->oflag & ~O_NONBLOCK :
fd_entry->path_data->oflag | O_NONBLOCK;
open:
@@ -2143,6 +2230,10 @@
_dispatch_operation_advise(dispatch_operation_t op, size_t chunk_size)
{
_dispatch_op_debug("advise", op);
+#if defined(_WIN32)
+ (void)op;
+ (void)chunk_size;
+#else
if (_dispatch_io_get_error(op, NULL, true)) return;
#if defined(__linux__) || defined(__FreeBSD__)
// linux does not support fcntl (F_RDAVISE)
@@ -2186,6 +2277,7 @@
default: (void)dispatch_assume_zero(err); break;
);
#endif
+#endif
}
static int
@@ -2219,7 +2311,17 @@
} else {
op->buf_siz = max_buf_siz;
}
+#if defined(_WIN32)
+ static bool bQueried = false;
+ static SYSTEM_INFO siInfo;
+ if (!bQueried) {
+ GetNativeSystemInfo(&siInfo);
+ bQueried = true;
+ }
+ op->buf = _aligned_malloc(op->buf_siz, siInfo.dwPageSize);
+#else
op->buf = valloc(op->buf_siz);
+#endif
_dispatch_op_debug("buffer allocated", op);
} else if (op->direction == DOP_DIR_WRITE) {
// Always write the first data piece, if that is smaller than a
@@ -2257,20 +2359,51 @@
}
void *buf = op->buf + op->buf_len;
size_t len = op->buf_siz - op->buf_len;
+#if defined(_WIN32)
+ assert(len <= UINT_MAX && "overflow for read/write");
+ LONGLONG off = (LONGLONG)((size_t)op->offset + op->total);
+#else
off_t off = (off_t)((size_t)op->offset + op->total);
+#endif
+#if defined(_WIN32)
+ long processed = -1;
+#else
ssize_t processed = -1;
+#endif
syscall:
if (op->direction == DOP_DIR_READ) {
if (op->params.type == DISPATCH_IO_STREAM) {
+#if defined(_WIN32)
+ ReadFile((HANDLE)op->fd_entry->fd, buf, (DWORD)len, (LPDWORD)&processed, NULL);
+#else
processed = read(op->fd_entry->fd, buf, len);
+#endif
} else if (op->params.type == DISPATCH_IO_RANDOM) {
+#if defined(_WIN32)
+ OVERLAPPED ovlOverlapped = {};
+ ovlOverlapped.Offset = off & 0xffffffff;
+ ovlOverlapped.OffsetHigh = (off >> 32) & 0xffffffff;
+ ReadFile((HANDLE)op->fd_entry->fd, buf, (DWORD)len, (LPDWORD)&processed, &ovlOverlapped);
+#else
processed = pread(op->fd_entry->fd, buf, len, off);
+#endif
}
} else if (op->direction == DOP_DIR_WRITE) {
if (op->params.type == DISPATCH_IO_STREAM) {
+#if defined(_WIN32)
+ WriteFile((HANDLE)op->fd_entry->fd, buf, (DWORD)len, (LPDWORD)&processed, NULL);
+#else
processed = write(op->fd_entry->fd, buf, len);
+#endif
} else if (op->params.type == DISPATCH_IO_RANDOM) {
+#if defined(_WIN32)
+ OVERLAPPED ovlOverlapped = {};
+ ovlOverlapped.Offset = off & 0xffffffff;
+ ovlOverlapped.OffsetHigh = (off >> 32) & 0xffffffff;
+ WriteFile((HANDLE)op->fd_entry->fd, buf, (DWORD)len, (LPDWORD)&processed, &ovlOverlapped);
+#else
processed = pwrite(op->fd_entry->fd, buf, len, off);
+#endif
}
}
// Encountered an error on the file descriptor
diff --git a/src/io_internal.h b/src/io_internal.h
index 672727f..d70e075 100644
--- a/src/io_internal.h
+++ b/src/io_internal.h
@@ -145,7 +145,11 @@
dispatch_queue_t op_q;
dispatch_op_direction_t direction; // READ OR WRITE
dispatch_io_param_s params;
+#if defined(_WIN32)
+ LONGLONG offset;
+#else
off_t offset;
+#endif
size_t length;
int err;
dispatch_io_handler_t handler;
@@ -172,7 +176,11 @@
dispatch_fd_entry_t fd_entry;
unsigned int atomic_flags;
dispatch_fd_t fd, fd_actual;
+#if defined(_WIN32)
+ LONGLONG f_ptr;
+#else
off_t f_ptr;
+#endif
int err; // contains creation errors only
};
diff --git a/src/object_internal.h b/src/object_internal.h
index 94cb463..0156503 100644
--- a/src/object_internal.h
+++ b/src/object_internal.h
@@ -340,7 +340,7 @@
#define _DISPATCH_INVOKE_AUTORELEASE_MASK 0x00300000u
);
-enum {
+DISPATCH_ENUM(dispatch_object_flags, unsigned long,
_DISPATCH_META_TYPE_MASK = 0xffff0000, // mask for object meta-types
_DISPATCH_TYPEFLAGS_MASK = 0x0000ff00, // mask for object typeflags
_DISPATCH_SUB_TYPE_MASK = 0x000000ff, // mask for object sub-types
@@ -386,8 +386,7 @@
DISPATCH_SOURCE_KEVENT_TYPE = 1 | _DISPATCH_SOURCE_TYPE,
DISPATCH_MACH_CHANNEL_TYPE = 2 | _DISPATCH_SOURCE_TYPE,
-
-};
+);
typedef struct _os_object_vtable_s {
_OS_OBJECT_CLASS_HEADER();
diff --git a/src/queue.c b/src/queue.c
index d747a59..896ed21 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -58,13 +58,13 @@
#endif
static void _dispatch_sig_thread(void *ctxt);
-static void _dispatch_cache_cleanup(void *value);
+static void DISPATCH_TSD_DTOR_CC _dispatch_cache_cleanup(void *value);
static void _dispatch_async_f2(dispatch_queue_t dq, dispatch_continuation_t dc);
-static void _dispatch_queue_cleanup(void *ctxt);
-static void _dispatch_wlh_cleanup(void *ctxt);
-static void _dispatch_deferred_items_cleanup(void *ctxt);
-static void _dispatch_frame_cleanup(void *ctxt);
-static void _dispatch_context_cleanup(void *ctxt);
+static void DISPATCH_TSD_DTOR_CC _dispatch_queue_cleanup(void *ctxt);
+static void DISPATCH_TSD_DTOR_CC _dispatch_wlh_cleanup(void *ctxt);
+static void DISPATCH_TSD_DTOR_CC _dispatch_deferred_items_cleanup(void *ctxt);
+static void DISPATCH_TSD_DTOR_CC _dispatch_frame_cleanup(void *ctxt);
+static void DISPATCH_TSD_DTOR_CC _dispatch_context_cleanup(void *ctxt);
static void _dispatch_queue_barrier_complete(dispatch_queue_t dq,
dispatch_qos_t qos, dispatch_wakeup_flags_t flags);
static void _dispatch_queue_non_barrier_complete(dispatch_queue_t dq);
@@ -87,6 +87,10 @@
#endif
#if DISPATCH_USE_PTHREAD_POOL
static void *_dispatch_worker_thread(void *context);
+#if defined(_WIN32)
+static unsigned WINAPI
+_dispatch_worker_thread_thunk(LPVOID lpParameter);
+#endif
#endif
#if DISPATCH_COCOA_COMPAT
@@ -101,7 +105,9 @@
#pragma mark dispatch_root_queue
struct dispatch_pthread_root_queue_context_s {
+#if !defined(_WIN32)
pthread_attr_t dpq_thread_attr;
+#endif
dispatch_block_t dpq_thread_configure;
struct dispatch_semaphore_s dpq_thread_mediator;
dispatch_pthread_root_queue_observer_hooks_s dpq_observer_hooks;
@@ -763,9 +769,11 @@
qc->dgq_thread_pool_size = thread_pool_size;
#if DISPATCH_USE_WORKQUEUES
if (qc->dgq_qos) {
+#if !defined(_WIN32)
(void)dispatch_assume_zero(pthread_attr_init(&pqc->dpq_thread_attr));
(void)dispatch_assume_zero(pthread_attr_setdetachstate(
&pqc->dpq_thread_attr, PTHREAD_CREATE_DETACHED));
+#endif
#if HAVE_PTHREAD_WORKQUEUE_QOS
(void)dispatch_assume_zero(pthread_attr_set_qos_class_np(
&pqc->dpq_thread_attr, qc->dgq_qos, 0));
@@ -906,7 +914,9 @@
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#endif
+#if !defined(_WIN32)
#include <sys/syscall.h>
+#endif
#ifndef __ANDROID__
#ifdef SYS_gettid
@@ -923,6 +933,13 @@
{
return (pid_t)pthread_getthreadid_np();
}
+#elif defined(_WIN32)
+DISPATCH_ALWAYS_INLINE
+static inline DWORD
+gettid(void)
+{
+ return GetCurrentThreadId();
+}
#else
#error "SYS_gettid unavailable on this system"
#endif /* SYS_gettid */
@@ -944,7 +961,7 @@
}
#endif
-void
+void DISPATCH_TSD_DTOR_CC
_libdispatch_tsd_cleanup(void *ctx)
{
struct dispatch_tsd *tsd = (struct dispatch_tsd*) ctx;
@@ -980,7 +997,11 @@
void
libdispatch_tsd_init(void)
{
+#if defined(_WIN32)
+ FlsSetValue(__dispatch_tsd_key, &__dispatch_tsd);
+#else
pthread_setspecific(__dispatch_tsd_key, &__dispatch_tsd);
+#endif /* defined(_WIN32) */
__dispatch_tsd.tid = gettid();
}
#endif
@@ -1164,8 +1185,6 @@
case DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM:
case DISPATCH_AUTORELEASE_FREQUENCY_NEVER:
break;
- default:
- return DISPATCH_BAD_INPUT;
}
if (!slowpath(dqa)) {
dqa = _dispatch_get_default_queue_attr();
@@ -2035,7 +2054,11 @@
volatile qos_class_t qos;
int default_prio;
int policy;
+#if defined(_WIN32)
+ HANDLE hThread;
+#else
pthread_t tid;
+#endif
} _dispatch_mgr_sched;
static dispatch_once_t _dispatch_mgr_sched_pred;
@@ -2053,6 +2076,15 @@
};
#endif // HAVE_PTHREAD_WORKQUEUE_QOS
+#if defined(_WIN32)
+static void
+_dispatch_mgr_sched_init(void *ctx DISPATCH_UNUSED)
+{
+ _dispatch_mgr_sched.policy = 0;
+ _dispatch_mgr_sched.default_prio = THREAD_PRIORITY_NORMAL;
+ _dispatch_mgr_sched.prio = _dispatch_mgr_sched.default_prio;
+}
+#else
static void
_dispatch_mgr_sched_init(void *ctxt DISPATCH_UNUSED)
{
@@ -2080,9 +2112,19 @@
_dispatch_mgr_sched.default_prio = param.sched_priority;
_dispatch_mgr_sched.prio = _dispatch_mgr_sched.default_prio;
}
+#endif /* defined(_WIN32) */
#endif // DISPATCH_ENABLE_PTHREAD_ROOT_QUEUES || DISPATCH_USE_KEVENT_WORKQUEUE
#if DISPATCH_USE_MGR_THREAD && DISPATCH_ENABLE_PTHREAD_ROOT_QUEUES
+#if defined(_WIN32)
+DISPATCH_NOINLINE
+static PHANDLE
+_dispatch_mgr_root_queue_init(void)
+{
+ dispatch_once_f(&_dispatch_mgr_sched_pred, NULL, _dispatch_mgr_sched_init);
+ return &_dispatch_mgr_sched.hThread;
+}
+#else
DISPATCH_NOINLINE
static pthread_t *
_dispatch_mgr_root_queue_init(void)
@@ -2111,10 +2153,21 @@
}
return &_dispatch_mgr_sched.tid;
}
+#endif
static inline void
_dispatch_mgr_priority_apply(void)
{
+#if defined(_WIN32)
+ int nPriority = _dispatch_mgr_sched.prio;
+ do {
+ if (nPriority > _dispatch_mgr_sched.default_prio) {
+ // TODO(compnerd) set thread scheduling policy
+ dispatch_assume_zero(SetThreadPriority(_dispatch_mgr_sched.hThread, nPriority));
+ nPriority = GetThreadPriority(_dispatch_mgr_sched.hThread);
+ }
+ } while (_dispatch_mgr_sched.prio > nPriority);
+#else
struct sched_param param;
do {
param.sched_priority = _dispatch_mgr_sched.prio;
@@ -2124,12 +2177,19 @@
¶m));
}
} while (_dispatch_mgr_sched.prio > param.sched_priority);
+#endif
}
DISPATCH_NOINLINE
void
_dispatch_mgr_priority_init(void)
{
+#if defined(_WIN32)
+ int nPriority = GetThreadPriority(_dispatch_mgr_sched.hThread);
+ if (slowpath(_dispatch_mgr_sched.prio > nPriority)) {
+ return _dispatch_mgr_priority_apply();
+ }
+#else
struct sched_param param;
pthread_attr_t *attr;
attr = &_dispatch_mgr_root_queue_pthread_context.dpq_thread_attr;
@@ -2148,9 +2208,11 @@
if (slowpath(_dispatch_mgr_sched.prio > param.sched_priority)) {
return _dispatch_mgr_priority_apply();
}
+#endif
}
#endif // DISPATCH_USE_MGR_THREAD && DISPATCH_ENABLE_PTHREAD_ROOT_QUEUES
+#if !defined(_WIN32)
#if DISPATCH_ENABLE_PTHREAD_ROOT_QUEUES
DISPATCH_NOINLINE
static void
@@ -2202,6 +2264,7 @@
#endif
}
#endif // DISPATCH_ENABLE_PTHREAD_ROOT_QUEUES
+#endif
#if DISPATCH_USE_KEVENT_WORKQUEUE
void
@@ -2274,6 +2337,9 @@
#endif
_dispatch_root_queue_init_pthread_pool(qc, pool_size, true);
+#if defined(_WIN32)
+ dispatch_assert(attr == NULL);
+#else
if (attr) {
memcpy(&pqc->dpq_thread_attr, attr, sizeof(pthread_attr_t));
_dispatch_mgr_priority_raise(&pqc->dpq_thread_attr);
@@ -2282,6 +2348,7 @@
}
(void)dispatch_assume_zero(pthread_attr_setdetachstate(
&pqc->dpq_thread_attr, PTHREAD_CREATE_DETACHED));
+#endif
if (configure) {
pqc->dpq_thread_configure = _dispatch_Block_copy(configure);
}
@@ -2296,6 +2363,9 @@
dispatch_pthread_root_queue_create(const char *label, unsigned long flags,
const pthread_attr_t *attr, dispatch_block_t configure)
{
+#if defined(_WIN32)
+ dispatch_assert(attr == NULL);
+#endif
return _dispatch_pthread_root_queue_create(label, flags, attr, configure,
NULL);
}
@@ -2345,7 +2415,9 @@
dispatch_root_queue_context_t qc = dq->do_ctxt;
dispatch_pthread_root_queue_context_t pqc = qc->dgq_ctxt;
+#if !defined(_WIN32)
pthread_attr_destroy(&pqc->dpq_thread_attr);
+#endif
_dispatch_semaphore_dispose(&pqc->dpq_thread_mediator, NULL);
if (pqc->dpq_thread_configure) {
Block_release(pqc->dpq_thread_configure);
@@ -2773,7 +2845,7 @@
}
DISPATCH_NOINLINE
-static void
+static void DISPATCH_TSD_DTOR_CC
_dispatch_cache_cleanup(void *value)
{
dispatch_continuation_t dc, next_dc = value;
@@ -4399,7 +4471,6 @@
#error "runloop support not implemented on this platform"
#endif
}
-#endif // DISPATCH_COCOA_COMPAT
DISPATCH_ALWAYS_INLINE
static inline dispatch_qos_t
@@ -4410,6 +4481,7 @@
old_state = os_atomic_and_orig2o(dqu._dq, dq_state, ~clear_bits, relaxed);
return _dq_state_max_qos(old_state);
}
+#endif // DISPATCH_COCOA_COMPAT
void
_dispatch_runloop_queue_wakeup(dispatch_queue_t dq, dispatch_qos_t qos,
@@ -4615,6 +4687,32 @@
} while (!os_atomic_cmpxchgvw2o(qc, dgq_thread_pool_size, t_count,
t_count - remaining, &t_count, acquire));
+#if defined(_WIN32)
+#if DISPATCH_USE_MGR_THREAD && DISPATCH_ENABLE_PTHREAD_ROOT_QUEUES
+ if (slowpath(dq == &_dispatch_mgr_root_queue)) {
+ _dispatch_mgr_root_queue_init();
+ }
+#endif
+ do {
+ _dispatch_retain(dq); // released in _dispatch_worker_thread
+#if DISPATCH_DEBUG
+ unsigned dwStackSize = 0;
+#else
+ unsigned dwStackSize = 64 * 1024;
+#endif
+ uintptr_t hThread = 0;
+ while (!(hThread = _beginthreadex(NULL, dwStackSize, _dispatch_worker_thread_thunk, dq, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL))) {
+ if (errno != EAGAIN) {
+ (void)dispatch_assume(hThread);
+ }
+ _dispatch_temporary_resource_shortage();
+ }
+ if (_dispatch_mgr_sched.prio > _dispatch_mgr_sched.default_prio) {
+ (void)dispatch_assume_zero(SetThreadPriority((HANDLE)hThread, _dispatch_mgr_sched.prio) == TRUE);
+ }
+ CloseHandle((HANDLE)hThread);
+ } while (--remaining);
+#else
pthread_attr_t *attr = &pqc->dpq_thread_attr;
pthread_t tid, *pthr = &tid;
#if DISPATCH_USE_MGR_THREAD && DISPATCH_ENABLE_PTHREAD_ROOT_QUEUES
@@ -4631,6 +4729,7 @@
_dispatch_temporary_resource_shortage();
}
} while (--remaining);
+#endif
#endif // DISPATCH_USE_PTHREAD_POOL
}
@@ -5951,6 +6050,15 @@
#if DISPATCH_USE_PTHREAD_POOL
// 6618342 Contact the team that owns the Instrument DTrace probe before
// renaming this symbol
+#if defined(_WIN32)
+static unsigned WINAPI
+_dispatch_worker_thread_thunk(LPVOID lpParameter)
+{
+ _dispatch_worker_thread(lpParameter);
+ return 0;
+}
+#endif
+
static void *
_dispatch_worker_thread(void *context)
{
@@ -5972,7 +6080,9 @@
}
// workaround tweaks the kernel workqueue does for us
+#if !defined(_WIN32)
_dispatch_sigmask();
+#endif
_dispatch_introspection_thread_add();
#if DISPATCH_USE_INTERNAL_WORKQUEUE
@@ -6248,7 +6358,11 @@
pthread_setspecific(dispatch_main_key, &dispatch_main_key);
_dispatch_sigmask();
#endif
+#if defined(_WIN32)
+ _endthreadex(0);
+#else
pthread_exit(NULL);
+#endif
DISPATCH_INTERNAL_CRASH(errno, "pthread_exit() returned");
#if HAVE_PTHREAD_MAIN_NP
}
@@ -6256,6 +6370,7 @@
#endif
}
+#if !defined(_WIN32)
DISPATCH_NOINLINE DISPATCH_NORETURN
static void
_dispatch_sigsuspend(void)
@@ -6266,6 +6381,7 @@
sigsuspend(&mask);
}
}
+#endif
DISPATCH_NORETURN
static void
@@ -6273,7 +6389,9 @@
{
// never returns, so burn bridges behind us
_dispatch_clear_stack(0);
+#if !defined(_WIN32)
_dispatch_sigsuspend();
+#endif
}
DISPATCH_NOINLINE
@@ -6320,7 +6438,7 @@
#endif
}
-static void
+static void DISPATCH_TSD_DTOR_CC
_dispatch_queue_cleanup(void *ctxt)
{
if (ctxt == &_dispatch_main_q) {
@@ -6331,7 +6449,7 @@
"Premature thread exit while a dispatch queue is running");
}
-static void
+static void DISPATCH_TSD_DTOR_CC
_dispatch_wlh_cleanup(void *ctxt)
{
// POSIX defines that destructors are only called if 'ctxt' is non-null
@@ -6341,7 +6459,7 @@
}
DISPATCH_NORETURN
-static void
+static void DISPATCH_TSD_DTOR_CC
_dispatch_deferred_items_cleanup(void *ctxt)
{
// POSIX defines that destructors are only called if 'ctxt' is non-null
@@ -6350,7 +6468,7 @@
}
DISPATCH_NORETURN
-static void
+static DISPATCH_TSD_DTOR_CC void
_dispatch_frame_cleanup(void *ctxt)
{
// POSIX defines that destructors are only called if 'ctxt' is non-null
@@ -6359,7 +6477,7 @@
}
DISPATCH_NORETURN
-static void
+static void DISPATCH_TSD_DTOR_CC
_dispatch_context_cleanup(void *ctxt)
{
// POSIX defines that destructors are only called if 'ctxt' is non-null
diff --git a/src/shims.h b/src/shims.h
index 4a78bfc..278b6ce 100644
--- a/src/shims.h
+++ b/src/shims.h
@@ -27,8 +27,12 @@
#ifndef __DISPATCH_OS_SHIMS__
#define __DISPATCH_OS_SHIMS__
+#if !defined(_WIN32)
#include <pthread.h>
-#if defined(__linux__) || defined(__FreeBSD__)
+#endif
+#if defined(_WIN32)
+#include "shims/generic_win_stubs.h"
+#elif defined(__unix__)
#include "shims/generic_unix_stubs.h"
#endif
@@ -74,12 +78,6 @@
#endif // HAVE_STRLCPY
-
-#if TARGET_OS_WIN32
-#define bzero(ptr,len) memset((ptr), 0, (len))
-#define snprintf _snprintf
-#endif // TARGET_OS_WIN32
-
#if PTHREAD_WORKQUEUE_SPI_VERSION < 20140716
static inline int
_pthread_workqueue_override_start_direct(mach_port_t thread,
diff --git a/src/shims/atomic.h b/src/shims/atomic.h
index 60f2891..1cb0940 100644
--- a/src/shims/atomic.h
+++ b/src/shims/atomic.h
@@ -32,7 +32,7 @@
#endif
// FreeBSD only defines _Bool in C mode. In C++ mode _Bool is not being defined.
-#if defined(__cplusplus) && defined(__FreeBSD__)
+#if defined(__cplusplus) && (defined(__FreeBSD__) || defined(_WIN32))
#define _Bool bool
#endif
#include <stdatomic.h>
diff --git a/src/shims/generic_win_stubs.c b/src/shims/generic_win_stubs.c
new file mode 100644
index 0000000..f6984a2
--- /dev/null
+++ b/src/shims/generic_win_stubs.c
@@ -0,0 +1,4 @@
+
+/*
+ * Stubbed out static data
+ */
diff --git a/src/shims/generic_win_stubs.h b/src/shims/generic_win_stubs.h
new file mode 100644
index 0000000..d7a6f21
--- /dev/null
+++ b/src/shims/generic_win_stubs.h
@@ -0,0 +1,50 @@
+
+#ifndef __DISPATCH__STUBS__INTERNAL
+#define __DISPATCH__STUBS__INTERNAL
+
+#include <stdint.h>
+
+#include <Windows.h>
+
+#include <io.h>
+#include <process.h>
+
+/*
+ * Stub out defines for some mach types and related macros
+ */
+
+typedef uint32_t mach_port_t;
+
+#define MACH_PORT_NULL (0)
+
+typedef uint32_t mach_msg_bits_t;
+typedef void *mach_msg_header_t;
+
+/*
+ * Stub out defines for other missing types
+ */
+
+// SIZE_T_MAX should not be hardcoded like this here.
+#ifndef SIZE_T_MAX
+#define SIZE_T_MAX (~(size_t)0)
+#endif
+
+typedef __typeof__(_Generic((__SIZE_TYPE__)0, \
+ unsigned long long int : (long long int)0, \
+ unsigned long int : (long int)0, \
+ unsigned int : (int)0, \
+ unsigned short : (short)0, \
+ unsigned char : (signed char)0)) ssize_t;
+
+#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#define S_ISFIFO(mode) ((mode) & _S_IFIFO)
+#define S_ISREG(mode) ((mode) & _S_IFREG)
+#define S_ISSOCK(mode) 0
+
+#define O_NONBLOCK 04000
+
+#define bzero(ptr,len) memset((ptr), 0, (len))
+#define snprintf _snprintf
+
+#endif
+
diff --git a/src/shims/hw_config.h b/src/shims/hw_config.h
index 485dad6..e788727 100644
--- a/src/shims/hw_config.h
+++ b/src/shims/hw_config.h
@@ -43,8 +43,6 @@
#error "could not determine pointer size as a constant int"
#endif // __SIZEOF_POINTER__
-#if !TARGET_OS_WIN32
-
typedef enum {
_dispatch_hw_config_logical_cpus,
_dispatch_hw_config_physical_cpus,
@@ -115,6 +113,64 @@
return (uint32_t)sysconf(_SC_NPROCESSORS_ONLN);
}
}
+#elif defined(_WIN32)
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION slpiInfo = NULL;
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION slpiCurrent = NULL;
+ DWORD dwProcessorLogicalCount = 0;
+ DWORD dwProcessorPackageCount = 0;
+ DWORD dwProcessorCoreCount = 0;
+ DWORD dwSize = 0;
+
+ while (true) {
+ DWORD dwResult;
+
+ if (GetLogicalProcessorInformation(slpiInfo, &dwSize))
+ break;
+
+ dwResult = GetLastError();
+
+ if (slpiInfo)
+ free(slpiInfo);
+
+ if (dwResult == ERROR_INSUFFICIENT_BUFFER) {
+ slpiInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(dwSize);
+ dispatch_assert(slpiInfo);
+ } else {
+ slpiInfo = NULL;
+ dwSize = 0;
+ break;
+ }
+ }
+
+ for (slpiCurrent = slpiInfo;
+ dwSize >= sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
+ slpiCurrent++, dwSize -= sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)) {
+ switch (slpiCurrent->Relationship) {
+ case RelationProcessorCore:
+ ++dwProcessorCoreCount;
+ dwProcessorLogicalCount += __popcnt64(slpiCurrent->ProcessorMask);
+ break;
+ case RelationProcessorPackage:
+ ++dwProcessorPackageCount;
+ break;
+ case RelationNumaNode:
+ case RelationCache:
+ case RelationGroup:
+ case RelationAll:
+ break;
+ }
+ }
+
+ free(slpiInfo);
+
+ switch (c) {
+ case _dispatch_hw_config_logical_cpus:
+ return dwProcessorLogicalCount;
+ case _dispatch_hw_config_physical_cpus:
+ return dwProcessorPackageCount;
+ case _dispatch_hw_config_active_cpus:
+ return dwProcessorCoreCount;
+ }
#else
const char *name = NULL;
int r;
@@ -160,31 +216,4 @@
#endif // DISPATCH_HAVE_HW_CONFIG_COMMPAGE
-#else // TARGET_OS_WIN32
-
-static inline long
-_dispatch_count_bits(unsigned long value)
-{
- long bits = 0;
- while (value) {
- bits += (value & 1);
- value = value >> 1;
- }
- return bits;
-}
-
-static inline uint32_t
-_dispatch_get_ncpus(void)
-{
- uint32_t val;
- DWORD_PTR procmask, sysmask;
- if (GetProcessAffinityMask(GetCurrentProcess(), &procmask, &sysmask)) {
- val = _dispatch_count_bits(procmask);
- } else {
- val = 1;
- }
- return val;
-}
-#endif // TARGET_OS_WIN32
-
#endif /* __DISPATCH_SHIMS_HW_CONFIG__ */
diff --git a/src/shims/lock.c b/src/shims/lock.c
index bc55450..27b0c10 100644
--- a/src/shims/lock.c
+++ b/src/shims/lock.c
@@ -51,6 +51,21 @@
#endif // HAVE_UL_UNFAIR_LOCK
#endif
+#if defined(_WIN32)
+#if !HAVE_UL_UNFAIR_LOCK
+DISPATCH_ALWAYS_INLINE
+static inline void
+_dispatch_thread_switch(dispatch_lock value, dispatch_lock_options_t flags,
+ uint32_t timeout)
+{
+ (void)value;
+ (void)flags;
+ (void)timeout;
+ SwitchToThread();
+}
+#endif
+#endif
+
#pragma mark - semaphores
#if USE_MACH_SEM
@@ -230,9 +245,7 @@
// aim for the best resolution we can accomplish
dispatch_once(&once, ^{
TIMECAPS tc;
- MMRESULT res;
- res = timeGetDevCaps(&tc, sizeof(tc));
- if (res == MMSYSERR_NOERROR) {
+ if (timeGetDevCaps(&tc, sizeof(tc)) == MMSYSERR_NOERROR) {
best_resolution = min(max(tc.wPeriodMin, best_resolution),
tc.wPeriodMax);
}
@@ -302,7 +315,7 @@
nsec = _dispatch_timeout(timeout);
msec = (DWORD)(nsec / (uint64_t)1000000);
resolution = _push_timer_resolution(msec);
- wait_result = WaitForSingleObject(dsema->dsema_handle, msec);
+ wait_result = WaitForSingleObject(sema, msec);
_pop_timer_resolution(resolution);
return wait_result == WAIT_TIMEOUT;
}
@@ -440,6 +453,8 @@
_dispatch_ulock_wait((uint32_t *)address, value, 0, flags);
#elif HAVE_FUTEX
_dispatch_futex_wait((uint32_t *)address, value, NULL, FUTEX_PRIVATE_FLAG);
+#elif defined(_WIN32)
+ WaitOnAddress(address, (PVOID)(uintptr_t)value, sizeof(value), INFINITE);
#else
mach_msg_timeout_t timeout = 1;
while (os_atomic_load(address, relaxed) == value) {
@@ -456,6 +471,8 @@
_dispatch_ulock_wake((uint32_t *)address, ULF_WAKE_ALL);
#elif HAVE_FUTEX
_dispatch_futex_wake((uint32_t *)address, INT_MAX, FUTEX_PRIVATE_FLAG);
+#elif defined(_WIN32)
+ WakeByAddressAll((uint32_t *)address);
#else
(void)address;
#endif
@@ -545,11 +562,11 @@
_dispatch_unfair_lock_lock_slow(dispatch_unfair_lock_t dul,
dispatch_lock_options_t flags)
{
- dispatch_lock cur, value_self = _dispatch_lock_value_for_self();
+ dispatch_lock cur, self = _dispatch_lock_value_for_self();
uint32_t timeout = 1;
while (unlikely(!os_atomic_cmpxchgv(&dul->dul_lock,
- DLOCK_OWNER_NULL, value_self, &cur, acquire))) {
+ DLOCK_OWNER_NULL, self, &cur, acquire))) {
if (unlikely(_dispatch_lock_is_locked_by(cur, self))) {
DISPATCH_CLIENT_CRASH(0, "trying to lock recursively");
}
diff --git a/src/shims/lock.h b/src/shims/lock.h
index 37a3ecf..4a9bd78 100644
--- a/src/shims/lock.h
+++ b/src/shims/lock.h
@@ -79,6 +79,27 @@
return lock_value & DLOCK_OWNER_MASK;
}
+#elif defined(_WIN32)
+
+#include <Windows.h>
+
+typedef DWORD dispatch_tid;
+typedef uint32_t dispatch_lock;
+
+#define DLOCK_OWNER_NULL ((dispatch_tid)0)
+#define DLOCK_OWNER_MASK ((dispatch_lock)0xfffffffc)
+#define DLOCK_WAITERS_BIT ((dispatch_lock)0x00000001)
+#define DLOCK_FAILED_TRYLOCK_BIT ((dispatch_lock)0x00000002)
+
+#define _dispatch_tid_self() ((dispatch_tid)(_dispatch_get_tsd_base()->tid << 2))
+
+DISPATCH_ALWAYS_INLINE
+static inline dispatch_tid
+_dispatch_lock_owner(dispatch_lock lock_value)
+{
+ return lock_value & DLOCK_OWNER_MASK;
+}
+
#else
# error define _dispatch_lock encoding scheme for your platform here
#endif
diff --git a/src/shims/time.h b/src/shims/time.h
index 6cc5a16..2e27605 100644
--- a/src/shims/time.h
+++ b/src/shims/time.h
@@ -31,7 +31,7 @@
#error "Please #include <dispatch/dispatch.h> instead of this file directly."
#endif
-#if TARGET_OS_WIN32
+#if defined(_WIN32)
static inline unsigned int
sleep(unsigned int seconds)
{
@@ -106,7 +106,7 @@
struct timespec ts;
dispatch_assume_zero(clock_gettime(CLOCK_REALTIME, &ts));
return _dispatch_timespec_to_nano(ts);
-#elif TARGET_OS_WIN32
+#elif defined(_WIN32)
// FILETIME is 100-nanosecond intervals since January 1, 1601 (UTC).
FILETIME ft;
ULARGE_INTEGER li;
@@ -147,9 +147,12 @@
struct timespec ts;
dispatch_assume_zero(clock_gettime(CLOCK_MONOTONIC, &ts));
return _dispatch_timespec_to_nano(ts);
-#elif TARGET_OS_WIN32
- LARGE_INTEGER now;
- return QueryPerformanceCounter(&now) ? now.QuadPart : 0;
+#elif defined(_WIN32)
+ ULONGLONG ullTime;
+ if (!QueryUnbiasedInterruptTime(&ullTime))
+ return 0;
+
+ return ullTime * 100ull;
#else
#error platform needs to implement _dispatch_absolute_time()
#endif
diff --git a/src/shims/tsd.h b/src/shims/tsd.h
index c119e4f..7271f45 100644
--- a/src/shims/tsd.h
+++ b/src/shims/tsd.h
@@ -69,6 +69,7 @@
#define __TSD_MACH_SPECIAL_REPLY 8
#endif
+
static const unsigned long dispatch_priority_key = __TSD_THREAD_QOS_CLASS;
static const unsigned long dispatch_r2k_key = __TSD_RETURN_TO_KERNEL;
@@ -99,15 +100,44 @@
}
#elif DISPATCH_USE_THREAD_LOCAL_STORAGE
+#if defined(_WIN32)
+#define DISPATCH_TSD_DTOR_CC __stdcall
+#else
+#define DISPATCH_TSD_DTOR_CC
+#endif
+
+#if defined(_WIN32)
+
DISPATCH_TSD_INLINE
static inline void
-_dispatch_thread_key_create(pthread_key_t *k, void (*d)(void *))
+_dispatch_thread_key_create(DWORD *k, void (DISPATCH_TSD_DTOR_CC *d)(void *))
+{
+ dispatch_assert_zero((*k = FlsAlloc(d)));
+}
+
+extern __declspec(thread) struct dispatch_tsd __dispatch_tsd;
+extern DWORD __dispatch_tsd_key;
+
+#else
+
+DISPATCH_TSD_INLINE
+static inline void
+_dispatch_thread_key_create(pthread_key_t *k, void (DISPATCH_TSD_DTOR_CC *d)(void *))
{
dispatch_assert_zero(pthread_key_create(k, d));
}
+extern __thread struct dispatch_tsd __dispatch_tsd;
+extern pthread_key_t __dispatch_tsd_key;
+
+#endif
+
struct dispatch_tsd {
+#if defined(_WIN32)
+ DWORD tid;
+#else
pid_t tid;
+#endif
void *dispatch_queue_key;
void *dispatch_frame_key;
void *dispatch_cache_key;
@@ -126,8 +156,6 @@
void *dispatch_deferred_items_key;
};
-extern __thread struct dispatch_tsd __dispatch_tsd;
-extern pthread_key_t __dispatch_tsd_key;
extern void libdispatch_tsd_init(void);
extern void _libdispatch_tsd_cleanup(void *ctx);
@@ -285,7 +313,7 @@
}
#endif
-#if TARGET_OS_WIN32
+#if defined(_WIN32)
#define _dispatch_thread_self() ((uintptr_t)GetCurrentThreadId())
#else
#if DISPATCH_USE_DIRECT_TSD
@@ -296,7 +324,7 @@
#endif
#endif
-#if TARGET_OS_WIN32
+#if defined(_WIN32)
#define _dispatch_thread_port() ((mach_port_t)0)
#elif !DISPATCH_USE_THREAD_LOCAL_STORAGE
#if DISPATCH_USE_DIRECT_TSD
diff --git a/src/shims/yield.h b/src/shims/yield.h
index 99864af..2373e50 100644
--- a/src/shims/yield.h
+++ b/src/shims/yield.h
@@ -83,6 +83,11 @@
#define _dispatch_contention_spins() \
((DISPATCH_CONTENTION_SPINS_MIN) + ((DISPATCH_CONTENTION_SPINS_MAX) - \
(DISPATCH_CONTENTION_SPINS_MIN)) / 2)
+#elif defined(_WIN32)
+#define _dispatch_contention_spins() ({ \
+ unsigned int _value; \
+ rand_s(&_value); \
+ (_value & DISPATCH_CONTENTION_SPINS_MAX) | DISPATCH_CONTENTION_SPINS_MIN; })
#else
// Use randomness to prevent threads from resonating at the same
// frequency and permanently contending. All threads sharing the same
@@ -151,7 +156,24 @@
SWITCH_OPTION_WAIT, (((u)-1)/1000)+1)
#endif
#else
+#if defined(_WIN32)
+DISPATCH_INLINE void
+_dispatch_contention_usleep(uint64_t useconds) {
+ static BOOL bQPFExecuted = FALSE;
+ static LARGE_INTEGER liFreq;
+ LARGE_INTEGER liStart, liNow;
+
+ if (!bQPFExecuted)
+ bQPFExecuted = QueryPerformanceFrequency(&liFreq);
+
+ QueryPerformanceCounter(&liStart);
+ do {
+ QueryPerformanceCounter(&liNow);
+ } while ((liNow.QuadPart - liStart.QuadPart) / (float)liFreq.QuadPart * 1000 * 1000 < useconds);
+}
+#else
#define _dispatch_contention_usleep(u) usleep((u))
+#endif
#endif // HAVE_MACH
#endif // __DISPATCH_SHIMS_YIELD__
diff --git a/src/swift/Block.swift b/src/swift/Block.swift
index e27079a..bf2cee1 100644
--- a/src/swift/Block.swift
+++ b/src/swift/Block.swift
@@ -19,23 +19,23 @@
public static let barrier = DispatchWorkItemFlags(rawValue: 0x1)
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public static let detached = DispatchWorkItemFlags(rawValue: 0x2)
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public static let assignCurrentContext = DispatchWorkItemFlags(rawValue: 0x4)
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public static let noQoS = DispatchWorkItemFlags(rawValue: 0x8)
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public static let inheritQoS = DispatchWorkItemFlags(rawValue: 0x10)
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public static let enforceQoS = DispatchWorkItemFlags(rawValue: 0x20)
}
-@available(OSX 10.10, iOS 8.0, *)
+@available(macOS 10.10, iOS 8.0, *)
public class DispatchWorkItem {
internal var _block: _DispatchBlock
diff --git a/src/swift/Dispatch.swift b/src/swift/Dispatch.swift
index ec73acb..221555f 100644
--- a/src/swift/Dispatch.swift
+++ b/src/swift/Dispatch.swift
@@ -16,14 +16,14 @@
/// dispatch_assert
-@available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public enum DispatchPredicate {
case onQueue(DispatchQueue)
case onQueueAsBarrier(DispatchQueue)
case notOnQueue(DispatchQueue)
}
-@available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public func _dispatchPreconditionTest(_ condition: DispatchPredicate) -> Bool {
switch condition {
case .onQueue(let q):
@@ -37,7 +37,7 @@
}
@_transparent
-@available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public func dispatchPrecondition(condition: @autoclosure () -> DispatchPredicate) {
// precondition is able to determine release-vs-debug asserts where the overlay
// cannot, so formulating this into a call that we can call with precondition()
@@ -50,44 +50,44 @@
public let qosClass: QoSClass
public let relativePriority: Int
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public static let background = DispatchQoS(qosClass: .background, relativePriority: 0)
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public static let utility = DispatchQoS(qosClass: .utility, relativePriority: 0)
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public static let `default` = DispatchQoS(qosClass: .default, relativePriority: 0)
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public static let userInitiated = DispatchQoS(qosClass: .userInitiated, relativePriority: 0)
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public static let userInteractive = DispatchQoS(qosClass: .userInteractive, relativePriority: 0)
public static let unspecified = DispatchQoS(qosClass: .unspecified, relativePriority: 0)
public enum QoSClass {
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
case background
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
case utility
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
case `default`
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
case userInitiated
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
case userInteractive
case unspecified
// _OSQoSClass is internal on Linux, so this initialiser has to
// remain as an internal init.
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
internal init?(rawValue: _OSQoSClass) {
switch rawValue {
case .QOS_CLASS_BACKGROUND: self = .background
@@ -100,7 +100,7 @@
}
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
internal var rawValue: _OSQoSClass {
switch self {
case .background: return .QOS_CLASS_BACKGROUND
@@ -135,7 +135,7 @@
public extension DispatchGroup {
public func notify(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], queue: DispatchQueue, execute work: @escaping @convention(block) () -> ()) {
- if #available(OSX 10.10, iOS 8.0, *), qos != .unspecified || !flags.isEmpty {
+ if #available(macOS 10.10, iOS 8.0, *), qos != .unspecified || !flags.isEmpty {
let item = DispatchWorkItem(qos: qos, flags: flags, block: work)
dispatch_group_notify(self.__wrapped, queue.__wrapped, item._block)
} else {
@@ -143,7 +143,7 @@
}
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public func notify(queue: DispatchQueue, work: DispatchWorkItem) {
dispatch_group_notify(self.__wrapped, queue.__wrapped, work._block)
}
diff --git a/src/swift/Queue.swift b/src/swift/Queue.swift
index c2ad7c2..f20dbbc 100644
--- a/src/swift/Queue.swift
+++ b/src/swift/Queue.swift
@@ -31,7 +31,7 @@
public static let concurrent = Attributes(rawValue: 1<<1)
- @available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+ @available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public static let initiallyInactive = Attributes(rawValue: 1<<2)
fileprivate func _attr() -> dispatch_queue_attr_t? {
@@ -40,7 +40,7 @@
if self.contains(.concurrent) {
attr = _swift_dispatch_queue_concurrent()
}
- if #available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
+ if #available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
if self.contains(.initiallyInactive) {
attr = CDispatch.dispatch_queue_attr_make_initially_inactive(attr)
}
@@ -50,19 +50,19 @@
}
public enum GlobalQueuePriority {
- @available(OSX, deprecated: 10.10, message: "Use qos attributes instead")
+ @available(macOS, deprecated: 10.10, message: "Use qos attributes instead")
@available(*, deprecated: 8.0, message: "Use qos attributes instead")
case high
- @available(OSX, deprecated: 10.10, message: "Use qos attributes instead")
+ @available(macOS, deprecated: 10.10, message: "Use qos attributes instead")
@available(*, deprecated: 8.0, message: "Use qos attributes instead")
case `default`
- @available(OSX, deprecated: 10.10, message: "Use qos attributes instead")
+ @available(macOS, deprecated: 10.10, message: "Use qos attributes instead")
@available(*, deprecated: 8.0, message: "Use qos attributes instead")
case low
- @available(OSX, deprecated: 10.10, message: "Use qos attributes instead")
+ @available(macOS, deprecated: 10.10, message: "Use qos attributes instead")
@available(*, deprecated: 8.0, message: "Use qos attributes instead")
case background
@@ -79,14 +79,14 @@
public enum AutoreleaseFrequency {
case inherit
- @available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+ @available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
case workItem
- @available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+ @available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
case never
internal func _attr(attr: dispatch_queue_attr_t?) -> dispatch_queue_attr_t? {
- if #available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
+ if #available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
switch self {
case .inherit:
// DISPATCH_AUTORELEASE_FREQUENCY_INHERIT
@@ -112,13 +112,13 @@
return DispatchQueue(queue: _swift_dispatch_get_main_queue())
}
- @available(OSX, deprecated: 10.10, message: "")
+ @available(macOS, deprecated: 10.10, message: "")
@available(*, deprecated: 8.0, message: "")
public class func global(priority: GlobalQueuePriority) -> DispatchQueue {
return DispatchQueue(queue: CDispatch.dispatch_get_global_queue(priority._translatedValue, 0))
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public class func global(qos: DispatchQoS.QoSClass = .default) -> DispatchQueue {
return DispatchQueue(queue: CDispatch.dispatch_get_global_queue(Int(qos.rawValue.rawValue), 0))
}
@@ -145,11 +145,11 @@
if autoreleaseFrequency != .inherit {
attr = autoreleaseFrequency._attr(attr: attr)
}
- if #available(OSX 10.10, iOS 8.0, *), qos != .unspecified {
+ if #available(macOS 10.10, iOS 8.0, *), qos != .unspecified {
attr = CDispatch.dispatch_queue_attr_make_with_qos_class(attr, qos.qosClass.rawValue.rawValue, Int32(qos.relativePriority))
}
- if #available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
+ if #available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
self.init(__label: label, attr: attr, queue: target)
} else {
self.init(__label: label, attr: attr)
@@ -161,17 +161,17 @@
return String(validatingUTF8: dispatch_queue_get_label(self.__wrapped))!
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public func sync(execute workItem: DispatchWorkItem) {
CDispatch.dispatch_sync(self.__wrapped, workItem._block)
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public func async(execute workItem: DispatchWorkItem) {
CDispatch.dispatch_async(self.__wrapped, workItem._block)
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public func async(group: DispatchGroup, execute workItem: DispatchWorkItem) {
CDispatch.dispatch_group_async(group.__wrapped, self.__wrapped, workItem._block)
}
@@ -194,7 +194,7 @@
}
var block: @convention(block) () -> Void = work
- if #available(OSX 10.10, iOS 8.0, *), (qos != .unspecified || !flags.isEmpty) {
+ if #available(macOS 10.10, iOS 8.0, *), (qos != .unspecified || !flags.isEmpty) {
let workItem = DispatchWorkItem(qos: qos, flags: flags, block: work)
block = workItem._block
}
@@ -233,7 +233,7 @@
}
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
private func _syncHelper<T>(
fn: (DispatchWorkItem) -> (),
flags: DispatchWorkItemFlags,
@@ -264,7 +264,7 @@
public func sync<T>(flags: DispatchWorkItemFlags, execute work: () throws -> T) rethrows -> T {
if flags == .barrier {
return try self._syncHelper(fn: _syncBarrier, execute: work, rescue: { throw $0 })
- } else if #available(OSX 10.10, iOS 8.0, *), !flags.isEmpty {
+ } else if #available(macOS 10.10, iOS 8.0, *), !flags.isEmpty {
return try self._syncHelper(fn: sync, flags: flags, execute: work, rescue: { throw $0 })
} else {
return try self._syncHelper(fn: sync, execute: work, rescue: { throw $0 })
@@ -277,7 +277,7 @@
flags: DispatchWorkItemFlags = [],
execute work: @escaping @convention(block) () -> Void)
{
- if #available(OSX 10.10, iOS 8.0, *), qos != .unspecified || !flags.isEmpty {
+ if #available(macOS 10.10, iOS 8.0, *), qos != .unspecified || !flags.isEmpty {
let item = DispatchWorkItem(qos: qos, flags: flags, block: work)
CDispatch.dispatch_after(deadline.rawValue, self.__wrapped, item._block)
} else {
@@ -291,7 +291,7 @@
flags: DispatchWorkItemFlags = [],
execute work: @escaping @convention(block) () -> Void)
{
- if #available(OSX 10.10, iOS 8.0, *), qos != .unspecified || !flags.isEmpty {
+ if #available(macOS 10.10, iOS 8.0, *), qos != .unspecified || !flags.isEmpty {
let item = DispatchWorkItem(qos: qos, flags: flags, block: work)
CDispatch.dispatch_after(wallDeadline.rawValue, self.__wrapped, item._block)
} else {
@@ -299,17 +299,17 @@
}
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public func asyncAfter(deadline: DispatchTime, execute: DispatchWorkItem) {
CDispatch.dispatch_after(deadline.rawValue, self.__wrapped, execute._block)
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public func asyncAfter(wallDeadline: DispatchWallTime, execute: DispatchWorkItem) {
CDispatch.dispatch_after(wallDeadline.rawValue, self.__wrapped, execute._block)
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public var qos: DispatchQoS {
var relPri: Int32 = 0
let cls = DispatchQoS.QoSClass(rawValue: _OSQoSClass(qosClass: dispatch_queue_get_qos_class(self.__wrapped, &relPri))!)!
diff --git a/src/swift/Source.swift b/src/swift/Source.swift
index a877121..4057c59 100644
--- a/src/swift/Source.swift
+++ b/src/swift/Source.swift
@@ -16,7 +16,7 @@
public extension DispatchSourceProtocol {
public func setEventHandler(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], handler: DispatchSourceHandler?) {
- if #available(OSX 10.10, iOS 8.0, *), let h = handler, qos != .unspecified || !flags.isEmpty {
+ if #available(macOS 10.10, iOS 8.0, *), let h = handler, qos != .unspecified || !flags.isEmpty {
let item = DispatchWorkItem(qos: qos, flags: flags, block: h)
CDispatch.dispatch_source_set_event_handler((self as! DispatchSource).__wrapped, item._block)
} else {
@@ -24,13 +24,13 @@
}
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public func setEventHandler(handler: DispatchWorkItem) {
CDispatch.dispatch_source_set_event_handler((self as! DispatchSource).__wrapped, handler._block)
}
public func setCancelHandler(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], handler: DispatchSourceHandler?) {
- if #available(OSX 10.10, iOS 8.0, *), let h = handler, qos != .unspecified || !flags.isEmpty {
+ if #available(macOS 10.10, iOS 8.0, *), let h = handler, qos != .unspecified || !flags.isEmpty {
let item = DispatchWorkItem(qos: qos, flags: flags, block: h)
CDispatch.dispatch_source_set_cancel_handler((self as! DispatchSource).__wrapped, item._block)
} else {
@@ -38,13 +38,13 @@
}
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public func setCancelHandler(handler: DispatchWorkItem) {
CDispatch.dispatch_source_set_cancel_handler((self as! DispatchSource).__wrapped, handler._block)
}
public func setRegistrationHandler(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], handler: DispatchSourceHandler?) {
- if #available(OSX 10.10, iOS 8.0, *), let h = handler, qos != .unspecified || !flags.isEmpty {
+ if #available(macOS 10.10, iOS 8.0, *), let h = handler, qos != .unspecified || !flags.isEmpty {
let item = DispatchWorkItem(qos: qos, flags: flags, block: h)
CDispatch.dispatch_source_set_registration_handler((self as! DispatchSource).__wrapped, item._block)
} else {
@@ -52,12 +52,12 @@
}
}
- @available(OSX 10.10, iOS 8.0, *)
+ @available(macOS 10.10, iOS 8.0, *)
public func setRegistrationHandler(handler: DispatchWorkItem) {
CDispatch.dispatch_source_set_registration_handler((self as! DispatchSource).__wrapped, handler._block)
}
- @available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+ @available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public func activate() {
(self as! DispatchSource).activate()
}
diff --git a/src/transform.c b/src/transform.c
index 44a1271..7f2c556 100644
--- a/src/transform.c
+++ b/src/transform.c
@@ -30,6 +30,9 @@
#include <sys/endian.h>
#define OSLittleEndian _LITTLE_ENDIAN
#define OSBigEndian _BIG_ENDIAN
+#elif defined(_WIN32)
+#define OSLittleEndian 1234
+#define OSBigEndian 4321
#endif
#if defined(__linux__) || defined(__FreeBSD__)
@@ -37,6 +40,11 @@
#define OSSwapBigToHostInt16 be16toh
#define OSSwapHostToLittleInt16 htole16
#define OSSwapHostToBigInt16 htobe16
+#elif defined(_WIN32)
+#define OSSwapLittleToHostInt16
+#define OSSwapBigToHostInt16 ntohs
+#define OSSwapHostToLittleInt16
+#define OSSwapHostToBigInt16 htons
#endif
#if defined(__LITTLE_ENDIAN__)
diff --git a/src/voucher.c b/src/voucher.c
index 458e2f0..e32bd29 100644
--- a/src/voucher.c
+++ b/src/voucher.c
@@ -157,7 +157,7 @@
return _voucher_release(voucher);
}
-void
+void DISPATCH_TSD_DTOR_CC
_voucher_thread_cleanup(void *voucher)
{
// when a thread exits and has a voucher left, the kernel
@@ -1515,7 +1515,7 @@
(void)v;
}
-void
+void DISPATCH_TSD_DTOR_CC
_voucher_thread_cleanup(void *voucher)
{
(void)voucher;
diff --git a/src/voucher_internal.h b/src/voucher_internal.h
index 772c8c4..9f5d72b 100644
--- a/src/voucher_internal.h
+++ b/src/voucher_internal.h
@@ -97,7 +97,7 @@
void _voucher_xref_dispose(voucher_t voucher);
void _voucher_dispose(voucher_t voucher);
size_t _voucher_debug(voucher_t v, char* buf, size_t bufsiz);
-void _voucher_thread_cleanup(void *voucher);
+void DISPATCH_TSD_DTOR_CC _voucher_thread_cleanup(void *voucher);
mach_voucher_t _voucher_get_mach_voucher(voucher_t voucher);
voucher_t _voucher_create_without_importance(voucher_t voucher);
voucher_t _voucher_create_accounting_voucher(voucher_t voucher);