2020-03-06 11:44:27 +00:00
|
|
|
From ae24940034c02ed671e3a5cc9c4cf31ebfc24fed Mon Sep 17 00:00:00 2001
|
2018-08-27 14:32:32 +00:00
|
|
|
From: Thomas Gleixner <tglx@linutronix.de>
|
|
|
|
Date: Fri, 11 Jan 2013 11:23:51 +0100
|
2020-04-09 19:44:24 +00:00
|
|
|
Subject: [PATCH 095/328] completion: Use simple wait queues
|
|
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/older/patches-4.19.106-rt46.tar.xz
|
2018-08-27 14:32:32 +00:00
|
|
|
|
|
|
|
Completions have no long lasting callbacks and therefor do not need
|
|
|
|
the complex waitqueue variant. Use simple waitqueues which reduces the
|
|
|
|
contention on the waitqueue lock.
|
|
|
|
|
|
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
|
|
---
|
2019-04-08 23:49:20 +00:00
|
|
|
arch/powerpc/platforms/ps3/device-init.c | 4 +--
|
|
|
|
.../wireless/intersil/orinoco/orinoco_usb.c | 4 +--
|
|
|
|
drivers/usb/gadget/function/f_fs.c | 2 +-
|
|
|
|
drivers/usb/gadget/legacy/inode.c | 4 +--
|
|
|
|
include/linux/completion.h | 8 ++---
|
|
|
|
include/linux/suspend.h | 6 ++++
|
|
|
|
include/linux/swait.h | 2 ++
|
|
|
|
kernel/power/hibernate.c | 7 ++++
|
|
|
|
kernel/power/suspend.c | 4 +++
|
|
|
|
kernel/sched/completion.c | 34 +++++++++----------
|
|
|
|
kernel/sched/core.c | 10 ++++--
|
|
|
|
kernel/sched/swait.c | 21 +++++++++++-
|
2018-10-30 12:40:05 +00:00
|
|
|
12 files changed, 75 insertions(+), 31 deletions(-)
|
2018-08-27 14:32:32 +00:00
|
|
|
|
2019-04-08 23:49:20 +00:00
|
|
|
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
|
|
|
|
index e7075aaff1bb..1580464a9d5b 100644
|
2018-10-30 12:40:05 +00:00
|
|
|
--- a/arch/powerpc/platforms/ps3/device-init.c
|
|
|
|
+++ b/arch/powerpc/platforms/ps3/device-init.c
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -752,8 +752,8 @@ static int ps3_notification_read_write(struct ps3_notification_device *dev,
|
2018-10-30 12:40:05 +00:00
|
|
|
}
|
|
|
|
pr_debug("%s:%u: notification %s issued\n", __func__, __LINE__, op);
|
|
|
|
|
|
|
|
- res = wait_event_interruptible(dev->done.wait,
|
|
|
|
- dev->done.done || kthread_should_stop());
|
|
|
|
+ res = swait_event_interruptible_exclusive(dev->done.wait,
|
|
|
|
+ dev->done.done || kthread_should_stop());
|
|
|
|
if (kthread_should_stop())
|
|
|
|
res = -EINTR;
|
|
|
|
if (res) {
|
2019-04-08 23:49:20 +00:00
|
|
|
diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
|
2020-03-06 11:44:27 +00:00
|
|
|
index b704e4bce171..c364abaac548 100644
|
2018-08-27 14:32:32 +00:00
|
|
|
--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
|
|
|
|
+++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -697,8 +697,8 @@ static void ezusb_req_ctx_wait(struct ezusb_priv *upriv,
|
2018-08-27 14:32:32 +00:00
|
|
|
while (!ctx->done.done && msecs--)
|
|
|
|
udelay(1000);
|
|
|
|
} else {
|
|
|
|
- wait_event_interruptible(ctx->done.wait,
|
2018-10-30 12:40:05 +00:00
|
|
|
- ctx->done.done);
|
|
|
|
+ swait_event_interruptible_exclusive(ctx->done.wait,
|
|
|
|
+ ctx->done.done);
|
2018-08-27 14:32:32 +00:00
|
|
|
}
|
|
|
|
break;
|
2018-10-30 12:40:05 +00:00
|
|
|
default:
|
2019-04-08 23:49:20 +00:00
|
|
|
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
|
2019-11-25 00:04:39 +00:00
|
|
|
index 2050993fb58b..e2ca75a6e241 100644
|
2018-08-27 14:32:32 +00:00
|
|
|
--- a/drivers/usb/gadget/function/f_fs.c
|
|
|
|
+++ b/drivers/usb/gadget/function/f_fs.c
|
2019-11-25 00:04:39 +00:00
|
|
|
@@ -1626,7 +1626,7 @@ static void ffs_data_put(struct ffs_data *ffs)
|
2018-08-27 14:32:32 +00:00
|
|
|
pr_info("%s(): freeing\n", __func__);
|
|
|
|
ffs_data_clear(ffs);
|
|
|
|
BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
|
|
|
|
- waitqueue_active(&ffs->ep0req_completion.wait) ||
|
|
|
|
+ swait_active(&ffs->ep0req_completion.wait) ||
|
|
|
|
waitqueue_active(&ffs->wait));
|
|
|
|
destroy_workqueue(ffs->io_completion_wq);
|
|
|
|
kfree(ffs->dev_name);
|
2019-04-08 23:49:20 +00:00
|
|
|
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
|
|
|
|
index 37ca0e669bd8..56a16587b221 100644
|
2018-08-27 14:32:32 +00:00
|
|
|
--- a/drivers/usb/gadget/legacy/inode.c
|
|
|
|
+++ b/drivers/usb/gadget/legacy/inode.c
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -343,7 +343,7 @@ ep_io (struct ep_data *epdata, void *buf, unsigned len)
|
2018-08-27 14:32:32 +00:00
|
|
|
spin_unlock_irq (&epdata->dev->lock);
|
|
|
|
|
|
|
|
if (likely (value == 0)) {
|
|
|
|
- value = wait_event_interruptible (done.wait, done.done);
|
2018-10-30 12:40:05 +00:00
|
|
|
+ value = swait_event_interruptible_exclusive(done.wait, done.done);
|
2018-08-27 14:32:32 +00:00
|
|
|
if (value != 0) {
|
|
|
|
spin_lock_irq (&epdata->dev->lock);
|
|
|
|
if (likely (epdata->ep != NULL)) {
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -352,7 +352,7 @@ ep_io (struct ep_data *epdata, void *buf, unsigned len)
|
2018-08-27 14:32:32 +00:00
|
|
|
usb_ep_dequeue (epdata->ep, epdata->req);
|
|
|
|
spin_unlock_irq (&epdata->dev->lock);
|
|
|
|
|
|
|
|
- wait_event (done.wait, done.done);
|
2018-10-30 12:40:05 +00:00
|
|
|
+ swait_event_exclusive(done.wait, done.done);
|
2018-08-27 14:32:32 +00:00
|
|
|
if (epdata->status == -ECONNRESET)
|
|
|
|
epdata->status = -EINTR;
|
|
|
|
} else {
|
2019-04-08 23:49:20 +00:00
|
|
|
diff --git a/include/linux/completion.h b/include/linux/completion.h
|
|
|
|
index 519e94915d18..bf8e77001f18 100644
|
2018-08-27 14:32:32 +00:00
|
|
|
--- a/include/linux/completion.h
|
|
|
|
+++ b/include/linux/completion.h
|
|
|
|
@@ -9,7 +9,7 @@
|
|
|
|
* See kernel/sched/completion.c for details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
-#include <linux/wait.h>
|
|
|
|
+#include <linux/swait.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* struct completion - structure used to maintain state for a "completion"
|
|
|
|
@@ -25,7 +25,7 @@
|
|
|
|
*/
|
|
|
|
struct completion {
|
|
|
|
unsigned int done;
|
|
|
|
- wait_queue_head_t wait;
|
|
|
|
+ struct swait_queue_head wait;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define init_completion_map(x, m) __init_completion(x)
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -34,7 +34,7 @@ static inline void complete_acquire(struct completion *x) {}
|
2018-08-27 14:32:32 +00:00
|
|
|
static inline void complete_release(struct completion *x) {}
|
|
|
|
|
|
|
|
#define COMPLETION_INITIALIZER(work) \
|
|
|
|
- { 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
|
|
|
|
+ { 0, __SWAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
|
|
|
|
|
|
|
|
#define COMPLETION_INITIALIZER_ONSTACK_MAP(work, map) \
|
|
|
|
(*({ init_completion_map(&(work), &(map)); &(work); }))
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -85,7 +85,7 @@ static inline void complete_release(struct completion *x) {}
|
2018-08-27 14:32:32 +00:00
|
|
|
static inline void __init_completion(struct completion *x)
|
|
|
|
{
|
|
|
|
x->done = 0;
|
|
|
|
- init_waitqueue_head(&x->wait);
|
|
|
|
+ init_swait_queue_head(&x->wait);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-04-08 23:49:20 +00:00
|
|
|
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
|
|
|
|
index 3f529ad9a9d2..328439ce71f5 100644
|
2018-08-27 14:32:32 +00:00
|
|
|
--- a/include/linux/suspend.h
|
|
|
|
+++ b/include/linux/suspend.h
|
|
|
|
@@ -196,6 +196,12 @@ struct platform_s2idle_ops {
|
|
|
|
void (*end)(void);
|
|
|
|
};
|
|
|
|
|
|
|
|
+#if defined(CONFIG_SUSPEND) || defined(CONFIG_HIBERNATION)
|
|
|
|
+extern bool pm_in_action;
|
|
|
|
+#else
|
|
|
|
+# define pm_in_action false
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
#ifdef CONFIG_SUSPEND
|
|
|
|
extern suspend_state_t mem_sleep_current;
|
|
|
|
extern suspend_state_t mem_sleep_default;
|
2019-04-08 23:49:20 +00:00
|
|
|
diff --git a/include/linux/swait.h b/include/linux/swait.h
|
|
|
|
index 73e06e9986d4..f426a0661aa0 100644
|
2018-08-27 14:32:32 +00:00
|
|
|
--- a/include/linux/swait.h
|
|
|
|
+++ b/include/linux/swait.h
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -160,7 +160,9 @@ static inline bool swq_has_sleeper(struct swait_queue_head *wq)
|
2018-10-30 12:40:05 +00:00
|
|
|
extern void swake_up_one(struct swait_queue_head *q);
|
2018-08-27 14:32:32 +00:00
|
|
|
extern void swake_up_all(struct swait_queue_head *q);
|
|
|
|
extern void swake_up_locked(struct swait_queue_head *q);
|
|
|
|
+extern void swake_up_all_locked(struct swait_queue_head *q);
|
|
|
|
|
2018-10-30 12:40:05 +00:00
|
|
|
+extern void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait);
|
|
|
|
extern void prepare_to_swait_exclusive(struct swait_queue_head *q, struct swait_queue *wait, int state);
|
|
|
|
extern long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait, int state);
|
|
|
|
|
2019-04-08 23:49:20 +00:00
|
|
|
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
|
2019-08-18 21:33:52 +00:00
|
|
|
index f5ce9f7ec132..0f00ba01376f 100644
|
2018-08-27 14:32:32 +00:00
|
|
|
--- a/kernel/power/hibernate.c
|
|
|
|
+++ b/kernel/power/hibernate.c
|
2019-08-18 21:33:52 +00:00
|
|
|
@@ -690,6 +690,10 @@ static int load_image_and_restore(void)
|
2018-08-27 14:32:32 +00:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
+#ifndef CONFIG_SUSPEND
|
|
|
|
+bool pm_in_action;
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
/**
|
|
|
|
* hibernate - Carry out system hibernation, including saving the image.
|
|
|
|
*/
|
2019-08-18 21:33:52 +00:00
|
|
|
@@ -703,6 +707,8 @@ int hibernate(void)
|
2018-08-27 14:32:32 +00:00
|
|
|
return -EPERM;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ pm_in_action = true;
|
|
|
|
+
|
|
|
|
lock_system_sleep();
|
|
|
|
/* The snapshot device should not be opened while we're running */
|
|
|
|
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
|
2019-08-18 21:33:52 +00:00
|
|
|
@@ -781,6 +787,7 @@ int hibernate(void)
|
2018-08-27 14:32:32 +00:00
|
|
|
atomic_inc(&snapshot_device_available);
|
|
|
|
Unlock:
|
|
|
|
unlock_system_sleep();
|
|
|
|
+ pm_in_action = false;
|
|
|
|
pr_info("hibernation exit\n");
|
|
|
|
|
|
|
|
return error;
|
2019-04-08 23:49:20 +00:00
|
|
|
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
|
|
|
|
index 0bd595a0b610..a4456772d98e 100644
|
2018-08-27 14:32:32 +00:00
|
|
|
--- a/kernel/power/suspend.c
|
|
|
|
+++ b/kernel/power/suspend.c
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -600,6 +600,8 @@ static int enter_state(suspend_state_t state)
|
2018-08-27 14:32:32 +00:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
+bool pm_in_action;
|
|
|
|
+
|
|
|
|
/**
|
|
|
|
* pm_suspend - Externally visible function for suspending the system.
|
|
|
|
* @state: System sleep state to enter.
|
2018-10-30 12:40:05 +00:00
|
|
|
@@ -614,6 +616,7 @@ int pm_suspend(suspend_state_t state)
|
2018-08-27 14:32:32 +00:00
|
|
|
if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ pm_in_action = true;
|
|
|
|
pr_info("suspend entry (%s)\n", mem_sleep_labels[state]);
|
|
|
|
error = enter_state(state);
|
|
|
|
if (error) {
|
2018-10-30 12:40:05 +00:00
|
|
|
@@ -623,6 +626,7 @@ int pm_suspend(suspend_state_t state)
|
2018-08-27 14:32:32 +00:00
|
|
|
suspend_stats.success++;
|
|
|
|
}
|
|
|
|
pr_info("suspend exit\n");
|
|
|
|
+ pm_in_action = false;
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(pm_suspend);
|
2019-04-08 23:49:20 +00:00
|
|
|
diff --git a/kernel/sched/completion.c b/kernel/sched/completion.c
|
|
|
|
index a1ad5b7d5521..755a58084978 100644
|
2018-08-27 14:32:32 +00:00
|
|
|
--- a/kernel/sched/completion.c
|
|
|
|
+++ b/kernel/sched/completion.c
|
|
|
|
@@ -29,12 +29,12 @@ void complete(struct completion *x)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
- spin_lock_irqsave(&x->wait.lock, flags);
|
|
|
|
+ raw_spin_lock_irqsave(&x->wait.lock, flags);
|
|
|
|
|
|
|
|
if (x->done != UINT_MAX)
|
|
|
|
x->done++;
|
|
|
|
- __wake_up_locked(&x->wait, TASK_NORMAL, 1);
|
|
|
|
- spin_unlock_irqrestore(&x->wait.lock, flags);
|
|
|
|
+ swake_up_locked(&x->wait);
|
|
|
|
+ raw_spin_unlock_irqrestore(&x->wait.lock, flags);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(complete);
|
|
|
|
|
|
|
|
@@ -58,10 +58,10 @@ void complete_all(struct completion *x)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
- spin_lock_irqsave(&x->wait.lock, flags);
|
|
|
|
+ raw_spin_lock_irqsave(&x->wait.lock, flags);
|
|
|
|
x->done = UINT_MAX;
|
|
|
|
- __wake_up_locked(&x->wait, TASK_NORMAL, 0);
|
|
|
|
- spin_unlock_irqrestore(&x->wait.lock, flags);
|
|
|
|
+ swake_up_all_locked(&x->wait);
|
|
|
|
+ raw_spin_unlock_irqrestore(&x->wait.lock, flags);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(complete_all);
|
|
|
|
|
|
|
|
@@ -70,20 +70,20 @@ do_wait_for_common(struct completion *x,
|
|
|
|
long (*action)(long), long timeout, int state)
|
|
|
|
{
|
|
|
|
if (!x->done) {
|
|
|
|
- DECLARE_WAITQUEUE(wait, current);
|
|
|
|
+ DECLARE_SWAITQUEUE(wait);
|
|
|
|
|
|
|
|
- __add_wait_queue_entry_tail_exclusive(&x->wait, &wait);
|
|
|
|
+ __prepare_to_swait(&x->wait, &wait);
|
|
|
|
do {
|
|
|
|
if (signal_pending_state(state, current)) {
|
|
|
|
timeout = -ERESTARTSYS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
__set_current_state(state);
|
|
|
|
- spin_unlock_irq(&x->wait.lock);
|
|
|
|
+ raw_spin_unlock_irq(&x->wait.lock);
|
|
|
|
timeout = action(timeout);
|
|
|
|
- spin_lock_irq(&x->wait.lock);
|
|
|
|
+ raw_spin_lock_irq(&x->wait.lock);
|
|
|
|
} while (!x->done && timeout);
|
|
|
|
- __remove_wait_queue(&x->wait, &wait);
|
|
|
|
+ __finish_swait(&x->wait, &wait);
|
|
|
|
if (!x->done)
|
|
|
|
return timeout;
|
|
|
|
}
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -100,9 +100,9 @@ __wait_for_common(struct completion *x,
|
2018-08-27 14:32:32 +00:00
|
|
|
|
|
|
|
complete_acquire(x);
|
|
|
|
|
|
|
|
- spin_lock_irq(&x->wait.lock);
|
|
|
|
+ raw_spin_lock_irq(&x->wait.lock);
|
|
|
|
timeout = do_wait_for_common(x, action, timeout, state);
|
|
|
|
- spin_unlock_irq(&x->wait.lock);
|
|
|
|
+ raw_spin_unlock_irq(&x->wait.lock);
|
|
|
|
|
|
|
|
complete_release(x);
|
|
|
|
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -291,12 +291,12 @@ bool try_wait_for_completion(struct completion *x)
|
2018-08-27 14:32:32 +00:00
|
|
|
if (!READ_ONCE(x->done))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
- spin_lock_irqsave(&x->wait.lock, flags);
|
|
|
|
+ raw_spin_lock_irqsave(&x->wait.lock, flags);
|
|
|
|
if (!x->done)
|
|
|
|
ret = false;
|
|
|
|
else if (x->done != UINT_MAX)
|
|
|
|
x->done--;
|
|
|
|
- spin_unlock_irqrestore(&x->wait.lock, flags);
|
|
|
|
+ raw_spin_unlock_irqrestore(&x->wait.lock, flags);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(try_wait_for_completion);
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -322,8 +322,8 @@ bool completion_done(struct completion *x)
|
2018-08-27 14:32:32 +00:00
|
|
|
* otherwise we can end up freeing the completion before complete()
|
|
|
|
* is done referencing it.
|
|
|
|
*/
|
|
|
|
- spin_lock_irqsave(&x->wait.lock, flags);
|
|
|
|
- spin_unlock_irqrestore(&x->wait.lock, flags);
|
|
|
|
+ raw_spin_lock_irqsave(&x->wait.lock, flags);
|
|
|
|
+ raw_spin_unlock_irqrestore(&x->wait.lock, flags);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(completion_done);
|
2019-04-08 23:49:20 +00:00
|
|
|
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
2020-01-03 23:36:11 +00:00
|
|
|
index 986ed04425be..584978640512 100644
|
2018-08-27 14:32:32 +00:00
|
|
|
--- a/kernel/sched/core.c
|
|
|
|
+++ b/kernel/sched/core.c
|
2020-01-03 23:36:11 +00:00
|
|
|
@@ -7154,7 +7154,10 @@ void migrate_disable(void)
|
2018-08-27 14:32:32 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#ifdef CONFIG_SCHED_DEBUG
|
|
|
|
- WARN_ON_ONCE(p->migrate_disable_atomic);
|
|
|
|
+ if (unlikely(p->migrate_disable_atomic)) {
|
|
|
|
+ tracing_off();
|
|
|
|
+ WARN_ON_ONCE(1);
|
|
|
|
+ }
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (p->migrate_disable) {
|
2020-01-03 23:36:11 +00:00
|
|
|
@@ -7184,7 +7187,10 @@ void migrate_enable(void)
|
2018-08-27 14:32:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_SCHED_DEBUG
|
|
|
|
- WARN_ON_ONCE(p->migrate_disable_atomic);
|
|
|
|
+ if (unlikely(p->migrate_disable_atomic)) {
|
|
|
|
+ tracing_off();
|
|
|
|
+ WARN_ON_ONCE(1);
|
|
|
|
+ }
|
|
|
|
#endif
|
|
|
|
|
|
|
|
WARN_ON_ONCE(p->migrate_disable <= 0);
|
2019-04-08 23:49:20 +00:00
|
|
|
diff --git a/kernel/sched/swait.c b/kernel/sched/swait.c
|
|
|
|
index 66b59ac77c22..c7cb30cdd1b7 100644
|
2018-08-27 14:32:32 +00:00
|
|
|
--- a/kernel/sched/swait.c
|
|
|
|
+++ b/kernel/sched/swait.c
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -32,6 +32,25 @@ void swake_up_locked(struct swait_queue_head *q)
|
2018-08-27 14:32:32 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(swake_up_locked);
|
|
|
|
|
|
|
|
+void swake_up_all_locked(struct swait_queue_head *q)
|
|
|
|
+{
|
|
|
|
+ struct swait_queue *curr;
|
|
|
|
+ int wakes = 0;
|
|
|
|
+
|
|
|
|
+ while (!list_empty(&q->task_list)) {
|
|
|
|
+
|
|
|
|
+ curr = list_first_entry(&q->task_list, typeof(*curr),
|
|
|
|
+ task_list);
|
|
|
|
+ wake_up_process(curr->task);
|
|
|
|
+ list_del_init(&curr->task_list);
|
|
|
|
+ wakes++;
|
|
|
|
+ }
|
|
|
|
+ if (pm_in_action)
|
|
|
|
+ return;
|
|
|
|
+ WARN(wakes > 2, "complete_all() with %d waiters\n", wakes);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(swake_up_all_locked);
|
|
|
|
+
|
2018-10-30 12:40:05 +00:00
|
|
|
void swake_up_one(struct swait_queue_head *q)
|
2018-08-27 14:32:32 +00:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
2019-04-08 23:49:20 +00:00
|
|
|
@@ -69,7 +88,7 @@ void swake_up_all(struct swait_queue_head *q)
|
2018-10-30 12:40:05 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(swake_up_all);
|
|
|
|
|
|
|
|
-static void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait)
|
|
|
|
+void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait)
|
|
|
|
{
|
|
|
|
wait->task = current;
|
|
|
|
if (list_empty(&wait->task_list))
|
2020-01-03 23:36:11 +00:00
|
|
|
--
|
2020-04-09 19:44:24 +00:00
|
|
|
2.25.1
|
2020-01-03 23:36:11 +00:00
|
|
|
|