| /* 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 "console.h" |
| #include "common.h" |
| #include "task.h" |
| #include "test_util.h" |
| #include "timer.h" |
| #include "util.h" |
| |
| static struct mutex mtx; |
| |
| /* period between 50us and 3.2ms */ |
| #define PERIOD_US(num) (((num % 64) + 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_event(0); |
| ccprintf("%c+\n", letter); |
| mutex_lock(&mtx); |
| ccprintf("%c=\n", letter); |
| task_wait_event(0); |
| ccprintf("%c-\n", letter); |
| mutex_unlock(&mtx); |
| } |
| |
| task_wait_event(0); |
| |
| return EC_SUCCESS; |
| } |
| |
| int mutex_second_task(void *unused) |
| { |
| task_id_t id = task_get_current(); |
| |
| ccprintf("\n[Mutex second task %d]\n", id); |
| |
| task_wait_event(0); |
| ccprintf("MTX2: locking..."); |
| mutex_lock(&mtx); |
| ccprintf("done\n"); |
| task_wake(TASK_ID_MTX1); |
| ccprintf("MTX2: unlocking...\n"); |
| mutex_unlock(&mtx); |
| |
| task_wait_event(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; |
| |
| ccprintf("\n[Mutex main task %d]\n", id); |
| |
| task_wait_event(0); |
| |
| /* --- Lock/Unlock without contention --- */ |
| ccprintf("No contention :"); |
| mutex_lock(&mtx); |
| mutex_unlock(&mtx); |
| mutex_lock(&mtx); |
| mutex_unlock(&mtx); |
| mutex_lock(&mtx); |
| mutex_unlock(&mtx); |
| ccprintf("done.\n"); |
| |
| /* --- Serialization to test simple contention --- */ |
| ccprintf("Simple contention :\n"); |
| /* lock the mutex from the other task */ |
| task_set_event(TASK_ID_MTX2, TASK_EVENT_WAKE, 1); |
| /* block on the mutex */ |
| ccprintf("MTX1: blocking...\n"); |
| mutex_lock(&mtx); |
| ccprintf("MTX1: get lock\n"); |
| mutex_unlock(&mtx); |
| |
| /* --- mass lock-unlocking from several tasks --- */ |
| ccprintf("Massive locking/unlocking :\n"); |
| for (i = 0; i < 500; i++) { |
| /* Wake up a random task */ |
| task_wake(RANDOM_TASK(rtask)); |
| /* next pseudo random delay */ |
| rtask = prng(rtask); |
| /* Wait for a "random" period */ |
| task_wait_event(PERIOD_US(rdelay)); |
| /* next pseudo random delay */ |
| rdelay = prng(rdelay); |
| } |
| |
| test_pass(); |
| task_wait_event(0); |
| |
| return EC_SUCCESS; |
| } |
| |
| void run_test(void) |
| { |
| wait_for_task_started(); |
| task_wake(TASK_ID_MTX1); |
| } |