1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4
5 #include "event-source.h"
6 #include "event-util.h"
7 #include "fd-util.h"
8 #include "log.h"
9 #include "string-util.h"
10
event_reset_time(sd_event * e,sd_event_source ** s,clockid_t clock,uint64_t usec,uint64_t accuracy,sd_event_time_handler_t callback,void * userdata,int64_t priority,const char * description,bool force_reset)11 int event_reset_time(
12 sd_event *e,
13 sd_event_source **s,
14 clockid_t clock,
15 uint64_t usec,
16 uint64_t accuracy,
17 sd_event_time_handler_t callback,
18 void *userdata,
19 int64_t priority,
20 const char *description,
21 bool force_reset) {
22
23 bool created = false;
24 int enabled, r;
25 clockid_t c;
26
27 assert(e);
28 assert(s);
29
30 if (*s) {
31 if (!force_reset) {
32 r = sd_event_source_get_enabled(*s, &enabled);
33 if (r < 0)
34 return log_debug_errno(r, "sd-event: Failed to query whether event source \"%s\" is enabled or not: %m",
35 strna((*s)->description ?: description));
36
37 if (enabled != SD_EVENT_OFF)
38 return 0;
39 }
40
41 r = sd_event_source_get_time_clock(*s, &c);
42 if (r < 0)
43 return log_debug_errno(r, "sd-event: Failed to get clock id of event source \"%s\": %m", strna((*s)->description ?: description));
44
45 if (c != clock)
46 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
47 "sd-event: Current clock id %i of event source \"%s\" is different from specified one %i.",
48 (int)c,
49 strna((*s)->description ? : description),
50 (int)clock);
51
52 r = sd_event_source_set_time(*s, usec);
53 if (r < 0)
54 return log_debug_errno(r, "sd-event: Failed to set time for event source \"%s\": %m", strna((*s)->description ?: description));
55
56 r = sd_event_source_set_time_accuracy(*s, accuracy);
57 if (r < 0)
58 return log_debug_errno(r, "sd-event: Failed to set accuracy for event source \"%s\": %m", strna((*s)->description ?: description));
59
60 /* callback function is not updated, as we do not have sd_event_source_set_time_callback(). */
61
62 (void) sd_event_source_set_userdata(*s, userdata);
63
64 r = sd_event_source_set_enabled(*s, SD_EVENT_ONESHOT);
65 if (r < 0)
66 return log_debug_errno(r, "sd-event: Failed to enable event source \"%s\": %m", strna((*s)->description ?: description));
67 } else {
68 r = sd_event_add_time(e, s, clock, usec, accuracy, callback, userdata);
69 if (r < 0)
70 return log_debug_errno(r, "sd-event: Failed to create timer event \"%s\": %m", strna(description));
71
72 created = true;
73 }
74
75 r = sd_event_source_set_priority(*s, priority);
76 if (r < 0)
77 return log_debug_errno(r, "sd-event: Failed to set priority for event source \"%s\": %m", strna((*s)->description ?: description));
78
79 if (description) {
80 r = sd_event_source_set_description(*s, description);
81 if (r < 0)
82 return log_debug_errno(r, "sd-event: Failed to set description for event source \"%s\": %m", description);
83 }
84
85 return created;
86 }
87
event_reset_time_relative(sd_event * e,sd_event_source ** s,clockid_t clock,uint64_t usec,uint64_t accuracy,sd_event_time_handler_t callback,void * userdata,int64_t priority,const char * description,bool force_reset)88 int event_reset_time_relative(
89 sd_event *e,
90 sd_event_source **s,
91 clockid_t clock,
92 uint64_t usec,
93 uint64_t accuracy,
94 sd_event_time_handler_t callback,
95 void *userdata,
96 int64_t priority,
97 const char *description,
98 bool force_reset) {
99
100 usec_t usec_now;
101 int r;
102
103 assert(e);
104
105 r = sd_event_now(e, clock, &usec_now);
106 if (r < 0)
107 return log_debug_errno(r, "sd-event: Failed to get the current time: %m");
108
109 return event_reset_time(e, s, clock, usec_add(usec_now, usec), accuracy, callback, userdata, priority, description, force_reset);
110 }
111
event_source_disable(sd_event_source * s)112 int event_source_disable(sd_event_source *s) {
113 if (!s)
114 return 0;
115
116 return sd_event_source_set_enabled(s, SD_EVENT_OFF);
117 }
118
event_source_is_enabled(sd_event_source * s)119 int event_source_is_enabled(sd_event_source *s) {
120 if (!s)
121 return false;
122
123 return sd_event_source_get_enabled(s, NULL);
124 }
125
event_add_time_change(sd_event * e,sd_event_source ** ret,sd_event_io_handler_t callback,void * userdata)126 int event_add_time_change(sd_event *e, sd_event_source **ret, sd_event_io_handler_t callback, void *userdata) {
127 _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
128 _cleanup_close_ int fd = -1;
129 int r;
130
131 assert(e);
132
133 /* Allocates an IO event source that gets woken up whenever the clock changes. Needs to be recreated on each event */
134
135 fd = time_change_fd();
136 if (fd < 0)
137 return fd;
138
139 r = sd_event_add_io(e, &s, fd, EPOLLIN, callback, userdata);
140 if (r < 0)
141 return r;
142
143 r = sd_event_source_set_io_fd_own(s, true);
144 if (r < 0)
145 return r;
146
147 TAKE_FD(fd);
148
149 r = sd_event_source_set_description(s, "time-change");
150 if (r < 0)
151 return r;
152
153 if (ret)
154 *ret = TAKE_PTR(s);
155 else {
156 r = sd_event_source_set_floating(s, true);
157 if (r < 0)
158 return r;
159 }
160
161 return 0;
162 }
163