1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/tests/sys/pthread_rwlock/main.c

176 lines
4.9 KiB
C

/*
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @ingroup tests
* @{
*
* @file
* @brief Test rwlock implementation.
*
* @author René Kijewski <rene.kijewski@fu-berlin.de>
*
* @}
*/
#include <pthread.h>
#include <stdio.h>
#include "random.h"
#include "sched.h"
#include "thread.h"
#include "xtimer.h"
#define NUM_READERS_HIGH 2
#define NUM_READERS_LOW 3
#define NUM_WRITERS_HIGH 1
#define NUM_WRITERS_LOW 2
#define NUM_READERS (NUM_READERS_HIGH + NUM_READERS_LOW)
#define NUM_WRITERS (NUM_WRITERS_HIGH + NUM_WRITERS_LOW)
#define NUM_CHILDREN (NUM_READERS + NUM_WRITERS)
#define NUM_ITERATIONS 5
#define RAND_SEED 0xC0FFEE
static pthread_rwlock_t rwlock;
static volatile unsigned counter;
static kernel_pid_t main_thread_pid;
/* The test assumes that 'printf/puts' are non interruptible operations
* use a mutex to guarantee it */
static mutex_t stdout_mutex = MUTEX_INIT;
#define PRINTF(FMT, ...) \
do { \
mutex_lock(&stdout_mutex); \
printf("%c%" PRIkernel_pid " (prio=%u): " FMT "\n", \
__func__[0], thread_getpid(), \
thread_get_active()->priority, \
(int)__VA_ARGS__); \
mutex_unlock(&stdout_mutex); \
} while (0)
#define PUTS(s) \
do { \
mutex_lock(&stdout_mutex); \
puts(s); \
mutex_unlock(&stdout_mutex); \
} while (0)
static void _notify_main_thread(void)
{
msg_t msg;
msg_send(&msg, main_thread_pid);
}
static void do_sleep(int factor)
{
uint32_t timeout_us = (random_uint32() % 100000) * factor;
PRINTF("sleep for % 8i µs.", timeout_us);
xtimer_usleep(timeout_us);
}
static void *writer(void *arg)
{
(void) arg;
PUTS("start");
for (unsigned i = 0; i < NUM_ITERATIONS; ++i) {
pthread_rwlock_wrlock(&rwlock);
unsigned cur = ++counter;
do_sleep(3); /* simulate time that it takes to write the value */
PRINTF("%i: write -> %2u (correct = %u)", i, cur, cur == counter);
pthread_rwlock_unlock(&rwlock);
do_sleep(2);
}
PUTS("done");
_notify_main_thread();
return NULL;
}
static void *reader(void *arg)
{
(void) arg;
PUTS("start");
for (unsigned i = 0; i < NUM_ITERATIONS; ++i) {
pthread_rwlock_rdlock(&rwlock);
unsigned cur = counter;
do_sleep(1); /* simulate time that it takes to read the value */
PRINTF("%i: read <- %2u (correct = %u)", i, cur, cur == counter);
pthread_rwlock_unlock(&rwlock);
do_sleep(1);
}
PUTS("done");
_notify_main_thread();
return NULL;
}
int main(void)
{
static char stacks[NUM_CHILDREN][THREAD_STACKSIZE_MAIN];
PUTS("START");
/* Get main thread pid */
main_thread_pid = thread_getpid();
for (unsigned i = 0; i < NUM_CHILDREN; ++i) {
int prio;
void *(*fun)(void *);
const char *name;
if (i < NUM_READERS) {
if (i < NUM_READERS_HIGH) {
prio = THREAD_PRIORITY_MAIN + 1;
}
else {
prio = THREAD_PRIORITY_MAIN + 2;
}
fun = reader;
name = "reader";
}
else {
if (i - NUM_READERS < NUM_WRITERS_HIGH) {
prio = THREAD_PRIORITY_MAIN + 1;
}
else {
prio = THREAD_PRIORITY_MAIN + 2;
}
fun = writer;
name = "writer";
}
thread_create(stacks[i], sizeof(stacks[i]),
prio, THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST,
fun, NULL, name);
}
/* Block until all children threads are done */
for (unsigned i = 0; i < NUM_CHILDREN; ++i) {
msg_t msg;
msg_receive(&msg);
}
PUTS("SUCCESS");
return 0;
}