Cygwin: strptime: add release note
[newlib-cygwin.git] / winsup / cygwin / fhandler / timerfd.cc
blob9269494dbd2cd798c267b0a0d519055e3b4bbc7c
1 /* fhandler_timerfd.cc: fhandler for timerfd, public timerfd API
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
7 details. */
9 #include "winsup.h"
10 #include "path.h"
11 #include "fhandler.h"
12 #include "pinfo.h"
13 #include "dtable.h"
14 #include "cygheap.h"
15 #include "timerfd.h"
16 #include <sys/timerfd.h>
17 #include <cygwin/signal.h>
19 fhandler_timerfd::fhandler_timerfd () :
20 fhandler_base ()
24 char *
25 fhandler_timerfd::get_proc_fd_name (char *buf)
27 return strcpy (buf, "anon_inode:[timerfd]");
30 /* The timers connected to a descriptor are stored on the cygheap
31 together with their fhandler. */
33 int
34 fhandler_timerfd::timerfd (clockid_t clock_id, int flags)
36 timerfd_tracker *tfd = (timerfd_tracker *)
37 ccalloc (HEAP_FHANDLER, 1, sizeof (timerfd_tracker));
38 if (!tfd)
40 set_errno (ENOMEM);
41 return -1;
43 new (tfd) timerfd_tracker ();
44 int ret = tfd->create (clock_id);
45 if (ret < 0)
47 cfree (tfd);
48 set_errno (-ret);
49 return -1;
51 if (flags & TFD_NONBLOCK)
52 set_nonblocking (true);
53 if (flags & TFD_CLOEXEC)
54 set_close_on_exec (true);
55 nohandle (true);
56 set_unique_id ();
57 set_ino (get_unique_id ());
58 set_flags (O_RDWR | O_BINARY);
59 timerid = (timer_t) tfd;
60 return 0;
63 int
64 fhandler_timerfd::settime (int flags, const struct itimerspec *new_value,
65 struct itimerspec *old_value)
67 int ret = -1;
69 __try
71 timerfd_tracker *tfd = (timerfd_tracker *) timerid;
72 ret = tfd->settime (flags, new_value, old_value);
73 if (ret < 0)
75 set_errno (-ret);
76 ret = -1;
79 __except (EFAULT) {}
80 __endtry
81 return ret;
84 int
85 fhandler_timerfd::gettime (struct itimerspec *ovalue)
87 int ret = -1;
89 __try
91 timerfd_tracker *tfd = (timerfd_tracker *) timerid;
92 ret = tfd->gettime (ovalue);
93 if (ret < 0)
95 set_errno (-ret);
96 ret = -1;
99 __except (EFAULT) {}
100 __endtry
101 return ret;
105 fhandler_timerfd::fstat (struct stat *buf)
107 int ret = fhandler_base::fstat (buf);
108 if (!ret)
110 buf->st_mode = S_IRUSR | S_IWUSR;
111 buf->st_dev = FH_TIMERFD;
112 buf->st_ino = get_unique_id ();
114 return ret;
117 void
118 fhandler_timerfd::read (void *ptr, size_t& len)
120 if (len < sizeof (LONG64))
122 set_errno (EINVAL);
123 len = (size_t) -1;
124 return;
127 __try
129 timerfd_tracker *tfd = (timerfd_tracker *) timerid;
130 LONG64 ret = tfd->wait (is_nonblocking ());
131 if (ret < 0)
133 set_errno (-ret);
134 __leave;
136 *(PLONG64) ptr = ret;
137 len = sizeof (LONG64);
138 return;
140 __except (EFAULT) {}
141 __endtry
142 len = (size_t) -1;
143 return;
146 ssize_t
147 fhandler_timerfd::write (const void *, size_t)
149 set_errno (EINVAL);
150 return -1;
153 HANDLE
154 fhandler_timerfd::get_timerfd_handle ()
156 __try
158 timerfd_tracker *tfd = (timerfd_tracker *) timerid;
159 return tfd->get_timerfd_handle ();
161 __except (EFAULT) {}
162 __endtry
163 return NULL;
167 fhandler_timerfd::dup (fhandler_base *child, int flags)
169 int ret = fhandler_base::dup (child, flags);
171 if (!ret)
173 fhandler_timerfd *fhc = (fhandler_timerfd *) child;
174 __try
176 timerfd_tracker *tfd = (timerfd_tracker *) fhc->timerid;
177 tfd->dup ();
178 ret = 0;
180 __except (EFAULT) {}
181 __endtry
183 return ret;
187 fhandler_timerfd::ioctl (unsigned int cmd, void *p)
189 int ret = -1;
190 uint64_t exp_cnt;
192 switch (cmd)
194 case TFD_IOC_SET_TICKS:
195 __try
197 timerfd_tracker *tfd = (timerfd_tracker *) timerid;
199 exp_cnt = *(uint64_t *) p;
200 ret = tfd->ioctl_set_ticks (exp_cnt);
201 if (ret < 0)
202 set_errno (-ret);
204 __except (EFAULT) {}
205 __endtry
206 break;
207 default:
208 ret = fhandler_base::ioctl (cmd, p);
209 break;
211 syscall_printf ("%d = ioctl_timerfd(%x, %p)", ret, cmd, p);
212 return ret;
215 void
216 fhandler_timerfd::fixup_after_fork (HANDLE)
218 __try
220 timerfd_tracker *tfd = (timerfd_tracker *) timerid;
221 tfd->fixup_after_fork ();
223 __except (EFAULT) {}
224 __endtry
227 void
228 fhandler_timerfd::fixup_after_exec ()
230 __try
232 timerfd_tracker *tfd = (timerfd_tracker *) timerid;
233 tfd->init_fixup_after_fork_exec ();
234 if (close_on_exec ())
235 timerfd_tracker::dtor (tfd);
236 else
237 tfd->fixup_after_exec ();
239 __except (EFAULT) {}
240 __endtry
244 fhandler_timerfd::close ()
246 int ret = -1;
248 __try
250 timerfd_tracker *tfd = (timerfd_tracker *) timerid;
251 timerfd_tracker::dtor (tfd);
252 ret = 0;
254 __except (EFAULT) {}
255 __endtry
256 return ret;
259 extern "C" int
260 timerfd_create (clockid_t clock_id, int flags)
262 int ret = -1;
263 fhandler_timerfd *fh;
265 debug_printf ("timerfd_create (%lu, %y)", clock_id, flags);
267 if (clock_id != CLOCK_REALTIME
268 && clock_id != CLOCK_MONOTONIC
269 && clock_id != CLOCK_BOOTTIME)
271 set_errno (EINVAL);
272 goto done;
274 if ((flags & ~(TFD_NONBLOCK | TFD_CLOEXEC)) != 0)
276 set_errno (EINVAL);
277 goto done;
281 /* Create new timerfd descriptor. */
282 cygheap_fdnew fd;
284 if (fd < 0)
285 goto done;
286 fh = (fhandler_timerfd *) build_fh_dev (*timerfd_dev);
287 if (fh && fh->timerfd (clock_id, flags) == 0)
289 fd = fh;
290 if (fd <= 2)
291 set_std_handle (fd);
292 ret = fd;
294 else
295 delete fh;
298 done:
299 syscall_printf ("%R = timerfd_create (%lu, %y)", ret, clock_id, flags);
300 return ret;
303 extern "C" int
304 timerfd_settime (int fd_in, int flags, const struct itimerspec *value,
305 struct itimerspec *ovalue)
307 if ((flags & ~(TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET)) != 0)
309 set_errno (EINVAL);
310 return -1;
313 cygheap_fdget fd (fd_in);
314 if (fd < 0)
315 return -1;
316 fhandler_timerfd *fh = fd->is_timerfd ();
317 if (!fh)
319 set_errno (EINVAL);
320 return -1;
322 return fh->settime (flags, value, ovalue);
325 extern "C" int
326 timerfd_gettime (int fd_in, struct itimerspec *ovalue)
328 cygheap_fdget fd (fd_in);
329 if (fd < 0)
330 return -1;
331 fhandler_timerfd *fh = fd->is_timerfd ();
332 if (!fh)
334 set_errno (EINVAL);
335 return -1;
337 return fh->gettime (ovalue);