MAJOR: threads/buffer: Make buffer wait queue thread safe
Adds a global lock to protect the buffer wait queue.
diff --git a/include/common/buffer.h b/include/common/buffer.h
index 17931cf..f11d6a9 100644
--- a/include/common/buffer.h
+++ b/include/common/buffer.h
@@ -52,6 +52,9 @@
extern struct buffer buf_empty;
extern struct buffer buf_wanted;
extern struct list buffer_wq;
+#ifdef USE_THREAD
+extern HA_SPINLOCK_T buffer_wq_lock;
+#endif
int init_buffer();
void deinit_buffer();
@@ -748,9 +751,13 @@
static inline void offer_buffers(void *from, unsigned int threshold)
{
- if (LIST_ISEMPTY(&buffer_wq))
+ SPIN_LOCK(BUF_WQ_LOCK, &buffer_wq_lock);
+ if (LIST_ISEMPTY(&buffer_wq)) {
+ SPIN_UNLOCK(BUF_WQ_LOCK, &buffer_wq_lock);
return;
+ }
__offer_buffer(from, threshold);
+ SPIN_UNLOCK(BUF_WQ_LOCK, &buffer_wq_lock);
}
/*************************************************************************/
diff --git a/include/common/hathreads.h b/include/common/hathreads.h
index 3a77bd1..1717cc9 100644
--- a/include/common/hathreads.h
+++ b/include/common/hathreads.h
@@ -156,6 +156,7 @@
STK_SESS_LOCK,
APPLETS_LOCK,
PEER_LOCK,
+ BUF_WQ_LOCK,
LOCK_LABELS
};
struct lock_stat {
@@ -242,7 +243,7 @@
"TASK_RQ", "TASK_WQ", "POOL",
"LISTENER", "LISTENER_QUEUE", "PROXY", "SERVER",
"UPDATED_SERVERS", "LBPRM", "SIGNALS", "STK_TABLE", "STK_SESS",
- "APPLETS", "PEER" };
+ "APPLETS", "PEER", "BUF_WQ" };
int lbl;
for (lbl = 0; lbl < LOCK_LABELS; lbl++) {
diff --git a/include/proto/applet.h b/include/proto/applet.h
index d9f0ce2..766fc92 100644
--- a/include/proto/applet.h
+++ b/include/proto/applet.h
@@ -88,8 +88,10 @@
}
if (!LIST_ISEMPTY(&appctx->buffer_wait.list)) {
+ SPIN_LOCK(BUF_WQ_LOCK, &buffer_wq_lock);
LIST_DEL(&appctx->buffer_wait.list);
LIST_INIT(&appctx->buffer_wait.list);
+ SPIN_UNLOCK(BUF_WQ_LOCK, &buffer_wq_lock);
}
pool_free2(pool2_connection, appctx);
diff --git a/include/proto/channel.h b/include/proto/channel.h
index 9e12b5e..83ad0aa 100644
--- a/include/proto/channel.h
+++ b/include/proto/channel.h
@@ -440,8 +440,12 @@
if (b_alloc_margin(&chn->buf, margin) != NULL)
return 1;
- if (LIST_ISEMPTY(&wait->list))
+ if (LIST_ISEMPTY(&wait->list)) {
+ SPIN_LOCK(BUF_WQ_LOCK, &buffer_wq_lock);
LIST_ADDQ(&buffer_wq, &wait->list);
+ SPIN_UNLOCK(BUF_WQ_LOCK, &buffer_wq_lock);
+ }
+
return 0;
}