Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (c) 2013 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 "tmacros.h"
0033 
0034 #include <stdio.h>
0035 #include <inttypes.h>
0036 
0037 const char rtems_test_name[] = "SMPSWITCHEXTENSION 1";
0038 
0039 #define CPU_COUNT 2
0040 
0041 #define TOGGLER_COUNT 2
0042 
0043 #define EXTENSION_COUNT 3
0044 
0045 #define PRIO_STOP 2
0046 
0047 #define PRIO_SWITCH 3
0048 
0049 #define PRIO_HIGH 4
0050 
0051 #define PRIO_NORMAL 5
0052 
0053 #define PRIO_LOW 6
0054 
0055 typedef struct {
0056   uint32_t toggles;
0057   uint32_t unused_space_for_cache_line_alignment[7];
0058 } test_toggler_counters;
0059 
0060 typedef struct {
0061   test_toggler_counters counters[TOGGLER_COUNT];
0062   rtems_id toggler_ids[TOGGLER_COUNT];
0063   rtems_id extension_ids[EXTENSION_COUNT];
0064   uint32_t extension_switches;
0065   uint32_t context_switches[EXTENSION_COUNT];
0066 } test_context;
0067 
0068 CPU_STRUCTURE_ALIGNMENT static test_context ctx_instance;
0069 
0070 static void switch_0(Thread_Control *executing, Thread_Control *heir)
0071 {
0072   test_context *ctx = &ctx_instance;
0073 
0074   (void) executing;
0075   (void) heir;
0076 
0077   ++ctx->context_switches[0];
0078 }
0079 
0080 static void switch_1(Thread_Control *executing, Thread_Control *heir)
0081 {
0082   test_context *ctx = &ctx_instance;
0083 
0084   (void) executing;
0085   (void) heir;
0086 
0087   ++ctx->context_switches[1];
0088 }
0089 
0090 static void switch_2(Thread_Control *executing, Thread_Control *heir)
0091 {
0092   test_context *ctx = &ctx_instance;
0093 
0094   (void) executing;
0095   (void) heir;
0096 
0097   ++ctx->context_switches[2];
0098 }
0099 
0100 static const rtems_extensions_table extensions[EXTENSION_COUNT] = {
0101   { .thread_switch = switch_0 },
0102   { .thread_switch = switch_1 },
0103   { .thread_switch = switch_2 }
0104 };
0105 
0106 static void toggler(rtems_task_argument self)
0107 {
0108   test_context *ctx = &ctx_instance;
0109   test_toggler_counters *counters = &ctx->counters[self];
0110 
0111   while (true) {
0112     rtems_status_code sc;
0113 
0114     ++counters->toggles;
0115 
0116     sc = rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
0117     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0118   }
0119 }
0120 
0121 static void switcher(rtems_task_argument self)
0122 {
0123   test_context *ctx = &ctx_instance;
0124 
0125   while (true) {
0126     size_t ext_index;
0127     rtems_status_code sc;
0128 
0129     ++ctx->extension_switches;
0130 
0131     for (ext_index = 0; ext_index < EXTENSION_COUNT; ++ext_index) {
0132       sc = rtems_extension_create(
0133         rtems_build_name('E', 'X', 'T', (char) ('0' + ext_index)),
0134         &extensions[ext_index],
0135         &ctx->extension_ids[ext_index]
0136       );
0137       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0138     }
0139 
0140     for (ext_index = 0; ext_index < EXTENSION_COUNT; ++ext_index) {
0141       sc = rtems_extension_delete(ctx->extension_ids[ext_index]);
0142       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0143     }
0144   }
0145 }
0146 
0147 static void stopper(rtems_task_argument arg)
0148 {
0149   (void) arg;
0150 
0151   while (true) {
0152     /* Do nothing */
0153   }
0154 }
0155 
0156 static void test(void)
0157 {
0158   test_context *ctx = &ctx_instance;
0159   rtems_status_code sc;
0160   rtems_task_argument toggler_index;
0161   rtems_id stopper_id;
0162   rtems_id switcher_id;
0163   size_t ext_index;
0164 
0165   sc = rtems_task_create(
0166     rtems_build_name('S', 'T', 'O', 'P'),
0167     PRIO_STOP,
0168     RTEMS_MINIMUM_STACK_SIZE,
0169     RTEMS_DEFAULT_MODES,
0170     RTEMS_DEFAULT_ATTRIBUTES,
0171     &stopper_id
0172   );
0173   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0174 
0175   sc = rtems_task_create(
0176     rtems_build_name('E', 'X', 'S', 'W'),
0177     PRIO_SWITCH,
0178     RTEMS_MINIMUM_STACK_SIZE,
0179     RTEMS_DEFAULT_MODES,
0180     RTEMS_DEFAULT_ATTRIBUTES,
0181     &switcher_id
0182   );
0183   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0184 
0185   for (toggler_index = 0; toggler_index < TOGGLER_COUNT; ++toggler_index) {
0186     sc = rtems_task_create(
0187       rtems_build_name('T', 'O', 'G', (char) ('0' + toggler_index)),
0188       PRIO_NORMAL,
0189       RTEMS_MINIMUM_STACK_SIZE,
0190       RTEMS_DEFAULT_MODES,
0191       RTEMS_DEFAULT_ATTRIBUTES,
0192       &ctx->toggler_ids[toggler_index]
0193     );
0194     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0195   }
0196 
0197   for (toggler_index = 0; toggler_index < TOGGLER_COUNT; ++toggler_index) {
0198     sc = rtems_task_start(ctx->toggler_ids[toggler_index], toggler, toggler_index);
0199     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0200   }
0201 
0202   sc = rtems_task_start(switcher_id, switcher, 0);
0203   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0204 
0205   sc = rtems_task_wake_after(10 * rtems_clock_get_ticks_per_second());
0206   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0207 
0208   sc = rtems_task_start(stopper_id, stopper, 0);
0209   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0210 
0211   for (toggler_index = 0; toggler_index < TOGGLER_COUNT; ++toggler_index) {
0212     test_toggler_counters *counters = &ctx->counters[toggler_index];
0213 
0214     printf(
0215       "toggler %" PRIuPTR "\n"
0216         "\ttoggles %" PRIu32 "\n",
0217       toggler_index,
0218       counters->toggles
0219     );
0220   }
0221 
0222   for (ext_index = 0; ext_index < EXTENSION_COUNT; ++ext_index) {
0223     printf(
0224       "extension %" PRIuPTR "\n"
0225         "\tcontext switches %" PRIu32 "\n",
0226       ext_index,
0227       ctx->context_switches[ext_index]
0228     );
0229   }
0230 
0231   printf(
0232     "extension switches %" PRIu32 "\n",
0233     ctx->extension_switches
0234   );
0235 }
0236 
0237 static void Init(rtems_task_argument arg)
0238 {
0239   TEST_BEGIN();
0240 
0241   if (rtems_scheduler_get_processor_maximum() >= 2) {
0242     test();
0243   }
0244 
0245   TEST_END();
0246   rtems_test_exit(0);
0247 }
0248 
0249 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0250 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0251 
0252 #define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
0253 
0254 #define CONFIGURE_MAXIMUM_TASKS (3 + TOGGLER_COUNT)
0255 
0256 #define CONFIGURE_MAXIMUM_USER_EXTENSIONS EXTENSION_COUNT
0257 
0258 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0259 
0260 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0261 
0262 #define CONFIGURE_INIT
0263 
0264 #include <rtems/confdefs.h>