mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-18 11:11:27 +00:00
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:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user