mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-27 04:50:28 +00:00
Improve Windows sleep accuracy from 15ms to 15µs
This commit is contained in:
parent
b40140e6c5
commit
b490e23d63
16 changed files with 189 additions and 67 deletions
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
|
@ -23,26 +24,37 @@
|
|||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/nt/enum/status.h"
|
||||
#include "libc/nt/ntdll.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/timer.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#ifdef __x86_64__
|
||||
|
||||
static atomic_int usingRes;
|
||||
static atomic_bool changedRes;
|
||||
|
||||
static textwindows int sys_clock_nanosleep_nt_impl(int clock,
|
||||
struct timespec abs,
|
||||
sigset_t waitmask) {
|
||||
uint32_t msdelay;
|
||||
struct timespec now;
|
||||
for (;;) {
|
||||
if (sys_clock_gettime_nt(clock, &now))
|
||||
return -1;
|
||||
if (timespec_cmp(now, abs) >= 0)
|
||||
return 0;
|
||||
msdelay = timespec_tomillis(timespec_sub(abs, now));
|
||||
msdelay = MIN(msdelay, -1u);
|
||||
if (_park_norestart(msdelay, waitmask) == -1)
|
||||
return -1;
|
||||
}
|
||||
struct timespec now, wall;
|
||||
uint32_t minRes, maxRes, oldRes;
|
||||
sys_clock_gettime_nt(0, &wall);
|
||||
if (sys_clock_gettime_nt(clock, &now))
|
||||
return -1;
|
||||
bool wantRes = clock == CLOCK_REALTIME || //
|
||||
clock == CLOCK_MONOTONIC || //
|
||||
clock == CLOCK_BOOTTIME;
|
||||
if (wantRes && !atomic_fetch_add(&usingRes, 1))
|
||||
changedRes = NtSuccess(NtQueryTimerResolution(&minRes, &maxRes, &oldRes)) &&
|
||||
NtSuccess(NtSetTimerResolution(maxRes, true, &oldRes));
|
||||
if (timespec_cmp(abs, now) > 0)
|
||||
wall = timespec_add(wall, timespec_sub(abs, now));
|
||||
int rc = _park_norestart(wall, waitmask);
|
||||
if (wantRes && atomic_fetch_sub(&usingRes, 1) == 1 && changedRes)
|
||||
NtSetTimerResolution(0, false, &minRes);
|
||||
return rc;
|
||||
}
|
||||
|
||||
textwindows int sys_clock_nanosleep_nt(int clock, int flags,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue