Skip to content

Commit

Permalink
Added test application for reentrant mutexes
Browse files Browse the repository at this point in the history
* fixed BOARD_INSUFFICIENT_MEMORY for rmutex
  • Loading branch information
martin-cherry committed Feb 9, 2017
1 parent b9c2fc8 commit b9bb22b
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 0 deletions.
6 changes: 6 additions & 0 deletions tests/rmutex/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
APPLICATION = rmutex
include ../Makefile.tests_common

BOARD_INSUFFICIENT_MEMORY := stm32f0discovery weio nucleo-f030 nucleo32-f042

include $(RIOTBASE)/Makefile.include
86 changes: 86 additions & 0 deletions tests/rmutex/README.md
Original file line number Diff line number Diff line change
@@ -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.
91 changes: 91 additions & 0 deletions tests/rmutex/main.c
Original file line number Diff line number Diff line change
@@ -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;
}
48 changes: 48 additions & 0 deletions tests/rmutex/tests/01-run.py
Original file line number Diff line number Diff line change
@@ -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))

0 comments on commit b9bb22b

Please sign in to comment.