mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-23 01:39:09 +08:00
347 lines
8.2 KiB
C
347 lines
8.2 KiB
C
/* SPDX-License-Identifier: BSD-2-Clause */
|
|
|
|
/*
|
|
* Copyright (c) 2018 embedded brains GmbH & Co. KG
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <sched.h>
|
|
|
|
#include <rtems.h>
|
|
#include <rtems/test-info.h>
|
|
#include <rtems/thread.h>
|
|
|
|
#include <tmacros.h>
|
|
|
|
const char rtems_test_name[] = "TMONETOONE";
|
|
|
|
typedef enum {
|
|
TEST_YIELD,
|
|
TEST_EVENTS,
|
|
TEST_BSEM,
|
|
TEST_CLASSIC_FIFO_BSEM,
|
|
TEST_CLASSIC_PRIO_BSEM
|
|
} test_variant;
|
|
|
|
typedef struct {
|
|
volatile uint32_t counter;
|
|
test_variant variant;
|
|
rtems_id task;
|
|
rtems_binary_semaphore bsem;
|
|
rtems_id classic_fifo_bsem;
|
|
rtems_id classic_prio_bsem;
|
|
rtems_id other_task;
|
|
rtems_binary_semaphore *other_bsem;
|
|
rtems_id other_classic_fifo_bsem;
|
|
rtems_id other_classic_prio_bsem;
|
|
} task_context RTEMS_ALIGNED( CPU_CACHE_LINE_BYTES );
|
|
|
|
typedef struct {
|
|
task_context a;
|
|
task_context b;
|
|
} test_context;
|
|
|
|
static test_context test_instance;
|
|
|
|
static void test_yield( task_context *tc )
|
|
{
|
|
rtems_event_set events;
|
|
uint32_t counter;
|
|
|
|
(void) rtems_event_receive(
|
|
RTEMS_EVENT_0,
|
|
RTEMS_WAIT | RTEMS_EVENT_ALL,
|
|
RTEMS_NO_TIMEOUT,
|
|
&events
|
|
);
|
|
|
|
counter = 0;
|
|
|
|
while ( true ) {
|
|
(void) sched_yield();
|
|
++counter;
|
|
tc->counter = counter;
|
|
}
|
|
}
|
|
|
|
static void test_events( task_context *tc )
|
|
{
|
|
uint32_t counter;
|
|
rtems_id other;
|
|
|
|
counter = 0;
|
|
other = tc->other_task;
|
|
|
|
while ( true ) {
|
|
rtems_event_set events;
|
|
|
|
(void) rtems_event_receive(
|
|
RTEMS_EVENT_0,
|
|
RTEMS_WAIT | RTEMS_EVENT_ALL,
|
|
RTEMS_NO_TIMEOUT,
|
|
&events
|
|
);
|
|
(void) rtems_event_send( other, RTEMS_EVENT_0 );
|
|
++counter;
|
|
tc->counter = counter;
|
|
}
|
|
}
|
|
|
|
static void test_bsem( task_context *tc )
|
|
{
|
|
uint32_t counter;
|
|
rtems_binary_semaphore *other;
|
|
|
|
counter = 0;
|
|
other = tc->other_bsem;
|
|
|
|
while ( true ) {
|
|
rtems_binary_semaphore_wait( &tc->bsem );
|
|
rtems_binary_semaphore_post( other );
|
|
++counter;
|
|
tc->counter = counter;
|
|
}
|
|
}
|
|
|
|
static void test_classic_fifo_bsem( task_context *tc )
|
|
{
|
|
uint32_t counter;
|
|
rtems_id own;
|
|
rtems_id other;
|
|
|
|
counter = 0;
|
|
own = tc->classic_fifo_bsem;
|
|
other = tc->other_classic_fifo_bsem;
|
|
|
|
while ( true ) {
|
|
(void) rtems_semaphore_obtain( own, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
|
|
(void) rtems_semaphore_release( other );
|
|
++counter;
|
|
tc->counter = counter;
|
|
}
|
|
}
|
|
|
|
static void test_classic_prio_bsem( task_context *tc )
|
|
{
|
|
uint32_t counter;
|
|
rtems_id own;
|
|
rtems_id other;
|
|
|
|
counter = 0;
|
|
own = tc->classic_prio_bsem;
|
|
other = tc->other_classic_prio_bsem;
|
|
|
|
while ( true ) {
|
|
(void) rtems_semaphore_obtain( own, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
|
|
(void) rtems_semaphore_release( other );
|
|
++counter;
|
|
tc->counter = counter;
|
|
}
|
|
}
|
|
|
|
static void worker_task( rtems_task_argument arg )
|
|
{
|
|
(void) arg;
|
|
|
|
task_context *tc;
|
|
|
|
tc = (task_context *) arg;
|
|
|
|
switch ( tc->variant ) {
|
|
case TEST_YIELD:
|
|
test_yield( tc );
|
|
break;
|
|
case TEST_EVENTS:
|
|
test_events( tc );
|
|
break;
|
|
case TEST_BSEM:
|
|
test_bsem( tc );
|
|
break;
|
|
case TEST_CLASSIC_FIFO_BSEM:
|
|
test_classic_fifo_bsem( tc );
|
|
break;
|
|
case TEST_CLASSIC_PRIO_BSEM:
|
|
test_classic_prio_bsem( tc );
|
|
break;
|
|
default:
|
|
rtems_test_assert( 0 );
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void create_task( task_context *tc )
|
|
{
|
|
rtems_status_code sc;
|
|
|
|
rtems_binary_semaphore_init( &tc->bsem, "test" );
|
|
|
|
sc = rtems_semaphore_create(
|
|
rtems_build_name( 'T', 'E', 'S', 'T' ),
|
|
0,
|
|
RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_FIFO,
|
|
0,
|
|
&tc->classic_fifo_bsem
|
|
);
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
|
|
sc = rtems_semaphore_create(
|
|
rtems_build_name( 'T', 'E', 'S', 'T' ),
|
|
0,
|
|
RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY,
|
|
0,
|
|
&tc->classic_prio_bsem
|
|
);
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
|
|
sc = rtems_task_create(
|
|
rtems_build_name( 'T', 'E', 'S', 'T' ),
|
|
2,
|
|
RTEMS_MINIMUM_STACK_SIZE,
|
|
RTEMS_DEFAULT_MODES,
|
|
RTEMS_DEFAULT_ATTRIBUTES,
|
|
&tc->task
|
|
);
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
|
|
sc = rtems_task_start( tc->task, worker_task, (rtems_task_argument) tc );
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
}
|
|
|
|
static const char *const variant_names[] = {
|
|
"yield",
|
|
"event",
|
|
"self-contained binary semaphore",
|
|
"Classic binary semaphore (FIFO)",
|
|
"Classic binary semaphore (priority)"
|
|
};
|
|
|
|
static void prepare( test_context *ctx, test_variant variant )
|
|
{
|
|
rtems_status_code sc;
|
|
|
|
printf( "%s\n", variant_names[ variant ] );
|
|
|
|
ctx->a.variant = variant;
|
|
ctx->b.variant = variant;
|
|
|
|
ctx->a.counter = 0;
|
|
ctx->b.counter = 0;
|
|
|
|
sc = rtems_task_restart( ctx->a.task, (rtems_task_argument) &ctx->a );
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
|
|
sc = rtems_task_restart( ctx->b.task, (rtems_task_argument) &ctx->b );
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
|
|
sc = rtems_task_wake_after( 2 );
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
}
|
|
|
|
static void run( test_context *ctx )
|
|
{
|
|
rtems_status_code sc;
|
|
|
|
sc = rtems_task_wake_after( rtems_clock_get_ticks_per_second() );
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
|
|
printf( "a %" PRIu32 "\nb %" PRIu32 "\n", ctx->a.counter, ctx->b.counter );
|
|
}
|
|
|
|
static void Init( rtems_task_argument arg )
|
|
{
|
|
(void) arg;
|
|
|
|
test_context *ctx = &test_instance;
|
|
rtems_status_code sc;
|
|
|
|
TEST_BEGIN();
|
|
|
|
create_task( &ctx->a );
|
|
create_task( &ctx->b );
|
|
|
|
ctx->a.other_task = ctx->b.task;
|
|
ctx->a.other_bsem = &ctx->b.bsem;
|
|
ctx->a.other_classic_fifo_bsem = ctx->b.classic_fifo_bsem;
|
|
ctx->a.other_classic_prio_bsem = ctx->b.classic_prio_bsem;
|
|
|
|
ctx->b.other_task = ctx->a.task;
|
|
ctx->b.other_bsem = &ctx->a.bsem;
|
|
ctx->b.other_classic_fifo_bsem = ctx->a.classic_fifo_bsem;
|
|
ctx->b.other_classic_prio_bsem = ctx->a.classic_prio_bsem;
|
|
|
|
prepare( ctx, TEST_YIELD );
|
|
|
|
sc = rtems_event_send( ctx->a.task, RTEMS_EVENT_0 );
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
|
|
sc = rtems_event_send( ctx->b.task, RTEMS_EVENT_0 );
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
|
|
run( ctx );
|
|
prepare( ctx, TEST_EVENTS );
|
|
|
|
sc = rtems_event_send( ctx->a.task, RTEMS_EVENT_0 );
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
|
|
run( ctx );
|
|
prepare( ctx, TEST_BSEM );
|
|
|
|
rtems_binary_semaphore_post( &ctx->a.bsem );
|
|
|
|
run( ctx );
|
|
prepare( ctx, TEST_CLASSIC_FIFO_BSEM );
|
|
|
|
sc = rtems_semaphore_release( ctx->a.classic_fifo_bsem );
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
|
|
run( ctx );
|
|
prepare( ctx, TEST_CLASSIC_PRIO_BSEM );
|
|
|
|
sc = rtems_semaphore_release( ctx->a.classic_prio_bsem );
|
|
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
|
|
|
|
run( ctx );
|
|
|
|
TEST_END();
|
|
rtems_test_exit( 0 );
|
|
}
|
|
|
|
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
|
|
#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
|
|
|
|
#define CONFIGURE_MAXIMUM_TASKS 3
|
|
|
|
#define CONFIGURE_MAXIMUM_SEMAPHORES 4
|
|
|
|
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
|
|
|
|
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
|
|
|
|
#define CONFIGURE_INIT
|
|
|
|
#include <rtems/confdefs.h>
|