summaryrefslogblamecommitdiffstats
path: root/testsuites/tmtests/tmonetoone/init.c
blob: 9c8af786db73dee736a9502f747e1996441d07ac (plain) (tree)
1
2
3
4
5

                                           


                                                                 



















                                                                              





                    

                  
                  
                            






                                            
             

























                                                   




















                                        

















































































                                                                    


                     
























































                                                                         
          

























































                                                                           








                                                    









































                                                                 
/* SPDX-License-Identifier: BSD-2-Clause */

/*
 * Copyright (c) 2018 embedded brains GmbH.  All rights reserved.
 *
 * 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)
{
  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)
{
  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>