Skip to content

Commit

Permalink
Merge pull request #14011 from maribu/tests_irq_disable_restore
Browse files Browse the repository at this point in the history
tests: Add test for irq_disable() / irq_restore()
  • Loading branch information
fjmolinas authored May 4, 2020
2 parents d03884d + 51c19d5 commit dbab3a6
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 0 deletions.
6 changes: 6 additions & 0 deletions tests/irq_disable_restore/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
include ../Makefile.tests_common

USEMODULE += fmt
USEMODULE += xtimer

include $(RIOTBASE)/Makefile.include
13 changes: 13 additions & 0 deletions tests/irq_disable_restore/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Test for `irq_disable()` and `irq_restore()`

This test checks if `irq_disable()` and `irq_restore()` work as intended. For
that, the test uses two variables *a* and *b*, both initialized with 0. The main
test will schedule a timer that expires in *T/2*. It will then set *a* to 1 and
waits for *T* until it also sets *b* to one. The expectation is that during the
ISR (the timer callback) *a* has a value of 1, but *b* still has a value of 0.

The test is repeated, but this time the main thread calls `irq_disable()`
before setting *a* and `irq_restore()` after setting *b*. It is now expected
that - even though the timer again expires after setting *a* and before setting
*b* - the execution of the ISR is delayed until `irq_restore()` is called. Thus,
both *a* and *b* should already contain the new value in the ISR.
99 changes: 99 additions & 0 deletions tests/irq_disable_restore/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (C) 2020 Otto-von-Guericke-Universität Magdeburg
*
* 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 irq_disable_restore test application
*
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
* @}
*/

#include <stdint.h>
#include <stdatomic.h>
#include <stdio.h>

#include "fmt.h"
#include "irq.h"
#include "xtimer.h"

#define DELAY (10 * US_PER_MS)

static atomic_uint a = ATOMIC_VAR_INIT(0);
static atomic_uint a_during_isr = ATOMIC_VAR_INIT(0);
static atomic_uint b = ATOMIC_VAR_INIT(0);
static atomic_uint b_during_isr = ATOMIC_VAR_INIT(0);

static void busy_delay(void)
{
uint32_t start = xtimer_now_usec();
while (xtimer_now_usec() - start < DELAY) { }
}

/* Timer callback run in interrupt context; should not trigger between
* irq_disable() and irq_restore()
*/
static void timer_callback(void *unused)
{
(void)unused;
atomic_store(&a_during_isr, atomic_load(&a));
atomic_store(&b_during_isr, atomic_load(&b));
}

int main(void)
{
xtimer_t xt = { .callback = timer_callback };

print_str("Test for irq_disable() / irq_restore()\n"
"======================================\n"
"\n");

print_str("Verifying test works: ");
xtimer_set(&xt, DELAY / 2);
atomic_store(&a, 1);
busy_delay();
atomic_store(&b, 1);

/* Timer should have fired in the middle of busy_delay(), thus value of
* a now and during ISR should both be 1, but value of b during ISR should
* still be 0 but not it should be 1 */
if ((atomic_load(&a) == atomic_load(&a_during_isr)) &&
(atomic_load(&b) != atomic_load(&b_during_isr)))
{
print_str("[SUCCESS]\n");
}
else {
print_str("[FAILURE]\n");
}

print_str("Test result: ");
xtimer_set(&xt, DELAY / 2);
unsigned state = irq_disable();
atomic_store(&a, 2);
busy_delay();
atomic_store(&b, 2);
irq_restore(state);

/* irq_disable() should have delayed execution of the timer until both
* a and b have been set to 2.
*/

if ((atomic_load(&a) == atomic_load(&a_during_isr)) &&
(atomic_load(&b) == atomic_load(&b_during_isr)))
{
print_str("[SUCCESS]\n");
}
else {
print_str("[FAILURE]\n");
}

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

# Copyright (C) 2020 Otto-von-Guericke-Universität Magdeburg
#
# 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("Verifying test works: [SUCCESS]")
child.expect_exact("Test result: [SUCCESS]")


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

0 comments on commit dbab3a6

Please sign in to comment.