1 /*
2 * ivykis, an event handling library
3 * Copyright (C) 2002, 2003, 2009, 2012 Lennert Buytenhek
4 * Dedicated to Marija Kulikova.
5 *
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License version
8 * 2.1 as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License version 2.1 for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License version 2.1 along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include <iv_event_raw.h>
22 #include "mutex.h"
23 #include "pthr.h"
24
25 #define MASKIN 1
26 #define MASKOUT 2
27 #define MASKERR 4
28
29 struct iv_state {
30 /* iv_main_posix.c */
31 int quit;
32 int numobjs;
33
34 /* iv_event.c */
35 int event_count;
36 struct iv_task events_local;
37 struct iv_event_raw events_kick;
38 ___mutex_t event_list_mutex;
39 struct iv_list_head events_pending;
40
41 /* iv_fd.c */
42 int numfds;
43 struct iv_fd_ *handled_fd;
44 int last_abs_count;
45 struct timespec last_abs;
46
47 /* iv_task.c */
48 struct iv_list_head tasks;
49 struct iv_list_head *tasks_current;
50 uint32_t task_epoch;
51
52 /* iv_timer.c */
53 struct timespec time;
54 int time_valid;
55 int num_timers;
56 int rat_depth;
57 union {
58 struct iv_timer_ratnode *timer_root;
59 struct iv_timer_ratnode first_leaf;
60 } ratnode;
61
62 /* poll methods */
63 union {
64 #ifdef HAVE_SYS_DEVPOLL_H
65 struct {
66 struct iv_avl_tree fds;
67 int poll_fd;
68 struct iv_list_head notify;
69 } dev_poll;
70 #endif
71
72 #ifdef HAVE_EPOLL_CREATE
73 struct {
74 struct iv_list_head notify;
75 int epoll_fd;
76 int timer_fd;
77 } epoll;
78 #endif
79
80 #ifdef HAVE_KQUEUE
81 struct {
82 struct iv_list_head notify;
83 int kqueue_fd;
84 int timeout_pending;
85 const struct timespec *timeout;
86 } kqueue;
87 #endif
88
89 struct {
90 struct pollfd *pfds;
91 struct iv_fd_ **fds;
92 int num_regd_fds;
93 } poll;
94
95 #ifdef HAVE_PORT_CREATE
96 struct {
97 struct iv_list_head notify;
98 int port_fd;
99 timer_t timer_id;
100 } port;
101 #endif
102 } u;
103 };
104
105 struct iv_fd_ {
106 /*
107 * User data.
108 */
109 int fd;
110 void *cookie;
111 void (*handler_in)(void *);
112 void (*handler_out)(void *);
113 void (*handler_err)(void *);
114
115 /*
116 * If this fd gathered any events during this polling round,
117 * fd->list_active will be on iv_main()'s active list, and
118 * fd->ready_bands will indicate which bands are currently
119 * active.
120 */
121 struct iv_list_head list_active;
122 uint8_t ready_bands;
123
124 /*
125 * Reflects whether the fd has been registered with
126 * iv_fd_register(). Will be zero in ->notify_fd() if the
127 * fd is being unregistered.
128 */
129 uint8_t registered;
130
131 /*
132 * ->wanted_bands is set by the ivykis core to indicate
133 * which bands currenty have handlers registered for them.
134 */
135 uint8_t wanted_bands;
136
137 /*
138 * ->registered_bands is maintained by the poll method to
139 * indicate which bands are currently registered with the
140 * kernel, so that the ivykis core knows when to call
141 * the poll method's ->notify_fd() on an fd.
142 */
143 uint8_t registered_bands;
144
145 #if defined(HAVE_SYS_DEVPOLL_H) || defined(HAVE_EPOLL_CREATE) || \
146 defined(HAVE_KQUEUE) || defined(HAVE_PORT_CREATE)
147 /*
148 * ->list_notify is used by poll methods that defer updating
149 * kernel registrations to ->poll() time.
150 */
151 struct iv_list_head list_notify;
152 #endif
153
154 /*
155 * This is for state internal to some of the poll methods:
156 * ->avl_node is used by the /dev/poll method to maintain an
157 * internal fd tree, and ->index is used by iv_fd_poll to
158 * maintain the index of this fd in the list of pollfds.
159 */
160 union {
161 #ifdef HAVE_SYS_DEVPOLL_H
162 struct iv_avl_node avl_node;
163 #endif
164 int index;
165 } u;
166 };
167
168 struct iv_fd_poll_method {
169 char *name;
170 int (*init)(struct iv_state *st);
171 int (*set_poll_timeout)(struct iv_state *st,
172 const struct timespec *abs);
173 void (*clear_poll_timeout)(struct iv_state *st);
174 int (*poll)(struct iv_state *st, struct iv_list_head *active,
175 const struct timespec *abs);
176 void (*register_fd)(struct iv_state *st, struct iv_fd_ *fd);
177 void (*unregister_fd)(struct iv_state *st, struct iv_fd_ *fd);
178 void (*notify_fd)(struct iv_state *st, struct iv_fd_ *fd);
179 int (*notify_fd_sync)(struct iv_state *st, struct iv_fd_ *fd);
180 void (*deinit)(struct iv_state *st);
181 int (*event_rx_on)(struct iv_state *st);
182 void (*event_rx_off)(struct iv_state *st);
183 void (*event_send)(struct iv_state *dest);
184 };
185
186 extern pthr_key_t iv_state_key;
187
is_mt_app(void)188 static inline int is_mt_app(void)
189 {
190 return pthreads_available();
191 }
192
iv_get_state(void)193 static inline struct iv_state *iv_get_state(void)
194 {
195 return pthr_getspecific(&iv_state_key);
196 }
197
198
199 extern int maxfd;
200 extern const struct iv_fd_poll_method *method;
201
202 extern const struct iv_fd_poll_method iv_fd_poll_method_dev_poll;
203 extern const struct iv_fd_poll_method iv_fd_poll_method_epoll;
204 extern const struct iv_fd_poll_method iv_fd_poll_method_epoll_timerfd;
205 extern const struct iv_fd_poll_method iv_fd_poll_method_kqueue;
206 extern const struct iv_fd_poll_method iv_fd_poll_method_poll;
207 extern const struct iv_fd_poll_method iv_fd_poll_method_port;
208 extern const struct iv_fd_poll_method iv_fd_poll_method_port_timer;
209 extern const struct iv_fd_poll_method iv_fd_poll_method_ppoll;
210
211 /* iv_fd.c */
212 void iv_fd_init(struct iv_state *st);
213 void iv_fd_deinit(struct iv_state *st);
214 int iv_fd_poll_and_run(struct iv_state *st, const struct timespec *abs);
215 void iv_fd_make_ready(struct iv_list_head *active,
216 struct iv_fd_ *fd, int bands);
217 void iv_fd_set_cloexec(int fd);
218 void iv_fd_set_nonblock(int fd);
219
220 /* iv_signal.c */
221 void iv_signal_child_reset_postfork(void);
222