Merge pull request #377 from adierking/fls
Ignore Windows FLS destructors during process exit
diff --git a/dispatch/base.h b/dispatch/base.h
index bd01f48..62579ec 100644
--- a/dispatch/base.h
+++ b/dispatch/base.h
@@ -65,6 +65,29 @@
#define DISPATCH_ALWAYS_INLINE __attribute__((__always_inline__))
#define DISPATCH_UNAVAILABLE __attribute__((__unavailable__))
#define DISPATCH_UNAVAILABLE_MSG(msg) __attribute__((__unavailable__(msg)))
+#elif defined(_MSC_VER)
+#define DISPATCH_NORETURN __declspec(noreturn)
+#define DISPATCH_NOTHROW __declspec(nothrow)
+#define DISPATCH_NONNULL1
+#define DISPATCH_NONNULL2
+#define DISPATCH_NONNULL3
+#define DISPATCH_NONNULL4
+#define DISPATCH_NONNULL5
+#define DISPATCH_NONNULL6
+#define DISPATCH_NONNULL7
+#define DISPATCH_NONNULL_ALL
+#define DISPATCH_SENTINEL
+#define DISPATCH_PURE
+#define DISPATCH_CONST
+#if (_MSC_VER >= 1700)
+#define DISPATCH_WARN_RESULT _Check_return_
+#else
+#define DISPATCH_WARN_RESULT
+#endif
+#define DISPATCH_MALLOC
+#define DISPATCH_ALWAYS_INLINE __forceinline
+#define DISPATCH_UNAVAILABLE
+#define DISPATCH_UNAVAILABLE_MSG(msg)
#else
/*! @parseOnly */
#define DISPATCH_NORETURN
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b817674..6b95a9b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -41,6 +41,7 @@
event/event_epoll.c
event/event_internal.h
event/event_kevent.c
+ event/event_windows.c
firehose/firehose_internal.h
shims/android_stubs.h
shims/atomic.h
diff --git a/src/event/event_config.h b/src/event/event_config.h
index fda5d22..c0c38b0 100644
--- a/src/event/event_config.h
+++ b/src/event/event_config.h
@@ -25,13 +25,16 @@
# include <sys/eventfd.h>
# define DISPATCH_EVENT_BACKEND_EPOLL 1
# define DISPATCH_EVENT_BACKEND_KEVENT 0
+# define DISPATCH_EVENT_BACKEND_WINDOWS 0
#elif __has_include(<sys/event.h>)
# include <sys/event.h>
# define DISPATCH_EVENT_BACKEND_EPOLL 0
# define DISPATCH_EVENT_BACKEND_KEVENT 1
+# define DISPATCH_EVENT_BACKEND_WINDOWS 0
#elif defined(_WIN32)
# define DISPATCH_EVENT_BACKEND_EPOLL 0
# define DISPATCH_EVENT_BACKEND_KEVENT 0
+# define DISPATCH_EVENT_BACKEND_WINDOWS 1
#else
# error unsupported event loop
#endif
diff --git a/src/event/event_internal.h b/src/event/event_internal.h
index 842c4ee..cf80a41 100644
--- a/src/event/event_internal.h
+++ b/src/event/event_internal.h
@@ -418,7 +418,9 @@
bool _dispatch_unote_unregister(dispatch_unote_t du, uint32_t flags);
void _dispatch_unote_dispose(dispatch_unote_t du);
+#if !DISPATCH_EVENT_BACKEND_WINDOWS
void _dispatch_event_loop_atfork_child(void);
+#endif
#define DISPATCH_EVENT_LOOP_CONSUME_2 DISPATCH_WAKEUP_CONSUME_2
#define DISPATCH_EVENT_LOOP_OVERRIDE 0x80000000
void _dispatch_event_loop_poke(dispatch_wlh_t wlh, uint64_t dq_state,
diff --git a/src/event/event_windows.c b/src/event/event_windows.c
new file mode 100644
index 0000000..2fe9680
--- /dev/null
+++ b/src/event/event_windows.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "internal.h"
+#if DISPATCH_EVENT_BACKEND_WINDOWS
+
+#pragma mark dispatch_unote_t
+
+bool
+_dispatch_unote_register(dispatch_unote_t du DISPATCH_UNUSED,
+ dispatch_wlh_t wlh DISPATCH_UNUSED,
+ dispatch_priority_t pri DISPATCH_UNUSED)
+{
+ WIN_PORT_ERROR();
+ return false;
+}
+
+void
+_dispatch_unote_resume(dispatch_unote_t du DISPATCH_UNUSED)
+{
+ WIN_PORT_ERROR();
+}
+
+bool
+_dispatch_unote_unregister(dispatch_unote_t du DISPATCH_UNUSED,
+ uint32_t flags DISPATCH_UNUSED)
+{
+ WIN_PORT_ERROR();
+ return false;
+}
+
+#pragma mark timers
+
+void
+_dispatch_event_loop_timer_arm(uint32_t tidx DISPATCH_UNUSED,
+ dispatch_timer_delay_s range DISPATCH_UNUSED,
+ dispatch_clock_now_cache_t nows DISPATCH_UNUSED)
+{
+ WIN_PORT_ERROR();
+}
+
+void
+_dispatch_event_loop_timer_delete(uint32_t tidx DISPATCH_UNUSED)
+{
+ WIN_PORT_ERROR();
+}
+
+#pragma mark dispatch_loop
+
+void
+_dispatch_event_loop_poke(dispatch_wlh_t wlh DISPATCH_UNUSED,
+ uint64_t dq_state DISPATCH_UNUSED, uint32_t flags DISPATCH_UNUSED)
+{
+ WIN_PORT_ERROR();
+}
+
+DISPATCH_NOINLINE
+void
+_dispatch_event_loop_drain(uint32_t flags DISPATCH_UNUSED)
+{
+ WIN_PORT_ERROR();
+}
+
+void
+_dispatch_event_loop_wake_owner(dispatch_sync_context_t dsc,
+ dispatch_wlh_t wlh, uint64_t old_state, uint64_t new_state)
+{
+ (void)dsc; (void)wlh; (void)old_state; (void)new_state;
+}
+
+void
+_dispatch_event_loop_wait_for_ownership(dispatch_sync_context_t dsc)
+{
+ if (dsc->dsc_release_storage) {
+ _dispatch_queue_release_storage(dsc->dc_data);
+ }
+}
+
+void
+_dispatch_event_loop_end_ownership(dispatch_wlh_t wlh, uint64_t old_state,
+ uint64_t new_state, uint32_t flags)
+{
+ (void)wlh; (void)old_state; (void)new_state; (void)flags;
+}
+
+#if DISPATCH_WLH_DEBUG
+void
+_dispatch_event_loop_assert_not_owned(dispatch_wlh_t wlh)
+{
+ (void)wlh;
+}
+#endif
+
+void
+_dispatch_event_loop_leave_immediate(dispatch_wlh_t wlh, uint64_t dq_state)
+{
+ (void)wlh; (void)dq_state;
+}
+
+#endif // DISPATCH_EVENT_BACKEND_WINDOWS
diff --git a/src/internal.h b/src/internal.h
index 1eb069c..bde3d4f 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -939,7 +939,7 @@
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__); \
+ snprintf(_msg, (unsigned)_length + 1, "%s" fmt, DISPATCH_ASSERTION_FAILED_MESSAGE, ##__VA_ARGS__); \
_dispatch_assert_crash(_msg); \
free(_msg); \
} while (0)
diff --git a/src/shims/generic_win_stubs.c b/src/shims/generic_win_stubs.c
index f6984a2..67b6f51 100644
--- a/src/shims/generic_win_stubs.c
+++ b/src/shims/generic_win_stubs.c
@@ -1,3 +1,23 @@
+#include "internal.h"
+
+/*
+ * This file contains stubbed out functions we are using during
+ * the initial Windows port. When the port is complete, this file
+ * should be empty (and thus removed).
+ */
+
+void
+_dispatch_runloop_queue_dispose(dispatch_queue_t dq DISPATCH_UNUSED,
+ bool *allow_free DISPATCH_UNUSED)
+{
+ WIN_PORT_ERROR();
+}
+
+void
+_dispatch_runloop_queue_xref_dispose(dispatch_queue_t dq DISPATCH_UNUSED)
+{
+ WIN_PORT_ERROR();
+}
/*
* Stubbed out static data
diff --git a/src/shims/generic_win_stubs.h b/src/shims/generic_win_stubs.h
index d7a6f21..0680112 100644
--- a/src/shims/generic_win_stubs.h
+++ b/src/shims/generic_win_stubs.h
@@ -5,6 +5,7 @@
#include <stdint.h>
#include <Windows.h>
+#include <crtdbg.h>
#include <io.h>
#include <process.h>
@@ -44,7 +45,9 @@
#define O_NONBLOCK 04000
#define bzero(ptr,len) memset((ptr), 0, (len))
-#define snprintf _snprintf
+
+// Report when an unported code path executes.
+#define WIN_PORT_ERROR() \
+ _RPTF1(_CRT_ASSERT, "WIN_PORT_ERROR in %s", __FUNCTION__)
#endif
-
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 508d977..13d8944 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,6 +1,19 @@
-execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink "${CMAKE_SOURCE_DIR}/private" "${CMAKE_CURRENT_BINARY_DIR}/dispatch")
-execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/leaks-wrapper.sh" "${CMAKE_CURRENT_BINARY_DIR}/leaks-wrapper")
+if(CMAKE_SYSTEM_NAME STREQUAL Windows)
+ execute_process(COMMAND
+ "${CMAKE_COMMAND}" -E copy "${CMAKE_SOURCE_DIR}/private"
+ "${CMAKE_CURRENT_BINARY_DIR}/dispatch")
+ execute_process(COMMAND
+ "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/leaks-wrapper.sh"
+ "${CMAKE_CURRENT_BINARY_DIR}/leaks-wrapper")
+else()
+ execute_process(COMMAND
+ "${CMAKE_COMMAND}" -E create_symlink "${CMAKE_SOURCE_DIR}/private"
+ "${CMAKE_CURRENT_BINARY_DIR}/dispatch")
+ execute_process(COMMAND
+ "${CMAKE_COMMAND}" -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/leaks-wrapper.sh"
+ "${CMAKE_CURRENT_BINARY_DIR}/leaks-wrapper")
+endif()
if(CMAKE_SYSTEM_NAME STREQUAL Linux)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lrt")