newlib/winsup/cygwin/timer.h
Corinna Vinschen 40481dbabb Cygwin: timerfd: reimplement from scratch
Using posix timers "timer_tracker" as base class for timerfd was flawed.
Posix timers are not inherited by child processes and don't survive
execve.  The method used by posix timers didn't allow to share timers
between processes. The timers were still per-process timers and worked
entirely separate from each other.  Reading from these timers via
different descriptors was only synchronized within the same process.

This does not reflect the timerfd semantics in Linux: The per-file
timers can be dup'ed and survive fork and execve.  They are still just
descriptors pointing to the same timer object originally created by
timerfd_create.  Synchronization is performed between all descriptor
instances of the same timer, system-wide.

Thus, reimplement timerfd using a timer instance in shared memory,
a kernel timer, and a handful of sync objects.

Every process maintains a per-process timerfd struct on the cygheap
maintaining a per-process thread.  Every process sharing the same
timerfd will run this thread checking the state of the timer, similar
to the posix timer thread, just working on the shared objects and
synchronizing its job with each other thread.

Drop the timerfd implementation in the posix timer code and move the
public API to fhandler_timerfd.c.  Keep the ttstart timer_tracker
anchor out of "NO_COPY" since the fixup_after_fork code should run to
avoid memory leakage.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2019-01-19 20:00:06 +01:00

51 lines
1.1 KiB
C++

/* timer.h: Define class timer_tracker, base class for posix timers
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. */
#ifndef __TIMER_H__
#define __TIMER_H__
#define TT_MAGIC 0x513e4a1c
class timer_tracker
{
unsigned magic;
timer_tracker *next;
clockid_t clock_id;
sigevent evp;
timespec it_interval;
HANDLE hcancel;
HANDLE syncthread;
int64_t interval_us;
int64_t sleepto_us;
LONG event_running;
LONG overrun_count_curr;
LONG64 overrun_count;
bool cancel ();
public:
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 *);
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__ */