From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 39278 invoked by alias); 11 Jan 2019 14:15:45 -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 39232 invoked by uid 9078); 11 Jan 2019 14:15:45 -0000 Date: Fri, 11 Jan 2019 14:15:00 -0000 Message-ID: <20190111141545.39229.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: timer: convert timer_tracker to a real C++ class X-Act-Checkin: newlib-cygwin X-Git-Author: Corinna Vinschen X-Git-Refname: refs/heads/master X-Git-Oldrev: 367df1d4e02dc1c6d636387d439533d4427d9b5b X-Git-Newrev: 8d1d8fc914725a88c3463895b36daa353ebd0d26 X-SW-Source: 2019-q1/txt/msg00036.txt.bz2 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=8d1d8fc914725a88c3463895b36daa353ebd0d26 commit 8d1d8fc914725a88c3463895b36daa353ebd0d26 Author: Corinna Vinschen Date: Fri Jan 11 15:13:11 2019 +0100 Cygwin: timer: convert timer_tracker to a real C++ class ...with private members and all the jazz Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/timer.cc | 139 ++++++++++++++++++++++++++++++------------------- 1 file changed, 84 insertions(+), 55 deletions(-) diff --git a/winsup/cygwin/timer.cc b/winsup/cygwin/timer.cc index e1d78eb..39a0f9d 100644 --- a/winsup/cygwin/timer.cc +++ b/winsup/cygwin/timer.cc @@ -17,9 +17,11 @@ details. */ #include #define TT_MAGIC 0x513e4a1c -struct timer_tracker +class timer_tracker { unsigned magic; + timer_tracker *next; + clockid_t clock_id; sigevent evp; timespec it_interval; @@ -27,13 +29,20 @@ struct timer_tracker HANDLE syncthread; long long interval_us; long long sleepto_us; + bool cancel (); - struct timer_tracker *next; - int settime (int, const itimerspec *, itimerspec *); - void gettime (itimerspec *); + + public: timer_tracker (clockid_t, const sigevent *); ~timer_tracker (); - friend void fixup_timers_after_fork (); + inline bool is_timer_tracker () { return magic == TT_MAGIC; } + + void gettime (itimerspec *); + int settime (int, const itimerspec *, itimerspec *); + int clean_and_unhook (); + + DWORD thread_func (); + void fixup_after_fork (); }; timer_tracker NO_COPY ttstart (CLOCK_REALTIME, NULL); @@ -115,66 +124,65 @@ timespec_to_us (const timespec& ts) return res; } -static DWORD WINAPI -timer_thread (VOID *x) +DWORD +timer_tracker::thread_func () { - timer_tracker *tt = ((timer_tracker *) x); long long now; - long long sleepto_us = tt->sleepto_us; + long long cur_sleepto_us = sleepto_us; while (1) { long long sleep_us; LONG sleep_ms; /* Account for delays in starting thread and sending the signal */ - now = get_clock (tt->clock_id)->usecs (); - sleep_us = sleepto_us - now; + now = get_clock (clock_id)->usecs (); + sleep_us = cur_sleepto_us - now; if (sleep_us > 0) { - tt->sleepto_us = sleepto_us; + sleepto_us = cur_sleepto_us; sleep_ms = (sleep_us + (USPERSEC / MSPERSEC) - 1) / (USPERSEC / MSPERSEC); } else { - tt->sleepto_us = now; + sleepto_us = now; sleep_ms = 0; } - debug_printf ("%p waiting for %u ms", x, sleep_ms); - switch (WaitForSingleObject (tt->hcancel, sleep_ms)) + 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", x); + debug_printf ("%p cancelled", this); goto out; default: - debug_printf ("%p wait failed, %E", x); + debug_printf ("%p wait failed, %E", this); goto out; } - switch (tt->evp.sigev_notify) + switch (evp.sigev_notify) { case SIGEV_SIGNAL: { siginfo_t si = {0}; - si.si_signo = tt->evp.sigev_signo; - si.si_sigval.sival_ptr = tt->evp.sigev_value.sival_ptr; + si.si_signo = evp.sigev_signo; + si.si_sigval.sival_ptr = evp.sigev_value.sival_ptr; si.si_code = SI_TIMER; - debug_printf ("%p sending signal %d", x, tt->evp.sigev_signo); + debug_printf ("%p sending signal %d", this, evp.sigev_signo); sig_send (myself_nowait, si); break; } case SIGEV_THREAD: { pthread_t notify_thread; - debug_printf ("%p starting thread", x); + debug_printf ("%p starting thread", this); pthread_attr_t *attr; pthread_attr_t default_attr; - if (tt->evp.sigev_notify_attributes) - attr = tt->evp.sigev_notify_attributes; + if (evp.sigev_notify_attributes) + attr = evp.sigev_notify_attributes; else { pthread_attr_init(attr = &default_attr); @@ -182,8 +190,8 @@ timer_thread (VOID *x) } int rc = pthread_create (¬ify_thread, attr, - (void * (*) (void *)) tt->evp.sigev_notify_function, - tt->evp.sigev_value.sival_ptr); + (void * (*) (void *)) evp.sigev_notify_function, + evp.sigev_value.sival_ptr); if (rc) { debug_printf ("thread creation failed, %E"); @@ -193,10 +201,10 @@ timer_thread (VOID *x) break; } } - if (!tt->interval_us) + if (!interval_us) break; - sleepto_us = tt->sleepto_us + tt->interval_us; + cur_sleepto_us = sleepto_us + interval_us; debug_printf ("looping"); } @@ -205,6 +213,13 @@ out: return 0; } +static DWORD WINAPI +timer_thread (VOID *x) +{ + timer_tracker *tt = ((timer_tracker *) x); + return tt->thread_func (); +} + static inline bool timespec_bad (const timespec& t) { @@ -282,6 +297,37 @@ timer_tracker::gettime (itimerspec *ovalue) } } +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 () +{ + hcancel = syncthread = NULL; + for (timer_tracker *tt = this; 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 () +{ + ttstart.fixup_after_fork (); +} + extern "C" int timer_gettime (timer_t timerid, struct itimerspec *ovalue) { @@ -290,7 +336,7 @@ timer_gettime (timer_t timerid, struct itimerspec *ovalue) __try { timer_tracker *tt = (timer_tracker *) timerid; - if (tt->magic != TT_MAGIC) + if (!tt->is_timer_tracker ()) { set_errno (EINVAL); return -1; @@ -342,7 +388,7 @@ timer_settime (timer_t timerid, int flags, __try { timer_tracker *tt = (timer_tracker *) timerid; - if (tt->magic != TT_MAGIC) + if (!tt->is_timer_tracker ()) { set_errno (EINVAL); __leave; @@ -362,43 +408,26 @@ timer_delete (timer_t timerid) __try { timer_tracker *in_tt = (timer_tracker *) timerid; - if (in_tt->magic != TT_MAGIC) + if (!in_tt->is_timer_tracker ()) { set_errno (EINVAL); __leave; } lock_timer_tracker here; - for (timer_tracker *tt = &ttstart; tt->next != NULL; tt = tt->next) - if (tt->next == in_tt) - { - tt->next = in_tt->next; - delete in_tt; - ret = 0; - __leave; - } - set_errno (EINVAL); - ret = 0; + if (in_tt->clean_and_unhook () == 0) + { + delete in_tt; + ret = 0; + } + else + set_errno (EINVAL); } __except (EFAULT) {} __endtry return ret; } -void -fixup_timers_after_fork () -{ - ttstart.hcancel = ttstart.syncthread = NULL; - 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; - } -} - - extern "C" int setitimer (int which, const struct itimerval *__restrict value, struct itimerval *__restrict ovalue)