42 static size_t io_timer_impl_dev_cancel(
io_dev_t *dev,
struct ev_task *task);
43 static size_t io_timer_impl_dev_abort(
io_dev_t *dev,
struct ev_task *task);
46 static const struct io_dev_vtbl io_timer_impl_dev_vtbl = {
47 &io_timer_impl_dev_get_ctx,
48 &io_timer_impl_dev_get_exec,
49 &io_timer_impl_dev_cancel,
50 &io_timer_impl_dev_abort
56 static int io_timer_impl_getoverrun(
const io_timer_t *timer);
57 static int io_timer_impl_gettime(
58 const io_timer_t *timer,
struct itimerspec *value);
59 static int io_timer_impl_settime(
io_timer_t *timer,
int flags,
60 const struct itimerspec *value,
struct itimerspec *ovalue);
61 static void io_timer_impl_submit_wait(
66 &io_timer_impl_get_dev,
67 &io_timer_impl_get_clock,
68 &io_timer_impl_getoverrun,
69 &io_timer_impl_gettime,
70 &io_timer_impl_settime,
71 &io_timer_impl_submit_wait
75 static void io_timer_impl_svc_shutdown(
struct io_svc *svc);
78 static const struct io_svc_vtbl io_timer_impl_svc_vtbl = {
80 &io_timer_impl_svc_shutdown
92 CRITICAL_SECTION CriticalSection1;
97 CRITICAL_SECTION CriticalSection2;
99 struct itimerspec value;
102 CRITICAL_SECTION CriticalSection3;
107 static void CALLBACK io_timer_impl_func(
108 PVOID lpParameter, BOOLEAN TimerOrWaitFired);
111 static inline struct io_timer_impl *io_timer_impl_from_timer(
114 const struct io_svc *svc);
127 return &impl->timer_vptr;
131 io_timer_free(
void *ptr)
134 free(io_timer_impl_from_timer(ptr));
141 struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
147 impl->dev_vptr = &io_timer_impl_dev_vtbl;
148 impl->timer_vptr = &io_timer_impl_vtbl;
155 impl->clockid = clockid;
158 InitializeCriticalSection(&impl->CriticalSection1);
164 InitializeCriticalSection(&impl->CriticalSection2);
166 impl->value = (
struct itimerspec){ { 0, 0 }, { 0, 0 } };
170 InitializeCriticalSection(&impl->CriticalSection3);
182 struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
186 io_timer_impl_svc_shutdown(&impl->svc);
189 DeleteTimerQueueTimer(NULL, impl->Timer, INVALID_HANDLE_VALUE);
192 DeleteCriticalSection(&impl->CriticalSection3);
193 DeleteCriticalSection(&impl->CriticalSection2);
194 DeleteCriticalSection(&impl->CriticalSection1);
205 dwErrCode = GetLastError();
209 io_timer_t *tmp = io_timer_init(timer, poll, exec, clockid);
211 dwErrCode = GetLastError();
219 io_timer_free((
void *)timer);
221 SetLastError(dwErrCode);
229 io_timer_fini(timer);
230 io_timer_free((
void *)timer);
235 io_timer_impl_dev_get_ctx(
const io_dev_t *dev)
237 const struct io_timer_impl *impl = io_timer_impl_from_dev(dev);
243 io_timer_impl_dev_get_exec(
const io_dev_t *dev)
245 const struct io_timer_impl *impl = io_timer_impl_from_dev(dev);
258 io_timer_impl_pop(impl, &queue, task);
260 return io_timer_wait_queue_post(&queue, -1, ERROR_OPERATION_ABORTED);
271 io_timer_impl_pop(impl, &queue, task);
277 io_timer_impl_get_dev(
const io_timer_t *timer)
279 const struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
281 return &impl->dev_vptr;
285 io_timer_impl_get_clock(
const io_timer_t *timer)
287 const struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
288 assert(impl->clockid == CLOCK_REALTIME
289 || impl->clockid == CLOCK_MONOTONIC);
291 switch (impl->clockid) {
294 default:
return NULL;
299 io_timer_impl_getoverrun(
const io_timer_t *timer)
301 const struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
304 EnterCriticalSection((LPCRITICAL_SECTION)&impl->CriticalSection2);
306 int overrun = impl->overrun;
308 LeaveCriticalSection((LPCRITICAL_SECTION)&impl->CriticalSection2);
315 io_timer_impl_gettime(
const io_timer_t *timer,
struct itimerspec *value)
317 const struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
321 EnterCriticalSection((LPCRITICAL_SECTION)&impl->CriticalSection2);
323 struct itimerspec value_ = impl->value;
325 LeaveCriticalSection((LPCRITICAL_SECTION)&impl->CriticalSection2);
328 if (value_.it_value.tv_sec || value_.it_value.tv_nsec) {
329 struct timespec now = { 0, 0 };
330 if (clock_gettime(impl->clockid, &now) == -1) {
344 io_timer_impl_settime(
io_timer_t *timer,
int flags,
345 const struct itimerspec *value,
struct itimerspec *ovalue)
347 struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
350 struct timespec now = { 0, 0 };
351 if (clock_gettime(impl->clockid, &now) == -1) {
356 ULONGLONG DueTime = 0;
357 ULONGLONG Period = 0;
359 struct timespec period = value->it_interval;
360 struct timespec expiry = value->it_value;
361 int arm = expiry.tv_sec || expiry.tv_nsec;
363 if (period.tv_nsec < 0 || period.tv_nsec >= 1000000000l) {
364 SetLastError(ERROR_INVALID_PARAMETER);
367 if (period.tv_sec < 0)
368 period = (
struct timespec){ 0, 0 };
369 Period = (ULONGLONG)period.tv_sec * 1000
370 + (period.tv_nsec + 999999l) / 1000000l;
371 period.tv_nsec = (Period % 1000) * 1000000l;
372 if (Period > ULONG_MAX) {
373 SetLastError(ERROR_INVALID_PARAMETER);
377 if (expiry.tv_nsec < 0 || expiry.tv_nsec >= 1000000000l) {
378 SetLastError(ERROR_INVALID_PARAMETER);
381 if (flags & TIMER_ABSTIME)
383 if (expiry.tv_sec < 0)
384 expiry = (
struct timespec){ 0, 0 };
385 DueTime = (ULONGLONG)expiry.tv_sec * 1000
386 + (expiry.tv_nsec + 999999l) / 1000000l;
387 if (DueTime > ULONG_MAX) {
388 SetLastError(ERROR_INVALID_PARAMETER);
394 period = (
struct timespec){ 0, 0 };
398 DWORD dwErrCode = GetLastError();
401 EnterCriticalSection(&impl->CriticalSection3);
405 DeleteTimerQueueTimer(NULL, impl->Timer, INVALID_HANDLE_VALUE);
410 EnterCriticalSection(&impl->CriticalSection2);
413 struct itimerspec ovalue_ = impl->value;
414 if (ovalue_.it_value.tv_sec || ovalue_.it_value.tv_nsec)
416 impl->value = (
struct itimerspec){ period, expiry };
420 ULONG Flags = WT_EXECUTEDEFAULT;
422 Flags |= WT_EXECUTEONLYONCE;
425 if (arm && !CreateTimerQueueTimer(&impl->Timer, NULL,
426 &io_timer_impl_func, impl, DueTime, Period, Flags)) {
429 dwErrCode = GetLastError();
431 impl->value = (
struct itimerspec){ { 0, 0 }, { 0, 0 } };
435 LeaveCriticalSection(&impl->CriticalSection2);
436 LeaveCriticalSection(&impl->CriticalSection3);
442 SetLastError(dwErrCode);
449 struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
454 task->
exec = impl->exec;
458 EnterCriticalSection(&impl->CriticalSection1);
460 if (impl->shutdown) {
462 LeaveCriticalSection(&impl->CriticalSection1);
464 io_timer_wait_post(wait, -1, ERROR_OPERATION_ABORTED);
468 LeaveCriticalSection(&impl->CriticalSection1);
474 io_timer_impl_svc_shutdown(
struct io_svc *svc)
480 EnterCriticalSection(&impl->CriticalSection1);
482 int shutdown = !impl->shutdown;
485 LeaveCriticalSection(&impl->CriticalSection1);
489 io_timer_impl_dev_cancel(dev, NULL);
493 io_timer_impl_func(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
497 (void)TimerOrWaitFired;
503 struct timespec now = { 0, 0 };
504 if (clock_gettime(impl->clockid, &now) == -1) {
513 EnterCriticalSection(&impl->CriticalSection2);
517 struct timespec *period = &impl->value.it_interval;
518 struct timespec *expiry = &impl->value.it_value;
519 if (period->tv_sec || period->tv_nsec) {
520 assert(!(period->tv_nsec % 1000000l));
521 ULONG Period = period->tv_sec * 1000
522 + period->tv_nsec / 1000000l;
526 impl->overrun =
MIN(
MAX(overrun, INT_MIN), INT_MAX);
528 *expiry = (
struct timespec){ 0, 0 };
531 overrun = impl->overrun;
534 if (overrun >= 0 || errc)
538 LeaveCriticalSection(&impl->CriticalSection2);
541 io_timer_wait_queue_post(&queue, overrun, errc);
546 io_timer_impl_from_dev(
const io_dev_t *dev)
554 io_timer_impl_from_timer(
const io_timer_t *timer)
562 io_timer_impl_from_svc(
const struct io_svc *svc)
577 EnterCriticalSection(&impl->CriticalSection1);
584 LeaveCriticalSection(&impl->CriticalSection1);