Skip to content

Commit 84ce163

Browse files
author
Junjie Mao
committed
Add an option to awake a single task on waitqueues at a time
With a large number of listeners on a single listen socket, waitqueues tend to awake too many processes for a single incoming connection (known as the thundering herd problem). This patch provides an option WQ_FLAG_LOADBALANCE for waitqueues. When enabled, this option makes waitqueues awake only one task at a time in a round robin way. A file mode option FMODE_SINGLE_WAKEUP is also provided to mark files whose events need be handled with WQ_FLAG_LOADBALANCE set. Signed-off-by: Xiaofeng Lin <jerrylin.lxf@gmail.com> Signed-off-by: Junjie Mao <eternal.n08@gmail.com>
1 parent d0c08e0 commit 84ce163

File tree

4 files changed

+12
-0
lines changed

4 files changed

+12
-0
lines changed

kernel/fs/eventpoll.c

+3
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,9 @@ static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
979979
init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
980980
pwq->whead = whead;
981981
pwq->base = epi;
982+
if (file->f_mode & FMODE_SINGLE_WAKEUP) {
983+
pwq->wait.flags |= WQ_FLAG_LOADBALANCE;
984+
}
982985
add_wait_queue(whead, &pwq->wait);
983986
list_add_tail(&pwq->llink, &epi->pwqlist);
984987
epi->nwait++;

kernel/include/linux/fs.h

+2
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ struct inodes_stat_t {
104104
#define FMODE_RANDOM ((__force fmode_t)4096)
105105
/* File for fastsocket */
106106
#define FMODE_FASTSOCKET ((__force fmode_t)8192)
107+
/* Wake up the task in a round bobin way, used with fastsocket*/
108+
#define FMODE_SINGLE_WAKEUP ((__force fmode_t)16384)
107109

108110
/*
109111
* The below are the various read and write types that we support. Some of

kernel/include/linux/wait.h

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ int default_wake_function(wait_queue_t *wait, unsigned mode, int flags, void *ke
3232
struct __wait_queue {
3333
unsigned int flags;
3434
#define WQ_FLAG_EXCLUSIVE 0x01
35+
#define WQ_FLAG_LOADBALANCE 0x02
3536
void *private;
3637
wait_queue_func_t func;
3738
struct list_head task_list;

kernel/kernel/sched.c

+6
Original file line numberDiff line numberDiff line change
@@ -6280,6 +6280,12 @@ static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
62806280
list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
62816281
unsigned flags = curr->flags;
62826282

6283+
if (flags & WQ_FLAG_LOADBALANCE) {
6284+
curr->func(curr, mode, wake_flags, key);
6285+
list_move_tail(&curr->task_list, &q->task_list);
6286+
break;
6287+
}
6288+
62836289
if (curr->func(curr, mode, wake_flags, key) &&
62846290
(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
62856291
break;

0 commit comments

Comments
 (0)