From daa5da87af8abec73199c08c224a4825a89138a2 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Sat, 18 Jun 2011 21:15:59 +0000 Subject: [PATCH] Several wait loops in the SCST source code are similar. Move the common code into a new macro called wait_event_locked(). Signed-off-by: Bart Van Assche + Micro-optimize wait_event_locked(). Switch from default_wake_function() to autoremove_wake_function() (via DEFINE_WAIT()). The result is that wait_queue_head_t.lock is locked once instead of twice for wakeup + wait queue removal. Signed-off-by: Bart Van Assche git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@3591 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/nthread.c | 36 ++------------ scst/include/scst.h | 34 +++++++++++-- scst/src/dev_handlers/scst_user.c | 40 ++-------------- scst/src/scst_sysfs.c | 19 +------- scst/src/scst_targ.c | 79 +++++-------------------------- 5 files changed, 53 insertions(+), 155 deletions(-) diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index a662c9bef..3c2974445 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -1095,22 +1095,8 @@ int istrd(void *arg) spin_lock_bh(&p->rd_lock); while (!kthread_should_stop()) { - wait_queue_t wait; - init_waitqueue_entry(&wait, current); - - if (!test_rd_list(p)) { - add_wait_queue_exclusive_head(&p->rd_waitQ, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (test_rd_list(p)) - break; - spin_unlock_bh(&p->rd_lock); - schedule(); - spin_lock_bh(&p->rd_lock); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&p->rd_waitQ, &wait); - } + wait_event_locked(p->rd_waitQ, test_rd_list(p), lock_bh, + p->rd_lock); scst_do_job_rd(p); } spin_unlock_bh(&p->rd_lock); @@ -1868,22 +1854,8 @@ int istwr(void *arg) spin_lock_bh(&p->wr_lock); while (!kthread_should_stop()) { - wait_queue_t wait; - init_waitqueue_entry(&wait, current); - - if (!test_wr_list(p)) { - add_wait_queue_exclusive_head(&p->wr_waitQ, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (test_wr_list(p)) - break; - spin_unlock_bh(&p->wr_lock); - schedule(); - spin_lock_bh(&p->wr_lock); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&p->wr_waitQ, &wait); - } + wait_event_locked(p->wr_waitQ, test_wr_list(p), lock_bh, + p->wr_lock); scst_do_job_wr(p); } spin_unlock_bh(&p->wr_lock); diff --git a/scst/include/scst.h b/scst/include/scst.h index e502c8f82..9ebf76562 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -4105,17 +4105,45 @@ int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun); * 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) + +static inline void prepare_to_wait_exclusive_head(wait_queue_head_t *q, + wait_queue_t *wait, int state) { unsigned long flags; wait->flags |= WQ_FLAG_EXCLUSIVE; spin_lock_irqsave(&q->lock, flags); - __add_wait_queue(q, wait); + if (list_empty(&wait->task_list)) + __add_wait_queue(q, wait); + set_current_state(state); spin_unlock_irqrestore(&q->lock, flags); } +/** + * wait_event_locked() - Wait until a condition becomes true. + * @wq: Wait queue to wait on if @condition is false. + * @condition: Condition to wait for. Can be any C expression. + * @lock_type: One of lock, lock_bh or lock_irq. + * @lock: A spinlock. + * + * Caller must hold lock of type @lock_type on @lock. + */ +#define wait_event_locked(wq, condition, lock_type, lock) \ +if (!(condition)) { \ + DEFINE_WAIT(__wait); \ + \ + do { \ + prepare_to_wait_exclusive_head(&(wq), &__wait, \ + TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + spin_un ## lock_type(&(lock)); \ + schedule(); \ + spin_ ## lock_type(&(lock)); \ + } while (!(condition)); \ + finish_wait(&(wq), &__wait); \ +} + #ifndef CONFIG_SCST_PROC /* diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index be71332b8..9c5b5e9a6 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -1862,29 +1862,13 @@ static int dev_user_get_next_cmd(struct scst_user_dev *dev, struct scst_user_cmd **ucmd) { int res = 0; - wait_queue_t wait; TRACE_ENTRY(); - init_waitqueue_entry(&wait, current); - while (1) { - if (!test_cmd_threads(dev)) { - add_wait_queue_exclusive_head( - &dev->udev_cmd_threads.cmd_list_waitQ, - &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (test_cmd_threads(dev)) - break; - spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock); - schedule(); - spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&dev->udev_cmd_threads.cmd_list_waitQ, - &wait); - } + wait_event_locked(dev->udev_cmd_threads.cmd_list_waitQ, + test_cmd_threads(dev), lock_irq, + dev->udev_cmd_threads.cmd_list_lock); dev_user_process_scst_commands(dev); @@ -3633,22 +3617,8 @@ static int dev_user_cleanup_thread(void *arg) spin_lock(&cleanup_lock); while (!kthread_should_stop()) { - wait_queue_t wait; - init_waitqueue_entry(&wait, current); - - if (!test_cleanup_list()) { - add_wait_queue_exclusive(&cleanup_list_waitQ, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (test_cleanup_list()) - break; - spin_unlock(&cleanup_lock); - schedule(); - spin_lock(&cleanup_lock); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&cleanup_list_waitQ, &wait); - } + wait_event_locked(cleanup_list_waitQ, test_cleanup_list(), + lock, cleanup_lock); /* * We have to poll devices, because commands can go from SCST diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index d5a1f41de..980b8484d 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -524,23 +524,8 @@ static int sysfs_work_thread_fn(void *arg) spin_lock(&sysfs_work_lock); while (!kthread_should_stop()) { - wait_queue_t wait; - init_waitqueue_entry(&wait, current); - - if (!test_sysfs_work_list()) { - add_wait_queue_exclusive(&sysfs_work_waitQ, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (test_sysfs_work_list()) - break; - spin_unlock(&sysfs_work_lock); - schedule(); - spin_lock(&sysfs_work_lock); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&sysfs_work_waitQ, &wait); - } - + wait_event_locked(sysfs_work_waitQ, test_sysfs_work_list(), + lock, sysfs_work_lock); scst_process_sysfs_works(); } spin_unlock(&sysfs_work_lock); diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index d53960493..a328738fe 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -4040,23 +4040,9 @@ int scst_init_thread(void *arg) spin_lock_irq(&scst_init_lock); while (!kthread_should_stop()) { - wait_queue_t wait; - init_waitqueue_entry(&wait, current); - - if (!test_init_cmd_list()) { - add_wait_queue_exclusive(&scst_init_cmd_list_waitQ, - &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (test_init_cmd_list()) - break; - spin_unlock_irq(&scst_init_lock); - schedule(); - spin_lock_irq(&scst_init_lock); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&scst_init_cmd_list_waitQ, &wait); - } + wait_event_locked(scst_init_cmd_list_waitQ, + test_init_cmd_list(), + lock_irq, scst_init_lock); scst_do_job_init(); } spin_unlock_irq(&scst_init_lock); @@ -4332,24 +4318,9 @@ int scst_cmd_thread(void *arg) spin_lock_irq(&p_cmd_threads->cmd_list_lock); while (!kthread_should_stop()) { - wait_queue_t wait; - init_waitqueue_entry(&wait, current); - - if (!test_cmd_threads(p_cmd_threads)) { - add_wait_queue_exclusive_head( - &p_cmd_threads->cmd_list_waitQ, - &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (test_cmd_threads(p_cmd_threads)) - break; - spin_unlock_irq(&p_cmd_threads->cmd_list_lock); - schedule(); - spin_lock_irq(&p_cmd_threads->cmd_list_lock); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&p_cmd_threads->cmd_list_waitQ, &wait); - } + wait_event_locked(p_cmd_threads->cmd_list_waitQ, + test_cmd_threads(p_cmd_threads), lock_irq, + p_cmd_threads->cmd_list_lock); if (tm_dbg_is_release()) { spin_unlock_irq(&p_cmd_threads->cmd_list_lock); @@ -5812,23 +5783,9 @@ int scst_tm_thread(void *arg) spin_lock_irq(&scst_mcmd_lock); while (!kthread_should_stop()) { - wait_queue_t wait; - init_waitqueue_entry(&wait, current); - - if (!test_mgmt_cmd_list()) { - add_wait_queue_exclusive(&scst_mgmt_cmd_list_waitQ, - &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (test_mgmt_cmd_list()) - break; - spin_unlock_irq(&scst_mcmd_lock); - schedule(); - spin_lock_irq(&scst_mcmd_lock); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&scst_mgmt_cmd_list_waitQ, &wait); - } + wait_event_locked(scst_mgmt_cmd_list_waitQ, + test_mgmt_cmd_list(), lock_irq, + scst_mcmd_lock); while (!list_empty(&scst_active_mgmt_cmd_list)) { int rc; @@ -6592,22 +6549,8 @@ int scst_global_mgmt_thread(void *arg) spin_lock_irq(&scst_mgmt_lock); while (!kthread_should_stop()) { - wait_queue_t wait; - init_waitqueue_entry(&wait, current); - - if (!test_mgmt_list()) { - add_wait_queue_exclusive(&scst_mgmt_waitQ, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (test_mgmt_list()) - break; - spin_unlock_irq(&scst_mgmt_lock); - schedule(); - spin_lock_irq(&scst_mgmt_lock); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&scst_mgmt_waitQ, &wait); - } + wait_event_locked(scst_mgmt_waitQ, test_mgmt_list(), lock_irq, + scst_mgmt_lock); while (!list_empty(&scst_sess_init_list)) { sess = list_entry(scst_sess_init_list.next,