Hello,
I have a question of the call path init/main.c:
init/main.c: start_kernel() ->
kernel/events/core.c: perf_pmu_register() ->
kernel/events/core.c: perf_event_init() ->
kernel/events/core.c: pmu_dev_alloc()
In this call path, start_kernel() calls local_irq_disable() to disable
the interrupt;
perf_pmu_register() calls mutex_lock() and idr_alloc(GFP_KERNEL), and
they can sleep;
pmu_dev_alloc() calls kzalloc(GFP_KERNEL), and it can sleep.
In my opinion, this code may sleep with interrupts are disabled.
I wonder why this code is okay?
Best wishes,
Jia-Ju Bai
On Fri, 6 Apr 2018, Jia-Ju Bai wrote:
> Hello,
>
> I have a question of the call path init/main.c:
> init/main.c: start_kernel() ->
> kernel/events/core.c: perf_pmu_register() ->
> kernel/events/core.c: perf_event_init() ->
> kernel/events/core.c: pmu_dev_alloc()
>
> In this call path, start_kernel() calls local_irq_disable() to disable the
> interrupt;
> perf_pmu_register() calls mutex_lock() and idr_alloc(GFP_KERNEL), and they can
> sleep;
> pmu_dev_alloc() calls kzalloc(GFP_KERNEL), and it can sleep.
>
> In my opinion, this code may sleep with interrupts are disabled.
> I wonder why this code is okay?
Because this is the very early boot up stage where contention of the mutex
cannot happen and the allocations are all implicitely converted to atomic
allocations. If the mutex would be contended then the system would fail to
boot anyway. If the allocations fail at that stage, it's unlikely that the
machine will come up at all.
So yes, it looks odd, but we don't want to have duplicated code pathes just
for the early boot up and the debugging mechanisms are aware of that
situation and don't emit warnings. Once the scheduler is functional and the
early boot stage is done, these 'magic' violations are not longer allowed.
Hope that helps.
Thanks,
tglx