Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: Add test for irq_disable() / irq_restore() #14011

Merged
merged 1 commit into from
May 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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))