Skip to content

Commit

Permalink
spl-time: Use KeQueryPerformanceCounter instead of KeQueryTickCount (o…
Browse files Browse the repository at this point in the history
…penzfs#326)

* spl-time: Use KeQueryPerformanceCounter instead of KeQueryTickCount

`KeQueryTickCount` seems to only have a 15.625ms resolution unless the
interrupt timer frequency is increased, which should be avoided due to
power usage.

Instead, this switches the `zfs_lbolt`, `gethrtime` and
`random_get_bytes` to use `KeQueryPerformanceCounter`.

On my system this gives a 100ns resolution.

Signed-off-by: Axel Gembe <axel@gembe.net>

* spl-time: Add assertion to gethrtime and cache NANOSEC / freq division

One less division for each call.

Signed-off-by: Axel Gembe <axel@gembe.net>

---------

Signed-off-by: Axel Gembe <axel@gembe.net>
  • Loading branch information
EchterAgo authored and lundman committed Dec 11, 2023
1 parent 8aa2396 commit eb5e25d
Showing 1 changed file with 12 additions and 18 deletions.
30 changes: 12 additions & 18 deletions module/os/windows/spl/spl-time.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,12 @@
* origin. Hence its primary use is to specify intervals.
*/

static hrtime_t
zfs_abs_to_nano(uint64_t elapsed)
{
return (elapsed * KeQueryTimeIncrement() * 100);
}

/* Open Solaris lbolt is in hz */
uint64_t
zfs_lbolt(void)
{
uint64_t lbolt_hz;
LARGE_INTEGER ticks;
KeQueryTickCount(&ticks);
lbolt_hz = ticks.QuadPart * KeQueryTimeIncrement();
lbolt_hz = gethrtime() / 100;
lbolt_hz /= (10000000 / 119); // Solaris hz ?
return (lbolt_hz);
}
Expand All @@ -59,14 +51,16 @@ hrtime_t
gethrtime(void)
{
static LARGE_INTEGER start = { 0 };
static LARGE_INTEGER freq = { 0 };
LARGE_INTEGER now;
if (start.QuadPart == 0) {
KeQueryTickCount(&start);
start.QuadPart--;
start = KeQueryPerformanceCounter(&freq);
ASSERT(freq.QuadPart < NANOSEC);
ASSERT(freq.QuadPart > 0);
freq.QuadPart = NANOSEC / freq.QuadPart;
}
KeQueryTickCount(&now);
ASSERT((now.QuadPart != start.QuadPart));
return (zfs_abs_to_nano(now.QuadPart - start.QuadPart));
now = KeQueryPerformanceCounter(NULL);
return ((now.QuadPart - start.QuadPart) * freq.QuadPart);
}

/*
Expand All @@ -76,21 +70,21 @@ gethrtime(void)
int
random_get_bytes(uint8_t *ptr, uint32_t len)
{
LARGE_INTEGER TickCount;
LARGE_INTEGER PerfCounter;
ULONG r;
PULONG b;
int i;

KeQueryTickCount(&TickCount);
PerfCounter = KeQueryPerformanceCounter(NULL);

b = (PULONG) ptr;

for (i = 0; i < len / sizeof (ULONG); i++)
b[i] = RtlRandomEx(&TickCount.LowPart);
b[i] = RtlRandomEx(&PerfCounter.LowPart);

len &= (sizeof (ULONG) - 1);
if (len > 0) {
r = RtlRandomEx(&TickCount.LowPart);
r = RtlRandomEx(&PerfCounter.LowPart);
RtlCopyMemory(&b[i], &r, len);
}
return (0);
Expand Down

0 comments on commit eb5e25d

Please sign in to comment.