Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:50

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (c) 2018 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031 
0032 #include <sched.h>
0033 
0034 #include <rtems.h>
0035 #include <rtems/test-info.h>
0036 #include <rtems/thread.h>
0037 
0038 #include <tmacros.h>
0039 
0040 const char rtems_test_name[] = "TMONETOONE";
0041 
0042 typedef enum {
0043   TEST_YIELD,
0044   TEST_EVENTS,
0045   TEST_BSEM,
0046   TEST_CLASSIC_FIFO_BSEM,
0047   TEST_CLASSIC_PRIO_BSEM
0048 } test_variant;
0049 
0050 typedef struct {
0051   volatile uint32_t counter;
0052   test_variant variant;
0053   rtems_id task;
0054   rtems_binary_semaphore bsem;
0055   rtems_id classic_fifo_bsem;
0056   rtems_id classic_prio_bsem;
0057   rtems_id other_task;
0058   rtems_binary_semaphore *other_bsem;
0059   rtems_id other_classic_fifo_bsem;
0060   rtems_id other_classic_prio_bsem;
0061 } task_context RTEMS_ALIGNED(CPU_CACHE_LINE_BYTES);
0062 
0063 typedef struct {
0064   task_context a;
0065   task_context b;
0066 } test_context;
0067 
0068 static test_context test_instance;
0069 
0070 static void test_yield(task_context *tc)
0071 {
0072   rtems_event_set events;
0073   uint32_t counter;
0074 
0075   (void)rtems_event_receive(
0076     RTEMS_EVENT_0,
0077     RTEMS_WAIT | RTEMS_EVENT_ALL,
0078     RTEMS_NO_TIMEOUT,
0079     &events
0080   );
0081 
0082   counter = 0;
0083 
0084   while (true) {
0085     (void)sched_yield();
0086     ++counter;
0087     tc->counter = counter;
0088   }
0089 }
0090 
0091 static void test_events(task_context *tc)
0092 {
0093   uint32_t counter;
0094   rtems_id other;
0095 
0096   counter = 0;
0097   other = tc->other_task;
0098 
0099   while (true) {
0100     rtems_event_set events;
0101 
0102     (void)rtems_event_receive(
0103       RTEMS_EVENT_0,
0104       RTEMS_WAIT | RTEMS_EVENT_ALL,
0105       RTEMS_NO_TIMEOUT,
0106       &events
0107     );
0108     (void)rtems_event_send(other, RTEMS_EVENT_0);
0109     ++counter;
0110     tc->counter = counter;
0111   }
0112 }
0113 
0114 static void test_bsem(task_context *tc)
0115 {
0116   uint32_t counter;
0117   rtems_binary_semaphore *other;
0118 
0119   counter = 0;
0120   other = tc->other_bsem;
0121 
0122   while (true) {
0123     rtems_binary_semaphore_wait(&tc->bsem);
0124     rtems_binary_semaphore_post(other);
0125     ++counter;
0126     tc->counter = counter;
0127   }
0128 }
0129 
0130 static void test_classic_fifo_bsem(task_context *tc)
0131 {
0132   uint32_t counter;
0133   rtems_id own;
0134   rtems_id other;
0135 
0136   counter = 0;
0137   own = tc->classic_fifo_bsem;
0138   other = tc->other_classic_fifo_bsem;
0139 
0140   while (true) {
0141     (void)rtems_semaphore_obtain(own, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0142     (void)rtems_semaphore_release(other);
0143     ++counter;
0144     tc->counter = counter;
0145   }
0146 }
0147 
0148 static void test_classic_prio_bsem(task_context *tc)
0149 {
0150   uint32_t counter;
0151   rtems_id own;
0152   rtems_id other;
0153 
0154   counter = 0;
0155   own = tc->classic_prio_bsem;
0156   other = tc->other_classic_prio_bsem;
0157 
0158   while (true) {
0159     (void)rtems_semaphore_obtain(own, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0160     (void)rtems_semaphore_release(other);
0161     ++counter;
0162     tc->counter = counter;
0163   }
0164 }
0165 
0166 static void worker_task(rtems_task_argument arg)
0167 {
0168   task_context *tc;
0169 
0170   tc = (task_context *) arg;
0171 
0172   switch (tc->variant) {
0173     case TEST_YIELD:
0174       test_yield(tc);
0175       break;
0176     case TEST_EVENTS:
0177       test_events(tc);
0178       break;
0179     case TEST_BSEM:
0180       test_bsem(tc);
0181       break;
0182     case TEST_CLASSIC_FIFO_BSEM:
0183       test_classic_fifo_bsem(tc);
0184       break;
0185     case TEST_CLASSIC_PRIO_BSEM:
0186       test_classic_prio_bsem(tc);
0187       break;
0188     default:
0189       rtems_test_assert(0);
0190       break;
0191   }
0192 }
0193 
0194 static void create_task(task_context *tc)
0195 {
0196   rtems_status_code sc;
0197 
0198   rtems_binary_semaphore_init(&tc->bsem, "test");
0199 
0200   sc = rtems_semaphore_create(
0201     rtems_build_name('T', 'E', 'S', 'T'),
0202     0,
0203     RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_FIFO,
0204     0,
0205     &tc->classic_fifo_bsem
0206   );
0207   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0208 
0209   sc = rtems_semaphore_create(
0210     rtems_build_name('T', 'E', 'S', 'T'),
0211     0,
0212     RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY,
0213     0,
0214     &tc->classic_prio_bsem
0215   );
0216   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0217 
0218   sc = rtems_task_create(
0219     rtems_build_name('T', 'E', 'S', 'T'),
0220     2,
0221     RTEMS_MINIMUM_STACK_SIZE,
0222     RTEMS_DEFAULT_MODES,
0223     RTEMS_DEFAULT_ATTRIBUTES,
0224     &tc->task
0225   );
0226   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0227 
0228   sc = rtems_task_start(tc->task, worker_task, (rtems_task_argument) tc);
0229   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0230 }
0231 
0232 static const char * const variant_names[] = {
0233   "yield",
0234   "event",
0235   "self-contained binary semaphore",
0236   "Classic binary semaphore (FIFO)",
0237   "Classic binary semaphore (priority)"
0238 };
0239 
0240 static void prepare(test_context *ctx, test_variant variant)
0241 {
0242   rtems_status_code sc;
0243 
0244   printf("%s\n", variant_names[variant]);
0245 
0246   ctx->a.variant = variant;
0247   ctx->b.variant = variant;
0248 
0249   ctx->a.counter = 0;
0250   ctx->b.counter = 0;
0251 
0252   sc = rtems_task_restart(ctx->a.task, (rtems_task_argument) &ctx->a);
0253   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0254 
0255   sc = rtems_task_restart(ctx->b.task, (rtems_task_argument) &ctx->b);
0256   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0257 
0258   sc = rtems_task_wake_after(2);
0259   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0260 }
0261 
0262 static void run(test_context *ctx)
0263 {
0264   rtems_status_code sc;
0265 
0266   sc = rtems_task_wake_after(rtems_clock_get_ticks_per_second());
0267   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0268 
0269   printf("a %" PRIu32 "\nb %" PRIu32 "\n", ctx->a.counter, ctx->b.counter);
0270 }
0271 
0272 static void Init(rtems_task_argument arg)
0273 {
0274   test_context *ctx = &test_instance;
0275   rtems_status_code sc;
0276 
0277   TEST_BEGIN();
0278 
0279   create_task(&ctx->a);
0280   create_task(&ctx->b);
0281 
0282   ctx->a.other_task = ctx->b.task;
0283   ctx->a.other_bsem = &ctx->b.bsem;
0284   ctx->a.other_classic_fifo_bsem = ctx->b.classic_fifo_bsem;
0285   ctx->a.other_classic_prio_bsem = ctx->b.classic_prio_bsem;
0286 
0287   ctx->b.other_task = ctx->a.task;
0288   ctx->b.other_bsem = &ctx->a.bsem;
0289   ctx->b.other_classic_fifo_bsem = ctx->a.classic_fifo_bsem;
0290   ctx->b.other_classic_prio_bsem = ctx->a.classic_prio_bsem;
0291 
0292   prepare(ctx, TEST_YIELD);
0293 
0294   sc = rtems_event_send(ctx->a.task, RTEMS_EVENT_0);
0295   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0296 
0297   sc = rtems_event_send(ctx->b.task, RTEMS_EVENT_0);
0298   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0299 
0300   run(ctx);
0301   prepare(ctx, TEST_EVENTS);
0302 
0303   sc = rtems_event_send(ctx->a.task, RTEMS_EVENT_0);
0304   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0305 
0306   run(ctx);
0307   prepare(ctx, TEST_BSEM);
0308 
0309   rtems_binary_semaphore_post(&ctx->a.bsem);
0310 
0311   run(ctx);
0312   prepare(ctx, TEST_CLASSIC_FIFO_BSEM);
0313 
0314   sc = rtems_semaphore_release(ctx->a.classic_fifo_bsem);
0315   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0316 
0317   run(ctx);
0318   prepare(ctx, TEST_CLASSIC_PRIO_BSEM);
0319 
0320   sc = rtems_semaphore_release(ctx->a.classic_prio_bsem);
0321   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0322 
0323   run(ctx);
0324 
0325   TEST_END();
0326   rtems_test_exit(0);
0327 }
0328 
0329 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0330 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0331 
0332 #define CONFIGURE_MAXIMUM_TASKS 3
0333 
0334 #define CONFIGURE_MAXIMUM_SEMAPHORES 4
0335 
0336 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0337 
0338 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0339 
0340 #define CONFIGURE_INIT
0341 
0342 #include <rtems/confdefs.h>