[XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1

Nicola Vetrini posted 11 patches 2 years, 6 months ago
[XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1
Posted by Nicola Vetrini 2 years, 6 months ago
The break statement after the return statement is definitely unreachable.
As such, an call to the ASSERT_UNREACHABLE() macro is added to signal
the intentionality of such construct.

Signed-off-by: Nicola Vetrini <nicola.vetrini@bugseng.com>
---
The break in the clause is mandated by Required Rule 16.3, which is
not yet an accepted rule for Xen, but may be in the future.
---
 xen/common/sched/core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/xen/common/sched/core.c b/xen/common/sched/core.c
index 022f548652..fcee902b4e 100644
--- a/xen/common/sched/core.c
+++ b/xen/common/sched/core.c
@@ -2233,6 +2233,7 @@ static bool sched_tasklet_check_cpu(unsigned int cpu)
         /* fallthrough */
     case TASKLET_enqueued|TASKLET_scheduled:
         return true;
+        ASSERT_UNREACHABLE();
         break;
     case TASKLET_scheduled:
         clear_bit(_TASKLET_scheduled, tasklet_work);
-- 
2.34.1
Re: [XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1
Posted by Julien Grall 2 years, 6 months ago
Hi,

On 02/08/2023 15:38, Nicola Vetrini wrote:
> The break statement after the return statement is definitely unreachable.
> As such, an call to the ASSERT_UNREACHABLE() macro is added to signal
> the intentionality of such construct.

How about using unreachable() rather than ASSERT_UNREACHABLE()? The main 
difference is the later will hint the compiler that the code cannot be 
reached and will not crash Xen in debug build (this could be changed).

> 
> Signed-off-by: Nicola Vetrini <nicola.vetrini@bugseng.com>
> ---
> The break in the clause is mandated by Required Rule 16.3, which is
> not yet an accepted rule for Xen, but may be in the future.
> ---
>   xen/common/sched/core.c | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/xen/common/sched/core.c b/xen/common/sched/core.c
> index 022f548652..fcee902b4e 100644
> --- a/xen/common/sched/core.c
> +++ b/xen/common/sched/core.c
> @@ -2233,6 +2233,7 @@ static bool sched_tasklet_check_cpu(unsigned int cpu)
>           /* fallthrough */
>       case TASKLET_enqueued|TASKLET_scheduled:
>           return true;
> +        ASSERT_UNREACHABLE();
>           break;
>       case TASKLET_scheduled:
>           clear_bit(_TASKLET_scheduled, tasklet_work);

Cheers,

-- 
Julien Grall
Re: [XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1
Posted by Jan Beulich 2 years, 6 months ago
On 08.08.2023 17:25, Julien Grall wrote:
> On 02/08/2023 15:38, Nicola Vetrini wrote:
>> The break statement after the return statement is definitely unreachable.
>> As such, an call to the ASSERT_UNREACHABLE() macro is added to signal
>> the intentionality of such construct.
> 
> How about using unreachable() rather than ASSERT_UNREACHABLE()? The main 
> difference is the later will hint the compiler that the code cannot be 
> reached and will not crash Xen in debug build (this could be changed).

Isn't using unreachable() in place of ASSERT_UNREACHABLE() unsafe (not
here but in general)? It'll tell the compiler that (in the extreme case)
it can omit the function epilogue, including the return instruction. In
the resulting build, if the code turns out to be reachable, execution
would fall through into whatever follows.

In the case here ...

>> --- a/xen/common/sched/core.c
>> +++ b/xen/common/sched/core.c
>> @@ -2233,6 +2233,7 @@ static bool sched_tasklet_check_cpu(unsigned int cpu)
>>           /* fallthrough */
>>       case TASKLET_enqueued|TASKLET_scheduled:
>>           return true;
>> +        ASSERT_UNREACHABLE();
>>           break;
>>       case TASKLET_scheduled:
>>           clear_bit(_TASKLET_scheduled, tasklet_work);

... "return" alone already tells the compiler that "break" is
unreachable. You don't need unreachable() for that. As said before,
"break" like this simply want purging (and Misra is wrong to demand
"break" everywhere - it should instead demand no [unannotated]
fall-through, which can also be achieved by return, continue, and
goto).

Jan
Re: [XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1
Posted by Julien Grall 2 years, 6 months ago
Hi,

On 08/08/2023 16:36, Jan Beulich wrote:
> On 08.08.2023 17:25, Julien Grall wrote:
>> On 02/08/2023 15:38, Nicola Vetrini wrote:
>>> The break statement after the return statement is definitely unreachable.
>>> As such, an call to the ASSERT_UNREACHABLE() macro is added to signal
>>> the intentionality of such construct.
>>
>> How about using unreachable() rather than ASSERT_UNREACHABLE()? The main
>> difference is the later will hint the compiler that the code cannot be
>> reached and will not crash Xen in debug build (this could be changed).
> 
> Isn't using unreachable() in place of ASSERT_UNREACHABLE() unsafe (not
> here but in general)?

Yes it is.

  It'll tell the compiler that (in the extreme case)
> it can omit the function epilogue, including the return instruction. In
> the resulting build, if the code turns out to be reachable, execution
> would fall through into whatever follows.

Right, but the problem is somewhat similar with adding 
ASSERT_UNREACHABLE() without proper error path because there is no 
guarantee the rest of the code will be correct in the unlikely case it 
is reachable.

> 
> In the case here ...
> 
>>> --- a/xen/common/sched/core.c
>>> +++ b/xen/common/sched/core.c
>>> @@ -2233,6 +2233,7 @@ static bool sched_tasklet_check_cpu(unsigned int cpu)
>>>            /* fallthrough */
>>>        case TASKLET_enqueued|TASKLET_scheduled:
>>>            return true;
>>> +        ASSERT_UNREACHABLE();
>>>            break;
>>>        case TASKLET_scheduled:
>>>            clear_bit(_TASKLET_scheduled, tasklet_work);
> 
> ... "return" alone already tells the compiler that "break" is
> unreachable. You don't need unreachable() for that. As said before,
> "break" like this simply want purging (and Misra is wrong to demand
> "break" everywhere - it should instead demand no [unannotated]
> fall-through, which can also be achieved by return, continue, and
> goto).

My suggestion was in the context of this series where we add 
ASSERT_UNREACHABLE() before break. From my understanding, we don't have 
a lot of leeway here because, from what Nicola wrote, rule 16.3 is 
mandatory.

So I think using unreachable is better if we every decide to use break 
after return.

Cheers,

-- 
Julien Grall
Re: [XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1
Posted by Nicola Vetrini 2 years, 6 months ago
>> 
>> ... "return" alone already tells the compiler that "break" is
>> unreachable. You don't need unreachable() for that. As said before,
>> "break" like this simply want purging (and Misra is wrong to demand
>> "break" everywhere - it should instead demand no [unannotated]
>> fall-through, which can also be achieved by return, continue, and
>> goto).
> 
> My suggestion was in the context of this series where we add
> ASSERT_UNREACHABLE() before break. From my understanding, we don't
> have a lot of leeway here because, from what Nicola wrote, rule 16.3
> is mandatory.
> 
> So I think using unreachable is better if we every decide to use break
> after return.
> 
> Cheers,

16.3 is not Mandatory, just Required. I was just reluctant to knowingly 
add one more violation
while fixing another before submitting the patch. If indeed 16.3 won't 
likely be adopted by Xen,
then that break should indeed go away.

However, the main thing that's holding me back from doing a slimmed-down 
v2 here is that
evidently there's no consensus even on the ASSERT_UNREACHABLE() patches.

-- 
Nicola Vetrini, BSc
Software Engineer, BUGSENG srl (https://bugseng.com)
Re: [XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1
Posted by Julien Grall 2 years, 6 months ago

On 08/08/2023 16:53, Nicola Vetrini wrote:
> 
>>>
>>> ... "return" alone already tells the compiler that "break" is
>>> unreachable. You don't need unreachable() for that. As said before,
>>> "break" like this simply want purging (and Misra is wrong to demand
>>> "break" everywhere - it should instead demand no [unannotated]
>>> fall-through, which can also be achieved by return, continue, and
>>> goto).
>>
>> My suggestion was in the context of this series where we add
>> ASSERT_UNREACHABLE() before break. From my understanding, we don't
>> have a lot of leeway here because, from what Nicola wrote, rule 16.3
>> is mandatory.
>>
>> So I think using unreachable is better if we every decide to use break
>> after return.
>>
>> Cheers,
> 
> 16.3 is not Mandatory, just Required.

Ah I misread what you wrote. In that case...

> I was just reluctant to knowingly 
> add one more violation
> while fixing another before submitting the patch. If indeed 16.3 won't 
> likely be adopted by Xen,
> then that break should indeed go away.
> 
> However, the main thing that's holding me back from doing a slimmed-down 
> v2 here is that
> evidently there's no consensus even on the ASSERT_UNREACHABLE() patches.

... I agree with the following statement from Jan:

"it should instead demand no [unannotated] fall-through, which can also 
be achieved by return, continue, and goto"

Cheers,

-- 
Julien Grall
Re: [XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1
Posted by Stefano Stabellini 2 years, 6 months ago
On Tue, 8 Aug 2023, Julien Grall wrote:
> On 08/08/2023 16:53, Nicola Vetrini wrote:
> > > > ... "return" alone already tells the compiler that "break" is
> > > > unreachable. You don't need unreachable() for that. As said before,
> > > > "break" like this simply want purging (and Misra is wrong to demand
> > > > "break" everywhere - it should instead demand no [unannotated]
> > > > fall-through, which can also be achieved by return, continue, and
> > > > goto).
> > > 
> > > My suggestion was in the context of this series where we add
> > > ASSERT_UNREACHABLE() before break. From my understanding, we don't
> > > have a lot of leeway here because, from what Nicola wrote, rule 16.3
> > > is mandatory.
> > > 
> > > So I think using unreachable is better if we every decide to use break
> > > after return.
> > > 
> > > Cheers,
> > 
> > 16.3 is not Mandatory, just Required.
> 
> Ah I misread what you wrote. In that case...
> 
> > I was just reluctant to knowingly add one more violation
> > while fixing another before submitting the patch. If indeed 16.3 won't
> > likely be adopted by Xen,
> > then that break should indeed go away.
> > 
> > However, the main thing that's holding me back from doing a slimmed-down v2
> > here is that
> > evidently there's no consensus even on the ASSERT_UNREACHABLE() patches.
> 
> ... I agree with the following statement from Jan:
> 
> "it should instead demand no [unannotated] fall-through, which can also be
> achieved by return, continue, and goto"

I also think it is a better idea to have no unannotated fall-through in
switch statements (unless we have a "case" with nothing underneath, so
two cases next to each other). In other words the following are all OK
in my view:

  case A:
    do();
    break;
  case B:
    do();
    return true;
  case Ca:
  case Cb:
    goto fail;
  case D:
    i++;
    continue;
  case E:
    do();
    /* fall-through */
  case F:
    do();
    break;

While the following is not OK:

  case A:
    do();
  case B:
    do();

This should be what we already do in Xen, although it is not documented
properly. Jan, Julien do you agree?

If so, could Eclair be configured to check for this pattern (or
similar)?

We must have one of the following:
- break, continue, return, goto
- /* fall-through */
- empty case body (case Ca/Cb)
Re: [XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1
Posted by Julien Grall 2 years, 6 months ago
Hi Stefano,

On 08/08/2023 22:14, Stefano Stabellini wrote:
> On Tue, 8 Aug 2023, Julien Grall wrote:
>> On 08/08/2023 16:53, Nicola Vetrini wrote:
>>>>> ... "return" alone already tells the compiler that "break" is
>>>>> unreachable. You don't need unreachable() for that. As said before,
>>>>> "break" like this simply want purging (and Misra is wrong to demand
>>>>> "break" everywhere - it should instead demand no [unannotated]
>>>>> fall-through, which can also be achieved by return, continue, and
>>>>> goto).
>>>>
>>>> My suggestion was in the context of this series where we add
>>>> ASSERT_UNREACHABLE() before break. From my understanding, we don't
>>>> have a lot of leeway here because, from what Nicola wrote, rule 16.3
>>>> is mandatory.
>>>>
>>>> So I think using unreachable is better if we every decide to use break
>>>> after return.
>>>>
>>>> Cheers,
>>>
>>> 16.3 is not Mandatory, just Required.
>>
>> Ah I misread what you wrote. In that case...
>>
>>> I was just reluctant to knowingly add one more violation
>>> while fixing another before submitting the patch. If indeed 16.3 won't
>>> likely be adopted by Xen,
>>> then that break should indeed go away.
>>>
>>> However, the main thing that's holding me back from doing a slimmed-down v2
>>> here is that
>>> evidently there's no consensus even on the ASSERT_UNREACHABLE() patches.
>>
>> ... I agree with the following statement from Jan:
>>
>> "it should instead demand no [unannotated] fall-through, which can also be
>> achieved by return, continue, and goto"
> 
> I also think it is a better idea to have no unannotated fall-through in
> switch statements (unless we have a "case" with nothing underneath, so
> two cases next to each other). In other words the following are all OK
> in my view:
> 
>    case A:
>      do();
>      break;
>    case B:
>      do();
>      return true;
>    case Ca:
>    case Cb:
>      goto fail;
>    case D:
>      i++;
>      continue;
>    case E:
>      do();
>      /* fall-through */
>    case F:
>      do();
>      break;
> 
> While the following is not OK:
> 
>    case A:
>      do();
>    case B:
>      do();
> 
> This should be what we already do in Xen, although it is not documented
> properly. Jan, Julien do you agree?

I agree.

Cheers,

-- 
Julien Grall
Re: [XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1
Posted by Jan Beulich 2 years, 6 months ago
On 08.08.2023 23:14, Stefano Stabellini wrote:
> On Tue, 8 Aug 2023, Julien Grall wrote:
>> On 08/08/2023 16:53, Nicola Vetrini wrote:
>>>>> ... "return" alone already tells the compiler that "break" is
>>>>> unreachable. You don't need unreachable() for that. As said before,
>>>>> "break" like this simply want purging (and Misra is wrong to demand
>>>>> "break" everywhere - it should instead demand no [unannotated]
>>>>> fall-through, which can also be achieved by return, continue, and
>>>>> goto).
>>>>
>>>> My suggestion was in the context of this series where we add
>>>> ASSERT_UNREACHABLE() before break. From my understanding, we don't
>>>> have a lot of leeway here because, from what Nicola wrote, rule 16.3
>>>> is mandatory.
>>>>
>>>> So I think using unreachable is better if we every decide to use break
>>>> after return.
>>>>
>>>> Cheers,
>>>
>>> 16.3 is not Mandatory, just Required.
>>
>> Ah I misread what you wrote. In that case...
>>
>>> I was just reluctant to knowingly add one more violation
>>> while fixing another before submitting the patch. If indeed 16.3 won't
>>> likely be adopted by Xen,
>>> then that break should indeed go away.
>>>
>>> However, the main thing that's holding me back from doing a slimmed-down v2
>>> here is that
>>> evidently there's no consensus even on the ASSERT_UNREACHABLE() patches.
>>
>> ... I agree with the following statement from Jan:
>>
>> "it should instead demand no [unannotated] fall-through, which can also be
>> achieved by return, continue, and goto"
> 
> I also think it is a better idea to have no unannotated fall-through in
> switch statements (unless we have a "case" with nothing underneath, so
> two cases next to each other). In other words the following are all OK
> in my view:
> 
>   case A:
>     do();
>     break;
>   case B:
>     do();
>     return true;
>   case Ca:
>   case Cb:
>     goto fail;
>   case D:
>     i++;
>     continue;
>   case E:
>     do();
>     /* fall-through */
>   case F:
>     do();
>     break;
> 
> While the following is not OK:
> 
>   case A:
>     do();
>   case B:
>     do();
> 
> This should be what we already do in Xen, although it is not documented
> properly. Jan, Julien do you agree?

Yes.

> If so, could Eclair be configured to check for this pattern (or
> similar)?
> 
> We must have one of the following:
> - break, continue, return, goto
> - /* fall-through */

- fallthrough;

(the pseudo keyword that we have; see compiler.h for actually having the
documentation you're looking for, albeit missing "continue", and of
course not really expected to live [just] there)

Jan

> - empty case body (case Ca/Cb)
Re: [XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1
Posted by Jan Beulich 2 years, 6 months ago
On 02.08.2023 16:38, Nicola Vetrini wrote:
> --- a/xen/common/sched/core.c
> +++ b/xen/common/sched/core.c
> @@ -2233,6 +2233,7 @@ static bool sched_tasklet_check_cpu(unsigned int cpu)
>          /* fallthrough */
>      case TASKLET_enqueued|TASKLET_scheduled:
>          return true;
> +        ASSERT_UNREACHABLE();
>          break;

What use is "break" after "return"? IOW rather than adding code here,
imo a line wants removing.

Jan
Re: [XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1
Posted by Nicola Vetrini 2 years, 6 months ago
On 03/08/2023 11:17, Jan Beulich wrote:
> On 02.08.2023 16:38, Nicola Vetrini wrote:
>> --- a/xen/common/sched/core.c
>> +++ b/xen/common/sched/core.c
>> @@ -2233,6 +2233,7 @@ static bool sched_tasklet_check_cpu(unsigned int 
>> cpu)
>>          /* fallthrough */
>>      case TASKLET_enqueued|TASKLET_scheduled:
>>          return true;
>> +        ASSERT_UNREACHABLE();
>>          break;
> 
> What use is "break" after "return"? IOW rather than adding code here,
> imo a line wants removing.
> 
> Jan

The "return false" after the switch would still be unreachable. The 
reasoning behind preserving the break
is mainly MISRA Rule 16.3: "An unconditional break statement shall 
terminate every switch-clause", which has
not yet been considered for adoption, but might be in future 
discussions, leading to putting back the break here.

-- 
Nicola Vetrini, BSc
Software Engineer, BUGSENG srl (https://bugseng.com)
Re: [XEN PATCH 10/11] xen/sched: add ASSERT_UNREACHABLE() to address MISRA C:2012 Rule 2.1
Posted by Jan Beulich 2 years, 6 months ago
On 07.08.2023 10:13, Nicola Vetrini wrote:
> On 03/08/2023 11:17, Jan Beulich wrote:
>> On 02.08.2023 16:38, Nicola Vetrini wrote:
>>> --- a/xen/common/sched/core.c
>>> +++ b/xen/common/sched/core.c
>>> @@ -2233,6 +2233,7 @@ static bool sched_tasklet_check_cpu(unsigned int 
>>> cpu)
>>>          /* fallthrough */
>>>      case TASKLET_enqueued|TASKLET_scheduled:
>>>          return true;
>>> +        ASSERT_UNREACHABLE();
>>>          break;
>>
>> What use is "break" after "return"? IOW rather than adding code here,
>> imo a line wants removing.
> 
> The "return false" after the switch would still be unreachable. The 
> reasoning behind preserving the break
> is mainly MISRA Rule 16.3: "An unconditional break statement shall 
> terminate every switch-clause", which has
> not yet been considered for adoption, but might be in future 
> discussions, leading to putting back the break here.

Well, adding such bogus "break"s is going to face my opposition, and
it is in direct conflict with the "no unreachable code" rule here.

Jan