From 47c740e0b2aea0da3e7520feb467835e58758e5c Mon Sep 17 00:00:00 2001 From: Vincent Palatin Date: Wed, 11 Jan 2012 22:51:08 +0000 Subject: mutex: add unit testing Exercise all basic use cases on mutexes. Signed-off-by: Vincent Palatin BUG=None TEST=make qemu-tests Change-Id: I40de3ae59862db96b40a067c9ad54a978f5646b8 --- test/build.mk | 3 +- test/mutex.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test/mutex.py | 25 ++++++++++++ test/mutex.tasklist | 14 +++++++ 4 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 test/mutex.c create mode 100644 test/mutex.py create mode 100644 test/mutex.tasklist (limited to 'test') diff --git a/test/build.mk b/test/build.mk index 44739752a0..7bc5731ac9 100644 --- a/test/build.mk +++ b/test/build.mk @@ -2,10 +2,11 @@ # on-board test binaries build # -test-list=hello pingpong timer_calib timer_dos +test-list=hello pingpong timer_calib timer_dos mutex #disable: powerdemo pingpong-y=pingpong.o powerdemo-y=powerdemo.o timer_calib-y=timer_calib.o timer_dos-y=timer_dos.o +mutex-y=mutex.o diff --git a/test/mutex.c b/test/mutex.c new file mode 100644 index 0000000000..a5b7244e36 --- /dev/null +++ b/test/mutex.c @@ -0,0 +1,112 @@ +/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * Copyright 2011 Google Inc. + * + * Tasks for mutexes basic tests. + */ + +#include "common.h" +#include "uart.h" +#include "task.h" +#include "timer.h" + +static struct mutex mtx; + +/* Linear congruential pseudo random number generator*/ +static uint32_t prng(uint32_t x) +{ + return 22695477 * x + 1; +} + +/* period between 50us and 12.8ms */ +#define PERIOD_US(num) (((num % 256) + 1) * 50) +/* one of the 3 MTX3x tasks */ +#define RANDOM_TASK(num) (TASK_ID_MTX3C + (num % 3)) + +int mutex_random_task(void *unused) +{ + char letter = 'A'+(TASK_ID_MTX3A - task_get_current()); + /* wait to be activated */ + + while (1) { + task_wait_msg(0); + uart_printf("%c+\n", letter); + mutex_lock(&mtx); + uart_printf("%c=\n", letter); + task_wait_msg(0); + uart_printf("%c-\n", letter); + mutex_unlock(&mtx); + } + + task_wait_msg(0); + + return EC_SUCCESS; +} + +int mutex_second_task(void *unused) +{ + task_id_t id = task_get_current(); + + uart_printf("\n[Mutex second task %d]\n", id); + + task_wait_msg(0); + uart_printf("MTX2: locking..."); + mutex_lock(&mtx); + uart_printf("done\n"); + task_send_msg(TASK_ID_MTX1, 1, 0); + uart_printf("MTX2: unlocking...\n"); + mutex_unlock(&mtx); + + task_wait_msg(0); + + return EC_SUCCESS; +} + +int mutex_main_task(void *unused) +{ + task_id_t id = task_get_current(); + uint32_t rdelay = (uint32_t)0x0bad1dea; + uint32_t rtask = (uint32_t)0x1a4e1dea; + int i; + + uart_printf("\n[Mutex main task %d]\n", id); + + /* --- Lock/Unlock without contention --- */ + uart_printf("No contention :"); + mutex_lock(&mtx); + mutex_unlock(&mtx); + mutex_lock(&mtx); + mutex_unlock(&mtx); + mutex_lock(&mtx); + mutex_unlock(&mtx); + uart_printf("done.\n"); + + /* --- Serialization to test simple contention --- */ + uart_printf("Simple contention :\n"); + /* lock the mutex from the other task */ + task_send_msg(TASK_ID_MTX2, 1, 1); + /* block on the mutex */ + uart_printf("MTX1: blocking...\n"); + mutex_lock(&mtx); + uart_printf("MTX1: get lock\n"); + mutex_unlock(&mtx); + + /* --- mass lock-unlocking from several tasks --- */ + uart_printf("Massive locking/unlocking :\n"); + for (i = 0; i < 500; i++) { + /* Wake up a random task */ + task_send_msg(RANDOM_TASK(rtask), 1, 0); + /* next pseudo random delay */ + rtask = prng(rtask); + /* Wait for a "random" period */ + task_wait_msg(PERIOD_US(rdelay)); + /* next pseudo random delay */ + rdelay = prng(rdelay); + } + + uart_printf("Test done.\n"); + task_wait_msg(0); + + return EC_SUCCESS; +} diff --git a/test/mutex.py b/test/mutex.py new file mode 100644 index 0000000000..afd342938c --- /dev/null +++ b/test/mutex.py @@ -0,0 +1,25 @@ +# Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Mutexes test +# + +def test(helper): + helper.wait_output("[Mutex main task") + + # 3 locking in a row without contention + helper.wait_output("No contention :done.") + + # serialization (simple contention) + helper.wait_output("Simple contention :") + helper.wait_output("MTX2: locking...done") + helper.wait_output("MTX1: blocking...") + helper.wait_output("MTX1: get lock") + + # multiple contention + helper.wait_output("Massive locking/unlocking :") + #TODO check sequence + helper.wait_output("Test done.") + + return True # PASS ! diff --git a/test/mutex.tasklist b/test/mutex.tasklist new file mode 100644 index 0000000000..92b2ae72d7 --- /dev/null +++ b/test/mutex.tasklist @@ -0,0 +1,14 @@ + +/** + * List of enabled tasks in the priority order + * + * The first one has the lowest priority. + */ +#define CONFIG_TASK_LIST \ + TASK(WATCHDOG, watchdog_task, NULL) \ + TASK(CONSOLE, console_task, NULL) \ + TASK(MTX3C, mutex_random_task, NULL) \ + TASK(MTX3B, mutex_random_task, NULL) \ + TASK(MTX3A, mutex_random_task, NULL) \ + TASK(MTX2, mutex_second_task, NULL) \ + TASK(MTX1, mutex_main_task, NULL) -- cgit v1.2.1