On Wed, Sep 30, 2020 at 09:02:28PM +0200, Peter Zijlstra wrote: > On Wed, Sep 30, 2020 at 08:18:18PM +0800, Boqun Feng wrote: > > > For one thing, I do think that LOCK_READ_USED trace is helpful for > > better reporting, because if there is a read lock in the dependency path > > which causes the deadlock, it's better to have the LOCK_READ_USED trace > > to know at least the initial READ usage. For example, if we have > > > > void f1(...) > > { > > write_lock(&A); > > spin_lock(&C); > > // A -> C > > ... > > } > > > > void g(...) > > { > > read_lock(&A); > > ... > > } > > void f2(...) > > { > > spin_lock(&B); > > g(...); > > // B -> A > > } > > > > void f3(...) { > > spin_lock(&C); > > spin_lock(&B); > > // C -> B, trigger lockdep splat > > } > > > > when lockdep reports the deadlock (at the time f3() is called), it will > > be useful if we have a trace like: > > > > INITIAL READ usage at: > > g+0x.../0x... > > f2+0x.../0x... > > > > Thoughts? > > Wouldn't that also be in LOCK_ENABLED_*_READ ? >
But what if f2() is called with interrupt disabled? Or f2() disables interrupt inside the function, like: void f2(...) { local_irq_disable(); spin_lock(&B); g(...); ... local_irq_enable(); } In this case, there wouldn't be any LOCK_ENABLED_*_READ usage for rwlock_t A. As a result, we won't see it in the lockdep splat. Regards, Boqun > That is, with PROVE_LOCKING on, the initial usage is bound to set more > states, except for !check||trylock usage, and those aren't really all > that interesting.