]> git.proxmox.com Git - systemd.git/blob - src/libsystemd/sd-event/event-source.h
New upstream version 240
[systemd.git] / src / libsystemd / sd-event / event-source.h
1 #pragma once
2 /* SPDX-License-Identifier: LGPL-2.1+ */
3
4 #include <sys/epoll.h>
5 #include <sys/timerfd.h>
6 #include <sys/wait.h>
7
8 #include "sd-event.h"
9
10 #include "fs-util.h"
11 #include "hashmap.h"
12 #include "list.h"
13 #include "prioq.h"
14
15 typedef enum EventSourceType {
16 SOURCE_IO,
17 SOURCE_TIME_REALTIME,
18 SOURCE_TIME_BOOTTIME,
19 SOURCE_TIME_MONOTONIC,
20 SOURCE_TIME_REALTIME_ALARM,
21 SOURCE_TIME_BOOTTIME_ALARM,
22 SOURCE_SIGNAL,
23 SOURCE_CHILD,
24 SOURCE_DEFER,
25 SOURCE_POST,
26 SOURCE_EXIT,
27 SOURCE_WATCHDOG,
28 SOURCE_INOTIFY,
29 _SOURCE_EVENT_SOURCE_TYPE_MAX,
30 _SOURCE_EVENT_SOURCE_TYPE_INVALID = -1
31 } EventSourceType;
32
33 /* All objects we use in epoll events start with this value, so that
34 * we know how to dispatch it */
35 typedef enum WakeupType {
36 WAKEUP_NONE,
37 WAKEUP_EVENT_SOURCE,
38 WAKEUP_CLOCK_DATA,
39 WAKEUP_SIGNAL_DATA,
40 WAKEUP_INOTIFY_DATA,
41 _WAKEUP_TYPE_MAX,
42 _WAKEUP_TYPE_INVALID = -1,
43 } WakeupType;
44
45 struct inode_data;
46
47 struct sd_event_source {
48 WakeupType wakeup;
49
50 unsigned n_ref;
51
52 sd_event *event;
53 void *userdata;
54 sd_event_handler_t prepare;
55
56 char *description;
57
58 EventSourceType type:5;
59 signed int enabled:3;
60 bool pending:1;
61 bool dispatching:1;
62 bool floating:1;
63
64 int64_t priority;
65 unsigned pending_index;
66 unsigned prepare_index;
67 uint64_t pending_iteration;
68 uint64_t prepare_iteration;
69
70 sd_event_destroy_t destroy_callback;
71
72 LIST_FIELDS(sd_event_source, sources);
73
74 union {
75 struct {
76 sd_event_io_handler_t callback;
77 int fd;
78 uint32_t events;
79 uint32_t revents;
80 bool registered:1;
81 bool owned:1;
82 } io;
83 struct {
84 sd_event_time_handler_t callback;
85 usec_t next, accuracy;
86 unsigned earliest_index;
87 unsigned latest_index;
88 } time;
89 struct {
90 sd_event_signal_handler_t callback;
91 struct signalfd_siginfo siginfo;
92 int sig;
93 } signal;
94 struct {
95 sd_event_child_handler_t callback;
96 siginfo_t siginfo;
97 pid_t pid;
98 int options;
99 } child;
100 struct {
101 sd_event_handler_t callback;
102 } defer;
103 struct {
104 sd_event_handler_t callback;
105 } post;
106 struct {
107 sd_event_handler_t callback;
108 unsigned prioq_index;
109 } exit;
110 struct {
111 sd_event_inotify_handler_t callback;
112 uint32_t mask;
113 struct inode_data *inode_data;
114 LIST_FIELDS(sd_event_source, by_inode_data);
115 } inotify;
116 };
117 };
118
119 struct clock_data {
120 WakeupType wakeup;
121 int fd;
122
123 /* For all clocks we maintain two priority queues each, one
124 * ordered for the earliest times the events may be
125 * dispatched, and one ordered by the latest times they must
126 * have been dispatched. The range between the top entries in
127 * the two prioqs is the time window we can freely schedule
128 * wakeups in */
129
130 Prioq *earliest;
131 Prioq *latest;
132 usec_t next;
133
134 bool needs_rearm:1;
135 };
136
137 struct signal_data {
138 WakeupType wakeup;
139
140 /* For each priority we maintain one signal fd, so that we
141 * only have to dequeue a single event per priority at a
142 * time. */
143
144 int fd;
145 int64_t priority;
146 sigset_t sigset;
147 sd_event_source *current;
148 };
149
150 /* A structure listing all event sources currently watching a specific inode */
151 struct inode_data {
152 /* The identifier for the inode, the combination of the .st_dev + .st_ino fields of the file */
153 ino_t ino;
154 dev_t dev;
155
156 /* An fd of the inode to watch. The fd is kept open until the next iteration of the loop, so that we can
157 * rearrange the priority still until then, as we need the original inode to change the priority as we need to
158 * add a watch descriptor to the right inotify for the priority which we can only do if we have a handle to the
159 * original inode. We keep a list of all inode_data objects with an open fd in the to_close list (see below) of
160 * the sd-event object, so that it is efficient to close everything, before entering the next event loop
161 * iteration. */
162 int fd;
163
164 /* The inotify "watch descriptor" */
165 int wd;
166
167 /* The combination of the mask of all inotify watches on this inode we manage. This is also the mask that has
168 * most recently been set on the watch descriptor. */
169 uint32_t combined_mask;
170
171 /* All event sources subscribed to this inode */
172 LIST_HEAD(sd_event_source, event_sources);
173
174 /* The inotify object we watch this inode with */
175 struct inotify_data *inotify_data;
176
177 /* A linked list of all inode data objects with fds to close (see above) */
178 LIST_FIELDS(struct inode_data, to_close);
179 };
180
181 /* A structure encapsulating an inotify fd */
182 struct inotify_data {
183 WakeupType wakeup;
184
185 /* For each priority we maintain one inotify fd, so that we only have to dequeue a single event per priority at
186 * a time */
187
188 int fd;
189 int64_t priority;
190
191 Hashmap *inodes; /* The inode_data structures keyed by dev+ino */
192 Hashmap *wd; /* The inode_data structures keyed by the watch descriptor for each */
193
194 /* The buffer we read inotify events into */
195 union inotify_event_buffer buffer;
196 size_t buffer_filled; /* fill level of the buffer */
197
198 /* How many event sources are currently marked pending for this inotify. We won't read new events off the
199 * inotify fd as long as there are still pending events on the inotify (because we have no strategy of queuing
200 * the events locally if they can't be coalesced). */
201 unsigned n_pending;
202
203 /* A linked list of all inotify objects with data already read, that still need processing. We keep this list
204 * to make it efficient to figure out what inotify objects to process data on next. */
205 LIST_FIELDS(struct inotify_data, buffered);
206 };