2014-01-10 16:21:35 +01:00
|
|
|
/*
|
2014-01-27 20:43:54 +01:00
|
|
|
* Copyright (C) 2013 Christian Mehlis <mehlis@inf.fu-berlin.de>
|
2014-01-10 16:21:35 +01:00
|
|
|
* Copyright (C) 2013 René Kijewski <rene.kijewski@fu-berlin.de>
|
2015-08-03 19:21:21 +02:00
|
|
|
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
|
2014-01-10 16:21:35 +01:00
|
|
|
*
|
2014-07-31 19:45:27 +02:00
|
|
|
* 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.
|
2014-01-10 16:21:35 +01:00
|
|
|
*/
|
|
|
|
|
2014-02-03 23:03:13 +01:00
|
|
|
/**
|
|
|
|
* @ingroup tests
|
|
|
|
* @{
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @brief Semaphore test application
|
|
|
|
*
|
|
|
|
* @author Christian Mehlis <mehlis@inf.fu-berlin.de>
|
|
|
|
* @author René Kijewski <rene.kijewski@fu-berlin.de>
|
2015-08-04 20:07:26 +02:00
|
|
|
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
2014-02-03 23:03:13 +01:00
|
|
|
*
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2014-01-10 16:21:35 +01:00
|
|
|
#include <stdio.h>
|
2015-10-19 16:43:27 +02:00
|
|
|
#include <semaphore.h>
|
2014-01-10 16:21:35 +01:00
|
|
|
|
2015-08-04 19:34:33 +02:00
|
|
|
#include "msg.h"
|
2015-08-04 20:07:26 +02:00
|
|
|
#include "timex.h"
|
2014-01-10 16:21:35 +01:00
|
|
|
#include "thread.h"
|
2015-08-04 20:07:26 +02:00
|
|
|
#include "vtimer.h"
|
2014-01-10 16:21:35 +01:00
|
|
|
|
2015-08-04 19:34:33 +02:00
|
|
|
#define SEMAPHORE_MSG_QUEUE_SIZE (8)
|
|
|
|
#define SEMAPHORE_TEST_THREADS (5)
|
|
|
|
static char test1_thread_stack[THREAD_STACKSIZE_MAIN];
|
|
|
|
static char test2_thread_stack[SEMAPHORE_TEST_THREADS][THREAD_STACKSIZE_MAIN];
|
|
|
|
static msg_t main_msg_queue[SEMAPHORE_MSG_QUEUE_SIZE];
|
|
|
|
static msg_t test1_msg_queue[SEMAPHORE_MSG_QUEUE_SIZE];
|
2014-01-10 16:21:35 +01:00
|
|
|
|
2015-08-04 19:52:12 +02:00
|
|
|
static sem_t s1;
|
|
|
|
static sem_t s2;
|
2014-01-10 16:21:35 +01:00
|
|
|
|
2014-03-04 20:20:01 +01:00
|
|
|
static void *test1_second_thread(void *arg)
|
2014-01-10 16:21:35 +01:00
|
|
|
{
|
2014-03-04 20:20:01 +01:00
|
|
|
(void) arg;
|
2015-08-04 19:34:33 +02:00
|
|
|
msg_init_queue(test1_msg_queue, SEMAPHORE_MSG_QUEUE_SIZE);
|
2014-01-10 16:21:35 +01:00
|
|
|
puts("second: sem_trywait");
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2015-10-25 19:25:12 +01:00
|
|
|
if (sem_trywait(&s1) < 0) {
|
2014-01-10 16:21:35 +01:00
|
|
|
puts("second: sem_trywait failed");
|
|
|
|
}
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2014-01-10 16:21:35 +01:00
|
|
|
puts("second: sem_trywait done with == 0");
|
|
|
|
|
|
|
|
puts("second: wait for post");
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2015-10-25 19:25:12 +01:00
|
|
|
if (sem_wait(&s1) < 0) {
|
2014-01-10 16:21:35 +01:00
|
|
|
puts("second: sem_wait failed");
|
|
|
|
}
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2014-01-10 16:21:35 +01:00
|
|
|
puts("second: sem was posted");
|
|
|
|
|
|
|
|
puts("second: end");
|
2014-03-04 20:20:01 +01:00
|
|
|
return NULL;
|
2014-01-10 16:21:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test1(void)
|
|
|
|
{
|
|
|
|
puts("first: sem_init");
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2015-10-25 19:25:12 +01:00
|
|
|
if (sem_init(&s1, 0, 0) < 0) {
|
2014-01-10 16:21:35 +01:00
|
|
|
puts("first: sem_init failed");
|
|
|
|
}
|
|
|
|
|
|
|
|
puts("first: thread create");
|
2014-07-06 22:57:56 +02:00
|
|
|
kernel_pid_t pid = thread_create(test1_thread_stack,
|
|
|
|
sizeof(test1_thread_stack),
|
2015-04-28 20:02:05 +02:00
|
|
|
THREAD_PRIORITY_MAIN - 1,
|
2014-07-06 22:57:56 +02:00
|
|
|
CREATE_STACKTEST | CREATE_WOUT_YIELD,
|
|
|
|
test1_second_thread,
|
|
|
|
NULL,
|
|
|
|
"second");
|
2014-08-06 11:52:00 +02:00
|
|
|
if (pid == KERNEL_PID_UNDEF) {
|
2014-01-10 16:21:35 +01:00
|
|
|
puts("first: thread create failed");
|
|
|
|
}
|
|
|
|
puts("first: thread created");
|
|
|
|
|
|
|
|
puts("first: sem_getvalue");
|
|
|
|
int val;
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2015-10-25 19:25:12 +01:00
|
|
|
if (sem_getvalue(&s1, &val) < 0 || val != 0) {
|
2014-11-19 01:07:50 +01:00
|
|
|
puts("first: sem_getvalue FAILED");
|
2014-01-10 16:21:35 +01:00
|
|
|
}
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2014-01-10 16:21:35 +01:00
|
|
|
puts("first: sem_getvalue != 0");
|
|
|
|
|
|
|
|
puts("first: do yield");
|
|
|
|
thread_yield();
|
|
|
|
puts("first: done yield");
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
puts("first: sem_trywait");
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2015-10-25 19:25:12 +01:00
|
|
|
if (sem_trywait(&s1) < 0) {
|
2014-11-19 01:07:50 +01:00
|
|
|
puts("first: sem_trywait FAILED");
|
2014-01-10 16:21:35 +01:00
|
|
|
}
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2014-01-10 16:21:35 +01:00
|
|
|
puts("first: sem_trywait done");
|
|
|
|
|
|
|
|
puts("first: sem_post");
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2015-10-25 19:25:12 +01:00
|
|
|
if (sem_post(&s1) < 0) {
|
2014-11-19 01:07:50 +01:00
|
|
|
puts("first: sem_post FAILED");
|
2014-01-10 16:21:35 +01:00
|
|
|
}
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2014-01-10 16:21:35 +01:00
|
|
|
puts("first: sem_post done");
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
puts("first: sem_destroy");
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2015-10-25 19:25:12 +01:00
|
|
|
if (sem_destroy(&s1) < 0) {
|
2014-11-19 01:07:50 +01:00
|
|
|
puts("first: sem_destroy FAILED");
|
2014-01-10 16:21:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
puts("first: end");
|
|
|
|
}
|
|
|
|
|
2014-11-19 01:07:50 +01:00
|
|
|
static void *priority_sema_thread(void *name)
|
2014-01-10 16:21:35 +01:00
|
|
|
{
|
2015-08-04 19:34:33 +02:00
|
|
|
msg_t msg_queue[SEMAPHORE_MSG_QUEUE_SIZE];
|
|
|
|
msg_init_queue(msg_queue, SEMAPHORE_MSG_QUEUE_SIZE);
|
2015-08-04 19:52:12 +02:00
|
|
|
sem_wait(&s1);
|
2014-11-19 01:07:50 +01:00
|
|
|
printf("Thread '%s' woke up.\n", (const char *) name);
|
2014-03-04 20:20:01 +01:00
|
|
|
return NULL;
|
2014-01-10 16:21:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
char names[SEMAPHORE_TEST_THREADS][16];
|
|
|
|
void test2(void)
|
|
|
|
{
|
|
|
|
puts("first: sem_init");
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2015-10-25 19:25:12 +01:00
|
|
|
if (sem_init(&s1, 0, 0) < 0) {
|
2014-11-19 01:07:50 +01:00
|
|
|
puts("first: sem_init FAILED");
|
2014-01-10 16:21:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < SEMAPHORE_TEST_THREADS; i++) {
|
2015-04-28 20:02:05 +02:00
|
|
|
int priority = THREAD_PRIORITY_MAIN - (i + 3) % 10 + 1;
|
2014-01-10 16:21:35 +01:00
|
|
|
|
|
|
|
snprintf(names[i], sizeof(names[i]), "priority %d", priority);
|
|
|
|
printf("first: thread create: %d\n", priority);
|
2014-07-06 22:57:56 +02:00
|
|
|
kernel_pid_t pid = thread_create(test2_thread_stack[i],
|
|
|
|
sizeof(test2_thread_stack[i]),
|
|
|
|
priority,
|
|
|
|
CREATE_STACKTEST,
|
|
|
|
priority_sema_thread,
|
2014-11-19 01:07:50 +01:00
|
|
|
names[i],
|
2014-07-06 22:57:56 +02:00
|
|
|
names[i]);
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2014-08-06 09:44:31 +02:00
|
|
|
if (pid == KERNEL_PID_UNDEF) {
|
2014-11-19 01:07:50 +01:00
|
|
|
puts("first: thread create FAILED");
|
2014-01-10 16:21:35 +01:00
|
|
|
}
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2014-01-10 16:21:35 +01:00
|
|
|
printf("first: thread created: %s (%d/%d)\n", names[i], i + 1, SEMAPHORE_TEST_THREADS);
|
|
|
|
}
|
|
|
|
|
|
|
|
puts("------------------------------------------");
|
2014-01-25 11:29:35 +01:00
|
|
|
|
2014-01-10 16:21:35 +01:00
|
|
|
for (int i = 0; i < SEMAPHORE_TEST_THREADS; i++) {
|
|
|
|
printf("post no. %d\n", i);
|
2015-08-04 19:52:12 +02:00
|
|
|
sem_post(&s1);
|
2014-01-10 16:21:35 +01:00
|
|
|
puts("Back in main thread.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-04 19:52:12 +02:00
|
|
|
static void *test3_one_two_thread(void *arg)
|
|
|
|
{
|
|
|
|
msg_t msg_queue[SEMAPHORE_MSG_QUEUE_SIZE];
|
|
|
|
(void)arg;
|
|
|
|
msg_init_queue(msg_queue, SEMAPHORE_MSG_QUEUE_SIZE);
|
|
|
|
sem_wait(&s1);
|
|
|
|
puts("Thread 1 woke up after waiting for s1.");
|
|
|
|
sem_wait(&s2);
|
|
|
|
puts("Thread 1 woke up after waiting for s2.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *test3_two_one_thread(void *arg)
|
|
|
|
{
|
|
|
|
msg_t msg_queue[SEMAPHORE_MSG_QUEUE_SIZE];
|
|
|
|
(void)arg;
|
|
|
|
msg_init_queue(msg_queue, SEMAPHORE_MSG_QUEUE_SIZE);
|
|
|
|
sem_wait(&s2);
|
|
|
|
puts("Thread 2 woke up after waiting for s2.");
|
|
|
|
sem_wait(&s1);
|
|
|
|
puts("Thread 2 woke up after waiting for s1.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void test3(void)
|
|
|
|
{
|
|
|
|
puts("first: sem_init s1");
|
2015-10-25 19:25:12 +01:00
|
|
|
if (sem_init(&s1, 0, 0) < 0) {
|
2015-08-04 19:52:12 +02:00
|
|
|
puts("first: sem_init FAILED");
|
|
|
|
}
|
|
|
|
puts("first: sem_init s2");
|
2015-10-25 19:25:12 +01:00
|
|
|
if (sem_init(&s2, 0, 0) < 0) {
|
2015-08-04 19:52:12 +02:00
|
|
|
puts("first: sem_init FAILED");
|
|
|
|
}
|
|
|
|
puts("first: create thread 1");
|
|
|
|
if (thread_create(test2_thread_stack[0], sizeof(test2_thread_stack[0]),
|
|
|
|
THREAD_PRIORITY_MAIN - 1, CREATE_STACKTEST,
|
|
|
|
test3_one_two_thread, NULL, "thread 1") < 0) {
|
|
|
|
puts("first: thread create FAILED");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
puts("first: create thread 2");
|
|
|
|
if (thread_create(test2_thread_stack[1], sizeof(test2_thread_stack[1]),
|
|
|
|
THREAD_PRIORITY_MAIN - 1, CREATE_STACKTEST,
|
|
|
|
test3_two_one_thread, NULL, "thread 2") < 0) {
|
|
|
|
puts("first: thread create FAILED");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
puts("------------------------------------------");
|
|
|
|
puts("post s1");
|
|
|
|
sem_post(&s1);
|
|
|
|
puts("post s2");
|
|
|
|
sem_post(&s2);
|
|
|
|
puts("post s2");
|
|
|
|
sem_post(&s2);
|
|
|
|
puts("post s1");
|
|
|
|
sem_post(&s1);
|
|
|
|
}
|
|
|
|
|
2015-08-04 20:07:26 +02:00
|
|
|
void test4(void)
|
|
|
|
{
|
|
|
|
struct timespec abs;
|
|
|
|
char timestamp[TIMEX_MAX_STR_LEN];
|
|
|
|
timex_t now, start, stop, exp = { 1, 0 };
|
|
|
|
vtimer_now(&now);
|
|
|
|
abs.tv_sec = now.seconds + 1;
|
|
|
|
abs.tv_nsec = now.microseconds * 1000;
|
|
|
|
puts("first: sem_init s1");
|
2015-10-25 19:25:12 +01:00
|
|
|
if (sem_init(&s1, 0, 0) < 0) {
|
2015-08-04 20:07:26 +02:00
|
|
|
puts("first: sem_init FAILED");
|
|
|
|
}
|
|
|
|
vtimer_now(&start);
|
|
|
|
puts("first: wait 1 sec for s1");
|
2015-10-25 19:25:12 +01:00
|
|
|
if (sem_timedwait(&s1, &abs) != 0) {
|
|
|
|
if (errno != ETIMEDOUT) {
|
|
|
|
printf("error waiting: %d\n", errno);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
puts("first: timed out");
|
|
|
|
}
|
|
|
|
}
|
2015-08-04 20:07:26 +02:00
|
|
|
vtimer_now(&stop);
|
|
|
|
stop = timex_sub(stop, start);
|
|
|
|
if (timex_cmp(stop, exp) < 0) {
|
|
|
|
printf("first: waited only %s => FAILED\n",
|
|
|
|
timex_to_str(stop, timestamp));
|
|
|
|
}
|
|
|
|
printf("first: waited %s\n", timex_to_str(stop, timestamp));
|
|
|
|
}
|
|
|
|
|
2014-01-10 16:21:35 +01:00
|
|
|
int main(void)
|
|
|
|
{
|
2015-08-04 19:34:33 +02:00
|
|
|
msg_init_queue(main_msg_queue, SEMAPHORE_MSG_QUEUE_SIZE);
|
2014-11-19 01:07:50 +01:00
|
|
|
puts("######################### TEST1:");
|
2014-01-10 16:21:35 +01:00
|
|
|
test1();
|
2014-11-19 01:07:50 +01:00
|
|
|
puts("######################### TEST2:");
|
2014-01-10 16:21:35 +01:00
|
|
|
test2();
|
2015-08-04 19:52:12 +02:00
|
|
|
puts("######################### TEST3:");
|
|
|
|
test3();
|
2015-08-04 20:07:26 +02:00
|
|
|
puts("######################### TEST4:");
|
|
|
|
test4();
|
2014-11-19 01:07:50 +01:00
|
|
|
puts("######################### DONE");
|
2014-06-20 20:00:20 +02:00
|
|
|
return 0;
|
2014-01-10 16:21:35 +01:00
|
|
|
}
|