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())
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())
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
+#include <linux/wait.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
*/
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 */
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);
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);