MINOR: xprt: add new xprt_set_idle and xprt_set_used methods

These functions are used on the mux layer to indicate that the connection
is becoming idle and that the xprt ought to be careful before checking the
context or that it's not idle anymore and that the context is safe. The
purpose is to allow a mux which is going to release a connection to tell
the xprt to be careful when touching it. At the moment, the xprt are
always careful and that's costly so we want to have the ability to relax
this a bit.

No xprt layer uses this yet.
diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h
index 033f761..9c2af7b 100644
--- a/include/haproxy/connection-t.h
+++ b/include/haproxy/connection-t.h
@@ -380,6 +380,8 @@
 	void (*destroy_srv)(struct server *srv);    /* destroy a server context */
 	int  (*get_alpn)(const struct connection *conn, void *xprt_ctx, const char **str, int *len); /* get application layer name */
 	int (*takeover)(struct connection *conn, void *xprt_ctx, int orig_tid); /* Let the xprt know the fd have been taken over */
+	void (*set_idle)(struct connection *conn, void *xprt_ctx); /* notify the xprt that the connection becomes idle. implies set_used. */
+	void (*set_used)(struct connection *conn, void *xprt_ctx); /* notify the xprt that the connection leaves idle. implies set_idle. */
 	char name[8];                               /* transport layer name, zero-terminated */
 	int (*subscribe)(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es); /* Subscribe <es> to events, such as "being able to send" */
 	int (*unsubscribe)(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es); /* Unsubscribe <es> from events */
diff --git a/include/haproxy/connection.h b/include/haproxy/connection.h
index d8aff5c..e00e6f8 100644
--- a/include/haproxy/connection.h
+++ b/include/haproxy/connection.h
@@ -868,6 +868,25 @@
 	return 0;
 }
 
+/* notify the next xprt that the connection is about to become idle and that it
+ * may be stolen at any time after the function returns and that any tasklet in
+ * the chain must be careful before dereferencing its context.
+ */
+static inline void xprt_set_idle(struct connection *conn, const struct xprt_ops *xprt, void *xprt_ctx)
+{
+	if (xprt->set_idle)
+		xprt->set_idle(conn, conn->xprt_ctx);
+}
+
+/* notify the next xprt that the connection is not idle anymore and that it may
+ * not be stolen before the next xprt_set_idle().
+ */
+static inline void xprt_set_used(struct connection *conn, const struct xprt_ops *xprt, void *xprt_ctx)
+{
+	if (xprt->set_used)
+		xprt->set_used(conn, conn->xprt_ctx);
+}
+
 static inline int conn_get_alpn(const struct connection *conn, const char **str, int *len)
 {
 	if (!conn_xprt_ready(conn) || !conn->xprt->get_alpn)
diff --git a/src/mux_fcgi.c b/src/mux_fcgi.c
index be063cf..b7d8e94 100644
--- a/src/mux_fcgi.c
+++ b/src/mux_fcgi.c
@@ -3489,6 +3489,7 @@
 
 	/* the connection is not idle anymore, let's mark this */
 	HA_ATOMIC_AND(&fconn->wait_event.tasklet->state, ~TASK_F_USR1);
+	xprt_set_used(conn, conn->xprt, conn->xprt_ctx);
 
 	TRACE_LEAVE(FCGI_EV_FSTRM_NEW, conn, fstrm);
 	return cs;
@@ -3620,6 +3621,8 @@
 				 * that the handler needs to check it under the idle conns lock.
 				 */
 				HA_ATOMIC_OR(&fconn->wait_event.tasklet->state, TASK_F_USR1);
+				xprt_set_idle(fconn->conn, fconn->conn->xprt, fconn->conn->xprt_ctx);
+
 				if (!srv_add_to_idle_list(objt_server(fconn->conn->target), fconn->conn, 1)) {
 					/* The server doesn't want it, let's kill the connection right away */
 					fconn->conn->mux->destroy(fconn);
diff --git a/src/mux_h1.c b/src/mux_h1.c
index 7d1bed4..c8dc71c 100644
--- a/src/mux_h1.c
+++ b/src/mux_h1.c
@@ -3007,6 +3007,7 @@
 
 	/* the connection is not idle anymore, let's mark this */
 	HA_ATOMIC_AND(&h1c->wait_event.tasklet->state, ~TASK_F_USR1);
+	xprt_set_used(conn, conn->xprt, conn->xprt_ctx);
 
 	TRACE_LEAVE(H1_EV_STRM_NEW, conn, h1s);
 	return cs;
@@ -3106,6 +3107,8 @@
 			 */
 			HA_ATOMIC_OR(&h1c->wait_event.tasklet->state, TASK_F_USR1);
 			h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
+			xprt_set_idle(h1c->conn, h1c->conn->xprt, h1c->conn->xprt_ctx);
+
 			if (!srv_add_to_idle_list(objt_server(h1c->conn->target), h1c->conn, is_not_first)) {
 				/* The server doesn't want it, let's kill the connection right away */
 				h1c->conn->mux->destroy(h1c);
diff --git a/src/mux_h2.c b/src/mux_h2.c
index 2ac61f7..9a4660e 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -4106,6 +4106,7 @@
 
 	/* the connection is not idle anymore, let's mark this */
 	HA_ATOMIC_AND(&h2c->wait_event.tasklet->state, ~TASK_F_USR1);
+	xprt_set_used(h2c->conn, h2c->conn->xprt, h2c->conn->xprt_ctx);
 
 	TRACE_LEAVE(H2_EV_H2S_NEW, conn, h2s);
 	return cs;
@@ -4254,6 +4255,8 @@
 					 * that the handler needs to check it under the idle conns lock.
 					 */
 					HA_ATOMIC_OR(&h2c->wait_event.tasklet->state, TASK_F_USR1);
+					xprt_set_idle(h2c->conn, h2c->conn->xprt, h2c->conn->xprt_ctx);
+
 					if (!srv_add_to_idle_list(objt_server(h2c->conn->target), h2c->conn, 1)) {
 						/* The server doesn't want it, let's kill the connection right away */
 						h2c->conn->mux->destroy(h2c);