diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 374272f4c..32c02b87b 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -354,6 +354,7 @@ DLL_OFILES:= \ pinfo.o \ poll.o \ posix_ipc.o \ + posix_timer.o \ pseudo-reloc.o \ pthread.o \ quotactl.o \ @@ -395,7 +396,6 @@ DLL_OFILES:= \ syslog.o \ termios.o \ thread.o \ - timer.o \ timerfd.o \ times.o \ tls_pbuf.o \ diff --git a/winsup/cygwin/cygheap_malloc.h b/winsup/cygwin/cygheap_malloc.h index 74f0bb619..cd545c35d 100644 --- a/winsup/cygwin/cygheap_malloc.h +++ b/winsup/cygwin/cygheap_malloc.h @@ -34,7 +34,8 @@ enum cygheap_types HEAP_2_DLL, HEAP_MMAP, HEAP_2_MAX = 200, - HEAP_3_FHANDLER + HEAP_3_FHANDLER, + HEAP_3_TIMER }; extern "C" { diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 205ad850e..491eedbe4 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -27,7 +27,7 @@ details. */ #include "child_info.h" #include "ntdll.h" #include "exception.h" -#include "timer.h" +#include "posix_timer.h" /* Definitions for code simplification */ #ifdef __x86_64__ @@ -1483,7 +1483,7 @@ sigpacket::process () if (handler == SIG_IGN) { if (si.si_code == SI_TIMER) - ((timer_tracker *) si.si_tid)->disarm_event (); + ((timer_tracker *) si.si_tid)->disarm_overrun_event (); sigproc_printf ("signal %d ignored", si.si_signo); goto done; } @@ -1508,7 +1508,7 @@ sigpacket::process () || si.si_signo == SIGURG) { if (si.si_code == SI_TIMER) - ((timer_tracker *) si.si_tid)->disarm_event (); + ((timer_tracker *) si.si_tid)->disarm_overrun_event (); sigproc_printf ("signal %d default is currently ignore", si.si_signo); goto done; } @@ -1637,7 +1637,7 @@ _cygtls::call_signal_handler () { timer_tracker *tt = (timer_tracker *) infodata.si_tid; - infodata.si_overrun = tt->disarm_event (); + infodata.si_overrun = tt->disarm_overrun_event (); } /* Save information locally on stack to pass to handler. */ diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 5cfdd9559..6813446cf 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -22,7 +22,6 @@ details. */ #include "tls_pbuf.h" #include "dll_init.h" #include "cygmalloc.h" -#include "timer.h" #include "ntdll.h" #define NPIDS_HELD 4 @@ -196,7 +195,6 @@ frok::child (volatile char * volatile here) ForceCloseHandle1 (fork_info->forker_finished, forker_finished); pthread::atforkchild (); - fixup_timers_after_fork (); cygbench ("fork-child"); ld_preload (); fixup_hooks_after_fork (); diff --git a/winsup/cygwin/timer.cc b/winsup/cygwin/posix_timer.cc similarity index 50% rename from winsup/cygwin/timer.cc rename to winsup/cygwin/posix_timer.cc index e24edd5e9..d4f2575f1 100644 --- a/winsup/cygwin/timer.cc +++ b/winsup/cygwin/posix_timer.cc @@ -14,65 +14,37 @@ details. */ #include "fhandler.h" #include "dtable.h" #include "cygheap.h" -#include "timer.h" +#include "posix_timer.h" #include -#define EVENT_DISARMED 0 -#define EVENT_ARMED -1 -#define EVENT_LOCK 1 +#define OVR_EVENT_DISARMED 0 +#define OVR_EVENT_ARMED 1 -/* Must not be NO_COPY to avoid memory leak after fork. */ -timer_tracker ttstart (CLOCK_REALTIME, NULL); - -class lock_timer_tracker -{ - static muto protect; -public: - lock_timer_tracker (); - ~lock_timer_tracker (); -}; - -muto NO_COPY lock_timer_tracker::protect; - -lock_timer_tracker::lock_timer_tracker () -{ - protect.init ("timer_protect")->acquire (); -} - -lock_timer_tracker::~lock_timer_tracker () -{ - protect.release (); -} +timer_tracker NO_COPY itimer_tracker (CLOCK_REALTIME, NULL); bool timer_tracker::cancel () { - if (!hcancel) - return false; + DWORD res; - SetEvent (hcancel); - DWORD res = WaitForSingleObject (syncthread, INFINITE); - if (res != WAIT_OBJECT_0) - system_printf ("WFSO returned unexpected value %u, %E", res); + if (!cancel_evt) + return false; + SetEvent (cancel_evt); + if (sync_thr) + { + res = WaitForSingleObject (sync_thr, INFINITE); + if (res != WAIT_OBJECT_0) + system_printf ("WFSO returned unexpected value %u, %E", res); + } return true; } -timer_tracker::~timer_tracker () -{ - if (cancel ()) - { - CloseHandle (hcancel); -#ifdef DEBUGGING - hcancel = NULL; -#endif - } - if (syncthread) - CloseHandle (syncthread); - magic = 0; -} - timer_tracker::timer_tracker (clockid_t c, const sigevent *e) +: magic (TT_MAGIC), clock_id (c), timer (NULL), cancel_evt (NULL), + sync_thr (NULL), interval (0), exp_ts (0), overrun_event_running (0), + overrun_count_curr (0), overrun_count (0) { + srwlock = SRWLOCK_INIT; if (e != NULL) evp = *e; else @@ -81,18 +53,17 @@ timer_tracker::timer_tracker (clockid_t c, const sigevent *e) evp.sigev_signo = SIGALRM; evp.sigev_value.sival_ptr = this; } - clock_id = c; - magic = TT_MAGIC; - hcancel = NULL; - event_running = EVENT_DISARMED; - overrun_count_curr = 0; - overrun_count = 0; - if (this != &ttstart) - { - lock_timer_tracker here; - next = ttstart.next; - ttstart.next = this; - } +} + +timer_tracker::~timer_tracker () +{ + AcquireSRWLockExclusive (&srwlock); + cancel (); + NtClose (cancel_evt); + NtClose (sync_thr); + NtClose (timer); + magic = 0; + ReleaseSRWLockExclusive (&srwlock); } static inline int64_t @@ -105,29 +76,26 @@ timespec_to_us (const timespec& ts) } /* Returns 0 if arming successful, -1 if a signal is already queued. - If so, it also increments overrun_count. */ + If so, it also increments overrun_count. Only call under lock! */ LONG -timer_tracker::arm_event () +timer_tracker::arm_overrun_event () { LONG ret; - while ((ret = InterlockedCompareExchange (&event_running, EVENT_ARMED, - EVENT_DISARMED)) == EVENT_LOCK) - yield (); - if (ret == EVENT_ARMED) - InterlockedIncrement64 (&overrun_count); + ret = InterlockedExchange (&overrun_event_running, OVR_EVENT_ARMED); + if (ret == OVR_EVENT_ARMED) + ret = InterlockedIncrement64 (&overrun_count); return ret; } LONG -timer_tracker::disarm_event () +timer_tracker::disarm_overrun_event () { LONG ret; - while ((ret = InterlockedCompareExchange (&event_running, EVENT_LOCK, - EVENT_ARMED)) == EVENT_LOCK) - yield (); - if (ret == EVENT_ARMED) + AcquireSRWLockExclusive (&srwlock); + ret = InterlockedExchange (&overrun_event_running, OVR_EVENT_DISARMED); + if (ret == OVR_EVENT_ARMED) { LONG64 ov_cnt; @@ -138,8 +106,8 @@ timer_tracker::disarm_event () overrun_count_curr = ov_cnt; ret = overrun_count_curr; InterlockedExchange64 (&overrun_count, 0); - InterlockedExchange (&event_running, EVENT_DISARMED); } + ReleaseSRWLockExclusive (&srwlock); return ret; } @@ -151,57 +119,69 @@ notify_thread_wrapper (void *arg) void * (*notify_func) (void *) = (void * (*) (void *)) evt->sigev_notify_function; - tt->disarm_event (); + tt->disarm_overrun_event (); return notify_func (evt->sigev_value.sival_ptr); } DWORD timer_tracker::thread_func () { - int64_t now; - int64_t cur_sleepto_us = sleepto_us; + HANDLE w4[2] = { timer, cancel_evt }; + + debug_printf ("%p timer armed", this); while (1) { - int64_t sleep_us; - LONG sleep_ms; - /* Account for delays in starting thread - and sending the signal */ - now = get_clock (clock_id)->usecs (); - sleep_us = cur_sleepto_us - now; - if (sleep_us > 0) + switch (WaitForMultipleObjects (2, w4, FALSE, INFINITE)) { - sleepto_us = cur_sleepto_us; - sleep_ms = (sleep_us + (USPERSEC / MSPERSEC) - 1) - / (USPERSEC / MSPERSEC); - } - else - { - int64_t num_intervals = (now - cur_sleepto_us) / interval_us; - InterlockedAdd64 (&overrun_count, num_intervals); - cur_sleepto_us += num_intervals * interval_us; - sleepto_us = cur_sleepto_us; - sleep_ms = 0; - } - - debug_printf ("%p waiting for %u ms", this, sleep_ms); - switch (WaitForSingleObject (hcancel, sleep_ms)) - { - case WAIT_TIMEOUT: - debug_printf ("timed out"); - break; case WAIT_OBJECT_0: - debug_printf ("%p cancelled", this); + debug_printf ("%p timer expired", this); + break; + case WAIT_OBJECT_0 + 1: + debug_printf ("%p timer disarmed, %E", this); goto out; default: debug_printf ("%p wait failed, %E", this); + continue; + } + AcquireSRWLockExclusive (&srwlock); + /* Make sure we haven't been abandoned and/or disarmed in the meantime */ + if (exp_ts == 0 && interval == 0) + { + ReleaseSRWLockExclusive (&srwlock); goto out; } + if (interval) + { + /* Compute expiration count. */ + LONG64 now = get_clock_now (); + LONG64 ts = get_exp_ts (); + LONG64 exp_cnt; + /* Make concessions for unexact realtime clock */ + if (ts > now) + ts = now - 1; + exp_cnt = (now - ts) / interval; + InterlockedAdd64 (&overrun_count, exp_cnt); + ts += interval * exp_cnt; + set_exp_ts (ts); + /* NtSetTimer allows periods of up to 24 days only. If the time + is longer, we set the timer up as one-shot timer for each + interval. Restart timer here with new due time. */ + if (interval > INT_MAX * (NS100PERSEC / MSPERSEC)) + { + /* TODO: CLOCK_REALTIME_ALARM / CLOCK_BOOTTIME_ALARM + See comment in arm_timer */ + BOOL Resume = FALSE; + LARGE_INTEGER DueTime = { QuadPart: -interval }; + + NtSetTimer (timer, &DueTime, NULL, NULL, Resume, 0, NULL); + } + } switch (evp.sigev_notify) { case SIGEV_SIGNAL: { - if (arm_event ()) + if (arm_overrun_event ()) { debug_printf ("%p timer signal already queued", this); break; @@ -217,7 +197,7 @@ timer_tracker::thread_func () } case SIGEV_THREAD: { - if (arm_event ()) + if (arm_overrun_event ()) { debug_printf ("%p timer thread already queued", this); break; @@ -243,10 +223,16 @@ timer_tracker::thread_func () break; } } - if (!interval_us) - break; - - cur_sleepto_us = sleepto_us + interval_us; + /* one-shot timer? */ + if (!interval) + { + memset (&time_spec, 0, sizeof time_spec); + exp_ts = 0; + overrun_event_running = OVR_EVENT_DISARMED; + ReleaseSRWLockExclusive (&srwlock); + goto out; + } + ReleaseSRWLockExclusive (&srwlock); debug_printf ("looping"); } @@ -262,58 +248,166 @@ timer_thread (VOID *x) return tt->thread_func (); } -static inline bool -timespec_bad (const timespec& t) +int +timer_tracker::gettime (itimerspec *curr_value, bool lock) { - if (t.tv_nsec < 0 || t.tv_nsec >= NSPERSEC || t.tv_sec < 0) + if (lock) { - set_errno (EINVAL); - return true; + AcquireSRWLockExclusive (&srwlock); + if (!is_timer_tracker ()) + { + ReleaseSRWLockExclusive (&srwlock); + return -EINVAL; + } } - return false; + if (!cancel_evt) + memset (curr_value, 0, sizeof (*curr_value)); + else + { + LONG64 next_relative_exp = get_exp_ts () - get_clock_now (); + curr_value->it_value.tv_sec = next_relative_exp / NS100PERSEC; + next_relative_exp -= curr_value->it_value.tv_sec * NS100PERSEC; + curr_value->it_value.tv_nsec = next_relative_exp + * (NSPERSEC / NS100PERSEC); + curr_value->it_interval = time_spec.it_interval; + } + if (lock) + ReleaseSRWLockExclusive (&srwlock); + return 0; } int -timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalue) +timer_tracker::settime (int flags, const itimerspec *new_value, + itimerspec *old_value) { int ret = -1; __try { - if (!value) + if (!new_value || !valid_timespec (new_value->it_value) + || !valid_timespec (new_value->it_interval)) { - set_errno (EINVAL); + ret = -EINVAL; __leave; } - if (timespec_bad (value->it_value) || timespec_bad (value->it_interval)) - __leave; + AcquireSRWLockExclusive (&srwlock); + if (!is_timer_tracker ()) + { + ReleaseSRWLockExclusive (&srwlock); + ret = -EINVAL; + __leave; + } - lock_timer_tracker here; - cancel (); + if (old_value) + gettime (old_value, false); - if (ovalue) - gettime (ovalue); - - if (!value->it_value.tv_sec && !value->it_value.tv_nsec) - interval_us = sleepto_us = 0; + if (!new_value->it_value.tv_sec && !new_value->it_value.tv_nsec) + { + cancel (); + memset (&time_spec, 0, sizeof time_spec); + interval = 0; + exp_ts = 0; + } else { - interval_us = timespec_to_us (value->it_interval); - sleepto_us = timespec_to_us (value->it_value); - if (!(in_flags & TIMER_ABSTIME)) - sleepto_us += get_clock (clock_id)->usecs (); - it_interval = value->it_interval; - if (!hcancel) - hcancel = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); + LONG64 ts; + LARGE_INTEGER DueTime; + BOOLEAN Resume; + LONG Period; + NTSTATUS status; + + if (!timer) + { + OBJECT_ATTRIBUTES attr; + + InitializeObjectAttributes (&attr, NULL, 0, NULL, + sec_none_nih.lpSecurityDescriptor); + status = NtCreateEvent (&cancel_evt, EVENT_ALL_ACCESS, &attr, + NotificationEvent, FALSE); + if (!NT_SUCCESS (status)) + { + ret = -geterrno_from_nt_status (status); + __leave; + } + status = NtCreateEvent (&sync_thr, EVENT_ALL_ACCESS, &attr, + NotificationEvent, FALSE); + if (!NT_SUCCESS (status)) + { + NtClose (cancel_evt); + cancel_evt = NULL; + ret = -geterrno_from_nt_status (status); + __leave; + } + status = NtCreateTimer (&timer, TIMER_ALL_ACCESS, &attr, + SynchronizationTimer); + if (!NT_SUCCESS (status)) + { + NtClose (cancel_evt); + NtClose (sync_thr); + cancel_evt = sync_thr = NULL; + ret = -geterrno_from_nt_status (status); + __leave; + } + } + ResetEvent (cancel_evt); + ResetEvent (sync_thr); + NtCancelTimer (timer, NULL); + /* Convert incoming itimerspec into 100ns interval and timestamp */ + interval = new_value->it_interval.tv_sec * NS100PERSEC + + (new_value->it_interval.tv_nsec + + (NSPERSEC / NS100PERSEC) - 1) + / (NSPERSEC / NS100PERSEC); + ts = new_value->it_value.tv_sec * NS100PERSEC + + (new_value->it_value.tv_nsec + (NSPERSEC / NS100PERSEC) - 1) + / (NSPERSEC / NS100PERSEC); + if (flags & TIMER_ABSTIME) + { + if (clock_id == CLOCK_REALTIME) + DueTime.QuadPart = ts + FACTOR; + else /* non-REALTIME clocks require relative DueTime. */ + { + DueTime.QuadPart = get_clock_now () - ts; + /* If the timestamp was earlier than now, compute number + of expirations and offset DueTime to expire immediately. */ + if (DueTime.QuadPart >= 0) + DueTime.QuadPart = -1LL; + } + } else - ResetEvent (hcancel); - if (!syncthread) - syncthread = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); + { + /* Keep relative timestamps relative for the timer, but store the + expiry timestamp absolute for the timer thread. */ + DueTime.QuadPart = -ts; + ts += get_clock_now (); + } + set_exp_ts (ts); + time_spec = *new_value; + overrun_count_curr = 0; + overrun_count = 0; + overrun_event_running = OVR_EVENT_DISARMED; + /* TODO: CLOCK_REALTIME_ALARM / CLOCK_BOOTTIME_ALARM + Note: Advanced Power Settings -> Sleep -> Allow Wake Timers + since W10 1709 */ + Resume = FALSE; + if (interval > INT_MAX * (NS100PERSEC / MSPERSEC)) + Period = 0; else - ResetEvent (syncthread); - new cygthread (timer_thread, this, "itimer", syncthread); + Period = (interval + (NS100PERSEC / MSPERSEC) - 1) + / (NS100PERSEC / MSPERSEC); + status = NtSetTimer (timer, &DueTime, NULL, NULL, Resume, Period, + NULL); + if (!NT_SUCCESS (status)) + { + memset (&time_spec, 0, sizeof time_spec); + interval = 0; + exp_ts = 0; + ret = -geterrno_from_nt_status (status); + __leave; + } + new cygthread (timer_thread, this, "itimer", sync_thr); } + ReleaseSRWLockExclusive (&srwlock); ret = 0; } __except (EFAULT) {} @@ -321,78 +415,12 @@ timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalu return ret; } -void -timer_tracker::gettime (itimerspec *ovalue) -{ - if (!hcancel) - memset (ovalue, 0, sizeof (*ovalue)); - else - { - ovalue->it_interval = it_interval; - int64_t now = get_clock (clock_id)->usecs (); - int64_t left_us = sleepto_us - now; - if (left_us < 0) - left_us = 0; - ovalue->it_value.tv_sec = left_us / USPERSEC; - ovalue->it_value.tv_nsec = (left_us % USPERSEC) * (NSPERSEC/USPERSEC); - } -} - -int -timer_tracker::clean_and_unhook () -{ - for (timer_tracker *tt = &ttstart; tt->next != NULL; tt = tt->next) - if (tt->next == this) - { - tt->next = this->next; - return 0; - } - return -1; -} - -void -timer_tracker::fixup_after_fork () -{ - ttstart.hcancel = ttstart.syncthread = NULL; - ttstart.event_running = EVENT_DISARMED; - ttstart.overrun_count_curr = 0; - ttstart.overrun_count = 0; - for (timer_tracker *tt = &ttstart; tt->next != NULL; /* nothing */) - { - timer_tracker *deleteme = tt->next; - tt->next = deleteme->next; - deleteme->hcancel = deleteme->syncthread = NULL; - delete deleteme; - } -} - -void -fixup_timers_after_fork () -{ - timer_tracker::fixup_after_fork (); -} - -extern "C" int -timer_gettime (timer_t timerid, struct itimerspec *ovalue) -{ - int ret = -1; - - __try - { - timer_tracker *tt = (timer_tracker *) timerid; - if (!tt->is_timer_tracker ()) - { - set_errno (EINVAL); - return -1; - } - - tt->gettime (ovalue); - ret = 0; - } - __except (EFAULT) {} - __endtry - return ret; -} +/* The timers are stored on the cygheap. */ +#define cnew(name, ...) \ + ({ \ + void* ptr = (void*) ccalloc (HEAP_3_TIMER, 1, sizeof (name)); \ + ptr ? new (ptr) name (__VA_ARGS__) : NULL; \ + }) extern "C" int timer_create (clockid_t clock_id, struct sigevent *__restrict evp, @@ -414,7 +442,7 @@ timer_create (clockid_t clock_id, struct sigevent *__restrict evp, return -1; } - *timerid = (timer_t) new timer_tracker (clock_id, evp); + *timerid = (timer_t) cnew (timer_tracker, clock_id, evp); ret = 0; } __except (EFAULT) {} @@ -422,6 +450,29 @@ timer_create (clockid_t clock_id, struct sigevent *__restrict evp, return ret; } +extern "C" int +timer_gettime (timer_t timerid, struct itimerspec *ovalue) +{ + int ret = -1; + + __try + { + timer_tracker *tt = (timer_tracker *) timerid; + if (!tt->is_timer_tracker ()) + { + set_errno (EINVAL); + return -1; + } + + ret = tt->gettime (ovalue, true); + if (ret < 0) + set_errno (-ret); + } + __except (EFAULT) {} + __endtry + return ret; +} + extern "C" int timer_settime (timer_t timerid, int flags, const struct itimerspec *__restrict value, @@ -438,6 +489,8 @@ timer_settime (timer_t timerid, int flags, __leave; } ret = tt->settime (flags, value, ovalue); + if (ret < 0) + set_errno (-ret); } __except (EFAULT) {} __endtry @@ -476,20 +529,12 @@ timer_delete (timer_t timerid) __try { timer_tracker *in_tt = (timer_tracker *) timerid; - if (!in_tt->is_timer_tracker ()) + if (!in_tt->is_timer_tracker () || in_tt == &itimer_tracker) { set_errno (EINVAL); __leave; } - - lock_timer_tracker here; - if (in_tt->clean_and_unhook () == 0) - { - delete in_tt; - ret = 0; - } - else - set_errno (EINVAL); + delete in_tt; } __except (EFAULT) {} __endtry @@ -513,7 +558,8 @@ setitimer (int which, const struct itimerval *__restrict value, spec_value.it_interval.tv_nsec = value->it_interval.tv_usec * 1000; spec_value.it_value.tv_sec = value->it_value.tv_sec; spec_value.it_value.tv_nsec = value->it_value.tv_usec * 1000; - ret = timer_settime ((timer_t) &ttstart, 0, &spec_value, &spec_ovalue); + ret = timer_settime ((timer_t) &itimer_tracker, 0, + &spec_value, &spec_ovalue); if (ret) ret = -1; else if (ovalue) @@ -541,7 +587,7 @@ getitimer (int which, struct itimerval *ovalue) __try { struct itimerspec spec_ovalue; - ret = timer_gettime ((timer_t) &ttstart, &spec_ovalue); + ret = timer_gettime ((timer_t) &itimer_tracker, &spec_ovalue); if (!ret) { ovalue->it_interval.tv_sec = spec_ovalue.it_interval.tv_sec; @@ -567,7 +613,7 @@ alarm (unsigned int seconds) if (seconds > (CLOCK_DELAY_MAX / 1000 - 1)) seconds = (CLOCK_DELAY_MAX / 1000 - 1); newt.it_value.tv_sec = seconds; - timer_settime ((timer_t) &ttstart, 0, &newt, &oldt); + timer_settime ((timer_t) &itimer_tracker, 0, &newt, &oldt); int ret = oldt.it_value.tv_sec + (oldt.it_value.tv_nsec > 0); syscall_printf ("%d = alarm(%u)", ret, seconds); return ret; @@ -589,7 +635,7 @@ ualarm (useconds_t value, useconds_t interval) timer.it_interval.tv_sec = interval / USPERSEC; timer.it_interval.tv_nsec = (interval % USPERSEC) * (NSPERSEC/USPERSEC); } - timer_settime ((timer_t) &ttstart, 0, &timer, &otimer); + timer_settime ((timer_t) &itimer_tracker, 0, &timer, &otimer); useconds_t ret = otimer.it_value.tv_sec * USPERSEC + (otimer.it_value.tv_nsec + (NSPERSEC/USPERSEC) - 1) / (NSPERSEC/USPERSEC); diff --git a/winsup/cygwin/timer.h b/winsup/cygwin/posix_timer.h similarity index 58% rename from winsup/cygwin/timer.h rename to winsup/cygwin/posix_timer.h index dd5b165c7..04a383fd6 100644 --- a/winsup/cygwin/timer.h +++ b/winsup/cygwin/posix_timer.h @@ -13,38 +13,43 @@ details. */ class timer_tracker { unsigned magic; - timer_tracker *next; - + SRWLOCK srwlock; clockid_t clock_id; sigevent evp; - timespec it_interval; - HANDLE hcancel; - HANDLE syncthread; - int64_t interval_us; - int64_t sleepto_us; - LONG event_running; + struct itimerspec time_spec; + HANDLE timer; + HANDLE cancel_evt; + HANDLE sync_thr; + LONG64 interval; + LONG64 exp_ts; + LONG overrun_event_running; LONG overrun_count_curr; LONG64 overrun_count; bool cancel (); public: + void *operator new (size_t, void *p) __attribute__ ((nothrow)) {return p;} + void operator delete (void *p) { cfree (p); } timer_tracker (clockid_t, const sigevent *); ~timer_tracker (); inline bool is_timer_tracker () const { return magic == TT_MAGIC; } inline sigevent_t *sigevt () { return &evp; } inline int getoverrun () const { return overrun_count_curr; } - void gettime (itimerspec *); + LONG64 get_clock_now () const { return get_clock (clock_id)->n100secs (); } + LONG64 get_exp_ts () const { return exp_ts; } + LONG64 get_interval () const { return interval; } + void set_exp_ts (LONG64 ts) { exp_ts = ts; } + + LONG arm_overrun_event (); + LONG disarm_overrun_event (); + + int gettime (itimerspec *, bool); int settime (int, const itimerspec *, itimerspec *); - int clean_and_unhook (); - LONG arm_event (); - LONG disarm_event (); DWORD thread_func (); static void fixup_after_fork (); }; -extern void fixup_timers_after_fork (); - #endif /* __TIMER_H__ */ diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc index fdde26058..abefedd7b 100644 --- a/winsup/cygwin/signal.cc +++ b/winsup/cygwin/signal.cc @@ -21,7 +21,7 @@ details. */ #include "dtable.h" #include "cygheap.h" #include "cygwait.h" -#include "timer.h" +#include "posix_timer.h" #define _SA_NORESTART 0x8000 @@ -619,7 +619,7 @@ sigwait_common (const sigset_t *set, siginfo_t *info, PLARGE_INTEGER waittime) { timer_tracker *tt = (timer_tracker *) _my_tls.infodata.si_tid; - _my_tls.infodata.si_overrun = tt->disarm_event (); + _my_tls.infodata.si_overrun = tt->disarm_overrun_event (); } if (info) *info = _my_tls.infodata;