| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- /*
- * Copyright (C) 2023 Amazon Inc. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
- #include "platform_api_extension.h"
- #include <winternl.h>
- #include "win_util.h"
- #define NANOSECONDS_PER_SECOND 1000000000ULL
- #define NANOSECONDS_PER_TICK 100
- static __wasi_errno_t
- calculate_monotonic_clock_frequency(uint64 *out_frequency)
- {
- LARGE_INTEGER frequency;
- if (!QueryPerformanceFrequency(&frequency))
- return convert_windows_error_code(GetLastError());
- *out_frequency = (uint64)frequency.QuadPart;
- return __WASI_ESUCCESS;
- }
- static __wasi_errno_t
- get_performance_counter_value(uint64 *out_counter)
- {
- LARGE_INTEGER counter;
- if (!QueryPerformanceCounter(&counter))
- return convert_windows_error_code(GetLastError());
- *out_counter = counter.QuadPart;
- return __WASI_ESUCCESS;
- }
- __wasi_errno_t
- os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution)
- {
- __wasi_errno_t error = __WASI_ESUCCESS;
- switch (clock_id) {
- case __WASI_CLOCK_MONOTONIC:
- {
- uint64 frequency;
- error = calculate_monotonic_clock_frequency(&frequency);
- if (error != __WASI_ESUCCESS)
- return error;
- const uint64 result = (uint64)NANOSECONDS_PER_SECOND / frequency;
- *resolution = result;
- return error;
- }
- case __WASI_CLOCK_REALTIME:
- case __WASI_CLOCK_PROCESS_CPUTIME_ID:
- case __WASI_CLOCK_THREAD_CPUTIME_ID:
- {
- #if WINAPI_PARTITION_DESKTOP
- ULONG maximum_time;
- ULONG minimum_time;
- ULONG current_time;
- NTSTATUS
- status = NtQueryTimerResolution(&maximum_time, &minimum_time,
- ¤t_time);
- uint64 result = (uint64)current_time * NANOSECONDS_PER_TICK;
- *resolution = result / (uint64)NANOSECONDS_PER_SECOND;
- return error;
- #else
- return __WASI_ENOTSUP;
- #endif
- }
- default:
- return __WASI_EINVAL;
- }
- }
- __wasi_errno_t
- os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision,
- __wasi_timestamp_t *time)
- {
- __wasi_errno_t error = __WASI_ESUCCESS;
- switch (clock_id) {
- case __WASI_CLOCK_REALTIME:
- {
- FILETIME sys_now;
- #if NTDDI_VERSION >= NTDDI_WIN8
- GetSystemTimePreciseAsFileTime(&sys_now);
- #else
- GetSystemTimeAsFileTime(&sys_now);
- #endif
- *time = convert_filetime_to_wasi_timestamp(&sys_now);
- return BHT_OK;
- }
- case __WASI_CLOCK_MONOTONIC:
- {
- uint64 frequency;
- error = calculate_monotonic_clock_frequency(&frequency);
- if (error != __WASI_ESUCCESS)
- return error;
- uint64 counter;
- error = get_performance_counter_value(&counter);
- if (error != __WASI_ESUCCESS)
- return error;
- if (NANOSECONDS_PER_SECOND % frequency == 0) {
- *time = counter * NANOSECONDS_PER_SECOND / frequency;
- }
- else {
- uint64 seconds = counter / frequency;
- uint64 fractions = counter % frequency;
- *time = seconds * NANOSECONDS_PER_SECOND
- + (fractions * NANOSECONDS_PER_SECOND) / frequency;
- }
- return error;
- }
- case __WASI_CLOCK_PROCESS_CPUTIME_ID:
- case __WASI_CLOCK_THREAD_CPUTIME_ID:
- {
- FILETIME creation_time;
- FILETIME exit_time;
- FILETIME kernel_time;
- FILETIME user_time;
- HANDLE handle = (clock_id == __WASI_CLOCK_PROCESS_CPUTIME_ID)
- ? GetCurrentProcess()
- : GetCurrentThread();
- if (!GetProcessTimes(handle, &creation_time, &exit_time,
- &kernel_time, &user_time))
- return convert_windows_error_code(GetLastError());
- *time = convert_filetime_to_wasi_timestamp(&kernel_time)
- + convert_filetime_to_wasi_timestamp(&user_time);
- return error;
- }
- default:
- return __WASI_EINVAL;
- }
- }
|