blob: 127cbe08d522d93b325a341aa6654d28ae8b9ba5 [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;
92 fd_updt[fd_nbupdt++] = fd;
93 fdtab[fd].updated = 1;
94}
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;
103 fd_spec[fd_nbspec++] = fd;
104 fdtab[fd].spec_p = fd_nbspec;
105}
106
107/* Removes entry used by fd <fd> from the spec list and replaces it with the
108 * last one. The fdtab.spec is adjusted to match the back reference if needed.
109 * If the fd has no entry assigned, return immediately.
110 */
111static inline void release_spec_entry(int fd)
112{
113 unsigned int pos;
114
115 pos = fdtab[fd].spec_p;
116 if (!pos)
117 return;
118 fdtab[fd].spec_p = 0;
119 fd_nbspec--;
120 if (pos <= fd_nbspec) {
121 /* was not the last entry */
122 fd = fd_spec[fd_nbspec];
123 fd_spec[pos - 1] = fd;
124 fdtab[fd].spec_p = pos;
125 }
126}
Willy Tarreau49b046d2012-08-09 12:11:58 +0200127
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100128/*
129 * Returns non-zero if <fd> is already monitored for events in direction <dir>.
130 */
131static inline int fd_ev_is_set(const int fd, int dir)
132{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100133 return ((unsigned)fdtab[fd].spec_e >> dir) & FD_EV_STATUS;
134}
135
136/* Disable processing of events on fd <fd> for direction <dir>. Note: this
137 * function was optimized to be used with a constant for <dir>.
138 */
139static inline void fd_ev_clr(const int fd, int dir)
140{
141 unsigned int i = ((unsigned int)fdtab[fd].spec_e) & (FD_EV_STATUS << dir);
142 if (i == 0)
143 return; /* already disabled */
144 fdtab[fd].spec_e ^= i;
145 updt_fd(fd); /* need an update entry to change the state */
146}
147
148/* Enable polling for events on fd <fd> for direction <dir>. Note: this
149 * function was optimized to be used with a constant for <dir>.
150 */
151static inline void fd_ev_wai(const int fd, int dir)
152{
153 unsigned int i = ((unsigned int)fdtab[fd].spec_e) & (FD_EV_STATUS << dir);
154 if (i == (FD_EV_POLLED << dir))
155 return; /* already in desired state */
156 fdtab[fd].spec_e ^= i ^ (FD_EV_POLLED << dir);
157 updt_fd(fd); /* need an update entry to change the state */
158}
159
160/* Enable processing of events on fd <fd> for direction <dir>. Note: this
161 * function was optimized to be used with a constant for <dir>.
162 */
163static inline void fd_ev_set(int fd, int dir)
164{
165 unsigned int i = ((unsigned int)fdtab[fd].spec_e) & (FD_EV_STATUS << dir);
166
167 /* note that we don't care about disabling the polled state when
168 * enabling the active state, since it brings no benefit but costs
169 * some syscalls.
170 */
171 if (i & (FD_EV_ACTIVE << dir))
172 return; /* already in desired state */
173 fdtab[fd].spec_e |= (FD_EV_ACTIVE << dir);
174 updt_fd(fd); /* need an update entry to change the state */
175}
176
177/* Disable processing of events on fd <fd> for both directions. */
178static inline void fd_ev_rem(const int fd)
179{
180 unsigned int i = ((unsigned int)fdtab[fd].spec_e) & FD_EV_CURR_MASK;
181 if (i == 0)
182 return; /* already disabled */
183 fdtab[fd].spec_e ^= i;
184 updt_fd(fd); /* need an update entry to change the state */
185}
186
Willy Tarreau49b046d2012-08-09 12:11:58 +0200187/* event manipulation primitives for use by I/O callbacks */
188static inline void fd_want_recv(int fd)
189{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100190 return fd_ev_set(fd, DIR_RD);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200191}
192
193static inline void fd_stop_recv(int fd)
194{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100195 return fd_ev_clr(fd, DIR_RD);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200196}
197
Willy Tarreaubabd05a2012-08-09 12:14:03 +0200198static inline void fd_poll_recv(int fd)
199{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100200 return fd_ev_wai(fd, DIR_RD);
Willy Tarreaubabd05a2012-08-09 12:14:03 +0200201}
202
Willy Tarreau49b046d2012-08-09 12:11:58 +0200203static inline void fd_want_send(int fd)
204{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100205 return fd_ev_set(fd, DIR_WR);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200206}
207
208static inline void fd_stop_send(int fd)
209{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100210 return fd_ev_clr(fd, DIR_WR);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200211}
Willy Tarreau2a429502006-10-15 14:52:29 +0200212
Willy Tarreaubabd05a2012-08-09 12:14:03 +0200213static inline void fd_poll_send(int fd)
214{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100215 return fd_ev_wai(fd, DIR_WR);
Willy Tarreaubabd05a2012-08-09 12:14:03 +0200216}
217
Willy Tarreau49b046d2012-08-09 12:11:58 +0200218static inline void fd_stop_both(int fd)
219{
Willy Tarreau6ea20b12012-11-11 16:05:19 +0100220 return fd_ev_rem(fd);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200221}
Willy Tarreau2a429502006-10-15 14:52:29 +0200222
Willy Tarreaud6f087e2008-01-18 17:20:13 +0100223/* Prepares <fd> for being polled */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224static inline void fd_insert(int fd)
225{
Willy Tarreaud6f087e2008-01-18 17:20:13 +0100226 fdtab[fd].ev = 0;
Willy Tarreau037d2c12012-11-06 02:34:46 +0100227 fdtab[fd].new = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 if (fd + 1 > maxfd)
229 maxfd = fd + 1;
230}
231
232
233#endif /* _PROTO_FD_H */
234
235/*
236 * Local variables:
237 * c-indent-level: 8
238 * c-basic-offset: 8
239 * End:
240 */