Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2020 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 <rtems/test.h>
0033 #include <rtems/test-info.h>
0034 
0035 #include <string.h>
0036 
0037 #include <rtems.h>
0038 
0039 static void
0040 prepare(void *arg)
0041 {
0042     Atomic_Uint *state;
0043 
0044     state = arg;
0045     _Atomic_Store_uint(state, 0, ATOMIC_ORDER_RELAXED);
0046 }
0047 
0048 static void
0049 action(void *arg)
0050 {
0051     Atomic_Uint *state;
0052     unsigned int expected;
0053     bool success_0;
0054     bool success_1;
0055 
0056     state = arg;
0057 
0058     /*
0059      * This code models a critical section in the operating system.  The
0060      * interrupt should happen between the two atomic operations.
0061      */
0062     expected = 0;
0063     success_0 = _Atomic_Compare_exchange_uint(state, &expected, 1,
0064         ATOMIC_ORDER_RELAXED, ATOMIC_ORDER_RELAXED);
0065     expected = 1;
0066     success_1 = _Atomic_Compare_exchange_uint(state, &expected, 2,
0067         ATOMIC_ORDER_RELAXED, ATOMIC_ORDER_RELAXED);
0068     T_quiet_true(success_0);
0069     T_quiet_true(success_1);
0070 
0071     T_interrupt_test_busy_wait_for_interrupt();
0072 }
0073 
0074 static T_interrupt_test_state
0075 interrupt(void *arg)
0076 {
0077     Atomic_Uint *state;
0078     unsigned int expected;
0079 
0080     if (T_interrupt_test_get_state() != T_INTERRUPT_TEST_ACTION) {
0081         return T_INTERRUPT_TEST_CONTINUE;
0082     }
0083 
0084     state = arg;
0085     expected = 1;
0086 
0087     if (_Atomic_Compare_exchange_uint(state, &expected, expected,
0088         ATOMIC_ORDER_RELAXED, ATOMIC_ORDER_RELAXED)) {
0089         return T_INTERRUPT_TEST_DONE;
0090     } else if (expected == 0) {
0091         return T_INTERRUPT_TEST_EARLY;
0092     } else {
0093         T_quiet_eq_uint(expected, 2);
0094         return T_INTERRUPT_TEST_LATE;
0095     }
0096 }
0097 
0098 static const T_interrupt_test_config done_config = {
0099     .prepare = prepare,
0100     .action = action,
0101     .interrupt = interrupt,
0102     .max_iteration_count = 10000
0103 };
0104 
0105 T_TEST_CASE(TestInterruptDone)
0106 {
0107     int i;
0108 
0109     for (i = 0; i < 10; ++i) {
0110         Atomic_Uint action_state;
0111         T_interrupt_test_state state;
0112 
0113         state = T_interrupt_test(&done_config, &action_state);
0114         T_eq_int(state, T_INTERRUPT_TEST_DONE);
0115     }
0116 }
0117 
0118 static const T_interrupt_test_config timeout_config = {
0119     .interrupt = interrupt,
0120     .action = action
0121 };
0122 
0123 T_TEST_CASE(TestInterruptTimeout)
0124 {
0125     Atomic_Uint action_state;
0126     T_interrupt_test_state state;
0127 
0128     T_plan(1);
0129     state = T_interrupt_test(&timeout_config, &action_state);
0130     T_step_eq_int(0, state, T_INTERRUPT_TEST_TIMEOUT);
0131 }
0132 
0133 static void
0134 fatal(void *arg)
0135 {
0136     (void)arg;
0137     T_plan(1);
0138     T_step(0);
0139     T_stop();
0140 }
0141 
0142 static const T_interrupt_test_config fatal_config = {
0143     .prepare = fatal,
0144     .action = action,
0145     .interrupt = interrupt,
0146     .max_iteration_count = 10000
0147 };
0148 
0149 T_TEST_CASE(TestInterruptFatal)
0150 {
0151     Atomic_Uint action_state;
0152 
0153     T_interrupt_test(&fatal_config, &action_state);
0154     T_unreachable();
0155 }
0156 
0157 static void
0158 suspend(void *arg)
0159 {
0160     rtems_status_code sc;
0161     rtems_id *id;
0162 
0163     id = arg;
0164     T_plan(2);
0165     sc = rtems_task_suspend(*id);
0166     T_step_rsc_success(1, sc);
0167 }
0168 
0169 static T_interrupt_test_state
0170 do_nothing(void *arg)
0171 {
0172     (void)arg;
0173     return T_INTERRUPT_TEST_ACTION;
0174 }
0175 
0176 static void
0177 resume(void *arg)
0178 {
0179     T_interrupt_test_state state;
0180 
0181     state = T_interrupt_test_change_state(T_INTERRUPT_TEST_ACTION,
0182         T_INTERRUPT_TEST_DONE);
0183 
0184     if (state == T_INTERRUPT_TEST_ACTION) {
0185         rtems_status_code sc;
0186         rtems_id *id;
0187 
0188         id = arg;
0189         sc = rtems_task_resume(*id);
0190         T_step_rsc_success(0, sc);
0191     }
0192 }
0193 
0194 static const T_interrupt_test_config blocked_config = {
0195     .action = suspend,
0196     .interrupt = do_nothing,
0197     .blocked = resume,
0198     .max_iteration_count = 10000
0199 };
0200 
0201 T_TEST_CASE(TestInterruptBlocked)
0202 {
0203     T_interrupt_test_state state;
0204     rtems_id id;
0205 
0206     T_plan(1);
0207     id = rtems_task_self();
0208     state = T_interrupt_test(&blocked_config, &id);
0209     T_step_eq_int(0, state, T_INTERRUPT_TEST_DONE);
0210 }
0211 
0212 T_TEST_CASE(TestThreadSwitch)
0213 {
0214     T_thread_switch_log_2 log_2;
0215     T_thread_switch_log_4 log_4;
0216     T_thread_switch_log_10 log_10;
0217     T_thread_switch_log *log;
0218     uint32_t executing;
0219     uint32_t heir;
0220     size_t i;
0221 
0222     memset(&log_2, 0xff, sizeof(log_2));
0223     log = T_thread_switch_record_2(&log_2);
0224     T_null(log);
0225     T_eq_sz(log_2.header.recorded, 0);
0226     T_eq_sz(log_2.header.capacity, 2);
0227     T_eq_u64(log_2.header.switches, 0);
0228 
0229     memset(&log_4, 0xff, sizeof(log_4));
0230     log = T_thread_switch_record_4(&log_4);
0231     T_eq_ptr(&log->header, &log_2.header);
0232     T_eq_sz(log_4.header.recorded, 0);
0233     T_eq_sz(log_4.header.capacity, 4);
0234     T_eq_u64(log_4.header.switches, 0);
0235 
0236     memset(&log_10, 0xff, sizeof(log_10));
0237     log = T_thread_switch_record_10(&log_10);
0238     T_eq_ptr(&log->header, &log_4.header);
0239     T_eq_sz(log_10.header.recorded, 0);
0240     T_eq_sz(log_10.header.capacity, 10);
0241     T_eq_u64(log_10.header.switches, 0);
0242 
0243     for (i = 0; i < 6; ++i) {
0244         rtems_status_code sc;
0245 
0246         sc = rtems_task_wake_after(2);
0247         T_rsc_success(sc);
0248     }
0249 
0250     log = T_thread_switch_record(NULL);
0251     T_eq_ptr(&log->header, &log_10.header);
0252     T_eq_sz(log->header.recorded, 10);
0253     T_eq_sz(log->header.capacity, 10);
0254     T_eq_u64(log->header.switches, 12);
0255     executing = rtems_task_self();
0256     T_eq_u32(log->events[0].executing, executing);
0257     T_ne_u32(log->events[0].heir, 0);
0258     heir = log->events[0].heir;
0259     T_eq_u32(log->events[0].cpu, 0);
0260     T_ne_u64(log->events[0].instant, 0);
0261 
0262     for (i = 1; i < 10; ++i) {
0263         uint32_t tmp;
0264 
0265         tmp = executing;
0266         executing = heir;
0267         heir = tmp;
0268 
0269         T_eq_u32(log->events[i].executing, executing);
0270         T_eq_u32(log->events[i].heir, heir);
0271         T_eq_u32(log->events[i].cpu, 0);
0272         T_gt_u64(log->events[i].instant, log->events[i - 1].instant);
0273     }
0274 }
0275 
0276 const char rtems_test_name[] = "TTEST 2";
0277 
0278 static void
0279 Init(rtems_task_argument argument)
0280 {
0281     rtems_test_run(argument, TEST_STATE);
0282 }
0283 
0284 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0285 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0286 
0287 #define CONFIGURE_MICROSECONDS_PER_TICK 1000
0288 
0289 #define CONFIGURE_MAXIMUM_TASKS 1
0290 
0291 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0292 
0293 #define CONFIGURE_INIT
0294 
0295 #include <rtems/confdefs.h>