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 <bvanassche@acm.org>

+

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 <bvanassche@acm.org>



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@3591 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2011-06-18 21:15:59 +00:00
parent 82fd6b42e5
commit daa5da87af
5 changed files with 53 additions and 155 deletions

View File

@@ -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);

View File

@@ -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
/*

View File

@@ -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

View File

@@ -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);

View File

@@ -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,