1 /* timerfd.h: Define timerfd classes
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
17 clockid_t _clockid
; /* clockid */
18 struct itimerspec _time_spec
; /* original incoming itimerspec */
19 LONG64 _exp_ts
; /* start timestamp or next expire timestamp
21 LONG64 _interval
; /* timer interval in 100ns */
22 LONG64 _expiration_count
; /* expiry counter */
23 int _flags
; /* settime flags */
24 DWORD _tc_time
; /* timestamp of the last WM_TIMECHANGE msg */
26 /* read access methods */
27 LONG64
get_clock_now () const { return get_clock (_clockid
)->n100secs (); }
28 struct itimerspec
&time_spec () { return _time_spec
; }
29 int get_flags () const { return _flags
; }
30 void set_flags (int nflags
) { _flags
= nflags
; }
32 /* write access methods */
33 void set_clockid (clockid_t clock_id
) { _clockid
= clock_id
; }
34 void increment_expiration_count (LONG64 add
)
35 { InterlockedAdd64 (&_expiration_count
, add
); }
36 void set_expiration_count (LONG64 newval
)
37 { InterlockedExchange64 (&_expiration_count
, newval
); }
38 LONG64
reset_expiration_count ()
39 { return InterlockedExchange64 (&_expiration_count
, 0); }
40 int arm_timer (int, const struct itimerspec
*);
43 memset (&_time_spec
, 0, sizeof _time_spec
);
46 /* _flags = 0; DON'T DO THAT. Required for TFD_TIMER_CANCEL_ON_SET */
49 void set_exp_ts (LONG64 ts
) { _exp_ts
= ts
; }
51 friend class timerfd_tracker
;
54 class timerfd_tracker
/* cygheap! */
57 HANDLE tfd_shared_hdl
; /* handle to shared mem */
58 HANDLE _access_mtx
; /* controls access to shared data */
59 HANDLE _arm_evt
; /* settimer sets event when timer is armed,
60 unsets event when timer gets disarmed. */
61 HANDLE _disarm_evt
; /* settimer sets event when timer is armed,
62 unsets event when timer gets disarmed. */
63 HANDLE _timer
; /* SynchronizationTimer */
64 HANDLE _expired_evt
; /* Signal if timer expired, Unsignal on read. */
65 /* Process-local handles */
66 HANDLE cancel_evt
; /* Signal thread to exit. */
67 HANDLE sync_thr
; /* cygthread sync object. */
68 /* pointer to shared timerfd, misc */
69 timerfd_shared
*tfd_shared
; /* pointer to shared mem, needs
70 NtMapViewOfSection in each new process. */
71 LONG instance_count
; /* each open fd increments this.
72 If 0 -> cancel thread. */
73 DWORD winpid
; /* This is used @ fork/exec time to know if
74 this tracker already has been fixed up. */
75 HWND window
; /* window handle */
76 ATOM atom
; /* window class */
78 void create_timechange_window ();
79 void delete_timechange_window ();
80 void handle_timechange_window ();
84 bool enter_critical_section ()
86 return (WaitForSingleObject (_access_mtx
, INFINITE
) & ~WAIT_ABANDONED_0
)
89 /* A version that honors a cancel event, for use in thread_func. */
90 int enter_critical_section_cancelable ();
91 void leave_critical_section ()
93 ReleaseMutex (_access_mtx
);
96 HANDLE
arm_evt () const { return _arm_evt
; }
97 HANDLE
disarm_evt () const { return _disarm_evt
; }
98 HANDLE
timer () const { return _timer
; }
99 HANDLE
expired_evt () const { return _expired_evt
; }
100 void timer_expired () { SetEvent (_expired_evt
); }
101 int arm_timer (int flags
, const struct itimerspec
*new_value
);
104 ResetEvent (_arm_evt
);
105 tfd_shared
->disarm_timer ();
106 NtCancelTimer (timer (), NULL
);
107 SetEvent (_disarm_evt
);
110 void timer_expired () const { timer_expired (); }
112 LONG64
expiration_count () const { return tfd_shared
->_expiration_count
; }
113 void increment_expiration_count (LONG64 add
) const
114 { tfd_shared
->increment_expiration_count (add
); }
115 void set_expiration_count (LONG64 exp_cnt
) const
116 { tfd_shared
->set_expiration_count ((LONG64
) exp_cnt
); }
117 LONG64
read_and_reset_expiration_count ()
119 LONG64 ret
= tfd_shared
->reset_expiration_count ();
121 ResetEvent (_expired_evt
);
125 struct timespec
it_value () const
126 { return tfd_shared
->time_spec ().it_value
; }
127 struct timespec
it_interval () const
128 { return tfd_shared
->time_spec ().it_interval
; }
130 void set_clockid (clockid_t clock_id
) { tfd_shared
->set_clockid (clock_id
); }
131 clock_t get_clockid () const { return tfd_shared
->_clockid
; }
132 LONG64
get_clock_now () const { return tfd_shared
->get_clock_now (); }
133 struct itimerspec
&time_spec () { return tfd_shared
->time_spec (); }
134 LONG64
get_exp_ts () const { return tfd_shared
->_exp_ts
; }
135 LONG64
get_interval () const { return tfd_shared
->_interval
; }
136 void set_interval (LONG64 intv
) { tfd_shared
->_interval
= intv
; }
137 int get_flags () const { return tfd_shared
->get_flags (); }
138 void set_flags (int nflags
) { tfd_shared
->set_flags (nflags
); }
139 DWORD
tc_time () const { return tfd_shared
->_tc_time
; }
140 void set_tc_time (DWORD new_time
) { tfd_shared
->_tc_time
= new_time
; }
142 void set_exp_ts (LONG64 ts
) const { tfd_shared
->set_exp_ts (ts
); }
143 LONG
decrement_instances () { return InterlockedDecrement (&instance_count
); }
146 void *operator new (size_t, void *p
) __attribute__ ((nothrow
)) {return p
;}
148 : tfd_shared_hdl (NULL
), _access_mtx (NULL
), _arm_evt (NULL
),
149 _disarm_evt (NULL
), cancel_evt (NULL
), sync_thr (NULL
), tfd_shared (NULL
),
150 instance_count (1), winpid (0), window (NULL
), atom (0) {}
152 void init_fixup_after_fork_exec ();
153 void fixup_after_fork_exec (bool);
154 void fixup_after_fork ()
156 init_fixup_after_fork_exec ();
157 fixup_after_fork_exec (false);
159 void fixup_after_exec () { fixup_after_fork_exec (true); }
161 void dup () { InterlockedIncrement (&instance_count
); }
162 HANDLE
get_timerfd_handle () const { return expired_evt (); }
164 int ioctl_set_ticks (uint64_t);
166 int create (clockid_t
);
167 int gettime (struct itimerspec
*);
168 int settime (int, const struct itimerspec
*, struct itimerspec
*);
170 static void dtor (timerfd_tracker
*);
171 DWORD
thread_func ();
174 #endif /* __TIMERFD_H__ */