blob: 472665f104bf1252de6f090ab9349c06439a8056 [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 *
5 * Copyright (C) 2000-2012 Willy Tarreau - w@1wt.eu
6 *
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 */
34extern int fd_nbspec; // number of speculative events in the list
35extern int fd_nbupdt; // number of updates in the list
36extern unsigned int *fd_spec; // speculative I/O list
37extern unsigned int *fd_updt; // FD updates list
38
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 Tarreau09f24562012-11-11 16:43:45 +010079/* Scan and process the speculative events. This should be called right after
80 * the poller.
81 */
82void fd_process_spec_events();
83
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
97/* allocate an entry for a speculative event. This can be done at any time. */
98static inline void alloc_spec_entry(const int fd)
99{
100 if (fdtab[fd].spec_p)
101 /* FD already in speculative I/O list */
102 return;
Willy Tarreau4a291442012-12-13 23:34:18 +0100103 fd_nbspec++;
Willy Tarreau7be79a42012-11-11 15:02:54 +0100104 fdtab[fd].spec_p = fd_nbspec;
Willy Tarreau4a291442012-12-13 23:34:18 +0100105 fd_spec[fd_nbspec-1] = fd;
Willy Tarreau7be79a42012-11-11 15:02:54 +0100106}
107
108/* Removes entry used by fd <fd> from the spec list and replaces it with the
109 * last one. The fdtab.spec is adjusted to match the back reference if needed.
110 * If the fd has no entry assigned, return immediately.
111 */
112static inline void release_spec_entry(int fd)
113{
114 unsigned int pos;
115
116 pos = fdtab[fd].spec_p;
117 if (!pos)
118 return;
119 fdtab[fd].spec_p = 0;
120 fd_nbspec--;
Willy Tarreau4a291442012-12-13 23:34:18 +0100121 if (likely(pos <= fd_nbspec)) {
Willy Tarreau7be79a42012-11-11 15:02:54 +0100122 /* was not the last entry */
123 fd = fd_spec[fd_nbspec];
124 fd_spec[pos - 1] = fd;
125 fdtab[fd].spec_p = pos;
126 }
127}
Willy Tarreau49b046d2012-08-09 12:11:58 +0200128
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100129/*
130 * Returns non-zero if <fd> is already monitored for events in direction <dir>.
131 */
132static inline int fd_ev_is_set(const int fd, int dir)
133{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100134 return ((unsigned)fdtab[fd].spec_e >> dir) & FD_EV_STATUS;
135}
136
137/* Disable processing of events on fd <fd> for direction <dir>. Note: this
138 * function was optimized to be used with a constant for <dir>.
139 */
140static inline void fd_ev_clr(const int fd, int dir)
141{
142 unsigned int i = ((unsigned int)fdtab[fd].spec_e) & (FD_EV_STATUS << dir);
143 if (i == 0)
144 return; /* already disabled */
145 fdtab[fd].spec_e ^= i;
146 updt_fd(fd); /* need an update entry to change the state */
147}
148
149/* Enable polling for events on fd <fd> for direction <dir>. Note: this
150 * function was optimized to be used with a constant for <dir>.
151 */
152static inline void fd_ev_wai(const int fd, int dir)
153{
154 unsigned int i = ((unsigned int)fdtab[fd].spec_e) & (FD_EV_STATUS << dir);
155 if (i == (FD_EV_POLLED << dir))
156 return; /* already in desired state */
157 fdtab[fd].spec_e ^= i ^ (FD_EV_POLLED << dir);
158 updt_fd(fd); /* need an update entry to change the state */
159}
160
161/* Enable processing of events on fd <fd> for direction <dir>. Note: this
162 * function was optimized to be used with a constant for <dir>.
163 */
164static inline void fd_ev_set(int fd, int dir)
165{
166 unsigned int i = ((unsigned int)fdtab[fd].spec_e) & (FD_EV_STATUS << dir);
167
168 /* note that we don't care about disabling the polled state when
169 * enabling the active state, since it brings no benefit but costs
170 * some syscalls.
171 */
172 if (i & (FD_EV_ACTIVE << dir))
173 return; /* already in desired state */
Willy Tarreau12082662013-12-27 20:11:50 +0100174
175 /* If we're touching an FD which is still being polled, and was
176 * recently disabled, we re-enable polling in order not to perform
177 * a syscall dance and to avoid a missed speculative event.
178 */
179 if ((((unsigned int)fdtab[fd].spec_e) >> 4) & (FD_EV_POLLED << dir))
180 fdtab[fd].spec_e ^= i ^ (FD_EV_POLLED << dir);
181 else
182 fdtab[fd].spec_e |= (FD_EV_ACTIVE << dir);
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100183 updt_fd(fd); /* need an update entry to change the state */
184}
185
186/* Disable processing of events on fd <fd> for both directions. */
187static inline void fd_ev_rem(const int fd)
188{
189 unsigned int i = ((unsigned int)fdtab[fd].spec_e) & FD_EV_CURR_MASK;
190 if (i == 0)
191 return; /* already disabled */
192 fdtab[fd].spec_e ^= i;
193 updt_fd(fd); /* need an update entry to change the state */
194}
195
Willy Tarreau49b046d2012-08-09 12:11:58 +0200196/* event manipulation primitives for use by I/O callbacks */
197static inline void fd_want_recv(int fd)
198{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100199 return fd_ev_set(fd, DIR_RD);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200200}
201
202static inline void fd_stop_recv(int fd)
203{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100204 return fd_ev_clr(fd, DIR_RD);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200205}
206
Willy Tarreaubabd05a2012-08-09 12:14:03 +0200207static inline void fd_poll_recv(int fd)
208{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100209 return fd_ev_wai(fd, DIR_RD);
Willy Tarreaubabd05a2012-08-09 12:14:03 +0200210}
211
Willy Tarreau49b046d2012-08-09 12:11:58 +0200212static inline void fd_want_send(int fd)
213{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100214 return fd_ev_set(fd, DIR_WR);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200215}
216
217static inline void fd_stop_send(int fd)
218{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100219 return fd_ev_clr(fd, DIR_WR);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200220}
Willy Tarreau2a429502006-10-15 14:52:29 +0200221
Willy Tarreaubabd05a2012-08-09 12:14:03 +0200222static inline void fd_poll_send(int fd)
223{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100224 return fd_ev_wai(fd, DIR_WR);
Willy Tarreaubabd05a2012-08-09 12:14:03 +0200225}
226
Willy Tarreau49b046d2012-08-09 12:11:58 +0200227static inline void fd_stop_both(int fd)
228{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100229 return fd_ev_rem(fd);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200230}
Willy Tarreau2a429502006-10-15 14:52:29 +0200231
Willy Tarreaud6f087e2008-01-18 17:20:13 +0100232/* Prepares <fd> for being polled */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233static inline void fd_insert(int fd)
234{
Willy Tarreaud6f087e2008-01-18 17:20:13 +0100235 fdtab[fd].ev = 0;
Willy Tarreau037d2c12012-11-06 02:34:46 +0100236 fdtab[fd].new = 1;
Willy Tarreauad38ace2013-12-15 14:19:38 +0100237 fdtab[fd].linger_risk = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 if (fd + 1 > maxfd)
239 maxfd = fd + 1;
240}
241
242
243#endif /* _PROTO_FD_H */
244
245/*
246 * Local variables:
247 * c-indent-level: 8
248 * c-basic-offset: 8
249 * End:
250 */