This patch fixes a subtle bug found when working on lazy stack changes and trying to establish some invariants in relevant places in the kernel code. One of the findings was that the memory allocation logic or more specifically the functions malloc() and free() require both interrupts and preemption enabled to function correctly.
If one starts analysis with memory::pool::alloc(), he/she will notice a DROP_LOCK(preempt_lock) executed under WITH_LOCK(preempt) if the pool is empty. This means that the code assumes the preemption must be enabled before calling alloc(), otherwise the code in DROP_LOCK would run with preemption disabled which is contrary to the intention. Also, after drilling down the add_page() calling path, one eventually would find the call to reclaimers::wait() which calls thread::wait_until(). The thread::do_wait_until() called by the former enforces that both interrupts and preemption needs to be enabled with assertion. The bottom line of the analysis above is that both interrupts and preemption must be enabled before calling malloc() (same applies to free()). This effectively means that trying to call malloc() after disabling interrupts might not work (which would only happen if relevent pool was out of free pages AND l1 pool was empty and had to refill from l2 pool which probably is quite rare). So this patch changes the code in trace::create_trace_dump() to avoid calling new/malloc() (see copies.emplace_back()) and instead makes it preallocate the vector ahead of time and then simply copy the trace buffer to a relevant spot in the vector. Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com> --- core/trace.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/trace.cc b/core/trace.cc index 60fa18b9..dc69c807 100644 --- a/core/trace.cc +++ b/core/trace.cc @@ -697,7 +697,7 @@ std::string trace::create_trace_dump() { semaphore signal(0); - std::vector<trace_buf> copies; + std::vector<trace_buf> copies(sched::cpus.size()); auto is_valid_tracepoint = [](const tracepoint_base * tp_test) { for (auto & tp : tracepoint_base::tp_list) { @@ -717,7 +717,7 @@ trace::create_trace_dump() irq.save(); arch::irq_disable_notrace(); auto * tbp = percpu_trace_buffer.for_cpu(cpu); - copies.emplace_back(*tbp); + copies[i] = trace_buf(*tbp); irq.restore(); signal.post(); }, sched::thread::attr().pin(cpu))); -- 2.34.1 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to osv-dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/20220829011346.432532-1-jwkozaczuk%40gmail.com.