diff options
| author | Peter Fors <peter.fors@mindkiller.com> | 2025-10-09 22:07:52 +0200 |
|---|---|---|
| committer | Peter Fors <peter.fors@mindkiller.com> | 2025-10-09 22:07:52 +0200 |
| commit | 030724a9aea346e4a9843d5842fb28c6d6c4cf1a (patch) | |
| tree | f06fb84aaef64b2f4e2d81b3d2d3eef71bad83ec /timer.c | |
| parent | 412b2ef851516c1de8ba5006ddd284192cbcaf9b (diff) | |
Rearrangement and refactoring and optimizations and more accuracy
Diffstat (limited to 'timer.c')
| -rw-r--r-- | timer.c | 149 |
1 files changed, 0 insertions, 149 deletions
diff --git a/timer.c b/timer.c deleted file mode 100644 index 96eb453..0000000 --- a/timer.c +++ /dev/null @@ -1,149 +0,0 @@ - - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <stdint.h> -#include <stdbool.h> - -struct timer_handle { - HANDLE htimer; - uint64_t interval_ns; - uint64_t qpc_frequency; - uint64_t next_deadline; - bool started; -}; - -static inline uint64_t qpc_now_ns(uint64_t freq) { - LARGE_INTEGER qpc; - QueryPerformanceCounter(&qpc); - return (uint64_t)((qpc.QuadPart * 1000000000ULL) / freq); -} - -struct timer_handle *timer_new(uint64_t interval_ns) { - struct timer_handle *t = (struct timer_handle *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct timer_handle)); - if(!t) return 0; - - t->htimer = CreateWaitableTimerW(0, TRUE, 0); - if(!t->htimer) { - HeapFree(GetProcessHeap(), 0, t); - return 0; - } - - LARGE_INTEGER freq; - QueryPerformanceFrequency(&freq); - t->qpc_frequency = freq.QuadPart; - t->interval_ns = interval_ns; - t->started = false; - - return t; -} - -bool timer_start(struct timer_handle *t) { - t->next_deadline = qpc_now_ns(t->qpc_frequency) + t->interval_ns; - t->started = true; - return true; -} - -bool timer_wait(struct timer_handle *t) { - if(!t->started) return false; - - uint64_t now = qpc_now_ns(t->qpc_frequency); - if(t->next_deadline <= now) { - t->next_deadline += t->interval_ns; - return true; - } - - uint64_t sleep_ns = t->next_deadline - now; - if(sleep_ns > 500000) { // > 0.5ms - LARGE_INTEGER due; - due.QuadPart = -(int64_t)((sleep_ns - 500000) / 100); // 100ns units, negative = relative - SetWaitableTimer(t->htimer, &due, 0, 0, 0, 0); - WaitForSingleObject(t->htimer, INFINITE); - } - - while(qpc_now_ns(t->qpc_frequency) < t->next_deadline) { - YieldProcessor(); // pause instruction - } - - t->next_deadline += t->interval_ns; - return true; -} - -void timer_destroy(struct timer_handle *t) { - if(t) { - if(t->htimer) CloseHandle(t->htimer); - HeapFree(GetProcessHeap(), 0, t); - } -} - - -#else // Linux -#include <sys/timerfd.h> -#include <sys/epoll.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdint.h> -#include <stdbool.h> - -struct timer_handle { - int tfd; - int epfd; - struct itimerspec spec; - int started; -}; - -static struct timer_handle *timer_new(uint64_t interval_ns) { - struct timer_handle *t = (struct timer_handle *)malloc(sizeof(struct timer_handle)); - if(!t) return 0; - - t->tfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); - if(t->tfd < 0) { free(t); return 0; } - - t->epfd = epoll_create1(EPOLL_CLOEXEC); - if(t->epfd < 0) { - close(t->tfd); free(t); return 0; - } - - struct epoll_event ev = { .events = EPOLLIN, .data = { .fd = t->tfd } }; - epoll_ctl(t->epfd, EPOLL_CTL_ADD, t->tfd, &ev); - - t->spec.it_interval.tv_sec = interval_ns / 1000000000ULL; - t->spec.it_interval.tv_nsec = interval_ns % 1000000000ULL; - t->spec.it_value.tv_sec = 0; - t->spec.it_value.tv_nsec = 0; - t->started = 0; - - return t; -} - -static bool timer_start(struct timer_handle *t) { - if(t->started) return true; - - t->spec.it_value = t->spec.it_interval; - if(timerfd_settime(t->tfd, 0, &t->spec, 0)) return false; - - t->started = 1; - return true; -} - -static bool timer_wait(struct timer_handle *t) { - if(!t->started) return false; - - struct epoll_event ev; - int r = epoll_wait(t->epfd, &ev, 1, -1); - if(r < 0) return false; - uint64_t expirations; - read(t->tfd, &expirations, sizeof(expirations)); - return true; -} - -static void timer_destroy(struct timer_handle *t) { - if(t) { - if(t->tfd >= 0) close(t->tfd); - if(t->epfd >= 0) close(t->epfd); - free(t); - } -} - -#endif |
