blob: 4f75bd6a33e3b678d335b741dea3e9a625e03290 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreau49b046d2012-08-09 12:11:58 +02002 * include/proto/fd.h
3 * File descriptors states.
4 *
Willy Tarreauf817e9f2014-01-10 16:58:45 +01005 * Copyright (C) 2000-2014 Willy Tarreau - w@1wt.eu
Willy Tarreau49b046d2012-08-09 12:11:58 +02006 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation, version 2.1
10 * exclusively.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
Willy Tarreaubaaee002006-06-26 02:48:02 +020021
22#ifndef _PROTO_FD_H
23#define _PROTO_FD_H
24
Willy Tarreau2ff76222007-04-09 19:29:56 +020025#include <stdio.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020026#include <sys/time.h>
27#include <sys/types.h>
28#include <unistd.h>
29
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020030#include <common/config.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020031#include <types/fd.h>
32
Willy Tarreau7be79a42012-11-11 15:02:54 +010033/* public variables */
Willy Tarreau16f649c2014-01-25 19:10:48 +010034extern unsigned int *fd_cache; // FD events cache
35extern unsigned int *fd_updt; // FD updates list
36extern int fd_cache_num; // number of events in the cache
37extern int fd_nbupdt; // number of updates in the list
Willy Tarreau7be79a42012-11-11 15:02:54 +010038
Willy Tarreaubaaee002006-06-26 02:48:02 +020039/* Deletes an FD from the fdsets, and recomputes the maxfd limit.
40 * The file descriptor is also closed.
41 */
42void fd_delete(int fd);
43
Willy Tarreau4f60f162007-04-08 16:39:58 +020044/* disable the specified poller */
45void disable_poller(const char *poller_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +020046
Willy Tarreau2a429502006-10-15 14:52:29 +020047/*
Willy Tarreau4f60f162007-04-08 16:39:58 +020048 * Initialize the pollers till the best one is found.
49 * If none works, returns 0, otherwise 1.
Willy Tarreauef1d1f82007-04-16 00:25:25 +020050 * The pollers register themselves just before main() is called.
Willy Tarreau2a429502006-10-15 14:52:29 +020051 */
Willy Tarreau4f60f162007-04-08 16:39:58 +020052int init_pollers();
Willy Tarreau2a429502006-10-15 14:52:29 +020053
Willy Tarreau4f60f162007-04-08 16:39:58 +020054/*
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +020055 * Deinitialize the pollers.
56 */
57void deinit_pollers();
58
59/*
Willy Tarreau2ff76222007-04-09 19:29:56 +020060 * Some pollers may lose their connection after a fork(). It may be necessary
61 * to create initialize part of them again. Returns 0 in case of failure,
62 * otherwise 1. The fork() function may be NULL if unused. In case of error,
63 * the the current poller is destroyed and the caller is responsible for trying
64 * another one by calling init_pollers() again.
65 */
66int fork_poller();
67
68/*
69 * Lists the known pollers on <out>.
70 * Should be performed only before initialization.
71 */
72int list_pollers(FILE *out);
73
74/*
Willy Tarreau4f60f162007-04-08 16:39:58 +020075 * Runs the polling loop
76 */
77void run_poller();
Willy Tarreau2a429502006-10-15 14:52:29 +020078
Willy Tarreau033cd9d2014-01-25 19:24:15 +010079/* Scan and process the cached events. This should be called right after
Willy Tarreau09f24562012-11-11 16:43:45 +010080 * the poller.
81 */
Willy Tarreau033cd9d2014-01-25 19:24:15 +010082void fd_process_cached_events();
Willy Tarreau09f24562012-11-11 16:43:45 +010083
Willy Tarreau7be79a42012-11-11 15:02:54 +010084/* Mark fd <fd> as updated and allocate an entry in the update list for this if
85 * it was not already there. This can be done at any time.
86 */
87static inline void updt_fd(const int fd)
88{
89 if (fdtab[fd].updated)
90 /* already scheduled for update */
91 return;
Willy Tarreau7be79a42012-11-11 15:02:54 +010092 fdtab[fd].updated = 1;
Willy Tarreau4a291442012-12-13 23:34:18 +010093 fd_updt[fd_nbupdt++] = fd;
Willy Tarreau7be79a42012-11-11 15:02:54 +010094}
95
96
Willy Tarreau899d9572014-01-25 19:20:35 +010097/* Allocates a cache entry for a file descriptor if it does not yet have one.
98 * This can be done at any time.
99 */
100static inline void fd_alloc_cache_entry(const int fd)
Willy Tarreau7be79a42012-11-11 15:02:54 +0100101{
Willy Tarreau15a4dec2014-01-20 11:09:39 +0100102 if (fdtab[fd].cache)
Willy Tarreau7be79a42012-11-11 15:02:54 +0100103 return;
Willy Tarreau16f649c2014-01-25 19:10:48 +0100104 fd_cache_num++;
105 fdtab[fd].cache = fd_cache_num;
106 fd_cache[fd_cache_num-1] = fd;
Willy Tarreau7be79a42012-11-11 15:02:54 +0100107}
108
Willy Tarreau899d9572014-01-25 19:20:35 +0100109/* Removes entry used by fd <fd> from the FD cache and replaces it with the
110 * last one. The fdtab.cache is adjusted to match the back reference if needed.
Willy Tarreau7be79a42012-11-11 15:02:54 +0100111 * If the fd has no entry assigned, return immediately.
112 */
Willy Tarreau899d9572014-01-25 19:20:35 +0100113static inline void fd_release_cache_entry(int fd)
Willy Tarreau7be79a42012-11-11 15:02:54 +0100114{
115 unsigned int pos;
116
Willy Tarreau15a4dec2014-01-20 11:09:39 +0100117 pos = fdtab[fd].cache;
Willy Tarreau7be79a42012-11-11 15:02:54 +0100118 if (!pos)
119 return;
Willy Tarreau15a4dec2014-01-20 11:09:39 +0100120 fdtab[fd].cache = 0;
Willy Tarreau16f649c2014-01-25 19:10:48 +0100121 fd_cache_num--;
122 if (likely(pos <= fd_cache_num)) {
Willy Tarreau7be79a42012-11-11 15:02:54 +0100123 /* was not the last entry */
Willy Tarreau16f649c2014-01-25 19:10:48 +0100124 fd = fd_cache[fd_cache_num];
125 fd_cache[pos - 1] = fd;
Willy Tarreau15a4dec2014-01-20 11:09:39 +0100126 fdtab[fd].cache = pos;
Willy Tarreau7be79a42012-11-11 15:02:54 +0100127 }
128}
Willy Tarreau49b046d2012-08-09 12:11:58 +0200129
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100130/* Automatically allocates or releases a cache entry for fd <fd> depending on
131 * its new state. This is meant to be used by pollers while processing updates.
132 */
133static inline void fd_alloc_or_release_cache_entry(int fd, int new_state)
134{
135 /* READY and ACTIVE states (the two with both flags set) require a cache entry */
136
137 if (((new_state & (FD_EV_READY_R | FD_EV_ACTIVE_R)) == (FD_EV_READY_R | FD_EV_ACTIVE_R)) ||
138 ((new_state & (FD_EV_READY_W | FD_EV_ACTIVE_W)) == (FD_EV_READY_W | FD_EV_ACTIVE_W))) {
139 fd_alloc_cache_entry(fd);
140 }
141 else {
142 fd_release_cache_entry(fd);
143 }
144}
145
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100146/*
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100147 * returns the FD's recv state (FD_EV_*)
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100148 */
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100149static inline int fd_recv_state(const int fd)
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100150{
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100151 return ((unsigned)fdtab[fd].state >> (4 * DIR_RD)) & FD_EV_STATUS;
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100152}
153
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100154/*
155 * returns true if the FD is active for recv
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100156 */
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100157static inline int fd_recv_active(const int fd)
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100158{
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100159 return (unsigned)fdtab[fd].state & FD_EV_ACTIVE_R;
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100160}
161
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100162/*
163 * returns true if the FD is ready for recv
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100164 */
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100165static inline int fd_recv_ready(const int fd)
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100166{
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100167 return (unsigned)fdtab[fd].state & FD_EV_READY_R;
168}
169
170/*
171 * returns true if the FD is polled for recv
172 */
173static inline int fd_recv_polled(const int fd)
174{
175 return (unsigned)fdtab[fd].state & FD_EV_POLLED_R;
176}
177
178/*
179 * returns the FD's send state (FD_EV_*)
180 */
181static inline int fd_send_state(const int fd)
182{
183 return ((unsigned)fdtab[fd].state >> (4 * DIR_WR)) & FD_EV_STATUS;
184}
185
186/*
187 * returns true if the FD is active for send
188 */
189static inline int fd_send_active(const int fd)
190{
191 return (unsigned)fdtab[fd].state & FD_EV_ACTIVE_W;
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100192}
193
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100194/*
195 * returns true if the FD is ready for send
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100196 */
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100197static inline int fd_send_ready(const int fd)
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100198{
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100199 return (unsigned)fdtab[fd].state & FD_EV_READY_W;
200}
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100201
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100202/*
203 * returns true if the FD is polled for send
204 */
205static inline int fd_send_polled(const int fd)
206{
207 return (unsigned)fdtab[fd].state & FD_EV_POLLED_W;
208}
209
210/* Disable processing recv events on fd <fd> */
211static inline void fd_stop_recv(int fd)
212{
213 if (!((unsigned int)fdtab[fd].state & FD_EV_ACTIVE_R))
214 return; /* already disabled */
215 fdtab[fd].state &= ~FD_EV_ACTIVE_R;
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100216 updt_fd(fd); /* need an update entry to change the state */
217}
218
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100219/* Disable processing send events on fd <fd> */
220static inline void fd_stop_send(int fd)
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100221{
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100222 if (!((unsigned int)fdtab[fd].state & FD_EV_ACTIVE_W))
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100223 return; /* already disabled */
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100224 fdtab[fd].state &= ~FD_EV_ACTIVE_W;
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100225 updt_fd(fd); /* need an update entry to change the state */
226}
227
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100228/* Disable processing of events on fd <fd> for both directions. */
229static inline void fd_stop_both(int fd)
Willy Tarreau49b046d2012-08-09 12:11:58 +0200230{
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100231 if (!((unsigned int)fdtab[fd].state & FD_EV_ACTIVE_RW))
232 return; /* already disabled */
233 fdtab[fd].state &= ~FD_EV_ACTIVE_RW;
234 updt_fd(fd); /* need an update entry to change the state */
Willy Tarreau49b046d2012-08-09 12:11:58 +0200235}
236
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100237/* Report that FD <fd> cannot receive anymore without polling (EAGAIN detected). */
238static inline void fd_cant_recv(const int fd)
Willy Tarreau49b046d2012-08-09 12:11:58 +0200239{
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100240 if (!(((unsigned int)fdtab[fd].state) & FD_EV_READY_R))
241 return; /* already marked as blocked */
242 fdtab[fd].state &= ~FD_EV_READY_R;
243 updt_fd(fd);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200244}
245
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100246/* Report that FD <fd> can receive anymore without polling. */
247static inline void fd_may_recv(const int fd)
Willy Tarreaubabd05a2012-08-09 12:14:03 +0200248{
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100249 if (((unsigned int)fdtab[fd].state) & FD_EV_READY_R)
250 return; /* already marked as blocked */
251 fdtab[fd].state |= FD_EV_READY_R;
252 updt_fd(fd);
Willy Tarreaubabd05a2012-08-09 12:14:03 +0200253}
254
Willy Tarreau6c11bd22014-01-24 00:54:27 +0100255/* Disable readiness when polled. This is useful to interrupt reading when it
256 * is suspected that the end of data might have been reached (eg: short read).
257 * This can only be done using level-triggered pollers, so if any edge-triggered
258 * is ever implemented, a test will have to be added here.
259 */
260static inline void fd_done_recv(const int fd)
261{
262 if (fd_recv_polled(fd))
263 fd_cant_recv(fd);
264}
265
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100266/* Report that FD <fd> cannot send anymore without polling (EAGAIN detected). */
267static inline void fd_cant_send(const int fd)
Willy Tarreau49b046d2012-08-09 12:11:58 +0200268{
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100269 if (!(((unsigned int)fdtab[fd].state) & FD_EV_READY_W))
270 return; /* already marked as blocked */
271 fdtab[fd].state &= ~FD_EV_READY_W;
272 updt_fd(fd);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200273}
274
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100275/* Report that FD <fd> can send anymore without polling (EAGAIN detected). */
276static inline void fd_may_send(const int fd)
Willy Tarreau49b046d2012-08-09 12:11:58 +0200277{
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100278 if (((unsigned int)fdtab[fd].state) & FD_EV_READY_W)
279 return; /* already marked as blocked */
280 fdtab[fd].state |= FD_EV_READY_W;
281 updt_fd(fd);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200282}
Willy Tarreau2a429502006-10-15 14:52:29 +0200283
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100284/* Prepare FD <fd> to try to receive */
285static inline void fd_want_recv(int fd)
Willy Tarreaubabd05a2012-08-09 12:14:03 +0200286{
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100287 if (((unsigned int)fdtab[fd].state & FD_EV_ACTIVE_R))
288 return; /* already enabled */
289 fdtab[fd].state |= FD_EV_ACTIVE_R;
290 updt_fd(fd); /* need an update entry to change the state */
Willy Tarreaubabd05a2012-08-09 12:14:03 +0200291}
292
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100293/* Prepare FD <fd> to try to send */
294static inline void fd_want_send(int fd)
Willy Tarreau49b046d2012-08-09 12:11:58 +0200295{
Willy Tarreauf817e9f2014-01-10 16:58:45 +0100296 if (((unsigned int)fdtab[fd].state & FD_EV_ACTIVE_W))
297 return; /* already enabled */
298 fdtab[fd].state |= FD_EV_ACTIVE_W;
299 updt_fd(fd); /* need an update entry to change the state */
Willy Tarreau49b046d2012-08-09 12:11:58 +0200300}
Willy Tarreau2a429502006-10-15 14:52:29 +0200301
Willy Tarreaud6f087e2008-01-18 17:20:13 +0100302/* Prepares <fd> for being polled */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303static inline void fd_insert(int fd)
304{
Willy Tarreaud6f087e2008-01-18 17:20:13 +0100305 fdtab[fd].ev = 0;
Willy Tarreau037d2c12012-11-06 02:34:46 +0100306 fdtab[fd].new = 1;
Willy Tarreauad38ace2013-12-15 14:19:38 +0100307 fdtab[fd].linger_risk = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308 if (fd + 1 > maxfd)
309 maxfd = fd + 1;
310}
311
312
313#endif /* _PROTO_FD_H */
314
315/*
316 * Local variables:
317 * c-indent-level: 8
318 * c-basic-offset: 8
319 * End:
320 */