2 * XXX: if you are a heavy user of time related calls, you should use vdso
3 * calls instead of syscalls. That depends on the arch.
7 #include <ulinux/compiler_types.h>
8 #include <ulinux/compiler_misc.h>
9 #include <ulinux/sysc.h>
10 #include <ulinux/types.h>
11 #include <ulinux/epoll.h>
12 #include <ulinux/file.h>
13 #include <ulinux/error.h>
14 #include <ulinux/time.h>
16 #include <ulinux/utils/mem.h>
17 #include <ulinux/utils/ascii/string/string.h>
18 #include <ulinux/utils/ascii/string/vsprintf.h>
20 /* ulinux namespace */
21 #define EINTR ULINUX_EINTR
22 #define EAGAIN ULINUX_EAGAIN
26 #define u64 ulinux_u64
27 /* kill process, aka thread group */
28 #define exit(code) ulinux_sysc(exit_group,1,code)
29 #define ISERR ULINUX_ISERR
30 #define CLOCK_MONOTONIC ULINUX_CLOCK_MONOTONIC
31 #define clock_gettime(a,b) ulinux_sysc(clock_gettime,2,a,b)
32 #define TFD_NONBLOCK ULINUX_TFD_NONBLOCK
33 #define TFD_TIMER_ABSTIME ULINUX_TFD_TIMER_ABSTIME
34 #define itimerspec ulinux_itimerspec
35 #define timerfd_create(a,b) ulinux_sysc(timerfd_create,2,a,b)
36 #define timerfd_settime(a,b,c,d) ulinux_sysc(timerfd_settime,4,a,b,c,d)
37 #define epoll_create1(a) ulinux_sysc(epoll_create1,1,a)
38 #define epoll_event ulinux_epoll_event
39 #define memset(a,b,c) ulinux_memset((ulinux_u8*)a,b,c)
40 #define EPOLLIN ULINUX_EPOLLIN
41 #define epoll_ctl(a,b,c,d) ulinux_sysc(epoll_ctl,4,a,b,c,d)
42 #define EPOLL_CTL_ADD ULINUX_EPOLL_CTL_ADD
43 /* common to x86_64 and aarch64 */
44 #define epoll_pwait(a,b,c,d,e) ulinux_sysc(epoll_pwait,5,a,b,c,d,e)
45 #define read(a,b,c) ulinux_sysc(read,3,a,b,c)
47 /* convenience macros */
49 static u8 dprint_buf
[BUFSIZ
];
50 #define POUT(fmt,...) ulinux_dprintf(1,&dprint_buf[0],BUFSIZ-1,fmt,##__VA_ARGS__)
51 #define EPOLL_EVENTS_N 10
54 #define INITIAL_EXPIRATION_SECS 8
60 struct itimerspec itimerspec
;
62 struct epoll_event evts
[EPOLL_EVENTS_N
];
65 dprint_buf
[BUFSIZ
- 1] = 0; /* secure a 0 terminating char */
67 timerfd
= (si
)timerfd_create(CLOCK_MONOTONIC
, TFD_NONBLOCK
);
69 POUT("unable to create the timer fd (%d)\n", timerfd
);
73 memset(&itimerspec
, 0, sizeof(itimerspec
));
75 /*--------------------------------------------------------------------*/
77 r
= clock_gettime(CLOCK_MONOTONIC
, &itimerspec
.value
);
79 POUT("error while getting the current monotonic clock time (%ld)\n", r
);
82 POUT("current monotonic clock is %ld secs and %ld nsecs\n", itimerspec
.value
.sec
, itimerspec
.value
.nsec
);
84 /*--------------------------------------------------------------------*/
86 /* initial expiration in the futur of current monotonic clock */
87 itimerspec
.value
.sec
+= INITIAL_EXPIRATION_SECS
;
88 itimerspec
.value
.nsec
= 0;
90 /* we are looking for an absolute initial expiration */
91 r
= timerfd_settime(timerfd
, TFD_TIMER_ABSTIME
, &itimerspec
, 0);
93 POUT("unable to arm the timer\n");
97 epfd
= (si
)epoll_create1(0);
99 POUT("unable to create the epoll fd\n");
103 memset(evts
, 0, sizeof(evts
));
104 evts
[0].events
= EPOLLIN
; /* could be EPOLLET too */
105 evts
[0].data
.fd
= timerfd
;
106 r
= epoll_ctl(epfd
, EPOLL_CTL_ADD
, timerfd
, &evts
[0]);
108 POUT("unable to add the timer fd to the epoll fd (%ld)\n", r
);
113 memset(evts
, 0, sizeof(evts
));
114 r
= epoll_pwait(epfd
, evts
, EPOLL_EVENTS_N
, -1, 0);
118 POUT("epoll_pwait was interruped by a signal (we did not set any timeout), restarting\n");
121 POUT("epoll_wait error (%ld)\n", r
);
130 if (evts
[evt
].data
.fd
== timerfd
) {
131 if ((evts
[evt
].events
& EPOLLIN
) != 0) {
132 u64 expirations_n
= 0; /* the count of expirations of our timer */
134 loop
{/* reads are atomic or err, aka no short reads */
135 r
= read(timerfd
, &expirations_n
, sizeof(u64
));
140 if (r
== -EAGAIN
) { /* for a non blocking fd, means we read it */
141 POUT("something is wrong: we got notified of some timer expirations, but there is no count of expirations!\n");
145 POUT("something went wrong while reading the count of expirations (%ld)\n", r
);
148 POUT("count of expirations=%lu\n", expirations_n
);
150 POUT("got an unwanted event on the timer fd\n");
154 ++evt
; /* next epoll event */
157 /*--------------------------------------------------------------------*/
159 memset(&itimerspec
, 0, sizeof(itimerspec
));
160 r
= clock_gettime(CLOCK_MONOTONIC
, &itimerspec
.value
);
162 POUT("error while getting the current monotonic clock time at exit time(%ld)\n", r
);
165 POUT("monotonic clock at exit is %ld secs and %ld nsecs\n", itimerspec
.value
.sec
, itimerspec
.value
.nsec
);