[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
This commit is contained in:
Geoffrey McRae 2021-07-26 16:36:56 +10:00
parent 120fe63c0f
commit 5f5f497cbd
9 changed files with 59 additions and 107 deletions

View File

@ -25,6 +25,13 @@
#if defined(_WIN32) #if defined(_WIN32)
#include <windows.h> #include <windows.h>
void windowsSetTimerResolution(void);
NTSYSCALLAPI NTSTATUS NTAPI NtDelayExecution(
_In_ BOOLEAN Alertable,
_In_opt_ PLARGE_INTEGER DelayInterval
);
#else #else
#include <time.h> #include <time.h>
#include <stdint.h> #include <stdint.h>
@ -49,6 +56,21 @@ static inline uint64_t microtime(void)
#endif #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) #if !defined(_WIN32)
//FIXME: make win32 versions //FIXME: make win32 versions
static inline uint64_t nanotime(void) 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; 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, static inline void tsDiff(struct timespec *diff, const struct timespec *left,
const struct timespec *right) const struct timespec *right)
{ {

View File

@ -8,6 +8,25 @@ include_directories(
# allow use of functions for Windows 7 or later # allow use of functions for Windows 7 or later
add_compile_definitions(WINVER=0x0601 _WIN32_WINNT=0x0601) 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 add_library(lg_common_platform_code STATIC
debug.c debug.c
crash.c crash.c
@ -22,6 +41,7 @@ add_library(lg_common_platform_code STATIC
target_link_libraries(lg_common_platform_code target_link_libraries(lg_common_platform_code
lg_common lg_common
setupapi setupapi
ntdll
) )
if (ENABLE_BACKTRACE) if (ENABLE_BACKTRACE)

View File

@ -71,3 +71,16 @@ void lgTimerDestroy(LGTimer * timer)
free(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);
}

View File

@ -10,7 +10,6 @@ add_library(platform_Windows STATIC
src/service.c src/service.c
src/mousehook.c src/mousehook.c
src/force_compose.c src/force_compose.c
src/delay.c
) )
# allow use of functions for Windows 7 or later # allow use of functions for Windows 7 or later
@ -18,31 +17,11 @@ add_compile_definitions(WINVER=0x0601 _WIN32_WINNT=0x0601)
add_subdirectory("capture") 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 target_link_libraries(platform_Windows
lg_common lg_common
capture capture
userenv userenv
ntdll
wtsapi32 wtsapi32
psapi psapi
shlwapi shlwapi

View File

@ -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 <windows.h>
void delayInit(void);
// like sleep but more accurate
void delayExecution(float ms);

View File

@ -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);
}

View File

@ -19,8 +19,8 @@
*/ */
#include "windows/mousehook.h" #include "windows/mousehook.h"
#include "windows/delay.h"
#include "common/windebug.h" #include "common/windebug.h"
#include "common/time.h"
#include "platform.h" #include "platform.h"
#include <windows.h> #include <windows.h>
@ -105,7 +105,7 @@ static DWORD WINAPI updateThreadProc(LPVOID lParam)
mouseHook.callback(mouseHook.x, mouseHook.y); mouseHook.callback(mouseHook.x, mouseHook.y);
// limit this to 1000Hz, who has a mouse that updates faster anyway? // limit this to 1000Hz, who has a mouse that updates faster anyway?
delayExecution(1.0f); nsleep(1000000);
break; break;
} }
} }

View File

@ -20,7 +20,6 @@
#include "platform.h" #include "platform.h"
#include "service.h" #include "service.h"
#include "windows/delay.h"
#include "windows/mousehook.h" #include "windows/mousehook.h"
#include <windows.h> #include <windows.h>
@ -38,6 +37,7 @@
#include "common/option.h" #include "common/option.h"
#include "common/locking.h" #include "common/locking.h"
#include "common/thread.h" #include "common/thread.h"
#include "common/time.h"
#define ID_MENU_SHOW_LOG 3000 #define ID_MENU_SHOW_LOG 3000
#define ID_MENU_EXIT 3001 #define ID_MENU_EXIT 3001
@ -495,7 +495,7 @@ bool app_init(void)
// always flush stderr // always flush stderr
setbuf(stderr, NULL); setbuf(stderr, NULL);
delayInit(); windowsSetTimerResolution();
// get the performance frequency for spinlocks // get the performance frequency for spinlocks
QueryPerformanceFrequency(&app.perfFreq); QueryPerformanceFrequency(&app.perfFreq);