-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10908 from miri64/tests/new/i10881
tests: add tests to reproduce #10881
- Loading branch information
Showing
3 changed files
with
150 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
DEVELHELP := 1 | ||
|
||
include ../Makefile.tests_common | ||
|
||
BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-nano arduino-uno \ | ||
nucleo-f031k6 | ||
|
||
DISABLE_MODULE += auto_init | ||
FEATURES_REQUIRED += periph_timer | ||
USEMODULE += random | ||
|
||
TEST_ON_CI_WHITELIST += all | ||
|
||
include $(RIOTBASE)/Makefile.include |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* Copyright (C) 2019 Freie Universität Berlin | ||
* | ||
* 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 Thread race condition test application to reproduce | ||
* https://github.com/RIOT-OS/RIOT/issues/10881 | ||
* | ||
* @author Martine Lenders <[email protected]> | ||
* | ||
* @} | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <unistd.h> | ||
|
||
#include "periph/timer.h" | ||
#include "random.h" | ||
#include "thread.h" | ||
#include "msg.h" | ||
|
||
#define CANARY_TYPE (0x21fd) | ||
|
||
#define TIMER_FREQ (1000000LU) | ||
#define TIMER_TIMEOUT_MIN (1U) | ||
#define TIMER_TIMEOUT_MAX (100U) | ||
|
||
static char _stack[THREAD_STACKSIZE_DEFAULT]; | ||
|
||
static kernel_pid_t _pid_main = KERNEL_PID_UNDEF; | ||
|
||
/** | ||
* @brief Schedule next timer event in TIMER_TIMEOUT_MIN to TIMER_TIMEOUT_MAX | ||
* ticks. | ||
*/ | ||
static void _sched_next(void) | ||
{ | ||
timer_set(TIMER_DEV(0), 0, random_uint32_range(TIMER_TIMEOUT_MIN, | ||
TIMER_TIMEOUT_MAX)); | ||
} | ||
|
||
/** | ||
* @brief The timer interrupt | ||
*/ | ||
static void _timer(void *arg, int channel) | ||
{ | ||
(void)arg; | ||
(void)channel; | ||
/* just continue rescheduling interrupt triggering at random time */ | ||
_sched_next(); | ||
} | ||
|
||
/** | ||
* @brief The sending thread | ||
*/ | ||
static void *_thread(void *arg) | ||
{ | ||
(void) arg; | ||
|
||
while (1) { | ||
msg_t msg = { .type = 0U }; | ||
|
||
write(STDOUT_FILENO, ".", 1U); | ||
/* send without blocking */ | ||
msg_try_send(&msg, _pid_main); | ||
thread_yield(); | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
int main(void) | ||
{ | ||
kernel_pid_t pid; | ||
|
||
timer_init(TIMER_DEV(0), TIMER_FREQ, _timer, NULL); | ||
random_init(timer_read(TIMER_DEV(0))); | ||
puts("Test is \"successful\" if it runs forever without halting\n" | ||
"on any of the assertion in this file\n"); | ||
_pid_main = sched_active_pid; | ||
|
||
puts("I will try to trigger an interrupt at random intervals. When an\n" | ||
"interrupt is fired while ISR is disable in the thread_yield_higher()\n" | ||
"function some platform-specific implementations used to not call\n" | ||
"sched_run() which was the cause of the bug tested here"); | ||
_sched_next(); | ||
pid = thread_create(_stack, sizeof(_stack), THREAD_PRIORITY_MAIN + 1, | ||
THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST, | ||
_thread, NULL, "nr2"); | ||
assert(pid != KERNEL_PID_UNDEF); | ||
|
||
while (1) { | ||
msg_t msg = { .type = CANARY_TYPE }; | ||
|
||
/* receive blocked */ | ||
msg_receive(&msg); | ||
/* check msg_receive() returned without blocking (i.e. the sending | ||
* thread did not get a chance to copy the message over) */ | ||
if (msg.type == CANARY_TYPE) { | ||
puts("Message was not written"); | ||
return 1; | ||
} | ||
write(STDOUT_FILENO, "\b", 1U); | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# Copyright (C) 2019 Freie Universität Berlin | ||
# | ||
# 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 | ||
from pexpect import TIMEOUT | ||
|
||
|
||
def testfunc(child): | ||
res = child.expect([TIMEOUT, "Message was not written"]) | ||
# we actually want the timeout here. The application runs into an assertion | ||
# pretty quickly when failing and runs forever on success | ||
assert(res == 0) | ||
|
||
|
||
if __name__ == "__main__": | ||
sys.exit(run(testfunc, timeout=10)) |