Mercurial > louis > mq > lightsd
changeset 553:b3de1b255605
windows wip, get the lgtd_time_monotonic library fully working and tested
author | Louis Opter <louis@opter.org> |
---|---|
date | Tue, 16 May 2017 09:06:44 -0700 |
parents | 384131f70406 |
children | 3fd912875434 |
files | add_windows_support.patch |
diffstat | 1 files changed, 199 insertions(+), 83 deletions(-) [+] |
line wrap: on
line diff
--- a/add_windows_support.patch Sun May 14 13:59:19 2017 -0700 +++ b/add_windows_support.patch Tue May 16 09:06:44 2017 -0700 @@ -1,5 +1,5 @@ # HG changeset patch -# Parent 3eaedf3f30570024bdac00f3b6a784bed52d01f9 +# Parent b80960a5db4446db68d47e60bb94660804e4ffae lightsd: add windows support diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -52,14 +52,13 @@ SET(CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE} "") IF (CMAKE_SYSTEM_NAME MATCHES "Linux") -@@ -74,6 +76,14 @@ +@@ -74,6 +76,13 @@ ADD_DEFINITIONS("-D_DARWIN_C_SOURCE=1") ENDIF () +IF (MSVC) + ADD_DEFINITIONS( + "-D_CRT_SECURE_NO_WARNINGS" -+ "-DWIN32_LEAN_AND_MEAN" + "-DNOMINMAX" + ) +ENDIF () @@ -67,7 +66,7 @@ ADD_DEFINITIONS( "-DLGTD_BIG_ENDIAN_SYSTEM=${BIG_ENDIAN_SYSTEM}" "-DLGTD_SIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P}" -@@ -99,11 +109,12 @@ +@@ -99,11 +108,12 @@ INCLUDE_DIRECTORIES( ${EVENT2_INCLUDE_DIR} @@ -85,22 +84,84 @@ diff --git a/CMakeScripts/CompatTimeMonotonic.cmake b/CMakeScripts/CompatTimeMonotonic.cmake --- a/CMakeScripts/CompatTimeMonotonic.cmake +++ b/CMakeScripts/CompatTimeMonotonic.cmake -@@ -1,6 +1,5 @@ +@@ -1,8 +1,6 @@ IF (NOT TIME_MONOTONIC_LIBRARY) SET(COMPAT_TIME_MONOTONIC_IMPL "${LIGHTSD_SOURCE_DIR}/compat/${CMAKE_SYSTEM_NAME}/time_monotonic.c") - SET(COMPAT_TIME_MONOTONIC_H "${LIGHTSD_SOURCE_DIR}/compat/${CMAKE_SYSTEM_NAME}/time_monotonic.h") SET(GENERIC_TIME_MONOTONIC_IMPL "${LIGHTSD_SOURCE_DIR}/compat/generic/time_monotonic.c") - SET(GENERIC_TIME_MONOTONIC_H "${LIGHTSD_SOURCE_DIR}/compat/generic/time_monotonic.h") +- SET(GENERIC_TIME_MONOTONIC_H "${LIGHTSD_SOURCE_DIR}/compat/generic/time_monotonic.h") SET(TIME_MONOTONIC_LIBRARY time_monotonic CACHE INTERNAL "lgtd_time_monotonic implementation") -@@ -44,7 +43,7 @@ + + IF (APPLE) +@@ -18,6 +16,7 @@ + ENDIF () + + SET(CMAKE_REQUIRED_QUIET TRUE) ++ + MESSAGE(STATUS "Looking for clock_gettime") + CHECK_FUNCTION_EXISTS("clock_gettime" HAVE_CLOCK_GETTIME) + IF (NOT HAVE_CLOCK_GETTIME) +@@ -32,19 +31,17 @@ + UNSET(TIME_MONOTONIC_LIBRARY_DEP CACHE) + ENDIF () + ENDIF () +- UNSET(CMAKE_REQUIRED_QUIET) ++ + UNSET(CMAKE_REQUIRED_FLAGS) + + IF (HAVE_CLOCK_GETTIME) + MESSAGE(STATUS "Looking for clock_gettime - found") +- FILE(COPY "${GENERIC_TIME_MONOTONIC_H}" DESTINATION "${LIGHTSD_BINARY_DIR}/core/") + SET( + TIME_MONOTONIC_IMPL ${GENERIC_TIME_MONOTONIC_IMPL} + CACHE INTERNAL "lgtd_time_monotonic (POSIX generic source)" ) ELSEIF (EXISTS "${COMPAT_TIME_MONOTONIC_IMPL}") MESSAGE(STATUS "Looking for clock_gettime - not found, using built-in compatibilty file") - FILE(COPY "${COMPAT_TIME_MONOTONIC_H}" DESTINATION "${LIGHTSD_BINARY_DIR}/core/") -+ FILE(COPY "${GENERIC_TIME_MONOTONIC_H}" DESTINATION "${LIGHTSD_BINARY_DIR}/core/") SET( TIME_MONOTONIC_IMPL "${COMPAT_TIME_MONOTONIC_IMPL}" CACHE INTERNAL "lgtd_time_monotonic (${CMAKE_SYSTEM_NAME} specific source)" +@@ -52,9 +49,38 @@ + ELSE () + MESSAGE(SEND_ERROR "Looking for clock_gettime - not found") + ENDIF () ++ ++ SET(COMPAT_SLEEP_MONOTONIC_IMPL "${LIGHTSD_SOURCE_DIR}/compat/${CMAKE_SYSTEM_NAME}/sleep_monotonic.c") ++ SET(GENERIC_SLEEP_MONOTONIC_IMPL "${LIGHTSD_SOURCE_DIR}/compat/generic/sleep_monotonic.c") ++ ++ MESSAGE(STATUS "Looking for nanosleep") ++ CHECK_FUNCTION_EXISTS("nanosleep" HAVE_NANOSLEEP) ++ IF (HAVE_NANOSLEEP) ++ MESSAGE(STATUS "Looking for nanosleep - found") ++ SET( ++ SLEEP_MONOTONIC_IMPL "${GENERIC_SLEEP_MONOTONIC_IMPL}" ++ CACHE INTERNAL "lgtd_sleep_monotonic (POSIX generic source)" ++ ) ++ ELSEIF (EXISTS "${COMPAT_SLEEP_MONOTONIC_IMPL}") ++ MESSAGE(STATUS "Looking for nanosleep - not found, using built-in compatibilty file") ++ SET( ++ SLEEP_MONOTONIC_IMPL "${COMPAT_SLEEP_MONOTONIC_IMPL}" ++ CACHE INTERNAL "lgtd_sleep_monotonic (${CMAKE_SYSTEM_NAME} specific source)" ++ ) ++ IF (WIN32) ++ SET(TIME_MONOTONIC_LIBRARY_DEP Winmm CACHE INTERNAL "dependency for lgtd_sleep_monotonic") ++ ENDIF () ++ ENDIF () ++ ++ UNSET(CMAKE_REQUIRED_QUIET) + ENDIF () + +-ADD_LIBRARY(${TIME_MONOTONIC_LIBRARY} STATIC "${TIME_MONOTONIC_IMPL}") ++ADD_LIBRARY( ++ ${TIME_MONOTONIC_LIBRARY} ++ STATIC ++ "${TIME_MONOTONIC_IMPL}" ++ "${SLEEP_MONOTONIC_IMPL}" ++) + + IF (TIME_MONOTONIC_LIBRARY_DEP) + TARGET_LINK_LIBRARIES(${TIME_MONOTONIC_LIBRARY} ${TIME_MONOTONIC_LIBRARY_DEP}) diff --git a/CMakeScripts/FindEndian.cmake b/CMakeScripts/FindEndian.cmake --- a/CMakeScripts/FindEndian.cmake +++ b/CMakeScripts/FindEndian.cmake @@ -160,47 +221,15 @@ diff --git a/compat/Darwin/time_monotonic.c b/compat/Darwin/time_monotonic.c --- a/compat/Darwin/time_monotonic.c +++ b/compat/Darwin/time_monotonic.c -@@ -22,9 +22,15 @@ - #include <mach/mach_time.h> - #include <sys/time.h> +@@ -24,7 +24,7 @@ #include <assert.h> -+#include <errno.h> -+#include <stdbool.h> -+#include <stdio.h> #include <stdint.h> -+#include <stdlib.h> -+#include <string.h> -#include "time_monotonic.h" +#include "core/time_monotonic.h" -+#include "core/lightsd.h" enum { MSECS_IN_NSEC = 1000000 }; -@@ -40,3 +46,23 @@ - - return time * timebase.numer / timebase.denom / MSECS_IN_NSEC; - } -+ -+void -+lgtd_sleep_monotonic_msecs(int msecs) -+{ -+ assert(msecs >= 0); -+ -+ struct timespec remainder = LGTD_MSECS_TO_TIMESPEC(msecs), -+ request = { 0, 0 }, -+ *rmtp = &remainder, -+ *rqtp = &request; -+ do { -+ LGTD_SWAP(struct timespec *, rqtp, rmtp); -+ int err = nanosleep(rqtp, rmtp); -+ if (err && errno != EINTR) { -+ const char *reason = strerror(errno); -+ fprintf(stderr, "lightsd: nanosleep failed: %s.\n", reason); -+ abort(); -+ } -+ } while (remainder.tv_sec > 0 && remainder.tv_nsec > 0); -+} diff --git a/compat/Darwin/time_monotonic.h b/compat/Darwin/time_monotonic.h deleted file mode 100644 --- a/compat/Darwin/time_monotonic.h @@ -268,11 +297,11 @@ +# define be64toh(x) _byteswap_uint64(x) +# define le64toh(x) (x) +#endif -diff --git a/compat/Windows/time_monotonic.c b/compat/Windows/time_monotonic.c +diff --git a/compat/Windows/sleep_monotonic.c b/compat/Windows/sleep_monotonic.c new file mode 100644 --- /dev/null -+++ b/compat/Windows/time_monotonic.c -@@ -0,0 +1,69 @@ ++++ b/compat/Windows/sleep_monotonic.c +@@ -0,0 +1,63 @@ +// Copyright (c) 2017, Louis Opter <louis@opter.org> +// +// This file is part of lighstd. @@ -290,6 +319,11 @@ +// You should have received a copy of the GNU General Public License +// along with lighstd. If not, see <http://www.gnu.org/licenses/>. + ++// See: ++// ++// https://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx ++// https://msdn.microsoft.com/en-us/library/dd743626(v=vs.85).aspx ++ +#include <Windows.h> +#include <stdbool.h> +#include <stdlib.h> @@ -297,13 +331,77 @@ +#include <stdint.h> + +#include "core/time_monotonic.h" ++#include "core/lightsd.h" + -+enum { MSECS_IN_NSEC = 1000000 }; ++enum { TIMER_RESOLUTION_MS = 1 }; ++ ++static UINT ++_lgtd_set_timer_resolution(UINT resolution_ms) ++{ ++ TIMECAPS tc; ++ if (timeGetDevCaps(&tc, sizeof(tc)) != TIMERR_NOERROR) { ++ fprintf(stderr, "lightsd: multimedia timers unavailable."); ++ exit(1); ++ } ++ ++ UINT resolution = LGTD_MAX(tc.wPeriodMin, resolution_ms); ++ resolution = LGTD_MIN(resolution, tc.wPeriodMax); ++ timeBeginPeriod(resolution); ++ return resolution; ++} ++ ++static void ++_lgtd_reset_timer_resolution(UINT resolution_ms) ++{ ++ if (timeEndPeriod(resolution_ms) != TIMERR_NOERROR) { ++ fprintf(stderr, "lightsd: can't reset timer resolution."); ++ } ++} ++ ++void ++lgtd_sleep_monotonic_msecs(int msecs) ++{ ++ UINT actual = _lgtd_set_timer_resolution(TIMER_RESOLUTION_MS); ++ Sleep(msecs); ++ _lgtd_reset_timer_resolution(actual); ++} +diff --git a/compat/Windows/time_monotonic.c b/compat/Windows/time_monotonic.c +new file mode 100644 +--- /dev/null ++++ b/compat/Windows/time_monotonic.c +@@ -0,0 +1,67 @@ ++// Copyright (c) 2017, Louis Opter <louis@opter.org> ++// ++// This file is part of lighstd. ++// ++// lighstd is free software: you can redistribute it and/or modify ++// it under the terms of the GNU General Public License as published by ++// the Free Software Foundation, either version 3 of the License, or ++// (at your option) any later version. ++// ++// lighstd is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License ++// along with lighstd. If not, see <http://www.gnu.org/licenses/>. ++ ++// This is pretty much "Using QPC in native code" from: ++// ++// https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx ++ ++#include <Windows.h> ++#include <stdbool.h> ++#include <stdint.h> ++#include <stdio.h> ++ ++#include "core/time_monotonic.h" + +lgtd_time_mono_t +lgtd_time_monotonic_msecs(void) +{ -+ static LARGE_INTEGER frequency = { .QuadPart = 0 }; ++ static LARGE_INTEGER frequency = { .QuadPart = 0 }; // ticks per second + if (frequency.QuadPart == 0 + && QueryPerformanceFrequency(&frequency) == false) { + LPSTR msg = NULL; @@ -332,48 +430,52 @@ + + LARGE_INTEGER time; + QueryPerformanceCounter(&time); -+ time.QuadPart = time.QuadPart * MSECS_IN_NSEC; -+ time.QuadPart = time.QuadPart / frequency.QuadPart; ++ // Multiply the number of ticks by 1000 first to get a final value in ms: ++ time.QuadPart *= 1000; ++ // Then (the order is important to avoid loosing precision) divide by the ++ // number of ticks per second: ++ time.QuadPart /= frequency.QuadPart; + return time.QuadPart; +} -+ -+void -+lgtd_sleep_monotonic_msecs(int msecs) -+{ -+ Sleep(msecs); -+} diff --git a/compat/generic/CMakeLists.txt b/compat/generic/CMakeLists.txt deleted file mode 100644 --- a/compat/generic/CMakeLists.txt +++ /dev/null @@ -1,1 +0,0 @@ -FILE(COPY sys DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -diff --git a/compat/generic/time_monotonic.c b/compat/generic/time_monotonic.c ---- a/compat/generic/time_monotonic.c -+++ b/compat/generic/time_monotonic.c -@@ -15,10 +15,17 @@ - // You should have received a copy of the GNU General Public License - // along with lighstd. If not, see <http://www.gnu.org/licenses/>. - +diff --git a/compat/generic/sleep_monotonic.c b/compat/generic/sleep_monotonic.c +new file mode 100644 +--- /dev/null ++++ b/compat/generic/sleep_monotonic.c +@@ -0,0 +1,48 @@ ++// Copyright (c) 2017, Louis Opter <louis@opter.org> ++// ++// This file is part of lighstd. ++// ++// lighstd is free software: you can redistribute it and/or modify ++// it under the terms of the GNU General Public License as published by ++// the Free Software Foundation, either version 3 of the License, or ++// (at your option) any later version. ++// ++// lighstd is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License ++// along with lighstd. If not, see <http://www.gnu.org/licenses/>. ++ +#include <assert.h> +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> - #include <stdint.h> ++#include <stdint.h> +#include <string.h> - #include <time.h> - --#include "time_monotonic.h" ++#include <time.h> ++ +#include "core/time_monotonic.h" +#include "core/lightsd.h" - - lgtd_time_mono_t - lgtd_time_monotonic_msecs(void) -@@ -27,3 +34,23 @@ - clock_gettime(CLOCK_MONOTONIC, &tp); - return tp.tv_sec * 1000 + tp.tv_nsec / 1000000; - } + +void +lgtd_sleep_monotonic_msecs(int msecs) @@ -394,14 +496,18 @@ + } + } while (remainder.tv_sec > 0 && remainder.tv_nsec > 0); +} -diff --git a/compat/generic/time_monotonic.h b/compat/generic/time_monotonic.h ---- a/compat/generic/time_monotonic.h -+++ b/compat/generic/time_monotonic.h -@@ -20,3 +20,4 @@ - typedef uint64_t lgtd_time_mono_t; +diff --git a/compat/generic/time_monotonic.c b/compat/generic/time_monotonic.c +--- a/compat/generic/time_monotonic.c ++++ b/compat/generic/time_monotonic.c +@@ -18,7 +18,7 @@ + #include <stdint.h> + #include <time.h> - lgtd_time_mono_t lgtd_time_monotonic_msecs(void); -+void lgtd_sleep_monotonic_msecs(int); +-#include "time_monotonic.h" ++#include "core/time_monotonic.h" + + lgtd_time_mono_t + lgtd_time_monotonic_msecs(void) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -444,6 +550,16 @@ #define LGTD_NSECS_TO_USECS(v) ((v) / (unsigned int)1E6) #define LGTD_NSECS_TO_SECS(v) ((v) / (unsigned int)1E9) #define LGTD_SECS_TO_NSECS(v) ((v) * (unsigned int)1E9) +diff --git a/compat/generic/time_monotonic.h b/core/time_monotonic.h +rename from compat/generic/time_monotonic.h +rename to core/time_monotonic.h +--- a/compat/generic/time_monotonic.h ++++ b/core/time_monotonic.h +@@ -20,3 +20,4 @@ + typedef uint64_t lgtd_time_mono_t; + + lgtd_time_mono_t lgtd_time_monotonic_msecs(void); ++void lgtd_sleep_monotonic_msecs(int); diff --git a/lifx/CMakeLists.txt b/lifx/CMakeLists.txt --- a/lifx/CMakeLists.txt +++ b/lifx/CMakeLists.txt @@ -490,11 +606,11 @@ +int +main(void) +{ -+ lgtd_time_mono_t elapsed = lgtd_time_monotonic_msecs(); ++ lgtd_time_mono_t start = lgtd_time_monotonic_msecs(); + lgtd_sleep_monotonic_msecs(50); -+ elapsed = lgtd_time_monotonic_msecs() - elapsed; -+ printf("slept for %jums\r\n", (uintmax_t)elapsed); -+ return LGTD_ABS(elapsed - 50) > 10; ++ int duration = (int)(lgtd_time_monotonic_msecs() - start); ++ printf("slept for %dms\r\n", duration); ++ return LGTD_ABS(duration - 50) > 10; +} diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt --- a/tests/core/CMakeLists.txt