MAJOR: session: implement a wait-queue for sessions who need a buffer
When a session_alloc_buffers() fails to allocate one or two buffers,
it subscribes the session to buffer_wq, and waits for another session
to release buffers. It's then removed from the queue and woken up with
TASK_WAKE_RES, and can attempt its allocation again.
We decide to try to wake as many waiters as we release buffers so
that if we release 2 and two waiters need only once, they both have
their chance. We must never come to the situation where we don't wake
enough tasks up.
It's common to release buffers after the completion of an I/O callback,
which can happen even if the I/O could not be performed due to half a
failure on memory allocation. In this situation, we don't want to move
out of the wait queue the session that was just added, otherwise it
will never get any buffer. Thus, we only force ourselves out of the
queue when freeing the session.
Note: at the moment, since session_alloc_buffers() is not used, no task
is subscribed to the wait queue.
diff --git a/include/proto/session.h b/include/proto/session.h
index e9b72bf..5e26edc 100644
--- a/include/proto/session.h
+++ b/include/proto/session.h
@@ -30,6 +30,7 @@
extern struct pool_head *pool2_session;
extern struct list sessions;
+extern struct list buffer_wq;
extern struct data_cb sess_conn_cb;
@@ -53,6 +54,7 @@
/* Update the session's backend and server time stats */
void session_update_time_stats(struct session *s);
+void session_offer_buffers(int count);
int session_alloc_buffers(struct session *s);
void session_release_buffers(struct session *s);
int session_alloc_recv_buffer(struct session *s, struct buffer **buf);
diff --git a/include/types/session.h b/include/types/session.h
index f17aff4..1f3ba48 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -123,6 +123,7 @@
struct list list; /* position in global sessions list */
struct list by_srv; /* position in server session list */
struct list back_refs; /* list of users tracking this session */
+ struct list buffer_wait; /* position in the list of sessions waiting for a buffer */
struct {
struct stksess *ts;