Messages in this thread | | | Date | Thu, 18 Aug 2016 18:51:44 +0900 | From | Sergey Senozhatsky <> | Subject | Re: [PATCH v10 1/2] printk: Make printk() completely async |
| |
On (08/18/16 11:33), Petr Mladek wrote: [..] > > > 2. Force synchronous printk inside WARN()/BUG() macros. > > > > will it help? semaphore up() calls wake_up_process() regardless the context. > > not to mention that we still may have spin_dump() enabled. > > Good point. That changes my preferences :-) > > > > > > 3. Force printk_deferred() inside WARN()/BUG() macros via the per-CPU > > > printk_func. > > > > > > It might be elegant. But we do not want this outside the scheduler > > > code. Therefore we would need special variants of WARN_*_SCHED() > > > BUG_*_SCHED() macros. > > Also we need to make sure that everything will be done on a single CPU > as the printk_func is per-CPU variable.
lib/dump_stack.c dump_stack() disables local IRQs, so we will stay on the same CPU.
schematically dump_stack_deferred() looks like the one below. I don't dump registers, that will require one more *_deferred() function. and as you can see I've replaced show_stack() with save_stack_trace(). it's not entirely universal (as of now), but worked for my needs at that time.
---
asmlinkage __visible void dump_stack_deferred(void) { unsigned long flags; unsigned long stack_trace[16]; int was_locked; int old, cpu; int i;
struct stack_trace trace = { .nr_entries = 0, .max_entries = ARRAY_SIZE(stack_trace), .entries = stack_trace, .skip = 0, };
local_irq_save(flags); retry: cpu = smp_processor_id(); old = atomic_cmpxchg(&dump_lock, -1, cpu); if (old == -1) { was_locked = 0; } else if (old == cpu) { was_locked = 1; } else { cpu_relax(); goto retry; }
save_stack_trace(&trace);
for (i = 0; i < trace.nr_entries; i++) { printk_deferred("[%p] %pS\n", (void *)stack_trace[i], (void *)stack_trace[i]); }
if (!was_locked) atomic_set(&dump_lock, -1);
local_irq_restore(flags); }
---
-ss
| |