2019-02-05 19:02:35

by Denys Vlasenko

[permalink] [raw]
Subject: preempt.h: some SOFTIRQ_OFFSET should be SOFTIRQ_MASK?

SOFTIRQ is a counter.
Why here:

#define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET)
#define in_task() (!(preempt_count() & \
(NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET)))

we check only lowest bit?


2019-02-13 09:20:05

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: preempt.h: some SOFTIRQ_OFFSET should be SOFTIRQ_MASK?

On Tue, Feb 05, 2019 at 07:34:31PM +0100, Denys Vlasenko wrote:
> SOFTIRQ is a counter.
> Why here:
>
> #define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET)
> #define in_task() (!(preempt_count() & \
> (NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET)))
>
> we check only lowest bit?

So we have SOFTIRQ_OFFSET that is used when serving softirqs.
And we have SOFTIRQ_DISABLE_OFFSET that is used when we disable
softirqs.

I think the choice is right on both tests above, or am I missing something?

2019-02-13 13:45:45

by Denys Vlasenko

[permalink] [raw]
Subject: Re: preempt.h: some SOFTIRQ_OFFSET should be SOFTIRQ_MASK?

On Wed, Feb 13, 2019 at 5:05 AM Frederic Weisbecker <[email protected]> wrote:
> On Tue, Feb 05, 2019 at 07:34:31PM +0100, Denys Vlasenko wrote:
> > SOFTIRQ is a counter.
> > Why here:
> >
> > #define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET)
> > #define in_task() (!(preempt_count() & \
> > (NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET)))
> >
> > we check only lowest bit?
>
> So we have SOFTIRQ_OFFSET that is used when serving softirqs.
> And we have SOFTIRQ_DISABLE_OFFSET that is used when we disable
> softirqs.
>
> I think the choice is right on both tests above, or am I missing something?

From my reading of the following:

* We put the hardirq and softirq counter into the preemption
* counter. The bitmask has the following meaning:
* - bits 0-7 are the preemption count (max preemption depth: 256)
* - bits 8-15 are the softirq count (max # of softirqs: 256)
* The hardirq count could in theory be the same as the number of
* interrupts in the system, but we run all interrupt handlers with
* interrupts disabled, so we cannot have nesting interrupts. Though
* there are a few palaeontologic drivers which reenable interrupts in
* the handler, so we need more than one bit here.
* PREEMPT_MASK: 0x000000ff
* SOFTIRQ_MASK: 0x0000ff00
* HARDIRQ_MASK: 0x000f0000
* NMI_MASK: 0x00100000
* PREEMPT_NEED_RESCHED: 0x80000000
*/
#define PREEMPT_BITS 8
#define SOFTIRQ_BITS 8
#define HARDIRQ_BITS 4
#define NMI_BITS 1

it seems that 8-bit SOFTIRQ_MASK contains depth count of nested softirqs.
Therefore, to test whether we are in softirq, you need:

define in_serving_softirq() (softirq_count() & SOFTIRQ_MASK)

But existing code uses SOFTIRQ_OFFSET, not SOFTIRQ_MASK, for the mask.
This means that if nest count is e.g. 2, in_serving_softirq() will return
"false".