From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 69264 invoked by alias); 22 Jan 2019 17:20:32 -0000 Mailing-List: contact cygwin-cvs-help@cygwin.com; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: cygwin-cvs-owner@cygwin.com Received: (qmail 68532 invoked by uid 9078); 22 Jan 2019 17:20:32 -0000 Date: Tue, 22 Jan 2019 17:20:00 -0000 Message-ID: <20190122172032.68530.qmail@sourceware.org> Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Corinna Vinschen To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: posix timers: fix overrun count always being 1 too big X-Act-Checkin: newlib-cygwin X-Git-Author: Corinna Vinschen X-Git-Refname: refs/heads/master X-Git-Oldrev: de0ec284a3aeb31601383c507904ddaf755854f6 X-Git-Newrev: 1f10a00ba717b22b154205508e60af0dcb641ed3 X-SW-Source: 2019-q1/txt/msg00090.txt.bz2 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=1f10a00ba717b22b154205508e60af0dcb641ed3 commit 1f10a00ba717b22b154205508e60af0dcb641ed3 Author: Corinna Vinschen Date: Tue Jan 22 18:20:18 2019 +0100 Cygwin: posix timers: fix overrun count always being 1 too big Combine with a bit of cleanup: - Drop overrun_event_running in favor of overrun_count being -1. - Fix include guard in posix_timer.h. - Drop ununsed function timespec_to_us. - Don't use Interlocked functions without need. Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/posix_timer.cc | 49 +++++++++++++++----------------------------- winsup/cygwin/posix_timer.h | 9 ++++---- 2 files changed, 21 insertions(+), 37 deletions(-) diff --git a/winsup/cygwin/posix_timer.cc b/winsup/cygwin/posix_timer.cc index 5f569b6..a76ba06 100644 --- a/winsup/cygwin/posix_timer.cc +++ b/winsup/cygwin/posix_timer.cc @@ -17,8 +17,7 @@ details. */ #include "posix_timer.h" #include -#define OVR_EVENT_DISARMED 0 -#define OVR_EVENT_ARMED 1 +#define OVR_DISARMED -1LL timer_tracker NO_COPY itimer_tracker (CLOCK_REALTIME, NULL); @@ -34,15 +33,15 @@ timer_tracker::cancel () { res = WaitForSingleObject (sync_thr, INFINITE); if (res != WAIT_OBJECT_0) - system_printf ("WFSO returned unexpected value %u, %E", res); + debug_printf ("WFSO returned unexpected value %u, %E", res); } return true; } 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) + sync_thr (NULL), interval (0), exp_ts (0), overrun_count_curr (0), + overrun_count (OVR_DISARMED) { srwlock = SRWLOCK_INIT; if (e != NULL) @@ -66,25 +65,14 @@ timer_tracker::~timer_tracker () ReleaseSRWLockExclusive (&srwlock); } -static inline int64_t -timespec_to_us (const timespec& ts) -{ - int64_t res = ts.tv_sec; - res *= USPERSEC; - res += (ts.tv_nsec + (NSPERSEC/USPERSEC) - 1) / (NSPERSEC/USPERSEC); - return res; -} - /* Returns 0 if arming successful, -1 if a signal is already queued. If so, it also increments overrun_count. Only call under lock! */ -LONG -timer_tracker::arm_overrun_event () +bool +timer_tracker::arm_overrun_event (LONG64 exp_cnt) { - LONG ret; + bool ret = (overrun_count != OVR_DISARMED); - ret = InterlockedExchange (&overrun_event_running, OVR_EVENT_ARMED); - if (ret == OVR_EVENT_ARMED) - ret = InterlockedIncrement64 (&overrun_count); + overrun_count += exp_cnt; return ret; } @@ -94,18 +82,17 @@ timer_tracker::disarm_overrun_event () LONG ret; AcquireSRWLockExclusive (&srwlock); - ret = InterlockedExchange (&overrun_event_running, OVR_EVENT_DISARMED); - if (ret == OVR_EVENT_ARMED) + if (overrun_count != OVR_DISARMED) { LONG64 ov_cnt; - InterlockedExchange64 (&ov_cnt, overrun_count); + ov_cnt = overrun_count; if (ov_cnt > DELAYTIMER_MAX || ov_cnt < 0) overrun_count_curr = DELAYTIMER_MAX; else overrun_count_curr = ov_cnt; ret = overrun_count_curr; - InterlockedExchange64 (&overrun_count, 0); + overrun_count = OVR_DISARMED; } ReleaseSRWLockExclusive (&srwlock); return ret; @@ -150,18 +137,17 @@ timer_tracker::thread_func () ReleaseSRWLockExclusive (&srwlock); goto out; } + LONG64 exp_cnt = 0; 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); + exp_cnt = (now - ts + interval - 1) / interval; ts += interval * exp_cnt; set_exp_ts (ts); /* NtSetTimer allows periods of up to 24 days only. If the time @@ -180,7 +166,7 @@ timer_tracker::thread_func () { case SIGEV_SIGNAL: { - if (arm_overrun_event ()) + if (arm_overrun_event (exp_cnt)) { debug_printf ("%p timer signal already queued", this); break; @@ -196,7 +182,7 @@ timer_tracker::thread_func () } case SIGEV_THREAD: { - if (arm_overrun_event ()) + if (arm_overrun_event (exp_cnt)) { debug_printf ("%p timer thread already queued", this); break; @@ -227,7 +213,7 @@ timer_tracker::thread_func () { memset (&time_spec, 0, sizeof time_spec); exp_ts = 0; - overrun_event_running = OVR_EVENT_DISARMED; + overrun_count = OVR_DISARMED; ReleaseSRWLockExclusive (&srwlock); goto out; } @@ -383,8 +369,7 @@ timer_tracker::settime (int flags, const itimerspec *new_value, set_exp_ts (ts); time_spec = *new_value; overrun_count_curr = 0; - overrun_count = 0; - overrun_event_running = OVR_EVENT_DISARMED; + overrun_count = OVR_DISARMED; /* Note: Advanced Power Settings -> Sleep -> Allow Wake Timers since W10 1709 */ Resume = (clock_id == CLOCK_REALTIME_ALARM diff --git a/winsup/cygwin/posix_timer.h b/winsup/cygwin/posix_timer.h index f69a179..e1cfe84 100644 --- a/winsup/cygwin/posix_timer.h +++ b/winsup/cygwin/posix_timer.h @@ -6,8 +6,8 @@ This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ -#ifndef __TIMER_H__ -#define __TIMER_H__ +#ifndef __POSIX_TIMER_H__ +#define __POSIX_TIMER_H__ #define TT_MAGIC 0x513e4a1c class timer_tracker @@ -22,7 +22,6 @@ class timer_tracker HANDLE sync_thr; LONG64 interval; LONG64 exp_ts; - LONG overrun_event_running; LONG overrun_count_curr; LONG64 overrun_count; @@ -42,7 +41,7 @@ class timer_tracker LONG64 get_interval () const { return interval; } void set_exp_ts (LONG64 ts) { exp_ts = ts; } - LONG arm_overrun_event (); + bool arm_overrun_event (LONG64); LONG disarm_overrun_event (); int gettime (itimerspec *, bool); @@ -52,4 +51,4 @@ class timer_tracker static void fixup_after_fork (); }; -#endif /* __TIMER_H__ */ +#endif /* __POSIX_TIMER_H__ */