From 5f5f497cbd13976d28c5406d819ea14a82647c18 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Mon, 26 Jul 2021 16:36:56 +1000 Subject: [PATCH] [host/common] windows: provide `delayExecution` via `nsleep` This change moves this platform specific sleep to `common` as the OS agnostic `nsleep` function. Ref PR #661 --- common/include/common/time.h | 32 +++++++++---- common/src/platform/windows/CMakeLists.txt | 20 ++++++++ .../src/platform/windows}/ntdll.def | 0 common/src/platform/windows/time.c | 13 ++++++ host/platform/Windows/CMakeLists.txt | 21 --------- host/platform/Windows/include/windows/delay.h | 26 ----------- host/platform/Windows/src/delay.c | 46 ------------------- host/platform/Windows/src/mousehook.c | 4 +- host/platform/Windows/src/platform.c | 4 +- 9 files changed, 59 insertions(+), 107 deletions(-) rename {host/platform/Windows => common/src/platform/windows}/ntdll.def (100%) delete mode 100644 host/platform/Windows/include/windows/delay.h delete mode 100644 host/platform/Windows/src/delay.c diff --git a/common/include/common/time.h b/common/include/common/time.h index 90b41a60..1ab9458d 100644 --- a/common/include/common/time.h +++ b/common/include/common/time.h @@ -25,6 +25,13 @@ #if defined(_WIN32) #include + +void windowsSetTimerResolution(void); +NTSYSCALLAPI NTSTATUS NTAPI NtDelayExecution( + _In_ BOOLEAN Alertable, + _In_opt_ PLARGE_INTEGER DelayInterval +); + #else #include #include @@ -49,6 +56,21 @@ static inline uint64_t microtime(void) #endif } +static inline void nsleep(uint64_t ns) +{ +#if defined(_WIN32) + LARGE_INTEGER interval = { .QuadPart = -(int64_t)(ns / 100LL) }; + NtDelayExecution(FALSE, &interval); +#else + const struct timespec ts = + { + .tv_sec = ns / 1e9, + .tv_nsec = ns - ((ns / 1e9) * 1e9) + }; + nanosleep(&ts, NULL); +#endif +} + #if !defined(_WIN32) //FIXME: make win32 versions static inline uint64_t nanotime(void) @@ -58,16 +80,6 @@ static inline uint64_t nanotime(void) return ((uint64_t)time.tv_sec * 1000000000LL) + time.tv_nsec; } -static inline void nsleep(uint64_t ns) -{ - const struct timespec ts = - { - .tv_sec = ns / 1e9, - .tv_nsec = ns - ((ns / 1e9) * 1e9) - }; - nanosleep(&ts, NULL); -} - static inline void tsDiff(struct timespec *diff, const struct timespec *left, const struct timespec *right) { diff --git a/common/src/platform/windows/CMakeLists.txt b/common/src/platform/windows/CMakeLists.txt index d66fcfd5..b737ee43 100644 --- a/common/src/platform/windows/CMakeLists.txt +++ b/common/src/platform/windows/CMakeLists.txt @@ -8,6 +8,25 @@ include_directories( # allow use of functions for Windows 7 or later add_compile_definitions(WINVER=0x0601 _WIN32_WINNT=0x0601) +if (MINGW) + # Build our own ntdll.dll import library + # This tricks MinGW into not linking stuff like memcpy from ntdll.dll instead of mscvrt.dll + if(NOT CMAKE_DLLTOOL) + # cmake older than 3.16 doesn't know how to find dlltool + find_program(CMAKE_DLLTOOL NAMES "x86_64-w64-mingw32-dlltool" "dlltool.exe" DOC "dlltool executable") + endif() + add_custom_command(OUTPUT "${PROJECT_BINARY_DIR}/ntdll.a" + COMMAND "${CMAKE_DLLTOOL}" -d "${PROJECT_SOURCE_DIR}/ntdll.def" -l "${PROJECT_BINARY_DIR}/ntdll.a" + MAIN_DEPENDENCY "${PROJECT_SOURCE_DIR}/ntdll.def" + COMMENT "Building import library ntdll.a" + VERBATIM + ) + add_custom_target(ntdll_target DEPENDS "${PROJECT_BINARY_DIR}/ntdll.a") + add_library(ntdll STATIC IMPORTED GLOBAL) + add_dependencies(ntdll ntdll_target) + set_target_properties(ntdll PROPERTIES IMPORTED_LOCATION "${PROJECT_BINARY_DIR}/ntdll.a") +endif() + add_library(lg_common_platform_code STATIC debug.c crash.c @@ -22,6 +41,7 @@ add_library(lg_common_platform_code STATIC target_link_libraries(lg_common_platform_code lg_common setupapi + ntdll ) if (ENABLE_BACKTRACE) diff --git a/host/platform/Windows/ntdll.def b/common/src/platform/windows/ntdll.def similarity index 100% rename from host/platform/Windows/ntdll.def rename to common/src/platform/windows/ntdll.def diff --git a/common/src/platform/windows/time.c b/common/src/platform/windows/time.c index 09dc2fc7..47df9bd4 100644 --- a/common/src/platform/windows/time.c +++ b/common/src/platform/windows/time.c @@ -71,3 +71,16 @@ void lgTimerDestroy(LGTimer * timer) free(timer); } + +NTSYSCALLAPI NTSTATUS NTAPI NtSetTimerResolution( + _In_ ULONG DesiredTime, + _In_ BOOLEAN SetResolution, + _Out_ PULONG ActualTime +); + +void windowsSetTimerResolution(void) +{ + ULONG actualResolution; + NtSetTimerResolution(1, true, &actualResolution); + DEBUG_INFO("System timer resolution: %.1f μs", actualResolution / 10.0); +} diff --git a/host/platform/Windows/CMakeLists.txt b/host/platform/Windows/CMakeLists.txt index a5bc1242..8ef3a05a 100644 --- a/host/platform/Windows/CMakeLists.txt +++ b/host/platform/Windows/CMakeLists.txt @@ -10,7 +10,6 @@ add_library(platform_Windows STATIC src/service.c src/mousehook.c src/force_compose.c - src/delay.c ) # allow use of functions for Windows 7 or later @@ -18,31 +17,11 @@ add_compile_definitions(WINVER=0x0601 _WIN32_WINNT=0x0601) add_subdirectory("capture") -if (MINGW) - # Build our own ntdll.dll import library - # This tricks MinGW into not linking stuff like memcpy from ntdll.dll instead of mscvrt.dll - if(NOT CMAKE_DLLTOOL) - # cmake older than 3.16 doesn't know how to find dlltool - find_program(CMAKE_DLLTOOL NAMES "x86_64-w64-mingw32-dlltool" "dlltool.exe" DOC "dlltool executable") - endif() - add_custom_command(OUTPUT "${PROJECT_BINARY_DIR}/ntdll.a" - COMMAND "${CMAKE_DLLTOOL}" -d "${PROJECT_SOURCE_DIR}/ntdll.def" -l "${PROJECT_BINARY_DIR}/ntdll.a" - MAIN_DEPENDENCY "${PROJECT_SOURCE_DIR}/ntdll.def" - COMMENT "Building import library ntdll.a" - VERBATIM - ) - add_custom_target(ntdll_target DEPENDS "${PROJECT_BINARY_DIR}/ntdll.a") - add_library(ntdll STATIC IMPORTED GLOBAL) - add_dependencies(ntdll ntdll_target) - set_target_properties(ntdll PROPERTIES IMPORTED_LOCATION "${PROJECT_BINARY_DIR}/ntdll.a") -endif() - target_link_libraries(platform_Windows lg_common capture userenv - ntdll wtsapi32 psapi shlwapi diff --git a/host/platform/Windows/include/windows/delay.h b/host/platform/Windows/include/windows/delay.h deleted file mode 100644 index 60055516..00000000 --- a/host/platform/Windows/include/windows/delay.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Looking Glass - * Copyright (C) 2017-2021 The Looking Glass Authors - * https://looking-glass.io - * - * This program 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 2 of the License, or (at your option) - * any later version. - * - * This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -void delayInit(void); - -// like sleep but more accurate -void delayExecution(float ms); diff --git a/host/platform/Windows/src/delay.c b/host/platform/Windows/src/delay.c deleted file mode 100644 index 8015f948..00000000 --- a/host/platform/Windows/src/delay.c +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Looking Glass - * Copyright (C) 2017-2021 The Looking Glass Authors - * https://looking-glass.io - * - * This program 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 2 of the License, or (at your option) - * any later version. - * - * This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "windows/delay.h" -#include "common/debug.h" - -NTSYSCALLAPI NTSTATUS NTAPI NtDelayExecution( - _In_ BOOLEAN Alertable, - _In_opt_ PLARGE_INTEGER DelayInterval -); - -NTSYSCALLAPI NTSTATUS NTAPI NtSetTimerResolution( - _In_ ULONG DesiredTime, - _In_ BOOLEAN SetResolution, - _Out_ PULONG ActualTime -); - -void delayInit(void) -{ - ULONG actualResolution; - NtSetTimerResolution(1, true, &actualResolution); - DEBUG_INFO("System timer resolution: %.1f μs", actualResolution / 10.0); -} - -void delayExecution(float ms) -{ - LARGE_INTEGER interval = { .QuadPart = -1 * (LONGLONG)(ms * 10000.0f) }; - NtDelayExecution(FALSE, &interval); -} diff --git a/host/platform/Windows/src/mousehook.c b/host/platform/Windows/src/mousehook.c index 809e28d4..24657423 100644 --- a/host/platform/Windows/src/mousehook.c +++ b/host/platform/Windows/src/mousehook.c @@ -19,8 +19,8 @@ */ #include "windows/mousehook.h" -#include "windows/delay.h" #include "common/windebug.h" +#include "common/time.h" #include "platform.h" #include @@ -105,7 +105,7 @@ static DWORD WINAPI updateThreadProc(LPVOID lParam) mouseHook.callback(mouseHook.x, mouseHook.y); // limit this to 1000Hz, who has a mouse that updates faster anyway? - delayExecution(1.0f); + nsleep(1000000); break; } } diff --git a/host/platform/Windows/src/platform.c b/host/platform/Windows/src/platform.c index 295f33e1..3433b901 100644 --- a/host/platform/Windows/src/platform.c +++ b/host/platform/Windows/src/platform.c @@ -20,7 +20,6 @@ #include "platform.h" #include "service.h" -#include "windows/delay.h" #include "windows/mousehook.h" #include @@ -38,6 +37,7 @@ #include "common/option.h" #include "common/locking.h" #include "common/thread.h" +#include "common/time.h" #define ID_MENU_SHOW_LOG 3000 #define ID_MENU_EXIT 3001 @@ -495,7 +495,7 @@ bool app_init(void) // always flush stderr setbuf(stderr, NULL); - delayInit(); + windowsSetTimerResolution(); // get the performance frequency for spinlocks QueryPerformanceFrequency(&app.perfFreq);