
4 changed files with 231 additions and 0 deletions
@ -0,0 +1,6 @@
|
||||
APPLICATION = rmutex
|
||||
include ../Makefile.tests_common |
||||
|
||||
BOARD_INSUFFICIENT_MEMORY := stm32f0discovery weio nucleo-f030 nucleo32-f042
|
||||
|
||||
include $(RIOTBASE)/Makefile.include |
@ -0,0 +1,86 @@
|
||||
Expected result |
||||
=============== |
||||
|
||||
When successful, you should see 5 different threads printing their |
||||
PID, priority and recursion depth. The thread with the lowest priority |
||||
should be able to lock (and unlock) the mutex first, followed by the |
||||
other threads in the order of their priority (highest next). If two |
||||
threads have the same priority the lower thread id should acquire the |
||||
lock. The output should look like the following: |
||||
|
||||
``` |
||||
main(): This is RIOT! (Version: xxx) |
||||
Recursive Mutex test |
||||
Please refer to the README.md for more information |
||||
|
||||
Recursive Mutex test |
||||
Please refer to the README.md for more information |
||||
|
||||
T3 (prio 6, depth 0): trying to lock rmutex now |
||||
T4 (prio 4, depth 0): trying to lock rmutex now |
||||
T5 (prio 5, depth 0): trying to lock rmutex now |
||||
T6 (prio 2, depth 0): trying to lock rmutex now |
||||
T7 (prio 3, depth 0): trying to lock rmutex now |
||||
main: unlocking recursive mutex |
||||
T6 (prio 2, depth 0): locked rmutex now |
||||
T6 (prio 2, depth 1): trying to lock rmutex now |
||||
T6 (prio 2, depth 1): locked rmutex now |
||||
T6 (prio 2, depth 2): trying to lock rmutex now |
||||
T6 (prio 2, depth 2): locked rmutex now |
||||
T6 (prio 2, depth 3): trying to lock rmutex now |
||||
T6 (prio 2, depth 3): locked rmutex now |
||||
T6 (prio 2, depth 3): unlocked rmutex |
||||
T6 (prio 2, depth 2): unlocked rmutex |
||||
T6 (prio 2, depth 1): unlocked rmutex |
||||
T6 (prio 2, depth 0): unlocked rmutex |
||||
T7 (prio 3, depth 0): locked rmutex now |
||||
T7 (prio 3, depth 1): trying to lock rmutex now |
||||
T7 (prio 3, depth 1): locked rmutex now |
||||
T7 (prio 3, depth 2): trying to lock rmutex now |
||||
T7 (prio 3, depth 2): locked rmutex now |
||||
T7 (prio 3, depth 3): trying to lock rmutex now |
||||
T7 (prio 3, depth 3): locked rmutex now |
||||
T7 (prio 3, depth 4): trying to lock rmutex now |
||||
T7 (prio 3, depth 4): locked rmutex now |
||||
T7 (prio 3, depth 4): unlocked rmutex |
||||
T7 (prio 3, depth 3): unlocked rmutex |
||||
T7 (prio 3, depth 2): unlocked rmutex |
||||
T7 (prio 3, depth 1): unlocked rmutex |
||||
T7 (prio 3, depth 0): unlocked rmutex |
||||
T4 (prio 4, depth 0): locked rmutex now |
||||
T4 (prio 4, depth 1): trying to lock rmutex now |
||||
T4 (prio 4, depth 1): locked rmutex now |
||||
T4 (prio 4, depth 2): trying to lock rmutex now |
||||
T4 (prio 4, depth 2): locked rmutex now |
||||
T4 (prio 4, depth 2): unlocked rmutex |
||||
T4 (prio 4, depth 1): unlocked rmutex |
||||
T4 (prio 4, depth 0): unlocked rmutex |
||||
T5 (prio 5, depth 0): locked rmutex now |
||||
T5 (prio 5, depth 1): trying to lock rmutex now |
||||
T5 (prio 5, depth 1): locked rmutex now |
||||
T5 (prio 5, depth 2): trying to lock rmutex now |
||||
T5 (prio 5, depth 2): locked rmutex now |
||||
T5 (prio 5, depth 2): unlocked rmutex |
||||
T5 (prio 5, depth 1): unlocked rmutex |
||||
T5 (prio 5, depth 0): unlocked rmutex |
||||
T3 (prio 6, depth 0): locked rmutex now |
||||
T3 (prio 6, depth 1): trying to lock rmutex now |
||||
T3 (prio 6, depth 1): locked rmutex now |
||||
T3 (prio 6, depth 2): trying to lock rmutex now |
||||
T3 (prio 6, depth 2): locked rmutex now |
||||
T3 (prio 6, depth 3): trying to lock rmutex now |
||||
T3 (prio 6, depth 3): locked rmutex now |
||||
T3 (prio 6, depth 4): trying to lock rmutex now |
||||
T3 (prio 6, depth 4): locked rmutex now |
||||
T3 (prio 6, depth 4): unlocked rmutex |
||||
T3 (prio 6, depth 3): unlocked rmutex |
||||
T3 (prio 6, depth 2): unlocked rmutex |
||||
T3 (prio 6, depth 1): unlocked rmutex |
||||
T3 (prio 6, depth 0): unlocked rmutex |
||||
|
||||
Test END, check the order of priorities above. |
||||
``` |
||||
|
||||
Background |
||||
========== |
||||
This test application stresses a mutex with a number of threads waiting on it. |
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Theobroma Systems Design & Consulting GmbH |
||||
* |
||||
* 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 Test application for testing recursive mutexes |
||||
* |
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> |
||||
* @author Martin Elshuber <martin.elshuber@theobroma-systems.com> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
|
||||
#include "rmutex.h" |
||||
#include "thread.h" |
||||
|
||||
#define THREAD_NUMOF (5U) |
||||
|
||||
extern volatile thread_t *sched_active_thread; |
||||
|
||||
static char stacks[THREAD_NUMOF][THREAD_STACKSIZE_MAIN]; |
||||
|
||||
static const char prios[THREAD_NUMOF] = {THREAD_PRIORITY_MAIN - 1, 4, 5, 2, 4}; |
||||
static const char depth[THREAD_NUMOF] = {5, 3, 3, 4, 5}; |
||||
|
||||
static rmutex_t testlock; |
||||
|
||||
static void lock_recursive(char n, char depth) |
||||
{ |
||||
volatile thread_t *t = sched_active_thread; |
||||
|
||||
printf("T%i (prio %i, depth %i): trying to lock rmutex now\n", |
||||
(int)t->pid, (int)t->priority, (int)n); |
||||
rmutex_lock(&testlock); |
||||
|
||||
printf("T%i (prio %i, depth %i): locked rmutex now\n", |
||||
(int)t->pid, (int)t->priority, (int)n); |
||||
|
||||
if (n + 1 < depth) |
||||
lock_recursive(n + 1, depth); |
||||
|
||||
thread_yield(); |
||||
|
||||
rmutex_unlock(&testlock); |
||||
|
||||
printf("T%i (prio %i, depth %i): unlocked rmutex\n", |
||||
(int)t->pid, (int)t->priority, (int)n); |
||||
} |
||||
|
||||
static void *lockme(void *arg) |
||||
{ |
||||
intptr_t depth = (intptr_t)arg; |
||||
|
||||
lock_recursive(0, depth); |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
int main(void) |
||||
{ |
||||
puts("Recursive Mutex test"); |
||||
puts("Please refer to the README.md for more information\n"); |
||||
|
||||
rmutex_init(&testlock); |
||||
|
||||
/* lock mutex, so that spawned threads have to wait */ |
||||
rmutex_lock(&testlock); |
||||
/* create threads */ |
||||
for (unsigned i = 0; i < THREAD_NUMOF; i++) { |
||||
thread_create(stacks[i], sizeof(stacks[i]), prios[i], 0, |
||||
lockme, (void*)(intptr_t)depth[i], "t"); |
||||
} |
||||
/* allow threads to lock the mutex */ |
||||
printf("main: unlocking recursive mutex\n"); |
||||
|
||||
rmutex_unlock(&testlock); |
||||
|
||||
rmutex_lock(&testlock); |
||||
puts("\nTest END, check the order of priorities above."); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# Copyright (C) 2016 Theobroma Systems Design & Consulting GmbH |
||||
# |
||||
# 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. |
||||
|
||||
# Author: Martin Elshuber <martin.elshuber@theobroma-systems.com> |
||||
|
||||
import os |
||||
import sys |
||||
|
||||
sys.path.append(os.path.join(os.environ['RIOTBASE'], 'dist/tools/testrunner')) |
||||
import testrunner |
||||
|
||||
thread_prio = { |
||||
3: 6, |
||||
4: 4, |
||||
5: 5, |
||||
6: 2, |
||||
7: 4 |
||||
} |
||||
|
||||
lock_depth = { |
||||
3: 5, |
||||
4: 3, |
||||
5: 3, |
||||
6: 4, |
||||
7: 5 |
||||
} |
||||
|
||||
def thread_prio_sort(x): |
||||
return thread_prio.get(x)*1000 + x |
||||
|
||||
def testfunc(child): |
||||
for k in thread_prio.keys(): |
||||
child.expect(u"T%i \(prio %i, depth 0\): trying to lock rmutex now" % |
||||
(k, thread_prio[k])) |
||||
|
||||
pri_sorted = sorted(thread_prio, key=thread_prio_sort); |
||||
for T in pri_sorted: |
||||
for depth in range(lock_depth[T]): |
||||
child.expect(u"T%i \(prio %i, depth %i\): locked rmutex now" % |
||||
(T, thread_prio[T], depth)) |
||||
|
||||
if __name__ == "__main__": |
||||
sys.exit(testrunner.run(testfunc)) |
Loading…
Reference in new issue