diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index da557ec03..04b733f9f 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -974,7 +974,7 @@ int istrd(void *arg) init_waitqueue_entry(&wait, current); if (!test_rd_list()) { - add_wait_queue_exclusive(&iscsi_rd_waitQ, &wait); + add_wait_queue_exclusive_head(&iscsi_rd_waitQ, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (test_rd_list()) @@ -1662,7 +1662,7 @@ int istwr(void *arg) init_waitqueue_entry(&wait, current); if (!test_wr_list()) { - add_wait_queue_exclusive(&iscsi_wr_waitQ, &wait); + add_wait_queue_exclusive_head(&iscsi_wr_waitQ, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (test_wr_list()) diff --git a/scst/include/scst.h b/scst/include/scst.h index 3b11b26b3..68b043578 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -3075,4 +3076,20 @@ int scst_tape_generic_dev_done(struct scst_cmd *cmd, */ int scst_obtain_device_parameters(struct scst_device *dev); +/* + * Has to be put here open coded, because Linux doesn't have equivalent, which + * allows exclusive wake ups of threads in LIFO order. We need it to let (yet) + * unneeded threads sleep and not pollute CPU cache by their stacks. + */ +static inline void add_wait_queue_exclusive_head(wait_queue_head_t *q, + wait_queue_t *wait) +{ + unsigned long flags; + + wait->flags |= WQ_FLAG_EXCLUSIVE; + spin_lock_irqsave(&q->lock, flags); + __add_wait_queue(q, wait); + spin_unlock_irqrestore(&q->lock, flags); +} + #endif /* __SCST_H */ diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index 4432f636e..0160a18de 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -1745,7 +1745,8 @@ static int dev_user_get_next_cmd(struct scst_user_dev *dev, while (1) { if (!test_cmd_lists(dev)) { - add_wait_queue_exclusive(&dev->cmd_lists.cmd_list_waitQ, + add_wait_queue_exclusive_head( + &dev->cmd_lists.cmd_list_waitQ, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index ef6539b89..05105ed7c 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -3735,7 +3735,8 @@ int scst_cmd_thread(void *arg) init_waitqueue_entry(&wait, current); if (!test_cmd_lists(p_cmd_lists)) { - add_wait_queue_exclusive(&p_cmd_lists->cmd_list_waitQ, + add_wait_queue_exclusive_head( + &p_cmd_lists->cmd_list_waitQ, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE);