Skip to content

Commit 5a1651a

Browse files
author
Bart Van Assche
committed
ANDROID: sched: Fix SCHED_WARN_ON()
SCHED_WARN_ON() uses WARN_ONCE() and WARN_ONCE() uses printk(). Using printk() from certain code paths in the process scheduler is not allowed because printk() acquires the console_lock and this may cause printk() to sleep. Sleeping is not allowed from many paths in the process scheduler. Hence make sure that SCHED_WARN_ON() uses printk_deferred() instead of printk(). This CL has the ANDROID: prefix because SCHED_WARN_ON() has been removed from the upstream kernel. This CL fixes e.g. the following lockdep complaint: ====================================================== WARNING: possible circular locking dependency detected 6.12.45-android16-5-maybe-dirty-4k #1 Tainted: G W OE ------------------------------------------------------ swapper/4/0 is trying to acquire lock: ffffffc082179768 (console_owner){-...}-{0:0}, at: console_lock_spinning_enable+0x44/0x80 but task is already holding lock: ffffff8b33d30a18 (&rq->__lock){-.-.}-{2:2}, at: __schedule+0x188/0x116c which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #5 (&rq->__lock){-.-.}-{2:2}: _raw_spin_lock_nested+0x50/0x70 __task_rq_lock+0x74/0x154 wake_up_new_task+0x110/0x40c kernel_clone+0x28c/0x508 user_mode_thread+0x60/0x8c rest_init+0x28/0x1b8 start_kernel+0x390/0x4b0 __primary_switched+0x88/0x94 -> #4 (&p->pi_lock){-.-.}-{2:2}: _raw_spin_lock_irqsave+0x64/0xac try_to_wake_up+0x6c/0xa18 default_wake_function+0x20/0x38 autoremove_wake_function+0x1c/0x64 __wake_up+0xac/0xfc rpm_suspend+0x484/0x668 pm_runtime_work+0x8c/0xa8 process_one_work+0x26c/0x65c worker_thread+0x33c/0x498 kthread+0x110/0x134 ret_from_fork+0x10/0x20 -> #3 (&dev->power.wait_queue){....}-{2:2}: _raw_spin_lock_irqsave+0x64/0xac __wake_up+0x34/0xfc rpm_resume+0x4e8/0x5c8 __pm_runtime_resume+0x6c/0xb0 dt_idle_attach_cpu+0x70/0x9c psci_cpuidle_probe+0x270/0x494 platform_probe+0xa0/0xe0 really_probe+0x114/0x454 __driver_probe_device+0xa4/0x160 driver_probe_device+0x44/0x23c __device_attach_driver+0x15c/0x1f4 bus_for_each_drv+0x10c/0x168 __device_attach+0xc0/0x1a0 device_initial_probe+0x14/0x24 bus_probe_device+0x94/0x120 device_add+0x298/0x498 platform_device_add+0x80/0x24c platform_device_register_full+0x144/0x154 psci_idle_init+0x74/0xc4 do_one_initcall+0x124/0x464 do_initcall_level+0xa8/0xd4 do_initcalls+0x74/0xf0 do_basic_setup+0x1c/0x28 kernel_init_freeable+0x154/0x204 kernel_init+0x20/0x1ac ret_from_fork+0x10/0x20 -> #2 (&dev->power.lock){-.-.}-{2:2}: _raw_spin_lock_irqsave+0x64/0xac __pm_runtime_resume+0x5c/0xb0 __uart_start+0x4c/0x120 uart_write+0xe8/0x304 n_tty_write+0x310/0x4c8 file_tty_write+0x154/0x32c redirected_tty_write+0x94/0xe0 vfs_write+0x2e8/0x3ac ksys_write+0x78/0xe8 __arm64_sys_write+0x1c/0x2c invoke_syscall+0x58/0x10c el0_svc_common+0xa8/0xdc do_el0_svc+0x1c/0x28 el0_svc+0x50/0xd4 el0t_64_sync_handler+0x70/0xbc el0t_64_sync+0x1bc/0x1c0 -> #1 (&port_lock_key){-...}-{2:2}: _raw_spin_lock_irqsave+0x64/0xac google_serial8250_console_write+0xe0/0x8f0 [google_8250_base] univ8250_console_write+0x2c/0x40 [google_8250] console_flush_all+0x210/0x420 console_unlock+0x84/0x12c vprintk_emit+0x12c/0x1b8 vprintk_default+0x44/0x70 vprintk+0xe4/0x164 _printk+0x54/0x80 register_console+0x428/0x524 serial_core_register_port+0x664/0x8b8 serial_ctrl_register_port+0x10/0x20 uart_add_one_port+0x10/0x20 google_serial8250_register_8250_port+0x834/0xa1c [google_8250] dw8250_probe+0x550/0x5f0 [google_8250_dw] platform_probe+0xa0/0xe0 really_probe+0x114/0x454 __driver_probe_device+0xa4/0x160 driver_probe_device+0x44/0x23c __driver_attach+0x124/0x278 bus_for_each_dev+0x104/0x160 driver_attach+0x24/0x34 bus_add_driver+0x144/0x2d4 driver_register+0x68/0x104 __platform_driver_register+0x20/0x30 0xffffffc07ed1e03c do_one_initcall+0x124/0x464 do_init_module+0x58/0x2f4 load_module+0x12c8/0x14b0 __arm64_sys_finit_module+0x238/0x33c invoke_syscall+0x58/0x10c el0_svc_common+0xa8/0xdc do_el0_svc+0x1c/0x28 el0_svc+0x50/0xd4 el0t_64_sync_handler+0x70/0xbc el0t_64_sync+0x1bc/0x1c0 -> #0 (console_owner){-...}-{0:0}: __lock_acquire+0x150c/0x2e24 lock_acquire+0x13c/0x2f0 console_lock_spinning_enable+0x6c/0x80 console_flush_all+0x1dc/0x420 console_unlock+0x84/0x12c vprintk_emit+0x12c/0x1b8 vprintk_default+0x44/0x70 vprintk+0xe4/0x164 _printk+0x54/0x80 __warn_printk+0x10c/0x1d4 sub_running_bw+0x164/0x1a8 task_non_contending+0x29c/0x4b0 dequeue_dl_entity+0x1f0/0x260 pick_task_dl+0x7c/0x1c4 __schedule+0x554/0x116c schedule_idle+0x24/0x48 do_idle+0x2f0/0x338 cpu_startup_entry+0x34/0x3c secondary_start_kernel+0x138/0x1a8 __secondary_switched+0xc0/0xc4 other info that might help us debug this: Chain exists of: console_owner --> &p->pi_lock --> &rq->__lock Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&rq->__lock); lock(&p->pi_lock); lock(&rq->__lock); lock(console_owner); *** DEADLOCK *** 3 locks held by swapper/4/0: #0: ffffff8b33d30a18 (&rq->__lock){-.-.}-{2:2}, at: __schedule+0x188/0x116c #1: ffffffc082179790 (console_lock){+.+.}-{0:0}, at: vprintk_emit+0x124/0x1b8 #2: ffffffc082109238 (console_srcu){....}-{0:0}, at: rcu_try_lock_acquire+0x0/0x40 stack backtrace: Call trace: dump_backtrace+0xfc/0x17c show_stack+0x18/0x28 dump_stack_lvl+0x40/0x104 dump_stack+0x18/0x3c print_circular_bug+0x32c/0x334 check_noncircular+0x158/0x178 __lock_acquire+0x150c/0x2e24 lock_acquire+0x13c/0x2f0 console_lock_spinning_enable+0x6c/0x80 console_flush_all+0x1dc/0x420 console_unlock+0x84/0x12c vprintk_emit+0x12c/0x1b8 vprintk_default+0x44/0x70 vprintk+0xe4/0x164 _printk+0x54/0x80 __warn_printk+0x10c/0x1d4 sub_running_bw+0x164/0x1a8 task_non_contending+0x29c/0x4b0 dequeue_dl_entity+0x1f0/0x260 pick_task_dl+0x7c/0x1c4 __schedule+0x554/0x116c schedule_idle+0x24/0x48 do_idle+0x2f0/0x338 cpu_startup_entry+0x34/0x3c secondary_start_kernel+0x138/0x1a8 __secondary_switched+0xc0/0xc4 libbinder.BackendUnifiedServiceManager: Thread Pool max thread count is 0. Cannot cache binder as linkToDeath cannot be implemented. serviceName: android.hardware.boot.IBootControl/default dl_rq->running_bw > old WARNING: CPU: 4 PID: 0 at kernel/sched/deadline.c:265 sub_running_bw+0x164/0x1a8 Bug: 416505362 Change-Id: I4c7fbcb48c242e37a3451c6400e4e298bf1466dd Signed-off-by: Bart Van Assche <bvanassche@google.com>
1 parent 30269ce commit 5a1651a

2 files changed

Lines changed: 22 additions & 0 deletions

File tree

kernel/printk/printk_safe.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@ void __printk_deferred_enter(void)
3131
cant_migrate();
3232
__printk_safe_enter();
3333
}
34+
EXPORT_SYMBOL(__printk_deferred_enter);
3435

3536
void __printk_deferred_exit(void)
3637
{
3738
cant_migrate();
3839
__printk_safe_exit();
3940
}
41+
EXPORT_SYMBOL(__printk_deferred_exit);
4042

4143
bool is_printk_legacy_deferred(void)
4244
{

kernel/sched/sched.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <linux/hrtimer_api.h>
3737
#include <linux/interrupt.h>
3838
#include <linux/irq_work.h>
39+
#include <linux/irqflags.h>
3940
#include <linux/jiffies.h>
4041
#include <linux/kref_api.h>
4142
#include <linux/kthread.h>
@@ -95,7 +96,26 @@ struct cpuidle_state;
9596
#include "cpudeadline.h"
9697

9798
#ifdef CONFIG_SCHED_DEBUG
99+
#ifdef CONFIG_PROVE_LOCKING
100+
# define SCHED_WARN_ON(x) \
101+
({ \
102+
bool __ret = false; \
103+
\
104+
if (unlikely(x)) { \
105+
unsigned long __flags; \
106+
\
107+
local_irq_save(__flags); \
108+
printk_deferred_enter(); \
109+
WARN_ONCE(true, #x); \
110+
printk_deferred_exit(); \
111+
local_irq_restore(__flags); \
112+
__ret = true; \
113+
} \
114+
unlikely(__ret); \
115+
})
116+
#else
98117
# define SCHED_WARN_ON(x) WARN_ONCE(x, #x)
118+
#endif
99119
#else
100120
# define SCHED_WARN_ON(x) ({ (void)(x), 0; })
101121
#endif

0 commit comments

Comments
 (0)