summaryrefslogtreecommitdiff
path: root/src/systemd/sd-event.h
blob: 020e7457460ee60a6b5829d23b2ddfb8285b9a95 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#ifndef foosdeventhfoo
#define foosdeventhfoo

/***
  This file is part of systemd.

  Copyright 2013 Lennart Poettering

  systemd is free software; you can redistribute it and/or modify it
  under the terms of the GNU Lesser General Public License as published by
  the Free Software Foundation; either version 2.1 of the License, or
  (at your option) any later version.

  systemd is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License
  along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/

#include <inttypes.h>
#include <signal.h>
#include <sys/epoll.h>
#include <sys/signalfd.h>
#include <sys/types.h>

#include "_sd-common.h"

/*
  Why is this better than pure epoll?

  - Supports event source prioritization
  - Scales better with a large number of time events because it does not require one timerfd each
  - Automatically tries to coalesce timer events system-wide
  - Handles signals and child PIDs
*/

_SD_BEGIN_DECLARATIONS;

typedef struct sd_event sd_event;
typedef struct sd_event_source sd_event_source;

enum {
        SD_EVENT_OFF = 0,
        SD_EVENT_ON = 1,
        SD_EVENT_ONESHOT = -1
};

enum {
        SD_EVENT_INITIAL,
        SD_EVENT_ARMED,
        SD_EVENT_PENDING,
        SD_EVENT_RUNNING,
        SD_EVENT_EXITING,
        SD_EVENT_FINISHED,
        SD_EVENT_PREPARING
};

enum {
        /* And everything in-between and outside is good too */
        SD_EVENT_PRIORITY_IMPORTANT = -100,
        SD_EVENT_PRIORITY_NORMAL = 0,
        SD_EVENT_PRIORITY_IDLE = 100
};

typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata);
typedef int (*sd_event_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata);
typedef int (*sd_event_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata);
typedef int (*sd_event_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
#if 1 /// elogind is musl-libc compatible, which has other guards for siginfo_t
#if ( defined(__GLIBC__) \
   && ( defined(__USE_POSIX199309) || defined(__USE_XOPEN_EXTENDED) ) ) \
 || (!defined(__GLIBC__) \
   && ( defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
     || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
     || defined(_BSD_SOURCE) ) )
typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata);
#else
typedef void* sd_event_child_handler_t;
#endif
#endif // 1

int sd_event_default(sd_event **e);

int sd_event_new(sd_event **e);
sd_event* sd_event_ref(sd_event *e);
sd_event* sd_event_unref(sd_event *e);

int sd_event_add_io(sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata);
int sd_event_add_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);
int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata);
int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata);
int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);

int sd_event_prepare(sd_event *e);
int sd_event_wait(sd_event *e, uint64_t usec);
int sd_event_dispatch(sd_event *e);
int sd_event_run(sd_event *e, uint64_t usec);
int sd_event_loop(sd_event *e);
int sd_event_exit(sd_event *e, int code);

int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec);

#if 0 /// UNNEEDED by elogind
int sd_event_get_fd(sd_event *e);
#endif // 0
int sd_event_get_state(sd_event *e);
#if 0 /// UNNEEDED by elogind
int sd_event_get_tid(sd_event *e, pid_t *tid);
int sd_event_get_exit_code(sd_event *e, int *code);
#endif // 0
int sd_event_set_watchdog(sd_event *e, int b);
#if 0 /// UNNEEDED by elogind
int sd_event_get_watchdog(sd_event *e);
#endif // 0
int sd_event_get_iteration(sd_event *e, uint64_t *ret);

#if 0 /// UNNEEDED by elogind
sd_event_source* sd_event_source_ref(sd_event_source *s);
#endif // 0
sd_event_source* sd_event_source_unref(sd_event_source *s);

sd_event *sd_event_source_get_event(sd_event_source *s);
#if 0 /// UNNEEDED by elogind
void* sd_event_source_get_userdata(sd_event_source *s);
void* sd_event_source_set_userdata(sd_event_source *s, void *userdata);
#endif // 0

int sd_event_source_set_description(sd_event_source *s, const char *description);
#if 0 /// UNNEEDED by elogind
int sd_event_source_get_description(sd_event_source *s, const char **description);
#endif // 0
int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback);
#if 0 /// UNNEEDED by elogind
int sd_event_source_get_pending(sd_event_source *s);
#endif // 0
int sd_event_source_get_priority(sd_event_source *s, int64_t *priority);
int sd_event_source_set_priority(sd_event_source *s, int64_t priority);
#if 0 /// UNNEEDED by elogind
int sd_event_source_get_enabled(sd_event_source *s, int *enabled);
#endif // 0
int sd_event_source_set_enabled(sd_event_source *s, int enabled);
#if 0 /// UNNEEDED by elogind
int sd_event_source_get_io_fd(sd_event_source *s);
#endif // 0
int sd_event_source_set_io_fd(sd_event_source *s, int fd);
#if 0 /// UNNEEDED by elogind
int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events);
#endif // 0
int sd_event_source_set_io_events(sd_event_source *s, uint32_t events);
#if 0 /// UNNEEDED by elogind
int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents);
#endif // 0
int sd_event_source_get_time(sd_event_source *s, uint64_t *usec);
int sd_event_source_set_time(sd_event_source *s, uint64_t usec);
#if 0 /// UNNEEDED by elogind
int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec);
int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec);
int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock);
int sd_event_source_get_signal(sd_event_source *s);
int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid);
#endif // 0

/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_unref);

_SD_END_DECLARATIONS;

#endif