These flags were used to report the readiness of the file descriptor.
Now this readiness is directly checked at the file descriptor itself.
This removes the need for constantly synchronizing updates between the
file descriptor and the connection and ensures that all layers share
the same level of information.
For now, the readiness is updated in conn_{sock,data}_poll_* by directly
touching the file descriptor. This must move to the lower layers instead
so that these functions can disappear as well. In this state, the change
works but is incomplete. It's sensible enough to avoid making it more
complex.
Now the sock/data updates become much simpler because they just have to
enable/disable access to a file descriptor and not to care anymore about
its readiness.
*/
static inline void conn_refresh_polling_flags(struct connection *conn)
{
- conn->flags &= ~(CO_FL_WAIT_ROOM | CO_FL_WAIT_RD | CO_FL_WAIT_DATA | CO_FL_WAIT_WR);
+ conn->flags &= ~(CO_FL_WAIT_ROOM | CO_FL_WAIT_DATA);
if ((conn->flags & CO_FL_CTRL_READY) && conn->ctrl) {
unsigned int flags = conn->flags & ~(CO_FL_CURR_RD_ENA | CO_FL_CURR_WR_ENA);
{
unsigned int f = c->flags;
f &= CO_FL_DATA_WR_ENA | CO_FL_DATA_RD_ENA | CO_FL_CURR_WR_ENA |
- CO_FL_CURR_RD_ENA | CO_FL_ERROR | CO_FL_WAIT_WR | CO_FL_WAIT_RD;
+ CO_FL_CURR_RD_ENA | CO_FL_ERROR;
- f = (f & (f << 2)) | /* test W & D */
- ((f ^ (f << 1)) & (CO_FL_CURR_WR_ENA|CO_FL_CURR_RD_ENA)); /* test C ^ D */
- return f & (CO_FL_WAIT_WR | CO_FL_WAIT_RD | CO_FL_CURR_WR_ENA | CO_FL_CURR_RD_ENA | CO_FL_ERROR);
+ f = (f ^ (f << 1)) & (CO_FL_CURR_WR_ENA|CO_FL_CURR_RD_ENA); /* test C ^ D */
+ return f & (CO_FL_CURR_WR_ENA | CO_FL_CURR_RD_ENA | CO_FL_ERROR);
}
/* inspects c->flags and returns non-zero if SOCK ENA changes from the CURR ENA
{
unsigned int f = c->flags;
f &= CO_FL_SOCK_WR_ENA | CO_FL_SOCK_RD_ENA | CO_FL_CURR_WR_ENA |
- CO_FL_CURR_RD_ENA | CO_FL_ERROR | CO_FL_WAIT_WR | CO_FL_WAIT_RD;
+ CO_FL_CURR_RD_ENA | CO_FL_ERROR;
- f = (f & (f << 3)) | /* test W & S */
- ((f ^ (f << 2)) & (CO_FL_CURR_WR_ENA|CO_FL_CURR_RD_ENA)); /* test C ^ S */
- return f & (CO_FL_WAIT_WR | CO_FL_WAIT_RD | CO_FL_CURR_WR_ENA | CO_FL_CURR_RD_ENA | CO_FL_ERROR);
+ f = (f ^ (f << 2)) & (CO_FL_CURR_WR_ENA|CO_FL_CURR_RD_ENA); /* test C ^ S */
+ return f & (CO_FL_CURR_WR_ENA | CO_FL_CURR_RD_ENA | CO_FL_ERROR);
}
/* Automatically updates polling on connection <c> depending on the DATA flags
static inline void __conn_data_poll_recv(struct connection *c)
{
- c->flags |= CO_FL_WAIT_RD | CO_FL_DATA_RD_ENA;
+ c->flags |= CO_FL_DATA_RD_ENA;
+ fd_cant_recv(c->t.sock.fd);
}
static inline void __conn_data_want_send(struct connection *c)
static inline void __conn_data_poll_send(struct connection *c)
{
- c->flags |= CO_FL_WAIT_WR | CO_FL_DATA_WR_ENA;
+ c->flags |= CO_FL_DATA_WR_ENA;
+ fd_cant_send(c->t.sock.fd);
}
static inline void __conn_data_stop_both(struct connection *c)
static inline void __conn_sock_poll_recv(struct connection *c)
{
- c->flags |= CO_FL_WAIT_RD | CO_FL_SOCK_RD_ENA;
+ c->flags |= CO_FL_SOCK_RD_ENA;
+ fd_cant_recv(c->t.sock.fd);
}
static inline void __conn_sock_want_send(struct connection *c)
static inline void __conn_sock_poll_send(struct connection *c)
{
- c->flags |= CO_FL_WAIT_WR | CO_FL_SOCK_WR_ENA;
+ c->flags |= CO_FL_SOCK_WR_ENA;
+ fd_cant_send(c->t.sock.fd);
}
static inline void __conn_sock_stop_both(struct connection *c)
if (conn->flags & CO_FL_SOCK_RD_SH)
return 1;
- if (conn->flags & CO_FL_WAIT_RD)
+ if (!fd_recv_ready(conn->t.sock.fd))
return 0;
if (!conn->ctrl->drain)
CO_FL_SOCK_RD_ENA = 0x00000001, /* receiving handshakes is allowed */
CO_FL_DATA_RD_ENA = 0x00000002, /* receiving data is allowed */
CO_FL_CURR_RD_ENA = 0x00000004, /* receiving is currently allowed */
- CO_FL_WAIT_RD = 0x00000008, /* receiving needs to poll first */
+ /* unused : 0x00000008 */
CO_FL_SOCK_WR_ENA = 0x00000010, /* sending handshakes is desired */
CO_FL_DATA_WR_ENA = 0x00000020, /* sending data is desired */
CO_FL_CURR_WR_ENA = 0x00000040, /* sending is currently desired */
- CO_FL_WAIT_WR = 0x00000080, /* sending needs to poll first */
+ /* unused : 0x00000080 */
/* These flags indicate whether the Control and Transport layers are initialized */
CO_FL_CTRL_READY = 0x00000100, /* FD was registered, fd_delete() needed */
if (unlikely(check->result == CHK_RES_FAILED))
goto out_wakeup;
- if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_WAIT_WR))
+ if (conn->flags & CO_FL_HANDSHAKE)
return;
if (retrieve_errno_from_socket(conn)) {
if (unlikely(check->result == CHK_RES_FAILED))
goto out_wakeup;
- if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_WAIT_RD))
+ if (conn->flags & CO_FL_HANDSHAKE)
return;
if (check->type == PR_O2_TCPCHK_CHK) {
check->current_step->action != TCPCHK_ACT_SEND ||
check->current_step->string_len >= buffer_total_space(check->bo))) {
- if ((conn->flags & CO_FL_WAIT_WR) ||
- conn->xprt->snd_buf(conn, check->bo, MSG_DONTWAIT | MSG_NOSIGNAL) <= 0) {
+ if (conn->xprt->snd_buf(conn, check->bo, MSG_DONTWAIT | MSG_NOSIGNAL) <= 0) {
if (conn->flags & CO_FL_ERROR) {
chk_report_conn_err(conn, errno, 0);
__conn_data_stop_both(conn);
if (unlikely(check->result == CHK_RES_FAILED))
goto out_end_tcpcheck;
- if ((conn->flags & CO_FL_WAIT_RD) ||
- conn->xprt->rcv_buf(conn, check->bi, check->bi->size) <= 0) {
+ if (conn->xprt->rcv_buf(conn, check->bi, check->bi->size) <= 0) {
if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_DATA_RD_SH)) {
done = 1;
if ((conn->flags & CO_FL_ERROR) && !check->bi->i) {
* around.
*/
while (unlikely(conn->flags & (CO_FL_HANDSHAKE | CO_FL_ERROR))) {
- if (unlikely(conn->flags & (CO_FL_ERROR|CO_FL_WAIT_RD|CO_FL_WAIT_WR)))
+ if (unlikely(conn->flags & CO_FL_ERROR))
goto leave;
if (conn->flags & CO_FL_ACCEPT_PROXY)
*/
if ((fdtab[fd].ev & (FD_POLL_IN | FD_POLL_HUP | FD_POLL_ERR)) &&
conn->xprt &&
- !(conn->flags & (CO_FL_WAIT_RD|CO_FL_WAIT_ROOM|CO_FL_ERROR|CO_FL_HANDSHAKE))) {
+ fd_recv_ready(fd) &&
+ !(conn->flags & (CO_FL_WAIT_ROOM|CO_FL_ERROR|CO_FL_HANDSHAKE))) {
/* force detection of a flag change : it's impossible to have both
* CONNECTED and WAIT_CONN so we're certain to trigger a change.
*/
if ((fdtab[fd].ev & (FD_POLL_OUT | FD_POLL_ERR)) &&
conn->xprt &&
- !(conn->flags & (CO_FL_WAIT_WR|CO_FL_WAIT_DATA|CO_FL_ERROR|CO_FL_HANDSHAKE))) {
+ fd_send_ready(fd) &&
+ !(conn->flags & (CO_FL_WAIT_DATA|CO_FL_ERROR|CO_FL_HANDSHAKE))) {
/* force detection of a flag change : it's impossible to have both
* CONNECTED and WAIT_CONN so we're certain to trigger a change.
*/
if (unlikely(conn->flags & (CO_FL_HANDSHAKE | CO_FL_ERROR)))
goto process_handshake;
- if (unlikely(conn->flags & CO_FL_WAIT_L4_CONN) && !(conn->flags & CO_FL_WAIT_WR)) {
+ if (unlikely(conn->flags & CO_FL_WAIT_L4_CONN) && fd_send_ready(conn->t.sock.fd)) {
/* still waiting for a connection to establish and nothing was
* attempted yet to probe the connection. Then let's retry the
* connect().
return;
/* update read status if needed */
- if (unlikely((f & (CO_FL_DATA_RD_ENA|CO_FL_WAIT_RD)) == (CO_FL_DATA_RD_ENA|CO_FL_WAIT_RD))) {
- fd_want_recv(c->t.sock.fd);
- fd_cant_recv(c->t.sock.fd);
- f |= CO_FL_CURR_RD_ENA;
- }
- else if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_DATA_RD_ENA)) == CO_FL_DATA_RD_ENA)) {
+ if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_DATA_RD_ENA)) == CO_FL_DATA_RD_ENA)) {
fd_want_recv(c->t.sock.fd);
f |= CO_FL_CURR_RD_ENA;
}
}
/* update write status if needed */
- if (unlikely((f & (CO_FL_DATA_WR_ENA|CO_FL_WAIT_WR)) == (CO_FL_DATA_WR_ENA|CO_FL_WAIT_WR))) {
- fd_want_send(c->t.sock.fd);
- fd_cant_send(c->t.sock.fd);
- f |= CO_FL_CURR_WR_ENA;
- }
- else if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_DATA_WR_ENA)) == CO_FL_DATA_WR_ENA)) {
+ if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_DATA_WR_ENA)) == CO_FL_DATA_WR_ENA)) {
fd_want_send(c->t.sock.fd);
f |= CO_FL_CURR_WR_ENA;
}
fd_stop_send(c->t.sock.fd);
f &= ~CO_FL_CURR_WR_ENA;
}
- c->flags = f & ~(CO_FL_WAIT_RD | CO_FL_WAIT_WR);
+ c->flags = f;
}
/* Update polling on connection <c>'s file descriptor depending on its current
return;
/* update read status if needed */
- if (unlikely((f & (CO_FL_SOCK_RD_ENA|CO_FL_WAIT_RD)) == (CO_FL_SOCK_RD_ENA|CO_FL_WAIT_RD))) {
- fd_want_recv(c->t.sock.fd);
- fd_cant_recv(c->t.sock.fd);
- f |= CO_FL_CURR_RD_ENA;
- }
- else if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_SOCK_RD_ENA)) == CO_FL_SOCK_RD_ENA)) {
+ if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_SOCK_RD_ENA)) == CO_FL_SOCK_RD_ENA)) {
fd_want_recv(c->t.sock.fd);
f |= CO_FL_CURR_RD_ENA;
}
}
/* update write status if needed */
- if (unlikely((f & (CO_FL_SOCK_WR_ENA|CO_FL_WAIT_WR)) == (CO_FL_SOCK_WR_ENA|CO_FL_WAIT_WR))) {
- fd_want_send(c->t.sock.fd);
- fd_cant_send(c->t.sock.fd);
- f |= CO_FL_CURR_WR_ENA;
- }
- else if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_SOCK_WR_ENA)) == CO_FL_SOCK_WR_ENA)) {
+ if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_SOCK_WR_ENA)) == CO_FL_SOCK_WR_ENA)) {
fd_want_send(c->t.sock.fd);
f |= CO_FL_CURR_WR_ENA;
}
fd_stop_send(c->t.sock.fd);
f &= ~CO_FL_CURR_WR_ENA;
}
- c->flags = f & ~(CO_FL_WAIT_RD | CO_FL_WAIT_WR);
+ c->flags = f;
}
/* This handshake handler waits a PROXY protocol header at the beginning of the
/* when we're here, we already know that there is no spliced
* data left, and that there are sendable buffered data.
*/
- if (!(conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH | CO_FL_DATA_WR_SH | CO_FL_WAIT_DATA | CO_FL_WAIT_WR | CO_FL_HANDSHAKE))) {
+ if (!(conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH | CO_FL_DATA_WR_SH | CO_FL_WAIT_DATA | CO_FL_HANDSHAKE))) {
/* check if we want to inform the kernel that we're interested in
* sending more data after this call. We want this if :
* - we're about to close after this last send and want to merge
* that if such an event is not handled above in splice, it will be handled here by
* recv().
*/
- while (!(conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_DATA_RD_SH | CO_FL_WAIT_RD | CO_FL_WAIT_ROOM | CO_FL_HANDSHAKE))) {
+ while (!(conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_DATA_RD_SH | CO_FL_WAIT_ROOM | CO_FL_HANDSHAKE))) {
max = bi_avail(chn);
if (!max) {