Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/timer.cc')
-rw-r--r--winsup/cygwin/timer.cc456
1 files changed, 0 insertions, 456 deletions
diff --git a/winsup/cygwin/timer.cc b/winsup/cygwin/timer.cc
deleted file mode 100644
index 91e71146c..000000000
--- a/winsup/cygwin/timer.cc
+++ /dev/null
@@ -1,456 +0,0 @@
-/* timer.cc
-
- Copyright 2004, 2005 Red Hat, Inc.
-
-This file is part of Cygwin.
-
-This software is a copyrighted work licensed under the terms of the
-Cygwin license. Please consult the file "CYGWIN_LICENSE" for
-details. */
-
-#include "winsup.h"
-#include "thread.h"
-#include "cygtls.h"
-#include "sigproc.h"
-#include "path.h"
-#include "fhandler.h"
-#include "dtable.h"
-#include "cygheap.h"
-
-#define TT_MAGIC 0x513e4a1c
-struct timer_tracker
-{
- unsigned magic;
- clockid_t clock_id;
- sigevent evp;
- timespec it_interval;
- HANDLE hcancel;
- 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 *);
- timer_tracker (clockid_t, const sigevent *);
- ~timer_tracker ();
- friend void fixup_timers_after_fork ();
-};
-
-timer_tracker NO_COPY 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 ();
-}
-
-bool
-timer_tracker::cancel ()
-{
- if (!hcancel)
- return false;
-
- SetEvent (hcancel);
- if (WaitForSingleObject (syncthread, INFINITE) != WAIT_OBJECT_0)
- api_fatal ("WFSO failed waiting for timer thread, %E");
- 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)
-{
- if (e != NULL)
- evp = *e;
- else
- {
- evp.sigev_notify = SIGEV_SIGNAL;
- evp.sigev_signo = SIGALRM;
- evp.sigev_value.sival_ptr = this;
- }
- clock_id = c;
- magic = TT_MAGIC;
- hcancel = NULL;
- if (this != &ttstart)
- {
- lock_timer_tracker here;
- next = ttstart.next;
- ttstart.next = this;
- }
-}
-
-static long long
-to_us (const timespec& ts)
-{
- long long res = ts.tv_sec;
- res *= 1000000;
- res += ts.tv_nsec / 1000 + ((ts.tv_nsec % 1000) ? 1 : 0);
- return res;
-}
-
-static DWORD WINAPI
-timer_thread (VOID *x)
-{
- timer_tracker *tt = ((timer_tracker *) x);
- long long now;
- long long sleepto_us = tt->sleepto_us;
- while (1)
- {
- long long sleep_us;
- long sleep_ms;
- /* Account for delays in starting thread
- and sending the signal */
- now = gtod.usecs ();
- sleep_us = sleepto_us - now;
- if (sleep_us > 0)
- {
- tt->sleepto_us = sleepto_us;
- sleep_ms = (sleep_us + 999) / 1000;
- }
- else
- {
- tt->sleepto_us = now;
- sleep_ms = 0;
- }
-
- debug_printf ("%p waiting for %u ms", x, sleep_ms);
- switch (WaitForSingleObject (tt->hcancel, sleep_ms))
- {
- case WAIT_TIMEOUT:
- debug_printf ("timed out");
- break;
- case WAIT_OBJECT_0:
- debug_printf ("%p cancelled", x);
- goto out;
- default:
- debug_printf ("%p wait failed, %E", x);
- goto out;
- }
-
- switch (tt->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_code = SI_TIMER;
- debug_printf ("%p sending sig %d", x, tt->evp.sigev_signo);
- sig_send (myself_nowait, si);
- break;
- }
- case SIGEV_THREAD:
- {
- pthread_t notify_thread;
- debug_printf ("%p starting thread", x);
- pthread_attr_t *attr;
- pthread_attr_t default_attr;
- if (tt->evp.sigev_notify_attributes)
- attr = tt->evp.sigev_notify_attributes;
- else
- {
- pthread_attr_init(attr = &default_attr);
- pthread_attr_setdetachstate (attr, PTHREAD_CREATE_DETACHED);
- }
-
- int rc = pthread_create (&notify_thread, attr,
- (void * (*) (void *)) tt->evp.sigev_notify_function,
- tt->evp.sigev_value.sival_ptr);
- if (rc)
- {
- debug_printf ("thread creation failed, %E");
- return 0;
- }
- // FIXME: pthread_join?
- break;
- }
- }
- if (!tt->interval_us)
- break;
-
- sleepto_us = tt->sleepto_us + tt->interval_us;
- debug_printf ("looping");
- }
-
-out:
- _my_tls._ctinfo->auto_release (); /* automatically return the cygthread to the cygthread pool */
- return 0;
-}
-
-static bool
-it_bad (const timespec& t)
-{
- if (t.tv_nsec < 0 || t.tv_nsec >= 1000000000 || t.tv_sec < 0)
- {
- set_errno (EINVAL);
- return true;
- }
- return false;
-}
-
-int
-timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalue)
-{
- if (!value)
- {
- set_errno (EINVAL);
- return -1;
- }
-
- myfault efault;
- if (efault.faulted (EFAULT)
- || it_bad (value->it_value)
- || it_bad (value->it_interval))
- return -1;
-
- long long now = in_flags & TIMER_ABSTIME ? 0 : gtod.usecs ();
-
- lock_timer_tracker here;
- cancel ();
-
- if (ovalue)
- gettime (ovalue);
-
- if (!value->it_value.tv_sec && !value->it_value.tv_nsec)
- interval_us = sleepto_us = 0;
- else
- {
- sleepto_us = now + to_us (value->it_value);
- interval_us = to_us (value->it_interval);
- it_interval = value->it_interval;
- if (!hcancel)
- hcancel = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
- else
- ResetEvent (hcancel);
- if (!syncthread)
- syncthread = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
- else
- ResetEvent (syncthread);
- new cygthread (timer_thread, this, "itimer", syncthread);
- }
-
- return 0;
-}
-
-void
-timer_tracker::gettime (itimerspec *ovalue)
-{
- if (!hcancel)
- memset (ovalue, 0, sizeof (*ovalue));
- else
- {
- ovalue->it_interval = it_interval;
- long long now = gtod.usecs ();
- long long left_us = sleepto_us - now;
- if (left_us < 0)
- left_us = 0;
- ovalue->it_value.tv_sec = left_us / 1000000;
- ovalue->it_value.tv_nsec = (left_us % 1000000) * 1000;
- }
-}
-
-extern "C" int
-timer_gettime (timer_t timerid, struct itimerspec *ovalue)
-{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- timer_tracker *tt = (timer_tracker *) timerid;
- if (tt->magic != TT_MAGIC)
- {
- set_errno (EINVAL);
- return -1;
- }
-
- tt->gettime (ovalue);
- return 0;
-}
-
-extern "C" int
-timer_create (clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
-{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (clock_id != CLOCK_REALTIME)
- {
- set_errno (EINVAL);
- return -1;
- }
-
- *timerid = (timer_t) new timer_tracker (clock_id, evp);
- return 0;
-}
-
-extern "C" int
-timer_settime (timer_t timerid, int flags, const struct itimerspec *value,
- struct itimerspec *ovalue)
-{
- timer_tracker *tt = (timer_tracker *) timerid;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (tt->magic != TT_MAGIC)
- {
- set_errno (EINVAL);
- return -1;
- }
-
- return tt->settime (flags, value, ovalue);
-}
-
-extern "C" int
-timer_delete (timer_t timerid)
-{
- timer_tracker *in_tt = (timer_tracker *) timerid;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (in_tt->magic != TT_MAGIC)
- {
- set_errno (EINVAL);
- return -1;
- }
-
- 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;
- return 0;
- }
- set_errno (EINVAL);
- return 0;
-}
-
-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 *value, struct itimerval *ovalue)
-{
- if (which != ITIMER_REAL)
- {
- set_errno (EINVAL);
- return -1;
- }
- struct itimerspec spec_value, spec_ovalue;
- int ret;
- spec_value.it_interval.tv_sec = value->it_interval.tv_sec;
- 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);
- if (!ret && ovalue)
- {
- ovalue->it_interval.tv_sec = spec_ovalue.it_interval.tv_sec;
- ovalue->it_interval.tv_usec = spec_ovalue.it_interval.tv_nsec / 1000;
- ovalue->it_value.tv_sec = spec_ovalue.it_value.tv_sec;
- ovalue->it_value.tv_usec = spec_ovalue.it_value.tv_nsec / 1000;
- }
- syscall_printf ("%d = setitimer ()", ret);
- return ret;
-}
-
-
-extern "C" int
-getitimer (int which, struct itimerval *ovalue)
-{
- if (which != ITIMER_REAL)
- {
- set_errno (EINVAL);
- return -1;
- }
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- struct itimerspec spec_ovalue;
- int ret = timer_gettime ((timer_t) &ttstart, &spec_ovalue);
- if (!ret)
- {
- ovalue->it_interval.tv_sec = spec_ovalue.it_interval.tv_sec;
- ovalue->it_interval.tv_usec = spec_ovalue.it_interval.tv_nsec / 1000;
- ovalue->it_value.tv_sec = spec_ovalue.it_value.tv_sec;
- ovalue->it_value.tv_usec = spec_ovalue.it_value.tv_nsec / 1000;
- }
- syscall_printf ("%d = getitimer ()", ret);
- return ret;
-}
-
-/* FIXME: POSIX - alarm survives exec */
-extern "C" unsigned int
-alarm (unsigned int seconds)
-{
- struct itimerspec newt = {}, oldt;
- /* alarm cannot fail, but only needs not be
- correct for arguments < 64k. Truncate */
- if (seconds > (HIRES_DELAY_MAX / 1000 - 1))
- seconds = (HIRES_DELAY_MAX / 1000 - 1);
- newt.it_value.tv_sec = seconds;
- timer_settime ((timer_t) &ttstart, 0, &newt, &oldt);
- int ret = oldt.it_value.tv_sec + (oldt.it_value.tv_nsec > 0);
- syscall_printf ("%d = alarm (%d)", ret, seconds);
- return ret;
-}
-
-extern "C" useconds_t
-ualarm (useconds_t value, useconds_t interval)
-{
- struct itimerspec timer = {}, otimer;
- /* ualarm cannot fail.
- Interpret negative arguments as zero */
- if (value > 0)
- {
- timer.it_value.tv_sec = (unsigned int) value / 1000000;
- timer.it_value.tv_nsec = ((unsigned int) value % 1000000) * 1000;
- }
- if (interval > 0)
- {
- timer.it_interval.tv_sec = (unsigned int) interval / 1000000;
- timer.it_interval.tv_nsec = ((unsigned int) interval % 1000000) * 1000;
- }
- timer_settime ((timer_t) &ttstart, 0, &timer, &otimer);
- useconds_t ret = otimer.it_value.tv_sec * 1000000 + (otimer.it_value.tv_nsec + 999) / 1000;
- syscall_printf ("%d = ualarm (%d , %d)", ret, value, interval);
- return ret;
-}