mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-19 13:46:25 +00:00
scst.h: Refactor wait_event_locked() to enhance usability and clarity
1. Set the default process state to TASK_UNINTERRUPTIBLE during sleep. This change is made because our current code does not check whether a process was interrupted by a signal. 2. Prefix all SCST wait_event-related macros with 'scst_'. This helps to distinguish SCST-specific macros from those provided by the Linux kernel itself. 3. Add the capability to return an error code when a process in a non-TASK_UNINTERRUPTIBLE state is interrupted by a signal. 4. Divide the wait_event_locked function based on each lock type, resulting in the following new functions: scst_wait_event_lock(), scst_wait_event_lock_bh(), and scst_wait_event_lock_irq().
This commit is contained in:
@@ -960,8 +960,7 @@ int istrd(void *arg)
|
|||||||
|
|
||||||
spin_lock_bh(&p->rd_lock);
|
spin_lock_bh(&p->rd_lock);
|
||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
wait_event_locked(p->rd_waitQ, test_rd_list(p), lock_bh,
|
scst_wait_event_lock_bh(p->rd_waitQ, test_rd_list(p), p->rd_lock);
|
||||||
p->rd_lock);
|
|
||||||
scst_do_job_rd(p);
|
scst_do_job_rd(p);
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&p->rd_lock);
|
spin_unlock_bh(&p->rd_lock);
|
||||||
@@ -1613,8 +1612,7 @@ int istwr(void *arg)
|
|||||||
|
|
||||||
spin_lock_bh(&p->wr_lock);
|
spin_lock_bh(&p->wr_lock);
|
||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
wait_event_locked(p->wr_waitQ, test_wr_list(p), lock_bh,
|
scst_wait_event_lock_bh(p->wr_waitQ, test_wr_list(p), p->wr_lock);
|
||||||
p->wr_lock);
|
|
||||||
scst_do_job_wr(p);
|
scst_do_job_wr(p);
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&p->wr_lock);
|
spin_unlock_bh(&p->wr_lock);
|
||||||
|
|||||||
+118
-32
@@ -36,6 +36,9 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||||
|
#include <linux/sched/signal.h>
|
||||||
|
#endif
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
#include <linux/dlm.h>
|
#include <linux/dlm.h>
|
||||||
@@ -5382,59 +5385,142 @@ void scst_dev_inquiry_data_changed(struct scst_device *dev);
|
|||||||
*/
|
*/
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) && \
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) && \
|
||||||
!defined(CONFIG_SUSE_KERNEL)
|
!defined(CONFIG_SUSE_KERNEL)
|
||||||
static inline void
|
static inline long
|
||||||
prepare_to_wait_exclusive_head(wait_queue_head_t *wq_head,
|
prepare_to_wait_exclusive_head(wait_queue_head_t *wq_head,
|
||||||
wait_queue_t *wq_entry, int state)
|
wait_queue_t *wq_entry, int state)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
long ret = 0;
|
||||||
|
|
||||||
wq_entry->flags |= WQ_FLAG_EXCLUSIVE;
|
wq_entry->flags |= WQ_FLAG_EXCLUSIVE;
|
||||||
|
|
||||||
spin_lock_irqsave(&wq_head->lock, flags);
|
spin_lock_irqsave(&wq_head->lock, flags);
|
||||||
if (list_empty(&wq_entry->task_list))
|
if (signal_pending_state(state, current)) {
|
||||||
__add_wait_queue(wq_head, wq_entry);
|
/*
|
||||||
set_current_state(state);
|
* Exclusive waiter must not fail if it was selected by wakeup,
|
||||||
|
* it should "consume" the condition we were waiting for.
|
||||||
|
*
|
||||||
|
* The caller will recheck the condition and return success if
|
||||||
|
* we were already woken up, we can not miss the event because
|
||||||
|
* wakeup locks/unlocks the same wq_head->lock.
|
||||||
|
*
|
||||||
|
* But we need to ensure that set-condition + wakeup after that
|
||||||
|
* can't see us, it should wake up another exclusive waiter if
|
||||||
|
* we fail.
|
||||||
|
*/
|
||||||
|
list_del_init(&wq_entry->task_list);
|
||||||
|
ret = -ERESTARTSYS;
|
||||||
|
} else {
|
||||||
|
if (list_empty(&wq_entry->task_list))
|
||||||
|
__add_wait_queue(wq_head, wq_entry);
|
||||||
|
set_current_state(state);
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&wq_head->lock, flags);
|
spin_unlock_irqrestore(&wq_head->lock, flags);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline void
|
static inline long
|
||||||
prepare_to_wait_exclusive_head(struct wait_queue_head *wq_head,
|
prepare_to_wait_exclusive_head(struct wait_queue_head *wq_head,
|
||||||
struct wait_queue_entry *wq_entry, int state)
|
struct wait_queue_entry *wq_entry, int state)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
long ret = 0;
|
||||||
|
|
||||||
wq_entry->flags |= WQ_FLAG_EXCLUSIVE;
|
wq_entry->flags |= WQ_FLAG_EXCLUSIVE;
|
||||||
|
|
||||||
spin_lock_irqsave(&wq_head->lock, flags);
|
spin_lock_irqsave(&wq_head->lock, flags);
|
||||||
if (list_empty(&wq_entry->entry))
|
if (signal_pending_state(state, current)) {
|
||||||
__add_wait_queue(wq_head, wq_entry);
|
/*
|
||||||
set_current_state(state);
|
* Exclusive waiter must not fail if it was selected by wakeup,
|
||||||
|
* it should "consume" the condition we were waiting for.
|
||||||
|
*
|
||||||
|
* The caller will recheck the condition and return success if
|
||||||
|
* we were already woken up, we can not miss the event because
|
||||||
|
* wakeup locks/unlocks the same wq_head->lock.
|
||||||
|
*
|
||||||
|
* But we need to ensure that set-condition + wakeup after that
|
||||||
|
* can't see us, it should wake up another exclusive waiter if
|
||||||
|
* we fail.
|
||||||
|
*/
|
||||||
|
list_del_init(&wq_entry->entry);
|
||||||
|
ret = -ERESTARTSYS;
|
||||||
|
} else {
|
||||||
|
if (list_empty(&wq_entry->entry))
|
||||||
|
__add_wait_queue(wq_head, wq_entry);
|
||||||
|
set_current_state(state);
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&wq_head->lock, flags);
|
spin_unlock_irqrestore(&wq_head->lock, flags);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
#define ___scst_wait_is_interruptible(state) \
|
||||||
* wait_event_locked() - Wait until a condition becomes true.
|
(!__builtin_constant_p(state) || \
|
||||||
* @wq: Wait queue to wait on if @condition is false.
|
(state & (TASK_INTERRUPTIBLE | TASK_WAKEKILL)))
|
||||||
* @condition: Condition to wait for. Can be any C expression.
|
|
||||||
* @lock_type: One of lock, lock_bh or lock_irq.
|
#define ___scst_wait_event(wq_head, condition, state, ret, cmd) \
|
||||||
* @lock: A spinlock.
|
({ \
|
||||||
*
|
__label__ __out; \
|
||||||
* Caller must hold lock of type @lock_type on @lock.
|
DEFINE_WAIT(__wq_entry); \
|
||||||
*/
|
long __ret = ret; /* explicit shadow */ \
|
||||||
#define wait_event_locked(wq, condition, lock_type, lock) do { \
|
\
|
||||||
if (!(condition)) { \
|
for (;;) { \
|
||||||
DEFINE_WAIT(__wait); \
|
long __int = prepare_to_wait_exclusive_head(&wq_head, &__wq_entry,\
|
||||||
\
|
state); \
|
||||||
do { \
|
\
|
||||||
prepare_to_wait_exclusive_head(&(wq), &__wait, \
|
if (condition) \
|
||||||
TASK_INTERRUPTIBLE); \
|
break; \
|
||||||
if (condition) \
|
\
|
||||||
break; \
|
if (___scst_wait_is_interruptible(state) && __int) { \
|
||||||
spin_un ## lock_type(&(lock)); \
|
__ret = __int; \
|
||||||
schedule(); \
|
goto __out; \
|
||||||
spin_ ## lock_type(&(lock)); \
|
} \
|
||||||
} while (!(condition)); \
|
\
|
||||||
finish_wait(&(wq), &__wait); \
|
cmd; \
|
||||||
} \
|
} \
|
||||||
|
finish_wait(&wq_head, &__wq_entry); \
|
||||||
|
__out: __ret; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define __scst_wait_event_lock(wq_head, condition, lock) \
|
||||||
|
(void)___scst_wait_event(wq_head, condition, TASK_UNINTERRUPTIBLE, 0, \
|
||||||
|
spin_unlock(&lock); \
|
||||||
|
schedule(); \
|
||||||
|
spin_lock(&lock))
|
||||||
|
|
||||||
|
#define scst_wait_event_lock(wq_head, condition, lock) \
|
||||||
|
do { \
|
||||||
|
if (condition) \
|
||||||
|
break; \
|
||||||
|
__scst_wait_event_lock(wq_head, condition, lock); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define __scst_wait_event_lock_bh(wq_head, condition, lock) \
|
||||||
|
(void)___scst_wait_event(wq_head, condition, TASK_UNINTERRUPTIBLE, 0, \
|
||||||
|
spin_unlock_bh(&lock); \
|
||||||
|
schedule(); \
|
||||||
|
spin_lock_bh(&lock))
|
||||||
|
|
||||||
|
#define scst_wait_event_lock_bh(wq_head, condition, lock) \
|
||||||
|
do { \
|
||||||
|
if (condition) \
|
||||||
|
break; \
|
||||||
|
__scst_wait_event_lock_bh(wq_head, condition, lock); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define __scst_wait_event_lock_irq(wq_head, condition, lock) \
|
||||||
|
(void)___scst_wait_event(wq_head, condition, TASK_UNINTERRUPTIBLE, 0, \
|
||||||
|
spin_unlock_irq(&lock); \
|
||||||
|
schedule(); \
|
||||||
|
spin_lock_irq(&lock))
|
||||||
|
|
||||||
|
#define scst_wait_event_lock_irq(wq_head, condition, lock) \
|
||||||
|
do { \
|
||||||
|
if (condition) \
|
||||||
|
break; \
|
||||||
|
__scst_wait_event_lock_irq(wq_head, condition, lock); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
||||||
|
|||||||
@@ -2233,9 +2233,9 @@ static int dev_user_get_next_cmd(struct scst_user_dev *dev,
|
|||||||
TRACE_ENTRY();
|
TRACE_ENTRY();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
wait_event_locked(dev->udev_cmd_threads.cmd_list_waitQ,
|
scst_wait_event_lock_irq(dev->udev_cmd_threads.cmd_list_waitQ,
|
||||||
test_cmd_threads(dev, can_block), lock_irq,
|
test_cmd_threads(dev, can_block),
|
||||||
dev->udev_cmd_threads.cmd_list_lock);
|
dev->udev_cmd_threads.cmd_list_lock);
|
||||||
|
|
||||||
dev_user_process_scst_commands(dev);
|
dev_user_process_scst_commands(dev);
|
||||||
|
|
||||||
@@ -4053,8 +4053,8 @@ static int dev_user_cleanup_thread(void *arg)
|
|||||||
|
|
||||||
spin_lock(&cleanup_lock);
|
spin_lock(&cleanup_lock);
|
||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
wait_event_locked(cleanup_list_waitQ, test_cleanup_list(),
|
scst_wait_event_lock(cleanup_list_waitQ, test_cleanup_list(),
|
||||||
lock, cleanup_lock);
|
cleanup_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have to poll devices, because commands can go from SCST
|
* We have to poll devices, because commands can go from SCST
|
||||||
|
|||||||
+1
-2
@@ -14978,8 +14978,7 @@ int scst_ext_block_dev(struct scst_device *dev, ext_blocker_done_fn_t done_fn,
|
|||||||
b->ext_blocker_done_fn = scst_sync_ext_blocking_done;
|
b->ext_blocker_done_fn = scst_sync_ext_blocking_done;
|
||||||
*((void **)&b->ext_blocker_data[0]) = &w;
|
*((void **)&b->ext_blocker_data[0]) = &w;
|
||||||
|
|
||||||
wait_event_locked(w, (dev->on_dev_cmd_count == 0),
|
scst_wait_event_lock_bh(w, dev->on_dev_cmd_count == 0, dev->dev_lock);
|
||||||
lock_bh, dev->dev_lock);
|
|
||||||
|
|
||||||
spin_unlock_bh(&dev->dev_lock);
|
spin_unlock_bh(&dev->dev_lock);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -470,8 +470,8 @@ static int sysfs_work_thread_fn(void *arg)
|
|||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
if (one_time_only && !test_sysfs_work_list())
|
if (one_time_only && !test_sysfs_work_list())
|
||||||
break;
|
break;
|
||||||
wait_event_locked(sysfs_work_waitQ, test_sysfs_work_list(),
|
scst_wait_event_lock(sysfs_work_waitQ, test_sysfs_work_list(),
|
||||||
lock, sysfs_work_lock);
|
sysfs_work_lock);
|
||||||
scst_process_sysfs_works();
|
scst_process_sysfs_works();
|
||||||
}
|
}
|
||||||
spin_unlock(&sysfs_work_lock);
|
spin_unlock(&sysfs_work_lock);
|
||||||
|
|||||||
@@ -4510,9 +4510,9 @@ int scst_init_thread(void *arg)
|
|||||||
|
|
||||||
spin_lock_irq(&scst_init_lock);
|
spin_lock_irq(&scst_init_lock);
|
||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
wait_event_locked(scst_init_cmd_list_waitQ,
|
scst_wait_event_lock_irq(scst_init_cmd_list_waitQ,
|
||||||
test_init_cmd_list(),
|
test_init_cmd_list(),
|
||||||
lock_irq, scst_init_lock);
|
scst_init_lock);
|
||||||
scst_do_job_init();
|
scst_do_job_init();
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&scst_init_lock);
|
spin_unlock_irq(&scst_init_lock);
|
||||||
@@ -6794,9 +6794,9 @@ int scst_tm_thread(void *arg)
|
|||||||
|
|
||||||
spin_lock_irq(&scst_mcmd_lock);
|
spin_lock_irq(&scst_mcmd_lock);
|
||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
wait_event_locked(scst_mgmt_cmd_list_waitQ,
|
scst_wait_event_lock_irq(scst_mgmt_cmd_list_waitQ,
|
||||||
test_mgmt_cmd_list(), lock_irq,
|
test_mgmt_cmd_list(),
|
||||||
scst_mcmd_lock);
|
scst_mcmd_lock);
|
||||||
|
|
||||||
while (!list_empty(&scst_active_mgmt_cmd_list)) {
|
while (!list_empty(&scst_active_mgmt_cmd_list)) {
|
||||||
int rc;
|
int rc;
|
||||||
@@ -7610,8 +7610,8 @@ int scst_global_mgmt_thread(void *arg)
|
|||||||
|
|
||||||
spin_lock_irq(&scst_mgmt_lock);
|
spin_lock_irq(&scst_mgmt_lock);
|
||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
wait_event_locked(scst_mgmt_waitQ, test_mgmt_list(), lock_irq,
|
scst_wait_event_lock_irq(scst_mgmt_waitQ, test_mgmt_list(),
|
||||||
scst_mgmt_lock);
|
scst_mgmt_lock);
|
||||||
|
|
||||||
while (!list_empty(&scst_sess_init_list)) {
|
while (!list_empty(&scst_sess_init_list)) {
|
||||||
sess = list_first_entry(&scst_sess_init_list,
|
sess = list_first_entry(&scst_sess_init_list,
|
||||||
|
|||||||
Reference in New Issue
Block a user