Merge pull request #245 from compnerd/windows-cleanups
Windows cleanups
diff --git a/cmake/modules/SwiftSupport.cmake b/cmake/modules/SwiftSupport.cmake
new file mode 100644
index 0000000..a29fd26
--- /dev/null
+++ b/cmake/modules/SwiftSupport.cmake
@@ -0,0 +1,69 @@
+
+include(CMakeParseArguments)
+
+function(add_swift_library library)
+ set(options)
+ set(single_value_options MODULE_NAME;MODULE_LINK_NAME;MODULE_PATH;MODULE_CACHE_PATH;OUTPUT)
+ set(multiple_value_options SOURCES;SWIFT_FLAGS;CFLAGS)
+
+ cmake_parse_arguments(ASL "${options}" "${single_value_options}" "${multiple_value_options}" ${ARGN})
+
+ set(flags ${CMAKE_SWIFT_FLAGS})
+
+ list(APPEND flags -emit-library)
+
+ if(ASL_MODULE_NAME)
+ list(APPEND flags -module-name;${ASL_MODULE_NAME})
+ endif()
+ if(ASL_MODULE_LINK_NAME)
+ list(APPEND flags -module-link-name;${ASL_MODULE_LINK_NAME})
+ endif()
+ if(ASL_MODULE_PATH)
+ list(APPEND flags -emit-module-path;${ASL_MODULE_PATH})
+ endif()
+ if(ASL_MODULE_CACHE_PATH)
+ list(APPEND flags -module-cache-path;${ASL_MODULE_CACHE_PATH})
+ endif()
+ if(ASL_SWIFT_FLAGS)
+ foreach(flag ${ASL_SWIFT_FLAGS})
+ list(APPEND flags ${flag})
+ endforeach()
+ endif()
+ if(ASL_CFLAGS)
+ foreach(flag ${ASL_CFLAGS})
+ list(APPEND flags -Xcc;${flag})
+ endforeach()
+ endif()
+
+ # FIXME: We shouldn't /have/ to build things in a single process.
+ # <rdar://problem/15972329>
+ list(APPEND flags -force-single-frontend-invocation)
+
+ set(sources)
+ foreach(source ${ASL_SOURCES})
+ get_filename_component(location ${source} PATH)
+ if(IS_ABSOLUTE ${location})
+ list(APPEND sources ${source})
+ else()
+ list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/${source})
+ endif()
+ endforeach()
+
+ get_filename_component(module_directory ${ASL_MODULE_PATH} DIRECTORY)
+
+ add_custom_command(OUTPUT
+ ${ASL_OUTPUT}
+ ${ASL_MODULE_PATH}
+ ${moodule_directory}/${ASL_MODULE_NAME}.swiftdoc
+ DEPENDS
+ ${ASL_SOURCES}
+ COMMAND
+ ${CMAKE_COMMAND} -E make_directory ${module_directory}
+ COMMAND
+ ${CMAKE_SWIFT_COMPILER} ${flags} -c ${sources} -o ${ASL_OUTPUT})
+ add_custom_target(${library}
+ DEPENDS
+ ${ASL_OUTPUT}
+ ${ASL_MODULE_PATH}
+ ${moodule_directory}/${ASL_MODULE_NAME}.swiftdoc)
+endfunction()
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 75c7266..8bc572b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,8 +1,44 @@
+include(SwiftSupport)
+
set(dispatch_BLOCK_SOURCES block.cpp)
if(HAVE_OBJC)
list(APPEND dispatch_BLOCK_SOURCES data.m object.m)
endif()
+set(dispatch_SWIFT_SOURCES)
+if(CMAKE_SWIFT_COMPILER)
+ set(swift_optimization_flags)
+ if(CMAKE_BUILD_TYPE MATCHES Release)
+ set(swift_optimization_flags -O)
+ endif()
+ add_swift_library(swiftDispatch
+ MODULE_NAME
+ Dispatch
+ MODULE_LINK_NAME
+ dispatch
+ MODULE_PATH
+ ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftmodule
+ OUTPUT
+ ${CMAKE_CURRENT_BINARY_DIR}/swiftDispatch.o
+ SOURCES
+ swift/Block.swift
+ swift/Data.swift
+ swift/Dispatch.swift
+ swift/IO.swift
+ swift/Private.swift
+ swift/Queue.swift
+ swift/Source.swift
+ swift/Time.swift
+ swift/Wrapper.swift
+ CFLAGS
+ -fblocks
+ -fmodule-map-file=${CMAKE_SOURCE_DIR}/dispatch/module.modulemap
+ SWIFT_FLAGS
+ -I ${CMAKE_SOURCE_DIR}
+ ${swift_optimization_flags})
+ list(APPEND dispatch_SWIFT_SOURCES
+ swift/DispatchStubs.cc;${CMAKE_CURRENT_BINARY_DIR}/swiftDispatch.o)
+endif()
add_library(dispatch
allocator.c
apply.c
@@ -55,7 +91,8 @@
shims/time.h
shims/tsd.h
shims/yield.h
- ${dispatch_BLOCK_SOURCES})
+ ${dispatch_BLOCK_SOURCES}
+ ${dispatch_SWIFT_SOURCES})
target_include_directories(dispatch
PRIVATE
${CMAKE_BINARY_DIR}
diff --git a/src/event/event_epoll.c b/src/event/event_epoll.c
index 2788b10..647552f 100644
--- a/src/event/event_epoll.c
+++ b/src/event/event_epoll.c
@@ -117,9 +117,28 @@
free(dmn);
}
+static pthread_t manager_thread;
+
+static void
+_dispatch_muxnote_signal_block_and_raise(int signo)
+{
+ // On linux, for signals to be delivered to the signalfd, signals
+ // must be blocked, else any thread that hasn't them blocked may
+ // receive them. Fix that by lazily noticing, blocking said signal,
+ // and raising the signal again when it happens
+ _dispatch_sigmask();
+ pthread_kill(manager_thread, signo);
+}
+
static dispatch_muxnote_t
_dispatch_muxnote_create(dispatch_unote_t du, uint32_t events)
{
+ static sigset_t signals_with_unotes;
+ static struct sigaction sa = {
+ .sa_handler = _dispatch_muxnote_signal_block_and_raise,
+ .sa_flags = SA_RESTART,
+ };
+
dispatch_muxnote_t dmn;
struct stat sb;
int fd = du._du->du_ident;
@@ -129,13 +148,17 @@
switch (filter) {
case EVFILT_SIGNAL:
+ if (!sigismember(&signals_with_unotes, du._du->du_ident)) {
+ manager_thread = pthread_self();
+ sigaddset(&signals_with_unotes, du._du->du_ident);
+ sigaction(du._du->du_ident, &sa, NULL);
+ }
sigemptyset(&sigmask);
sigaddset(&sigmask, du._du->du_ident);
fd = signalfd(-1, &sigmask, SFD_NONBLOCK | SFD_CLOEXEC);
if (fd < 0) {
return NULL;
}
- sigprocmask(SIG_BLOCK, &sigmask, NULL);
break;
case EVFILT_WRITE:
diff --git a/src/event/event_kevent.c b/src/event/event_kevent.c
index b3bd63f..3275888 100644
--- a/src/event/event_kevent.c
+++ b/src/event/event_kevent.c
@@ -1557,7 +1557,7 @@
kern_return_t kr;
#if HAVE_MACH_PORT_CONSTRUCT
mach_port_options_t opts = { .flags = MPO_CONTEXT_AS_GUARD | MPO_STRICT };
-#ifdef __LP64__
+#if DISPATCH_SIZEOF_PTR == 8
const mach_port_context_t guard = 0xfeed09071f1ca7edull;
#else
const mach_port_context_t guard = 0xff1ca7edull;
diff --git a/src/init.c b/src/init.c
index a04daeb..4ccb1f2 100644
--- a/src/init.c
+++ b/src/init.c
@@ -72,6 +72,29 @@
_dispatch_unsafe_fork = 0;
}
+int
+_dispatch_sigmask(void)
+{
+ sigset_t mask;
+ int r = 0;
+
+ /* Workaround: 6269619 Not all signals can be delivered on any thread */
+ r |= sigfillset(&mask);
+ r |= sigdelset(&mask, SIGILL);
+ r |= sigdelset(&mask, SIGTRAP);
+#if HAVE_DECL_SIGEMT
+ r |= sigdelset(&mask, SIGEMT);
+#endif
+ r |= sigdelset(&mask, SIGFPE);
+ r |= sigdelset(&mask, SIGBUS);
+ r |= sigdelset(&mask, SIGSEGV);
+ r |= sigdelset(&mask, SIGSYS);
+ r |= sigdelset(&mask, SIGPIPE);
+ r |= sigdelset(&mask, SIGPROF);
+ r |= pthread_sigmask(SIG_BLOCK, &mask, NULL);
+ (void)dispatch_assume_zero(r);
+}
+
#pragma mark -
#pragma mark dispatch_globals
diff --git a/src/internal.h b/src/internal.h
index 743d0b2..489da74 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -990,6 +990,8 @@
#endif // DISPATCH_USE_EVFILT_MACHPORT_DIRECT
+int _dispatch_sigmask(void);
+
/* #includes dependent on internal.h */
#include "object_internal.h"
#include "semaphore_internal.h"
diff --git a/src/object_internal.h b/src/object_internal.h
index abc3f48..61caebf 100644
--- a/src/object_internal.h
+++ b/src/object_internal.h
@@ -225,7 +225,7 @@
.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT
#endif
-#ifdef __LP64__
+#if DISPATCH_SIZEOF_PTR == 8
// the bottom nibble must not be zero, the rest of the bits should be random
// we sign extend the 64-bit version so that a better instruction encoding is
// generated on Intel
diff --git a/src/queue.c b/src/queue.c
index 088c5cf..be831ab 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -66,7 +66,6 @@
#endif
#if DISPATCH_USE_PTHREAD_POOL
static void *_dispatch_worker_thread(void *context);
-static int _dispatch_pthread_sigmask(int how, sigset_t *set, sigset_t *oset);
#endif
#if DISPATCH_COCOA_COMPAT
@@ -5466,13 +5465,8 @@
pqc->dpq_thread_configure();
}
- sigset_t mask;
- int r;
// workaround tweaks the kernel workqueue does for us
- r = sigfillset(&mask);
- (void)dispatch_assume_zero(r);
- r = _dispatch_pthread_sigmask(SIG_BLOCK, &mask, NULL);
- (void)dispatch_assume_zero(r);
+ _dispatch_sigmask();
_dispatch_introspection_thread_add();
const int64_t timeout = 5ull * NSEC_PER_SEC;
@@ -5489,37 +5483,6 @@
return NULL;
}
-
-int
-_dispatch_pthread_sigmask(int how, sigset_t *set, sigset_t *oset)
-{
- int r;
-
- /* Workaround: 6269619 Not all signals can be delivered on any thread */
-
- r = sigdelset(set, SIGILL);
- (void)dispatch_assume_zero(r);
- r = sigdelset(set, SIGTRAP);
- (void)dispatch_assume_zero(r);
-#if HAVE_DECL_SIGEMT
- r = sigdelset(set, SIGEMT);
- (void)dispatch_assume_zero(r);
-#endif
- r = sigdelset(set, SIGFPE);
- (void)dispatch_assume_zero(r);
- r = sigdelset(set, SIGBUS);
- (void)dispatch_assume_zero(r);
- r = sigdelset(set, SIGSEGV);
- (void)dispatch_assume_zero(r);
- r = sigdelset(set, SIGSYS);
- (void)dispatch_assume_zero(r);
- r = sigdelset(set, SIGPIPE);
- (void)dispatch_assume_zero(r);
- r = sigdelset(set, SIGPROF);
- (void)dispatch_assume_zero(r);
-
- return pthread_sigmask(how, set, oset);
-}
#endif // DISPATCH_USE_PTHREAD_POOL
#pragma mark -
@@ -5749,6 +5712,7 @@
pthread_key_t dispatch_main_key;
pthread_key_create(&dispatch_main_key, _dispatch_sig_thread);
pthread_setspecific(dispatch_main_key, &dispatch_main_key);
+ _dispatch_sigmask();
#endif
pthread_exit(NULL);
DISPATCH_INTERNAL_CRASH(errno, "pthread_exit() returned");
diff --git a/src/queue_internal.h b/src/queue_internal.h
index 29e83cc..ca9886c 100644
--- a/src/queue_internal.h
+++ b/src/queue_internal.h
@@ -748,7 +748,6 @@
void *dc_ctxt; \
void *dc_data; \
void *dc_other
-#define _DISPATCH_SIZEOF_PTR 8
#elif OS_OBJECT_HAVE_OBJC1
#define DISPATCH_CONTINUATION_HEADER(x) \
dispatch_function_t dc_func; \
@@ -766,7 +765,6 @@
void *dc_ctxt; \
void *dc_data; \
void *dc_other
-#define _DISPATCH_SIZEOF_PTR 4
#else
#define DISPATCH_CONTINUATION_HEADER(x) \
union { \
@@ -784,17 +782,16 @@
void *dc_ctxt; \
void *dc_data; \
void *dc_other
-#define _DISPATCH_SIZEOF_PTR 4
#endif
#define _DISPATCH_CONTINUATION_PTRS 8
#if DISPATCH_HW_CONFIG_UP
// UP devices don't contend on continuations so we don't need to force them to
// occupy a whole cacheline (which is intended to avoid contention)
#define DISPATCH_CONTINUATION_SIZE \
- (_DISPATCH_CONTINUATION_PTRS * _DISPATCH_SIZEOF_PTR)
+ (_DISPATCH_CONTINUATION_PTRS * DISPATCH_SIZEOF_PTR)
#else
#define DISPATCH_CONTINUATION_SIZE ROUND_UP_TO_CACHELINE_SIZE( \
- (_DISPATCH_CONTINUATION_PTRS * _DISPATCH_SIZEOF_PTR))
+ (_DISPATCH_CONTINUATION_PTRS * DISPATCH_SIZEOF_PTR))
#endif
#define ROUND_UP_TO_CONTINUATION_SIZE(x) \
(((x) + (DISPATCH_CONTINUATION_SIZE - 1u)) & \
diff --git a/src/shims/hw_config.h b/src/shims/hw_config.h
index 6b5a069..26856bc 100644
--- a/src/shims/hw_config.h
+++ b/src/shims/hw_config.h
@@ -27,6 +27,22 @@
#ifndef __DISPATCH_SHIMS_HW_CONFIG__
#define __DISPATCH_SHIMS_HW_CONFIG__
+#ifdef __SIZEOF_POINTER__
+#define DISPATCH_SIZEOF_PTR __SIZEOF_POINTER__
+#elif defined(_WIN64)
+#define DISPATCH_SIZEOF_PTR 8
+#elif defined(_WIN32)
+#define DISPATCH_SIZEOF_PTR 4
+#elif defined(_MSC_VER)
+#error "could not determine pointer size as a constant int for MSVC"
+#elif defined(__LP64__) || defined(__LLP64__)
+#define DISPATCH_SIZEOF_PTR 8
+#elif defined(__ILP32__)
+#define DISPATCH_SIZEOF_PTR 4
+#else
+#error "could not determine pointer size as a constant int"
+#endif // __SIZEOF_POINTER__
+
#if !TARGET_OS_WIN32
typedef enum {
diff --git a/tests/dispatch_queue_finalizer.c b/tests/dispatch_queue_finalizer.c
index ec9daa5..9c16e7e 100644
--- a/tests/dispatch_queue_finalizer.c
+++ b/tests/dispatch_queue_finalizer.c
@@ -50,7 +50,7 @@
{
dispatch_test_start("Dispatch Queue Finalizer");
-#ifdef __LP64__
+#if DISPATCH_SIZEOF_PTR == 8
ctxt_magic = (void*)((uintptr_t)arc4random() << 32 | arc4random());
#else
ctxt_magic = (void*)arc4random();