summaryrefslogtreecommitdiff
path: root/timer.c
diff options
context:
space:
mode:
authorPeter Fors <peter.fors@mindkiller.com>2025-10-09 22:07:52 +0200
committerPeter Fors <peter.fors@mindkiller.com>2025-10-09 22:07:52 +0200
commit030724a9aea346e4a9843d5842fb28c6d6c4cf1a (patch)
treef06fb84aaef64b2f4e2d81b3d2d3eef71bad83ec /timer.c
parent412b2ef851516c1de8ba5006ddd284192cbcaf9b (diff)
Rearrangement and refactoring and optimizations and more accuracy
Diffstat (limited to 'timer.c')
-rw-r--r--timer.c149
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