-
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.
tests: Add another test for atomic_utils
This tests can be used to test for implementations violating atomic attribute.
- Loading branch information
Showing
6 changed files
with
1,694 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,9 @@ | ||
include ../Makefile.tests_common | ||
|
||
USEMODULE += atomic_utils | ||
USEMODULE += fmt | ||
USEMODULE += random | ||
USEMODULE += shell | ||
USEMODULE += xtimer | ||
|
||
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,10 @@ | ||
BOARD_INSUFFICIENT_MEMORY := \ | ||
arduino-duemilanove \ | ||
arduino-leonardo \ | ||
arduino-nano \ | ||
arduino-uno \ | ||
atmega328p \ | ||
nucleo-f031k6 \ | ||
nucleo-l011k4 \ | ||
stm32f030f4-demo \ | ||
# |
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,87 @@ | ||
# Test Application for `sys/atomic_utils` | ||
|
||
## Design of the Test | ||
|
||
This test application will launch one worker and one tester thread. The | ||
worker thread will perform a specific operation (such as | ||
`atomic_fetch_add_u32()`) over and over again on a single target variable, and | ||
the tester thread occasionally interrupts to verify the target variable's value | ||
is valid. If the variable has corrupted, this is reported. | ||
|
||
This test works only *statistically*. Absence of detected corruption does not | ||
guarantee, that a specific function indeed works correctly. (But a detected | ||
corruptions guarantees that something is indeed broken.) However, the longer | ||
the tests runs the higher the odds are that a malfunctioning implementation is | ||
indeed caught corrupting memory. | ||
|
||
## Types of Corruptions Tested For | ||
|
||
### Lost Update | ||
|
||
In the lost update the worker thread will perform an operation that has no | ||
effect (addition, subtraction, binary or, and binary xor with `0` as | ||
second parameter, or binary and with `0xff...`). The checker thread will | ||
atomically increment the target value. If in the next iteration the of the | ||
checker thread the value has changed, a corruption is detected. This could | ||
happen e.g. by | ||
|
||
``` | ||
Worker Thread | Checker Thread | Value of t | ||
| | | ||
| t++ | 1 | ||
reg1 = t | | 1 | ||
reg1 += 0 | | 1 | ||
| t++ | 2 | ||
t = reg1 | | 1 | ||
``` | ||
|
||
Here, the read-modify-write sequence (`reg1 = t; reg1 += 0; t = reg1;`) has | ||
been interrupted by the Checker Thread. The update of `t` (the atomic `t++` | ||
operation) is afterwards lost, when the Worker Thread writes `reg1` into | ||
`t`. Such a lost update proves that the read-modify-write operation was not | ||
atomic. | ||
|
||
Note: Only the `atomic_<op>_u<width>` family of functions must pass this test. | ||
A failure for the other families does ***not*** indicate an issue. | ||
|
||
### Store Tearing | ||
|
||
In the tearing test the worker thread will first initialize the target variable, | ||
e.g. with zero. Then, a sequence of read-modify-write operations is performed, | ||
e.g. 3 times `atomic_fetch_add_u16(&target, 0x5555)`. During this sequence, only | ||
the target variable should contain on of the following values: | ||
`0x0000`, `0x5555`, `0xaaaa`, and `0xffff`. | ||
|
||
After each sequence is complete, the target variable will be atomically | ||
re-initialized and the next sequence starts. If e.g. on AVR the write is | ||
interrupted after only one byte is written (AVR is an 8-bit platform and only | ||
can write 8 bits per store), e.g. a value of `0x55aa` or `0xaa55` might be | ||
stored in the target variable. If such an value is observed, an atomic store | ||
operation was torn apart into two parts and a memory corruption was detected. | ||
|
||
Note: Both the `atomic_<op>_u<width>` and `semi_atomic_<op>_u<width>` families | ||
of functions must pass this test. A failure of the | ||
`volatile_<op>_u<width>` family of functions does ***not*** indicate an | ||
issue. | ||
|
||
## Usage | ||
|
||
The test will drop you into a shell. The welcome message and the help command | ||
contain all information on how to use the test. In addition, `make test` will | ||
run all tests that are expected to pass for one second each. This is hopefully | ||
long enough to detect any issues. It is certainly not possible to run the test | ||
longer in automated tests. | ||
|
||
## Test Self Check | ||
|
||
The test brings an alternative implementation of the `atomic_<op>_u<width>` | ||
family of functions called `volatile_<op>_u<width>`. This implementation | ||
incorrectly assumes that `volatile` provides atomic access. Thus, checking | ||
this implementation should result in failures: | ||
|
||
- The lost update test is expected to (eventually) fail for every platform | ||
- The tearing test is expected for width bigger than the word size | ||
- Cortex-M7 is one exception: Due to instruction fusion two 32 bit writes | ||
can be issued in one CPU cycle, so that a 64 bit write can indeed be | ||
atomic for this platform. Thus, it could happen that no tearing failure | ||
is detected for the `volatile` implementation on Cortex-M7 at all. |
Oops, something went wrong.