/src/haproxy/include/haproxy/fd-t.h
Line | Count | Source |
1 | | /* |
2 | | * include/haproxy/fd-t.h |
3 | | * File descriptors states - check src/fd.c for explanations. |
4 | | * |
5 | | * Copyright (C) 2000-2014 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 | | */ |
21 | | |
22 | | #ifndef _HAPROXY_FD_T_H |
23 | | #define _HAPROXY_FD_T_H |
24 | | |
25 | | #include <haproxy/api-t.h> |
26 | | #include <haproxy/port_range-t.h> |
27 | | #include <haproxy/show_flags-t.h> |
28 | | |
29 | | /* Direction for each FD event update */ |
30 | | enum { |
31 | | DIR_RD=0, |
32 | | DIR_WR=1, |
33 | | }; |
34 | | |
35 | | |
36 | | /* fdtab[].state is a composite state describing what is known about the FD. |
37 | | * For now, the following information are stored in it: |
38 | | * - event configuration and status for each direction (R,W) split into |
39 | | * active, ready, shutdown categories (FD_EV_*). These are known by their |
40 | | * bit values as well so that test-and-set bit operations are possible. |
41 | | * |
42 | | * - last known polling status (FD_POLL_*). For ease of troubleshooting, |
43 | | * avoid visually mixing these ones with the other ones above. 3 of these |
44 | | * flags are updated on each poll() report (FD_POLL_IN, FD_POLL_OUT, |
45 | | * FD_POLL_PRI). FD_POLL_HUP and FD_POLL_ERR are "sticky" in that once they |
46 | | * are reported, they will not be cleared until the FD is closed. |
47 | | */ |
48 | | |
49 | | /* bits positions for a few flags */ |
50 | 0 | #define FD_EV_ACTIVE_R_BIT 0 |
51 | 0 | #define FD_EV_READY_R_BIT 1 |
52 | 0 | #define FD_EV_SHUT_R_BIT 2 |
53 | | /* unused: 3 */ |
54 | | |
55 | 0 | #define FD_EV_ACTIVE_W_BIT 4 |
56 | 0 | #define FD_EV_READY_W_BIT 5 |
57 | 0 | #define FD_EV_SHUT_W_BIT 6 |
58 | 0 | #define FD_EV_ERR_RW_BIT 7 |
59 | | |
60 | 0 | #define FD_POLL_IN_BIT 8 |
61 | 0 | #define FD_POLL_PRI_BIT 9 |
62 | 0 | #define FD_POLL_OUT_BIT 10 |
63 | 0 | #define FD_POLL_ERR_BIT 11 |
64 | 0 | #define FD_POLL_HUP_BIT 12 |
65 | | |
66 | | /* info/config bits */ |
67 | 0 | #define FD_LINGER_RISK_BIT 16 /* must kill lingering before closing */ |
68 | 0 | #define FD_CLONED_BIT 17 /* cloned socket, requires EPOLL_CTL_DEL on close */ |
69 | | #define FD_INITIALIZED_BIT 18 /* init phase was done (e.g. output pipe set non-blocking) */ |
70 | 0 | #define FD_ET_POSSIBLE_BIT 19 /* edge-triggered is possible on this FD */ |
71 | 0 | #define FD_EXPORTED_BIT 20 /* FD is exported and must not be closed */ |
72 | | #define FD_EXCL_SYSCALL_BIT 21 /* a syscall claims exclusivity on this FD */ |
73 | 0 | #define FD_DISOWN_BIT 22 /* this fd will be closed by some external code */ |
74 | | #define FD_MUST_CLOSE_BIT 23 /* this fd will be closed by some external code */ |
75 | | #define FD_HAS_PORT_BIT 24 /* This fd had a port allocated from a port range */ |
76 | | #define FD_OWNER_PR_BIT 27 /* The owner is actually a port range */ |
77 | | |
78 | | |
79 | | /* and flag values */ |
80 | 0 | #define FD_EV_ACTIVE_R (1U << FD_EV_ACTIVE_R_BIT) |
81 | 0 | #define FD_EV_ACTIVE_W (1U << FD_EV_ACTIVE_W_BIT) |
82 | 0 | #define FD_EV_ACTIVE_RW (FD_EV_ACTIVE_R | FD_EV_ACTIVE_W) |
83 | | |
84 | 0 | #define FD_EV_READY_R (1U << FD_EV_READY_R_BIT) |
85 | 0 | #define FD_EV_READY_W (1U << FD_EV_READY_W_BIT) |
86 | | #define FD_EV_READY_RW (FD_EV_READY_R | FD_EV_READY_W) |
87 | | |
88 | | /* note that when FD_EV_SHUT is set, ACTIVE and READY are cleared */ |
89 | 0 | #define FD_EV_SHUT_R (1U << FD_EV_SHUT_R_BIT) |
90 | 0 | #define FD_EV_SHUT_W (1U << FD_EV_SHUT_W_BIT) |
91 | | #define FD_EV_SHUT_RW (FD_EV_SHUT_R | FD_EV_SHUT_W) |
92 | | |
93 | | /* note that when FD_EV_ERR is set, SHUT is also set. Also, ERR is for both |
94 | | * directions at once (write error, socket dead, etc). |
95 | | */ |
96 | 0 | #define FD_EV_ERR_RW (1U << FD_EV_ERR_RW_BIT) |
97 | | |
98 | | /* mask covering all use cases above */ |
99 | | #define FD_EV_ANY (FD_EV_ACTIVE_RW | FD_EV_READY_RW | FD_EV_SHUT_RW | FD_EV_ERR_RW) |
100 | | |
101 | | /* polling status */ |
102 | 0 | #define FD_POLL_IN (1U << FD_POLL_IN_BIT) |
103 | 0 | #define FD_POLL_PRI (1U << FD_POLL_PRI_BIT) |
104 | 0 | #define FD_POLL_OUT (1U << FD_POLL_OUT_BIT) |
105 | 0 | #define FD_POLL_ERR (1U << FD_POLL_ERR_BIT) |
106 | 0 | #define FD_POLL_HUP (1U << FD_POLL_HUP_BIT) |
107 | 0 | #define FD_POLL_UPDT_MASK (FD_POLL_IN | FD_POLL_PRI | FD_POLL_OUT) |
108 | | #define FD_POLL_ANY_MASK (FD_POLL_IN | FD_POLL_PRI | FD_POLL_OUT | FD_POLL_ERR | FD_POLL_HUP) |
109 | | |
110 | | /* information/configuration flags */ |
111 | 0 | #define FD_LINGER_RISK (1U << FD_LINGER_RISK_BIT) |
112 | 0 | #define FD_CLONED (1U << FD_CLONED_BIT) |
113 | | #define FD_INITIALIZED (1U << FD_INITIALIZED_BIT) |
114 | 0 | #define FD_ET_POSSIBLE (1U << FD_ET_POSSIBLE_BIT) |
115 | 0 | #define FD_EXPORTED (1U << FD_EXPORTED_BIT) |
116 | | #define FD_EXCL_SYSCALL (1U << FD_EXCL_SYSCALL_BIT) |
117 | 0 | #define FD_DISOWN (1U << FD_DISOWN_BIT) |
118 | | #define FD_MUST_CLOSE (1U << FD_MUST_CLOSE_BIT) |
119 | | #define FD_HAS_PORT (1U << FD_HAS_PORT_BIT) |
120 | | #define FD_OWNER_PR (1U << FD_OWNER_PR_BIT) |
121 | | |
122 | | /* This function is used to report flags in debugging tools. Please reflect |
123 | | * below any single-bit flag addition above in the same order via the |
124 | | * __APPEND_FLAG macro. The new end of the buffer is returned. |
125 | | */ |
126 | | static forceinline char *fd_show_flags(char *buf, size_t len, const char *delim, uint flg) |
127 | 0 | { |
128 | 0 | #define _(f, ...) __APPEND_FLAG(buf, len, delim, flg, f, #f, __VA_ARGS__) |
129 | 0 | /* prologue */ |
130 | 0 | _(0); |
131 | 0 | /* flags */ |
132 | 0 | _(FD_EV_ACTIVE_R, _(FD_EV_ACTIVE_W, _(FD_EV_READY_R, _(FD_EV_READY_W, |
133 | 0 | _(FD_EV_SHUT_R, _(FD_EV_SHUT_W, _(FD_EV_ERR_RW, _(FD_POLL_IN, |
134 | 0 | _(FD_POLL_PRI, _(FD_POLL_OUT, _(FD_POLL_ERR, _(FD_POLL_HUP, |
135 | 0 | _(FD_LINGER_RISK, _(FD_CLONED, _(FD_INITIALIZED, _(FD_ET_POSSIBLE, |
136 | 0 | _(FD_EXPORTED, _(FD_EXCL_SYSCALL, _(FD_DISOWN))))))))))))))))))); |
137 | 0 | /* epilogue */ |
138 | 0 | _(~0U); |
139 | 0 | return buf; |
140 | 0 | #undef _ |
141 | 0 | } Unexecuted instantiation: tools.c:fd_show_flags Unexecuted instantiation: applet.c:fd_show_flags Unexecuted instantiation: cfgparse.c:fd_show_flags Unexecuted instantiation: channel.c:fd_show_flags Unexecuted instantiation: cli.c:fd_show_flags Unexecuted instantiation: connection.c:fd_show_flags Unexecuted instantiation: debug.c:fd_show_flags Unexecuted instantiation: dgram.c:fd_show_flags Unexecuted instantiation: errors.c:fd_show_flags Unexecuted instantiation: fd.c:fd_show_flags Unexecuted instantiation: frontend.c:fd_show_flags Unexecuted instantiation: haproxy.c:fd_show_flags Unexecuted instantiation: http_ana.c:fd_show_flags Unexecuted instantiation: http_ext.c:fd_show_flags Unexecuted instantiation: http_htx.c:fd_show_flags Unexecuted instantiation: http_rules.c:fd_show_flags Unexecuted instantiation: limits.c:fd_show_flags Unexecuted instantiation: listener.c:fd_show_flags Unexecuted instantiation: log.c:fd_show_flags Unexecuted instantiation: mailers.c:fd_show_flags Unexecuted instantiation: mworker.c:fd_show_flags Unexecuted instantiation: peers.c:fd_show_flags Unexecuted instantiation: pool.c:fd_show_flags Unexecuted instantiation: proto_rhttp.c:fd_show_flags Unexecuted instantiation: proto_sockpair.c:fd_show_flags Unexecuted instantiation: protocol.c:fd_show_flags Unexecuted instantiation: proxy.c:fd_show_flags Unexecuted instantiation: queue.c:fd_show_flags Unexecuted instantiation: resolvers.c:fd_show_flags Unexecuted instantiation: ring.c:fd_show_flags Unexecuted instantiation: sample.c:fd_show_flags Unexecuted instantiation: server.c:fd_show_flags Unexecuted instantiation: session.c:fd_show_flags Unexecuted instantiation: signal.c:fd_show_flags Unexecuted instantiation: sink.c:fd_show_flags Unexecuted instantiation: sock.c:fd_show_flags Unexecuted instantiation: sock_inet.c:fd_show_flags Unexecuted instantiation: stats-html.c:fd_show_flags Unexecuted instantiation: stats-proxy.c:fd_show_flags Unexecuted instantiation: stats.c:fd_show_flags Unexecuted instantiation: stconn.c:fd_show_flags Unexecuted instantiation: stick_table.c:fd_show_flags Unexecuted instantiation: stream.c:fd_show_flags Unexecuted instantiation: task.c:fd_show_flags Unexecuted instantiation: tcp_rules.c:fd_show_flags Unexecuted instantiation: tcpcheck.c:fd_show_flags Unexecuted instantiation: thread.c:fd_show_flags Unexecuted instantiation: trace.c:fd_show_flags Unexecuted instantiation: vars.c:fd_show_flags Unexecuted instantiation: action.c:fd_show_flags Unexecuted instantiation: activity.c:fd_show_flags Unexecuted instantiation: backend.c:fd_show_flags Unexecuted instantiation: cfgparse-global.c:fd_show_flags Unexecuted instantiation: cfgparse-listen.c:fd_show_flags Unexecuted instantiation: check.c:fd_show_flags Unexecuted instantiation: compression.c:fd_show_flags Unexecuted instantiation: dns.c:fd_show_flags Unexecuted instantiation: dns_ring.c:fd_show_flags Unexecuted instantiation: event_hdl.c:fd_show_flags Unexecuted instantiation: extcheck.c:fd_show_flags Unexecuted instantiation: filters.c:fd_show_flags Unexecuted instantiation: flt_decomp.c:fd_show_flags Unexecuted instantiation: flt_http_comp.c:fd_show_flags Unexecuted instantiation: haterm.c:fd_show_flags Unexecuted instantiation: http_fetch.c:fd_show_flags Unexecuted instantiation: lb_chash.c:fd_show_flags Unexecuted instantiation: lb_fwlc.c:fd_show_flags Unexecuted instantiation: mux_spop.c:fd_show_flags Unexecuted instantiation: pattern.c:fd_show_flags Unexecuted instantiation: payload.c:fd_show_flags Unexecuted instantiation: proto_tcp.c:fd_show_flags Unexecuted instantiation: stats-file.c:fd_show_flags Unexecuted instantiation: stats-json.c:fd_show_flags Unexecuted instantiation: cache.c:fd_show_flags Unexecuted instantiation: fcgi-app.c:fd_show_flags Unexecuted instantiation: flt_spoe.c:fd_show_flags |
142 | | |
143 | | /* FD update status after fd_update_events() */ |
144 | | enum { |
145 | | FD_UPDT_DONE = 0, // update done, nothing else to be done |
146 | | FD_UPDT_CLOSED, // FD was closed |
147 | | FD_UPDT_MIGRATED, // FD was migrated, ignore it now |
148 | | }; |
149 | | |
150 | | /* This is the value used to mark a file descriptor as dead. This value is |
151 | | * negative, this is important so that tests on fd < 0 properly match. It |
152 | | * also has the nice property of being highly negative but neither overflowing |
153 | | * nor changing sign on 32-bit machines when multiplied by sizeof(fdtab). |
154 | | * This ensures that any unexpected dereference of such an uninitialized |
155 | | * file descriptor will lead to so large a dereference that it will crash |
156 | | * the process at the exact location of the bug with a clean stack trace |
157 | | * instead of causing silent manipulation of other FDs. And it's readable |
158 | | * when found in a dump. |
159 | | */ |
160 | 0 | #define DEAD_FD_MAGIC 0xFDDEADFD |
161 | | |
162 | | /* fdlist_entry: entry used by the fd cache. |
163 | | * >= 0 means we're in the cache and gives the FD of the next in the cache, |
164 | | * -1 means we're in the cache and the last element, |
165 | | * -2 means the entry is locked, |
166 | | * <= -3 means not in the cache, and next element is -4-fd |
167 | | * |
168 | | * It must remain 8-aligned so that aligned CAS operations may be done on both |
169 | | * entries at once. |
170 | | */ |
171 | | struct fdlist_entry { |
172 | | int next; |
173 | | int prev; |
174 | | } ALIGNED(8); |
175 | | |
176 | | /* head of the fd cache, per-group */ |
177 | | struct fdlist { |
178 | | int first; |
179 | | int last; |
180 | | } ALIGNED(64); |
181 | | |
182 | | /* info about one given fd. Note: only align on cache lines when using threads; |
183 | | * 32-bit small archs can put everything in 32-bytes when threads are disabled. |
184 | | * refc_tgid is an atomic 32-bit composite value made of 16 higher bits |
185 | | * containing a refcount on tgid and the running_mask, and 16 lower bits |
186 | | * containing a thread group ID and a lock bit on the 16th. The tgid may only |
187 | | * be changed when refc is zero and running may only be checked/changed when |
188 | | * refc is held and shows the reader is alone. An FD with tgid zero belongs to |
189 | | * nobody. |
190 | | */ |
191 | | struct fdtab { |
192 | | unsigned long running_mask; /* mask of thread IDs currently using the fd */ |
193 | | unsigned long thread_mask; /* mask of thread IDs authorized to process the fd */ |
194 | | unsigned long update_mask; /* mask of thread IDs having an update for fd */ |
195 | | struct fdlist_entry update; /* Entry in the global update list */ |
196 | | void (*iocb)(int fd); /* I/O handler */ |
197 | | void *owner; /* the connection or listener associated with this fd, NULL if closed */ |
198 | | unsigned int state; /* FD state for read and write directions (FD_EV_*) + FD_POLL_* */ |
199 | | unsigned int refc_tgid; /* refcounted tgid, updated atomically */ |
200 | | /* the info below are mainly used for epoll debugging/strengthening. |
201 | | * they're filling the rest of the cache line but may easily be dropped |
202 | | * if the room is needed for more important stuff. |
203 | | */ |
204 | | unsigned int nb_takeover; /* number of times this FD was taken over since inserted (used for debugging) */ |
205 | | unsigned int generation; /* number of times this FD was closed before (used for epoll strengthening) */ |
206 | | #ifdef DEBUG_FD |
207 | | unsigned int event_count; /* number of events reported */ |
208 | | #endif |
209 | | } THREAD_ALIGNED(); |
210 | | |
211 | | /* polled mask, one bit per thread and per direction for each FD */ |
212 | | struct polled_mask { |
213 | | unsigned long poll_recv; |
214 | | unsigned long poll_send; |
215 | | }; |
216 | | |
217 | | /* |
218 | | * Poller descriptors. |
219 | | * - <name> is initialized by the poller's register() function, and should not |
220 | | * be allocated, just linked to. |
221 | | * - <pref> is initialized by the poller's register() function. It is set to 0 |
222 | | * by default, meaning the poller is disabled. init() should set it to 0 in |
223 | | * case of failure. term() must set it to 0. A generic unoptimized select() |
224 | | * poller should set it to 100. |
225 | | * - <private> is initialized by the poller's init() function, and cleaned by |
226 | | * the term() function. |
227 | | * - clo() should be used to do indicate the poller that fd will be closed. |
228 | | * - poll() calls the poller, expiring at <exp>, or immediately if <wake> is set |
229 | | * - flags indicate what the poller supports (HAP_POLL_F_*) |
230 | | */ |
231 | | |
232 | | #define HAP_POLL_F_RDHUP 0x00000001 /* the poller notifies of HUP with reads */ |
233 | 0 | #define HAP_POLL_F_ERRHUP 0x00000002 /* the poller reports ERR and HUP */ |
234 | 0 | #define HAP_POLL_F_NO_FD_SHARING 0x00000004 /* the poller supports not sharing fds across thread groups */ |
235 | | |
236 | | struct poller { |
237 | | void *private; /* any private data for the poller */ |
238 | | void (*clo)(const int fd); /* mark <fd> as closed */ |
239 | | void (*poll)(struct poller *p, int exp, int wake); /* the poller itself */ |
240 | | int (*init)(struct poller *p); /* poller initialization */ |
241 | | void (*term)(struct poller *p); /* termination of this poller */ |
242 | | int (*test)(struct poller *p); /* pre-init check of the poller */ |
243 | | int (*fork)(struct poller *p); /* post-fork re-opening */ |
244 | | void (*fixup_tgid_takeover)(struct poller *p, const int fd, const int old_tid, const int old_tgid); /* Fixup anything necessary after a FD takeover across tgids */ |
245 | | const char *name; /* poller name */ |
246 | | unsigned int flags; /* HAP_POLL_F_* */ |
247 | | int pref; /* try pollers with higher preference first */ |
248 | | }; |
249 | | |
250 | | #endif /* _HAPROXY_FD_T_H */ |
251 | | |
252 | | /* |
253 | | * Local variables: |
254 | | * c-indent-level: 8 |
255 | | * c-basic-offset: 8 |
256 | | * End: |
257 | | */ |