Skip to content

Commit

Permalink
Merge pull request #16754 from kaspar030/native_deferred_yield_higher
Browse files Browse the repository at this point in the history
cpu/native: fix thread_yield_higher() with IRQs disabled
  • Loading branch information
kaspar030 authored Aug 25, 2021
2 parents dde4772 + fe1d998 commit da140c2
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 4 deletions.
5 changes: 5 additions & 0 deletions cpu/native/irq_cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,11 @@ unsigned irq_enable(void)

_native_syscall_leave();

if (_native_in_isr == 0 && sched_context_switch_request) {
DEBUG("irq_enable() deferred thread_yield_higher()\n");
thread_yield_higher();
}

DEBUG("irq_enable(): return\n");

return prev_state;
Expand Down
5 changes: 1 addition & 4 deletions cpu/native/native_cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,9 @@ void thread_yield_higher(void)
{
sched_context_switch_request = 1;

if (_native_in_isr == 0) {
if (_native_in_isr == 0 && native_interrupts_enabled) {
ucontext_t *ctx = (ucontext_t *)(thread_get_active()->sp);
_native_in_isr = 1;
if (!native_interrupts_enabled) {
warnx("thread_yield_higher: interrupts are disabled - this should not be");
}
irq_disable();
native_isr_context.uc_stack.ss_sp = __isr_stack;
native_isr_context.uc_stack.ss_size = SIGSTKSZ;
Expand Down
5 changes: 5 additions & 0 deletions tests/deferred_yield_higher/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include ../Makefile.tests_common

FEATURES_BLACKLIST += arch_avr8 arch_msp430 arch_riscv arch_mips32r2

include $(RIOTBASE)/Makefile.include
3 changes: 3 additions & 0 deletions tests/deferred_yield_higher/Makefile.ci
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
BOARD_INSUFFICIENT_MEMORY := \
nucleo-l011k4 \
#
14 changes: 14 additions & 0 deletions tests/deferred_yield_higher/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Introduction
============

This test verifies that a thread can call "thread_yield_higher()" with IRQs
disabled, and that the actual context switch is deferred until IRQs are
re-enabled.

For the test to be successful, the printed messages must be in order, as follows:

```
1. post yield
2. second thread scheduled
3. post irq enable
```
52 changes: 52 additions & 0 deletions tests/deferred_yield_higher/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2021 Inria
* 2021 Freie Universität Berlin
* 2021 Kaspar Schleiser <kaspar@schleiser.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @ingroup tests
* @{
*
* @file
* @brief Application for testing thread_yield_higher() with IRQs disabled
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*
* @}
*/

#include <stdio.h>
#include "irq.h"
#include "thread.h"

static char t2_stack[THREAD_STACKSIZE_DEFAULT];

static void *second_thread(void *arg)
{
puts("2. second thread scheduled");
return arg;
}

int main(void)
{
thread_create(
t2_stack, sizeof(t2_stack),
THREAD_PRIORITY_MAIN - 1,
THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST,
second_thread, NULL, "nr2");

irq_disable();
thread_yield_higher();
puts("1. post yield");
irq_enable();
puts("3. post irq enable");

puts("if above messages are in order, this test succeeded.");

return 0;
}
20 changes: 20 additions & 0 deletions tests/deferred_yield_higher/tests/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env python3

# Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de>
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.

import sys
from testrunner import run


def testfunc(child):
child.expect_exact('1. post yield')
child.expect_exact('2. second thread scheduled')
child.expect_exact('3. post irq enable')


if __name__ == "__main__":
sys.exit(run(testfunc))

0 comments on commit da140c2

Please sign in to comment.