Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  COPYRIGHT (c) 1989-2012.
0005  *  On-Line Applications Research Corporation (OAR).
0006  *
0007  *  Copyright (C) 2013, 2020 embedded brains GmbH & Co. KG
0008  *
0009  * Redistribution and use in source and binary forms, with or without
0010  * modification, are permitted provided that the following conditions
0011  * are met:
0012  * 1. Redistributions of source code must retain the above copyright
0013  *    notice, this list of conditions and the following disclaimer.
0014  * 2. Redistributions in binary form must reproduce the above copyright
0015  *    notice, this list of conditions and the following disclaimer in the
0016  *    documentation and/or other materials provided with the distribution.
0017  *
0018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0028  * POSSIBILITY OF SUCH DAMAGE.
0029  */
0030 
0031 #ifdef HAVE_CONFIG_H
0032 #include "config.h"
0033 #endif
0034 
0035 #include <tmacros.h>
0036 #include <rtems/test.h>
0037 
0038 #include <rtems/score/threadimpl.h>
0039 #include <rtems/rtems/eventimpl.h>
0040 
0041 const char rtems_test_name[] = "SPINTRCRITICAL 10";
0042 
0043 #define MAX_ITERATION_COUNT 10000
0044 
0045 #define GREEN RTEMS_EVENT_0
0046 
0047 #define RED RTEMS_EVENT_1
0048 
0049 #define EVENTS (GREEN | RED)
0050 
0051 #define DEADBEEF 0xdeadbeef
0052 
0053 typedef struct {
0054   Thread_Control *thread;
0055 } test_context;
0056 
0057 static bool blocks_for_event(Thread_Wait_flags flags)
0058 {
0059   return flags == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTEND_TO_BLOCK)
0060     || flags == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_BLOCKED);
0061 }
0062 
0063 static bool interrupts_blocking_op(Thread_Wait_flags flags)
0064 {
0065   return
0066     flags == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTEND_TO_BLOCK);
0067 }
0068 
0069 static T_interrupt_test_state any_satisfy_before_timeout_interrupt(void *arg)
0070 {
0071   rtems_status_code sc;
0072   test_context *ctx = arg;
0073   Thread_Control *thread = ctx->thread;
0074   Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
0075   T_interrupt_test_state state;
0076 
0077   if (blocks_for_event(flags)) {
0078     if (interrupts_blocking_op(flags)) {
0079       state = T_INTERRUPT_TEST_DONE;
0080     } else {
0081       state = T_INTERRUPT_TEST_LATE;
0082     }
0083 
0084     rtems_test_assert(
0085       *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
0086     );
0087     rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
0088 
0089     sc = rtems_event_send(thread->Object.id, GREEN);
0090     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0091 
0092     rtems_test_assert(
0093       *(rtems_event_set *) thread->Wait.return_argument == GREEN
0094     );
0095     rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
0096 
0097     sc = rtems_event_send(thread->Object.id, RED);
0098     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0099 
0100     rtems_test_assert(
0101       *(rtems_event_set *) thread->Wait.return_argument == GREEN
0102     );
0103     rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
0104 
0105     _Thread_Timeout(&thread->Timer.Watchdog);
0106 
0107     rtems_test_assert(
0108       *(rtems_event_set *) thread->Wait.return_argument == GREEN
0109     );
0110     rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
0111 
0112     if (state == T_INTERRUPT_TEST_DONE) {
0113       rtems_test_assert(
0114         _Thread_Wait_flags_get(thread) == THREAD_WAIT_STATE_READY
0115       );
0116     }
0117 
0118     rtems_test_assert(thread->Wait.count == EVENTS);
0119   } else {
0120     state = T_INTERRUPT_TEST_EARLY;
0121   }
0122 
0123   return state;
0124 }
0125 
0126 static void any_satisfy_before_timeout_action(void *arg)
0127 {
0128   rtems_status_code sc;
0129   rtems_event_set out;
0130 
0131   (void) arg;
0132 
0133   out = DEADBEEF;
0134   sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ANY | RTEMS_WAIT, 1, &out);
0135   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0136   rtems_test_assert(out == GREEN);
0137 
0138   out = DEADBEEF;
0139   sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, 0, &out);
0140   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0141   rtems_test_assert(out == RED);
0142 }
0143 
0144 static const T_interrupt_test_config any_satisfy_before_timeout_config = {
0145   .action = any_satisfy_before_timeout_action,
0146   .interrupt = any_satisfy_before_timeout_interrupt,
0147   .max_iteration_count = MAX_ITERATION_COUNT
0148 };
0149 
0150 T_TEST_CASE(EventAnySatisfyBeforeTimeout)
0151 {
0152   test_context ctx;
0153   T_interrupt_test_state state;
0154 
0155   ctx.thread = _Thread_Get_executing();
0156   state = T_interrupt_test(&any_satisfy_before_timeout_config, &ctx);
0157   T_eq_int(state, T_INTERRUPT_TEST_DONE);
0158 }
0159 
0160 static T_interrupt_test_state all_satisfy_before_timeout_interrupt(void *arg)
0161 {
0162   rtems_status_code sc;
0163   test_context *ctx = arg;
0164   Thread_Control *thread = ctx->thread;
0165   Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
0166   T_interrupt_test_state state;
0167 
0168   if (blocks_for_event(flags)) {
0169     if (interrupts_blocking_op(flags)) {
0170       state = T_INTERRUPT_TEST_DONE;
0171     } else {
0172       state = T_INTERRUPT_TEST_LATE;
0173     }
0174 
0175     rtems_test_assert(
0176       *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
0177     );
0178     rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
0179 
0180     sc = rtems_event_send(thread->Object.id, GREEN);
0181     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0182 
0183     rtems_test_assert(
0184       *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
0185     );
0186     rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
0187 
0188     sc = rtems_event_send(thread->Object.id, RED);
0189     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0190 
0191     rtems_test_assert(
0192       *(rtems_event_set *) thread->Wait.return_argument == EVENTS
0193     );
0194     rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
0195 
0196     _Thread_Timeout(&thread->Timer.Watchdog);
0197 
0198     rtems_test_assert(
0199       *(rtems_event_set *) thread->Wait.return_argument == EVENTS
0200     );
0201     rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
0202 
0203     if (state == T_INTERRUPT_TEST_DONE) {
0204       rtems_test_assert(
0205         _Thread_Wait_flags_get(thread) == THREAD_WAIT_STATE_READY
0206       );
0207     }
0208 
0209     rtems_test_assert(thread->Wait.count == EVENTS);
0210   } else {
0211     state = T_INTERRUPT_TEST_EARLY;
0212   }
0213 
0214   return state;
0215 }
0216 
0217 static void all_satisfy_before_timeout_action(void *arg)
0218 {
0219   rtems_status_code sc;
0220   rtems_event_set out;
0221 
0222   out = DEADBEEF;
0223   sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_WAIT, 1, &out);
0224   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0225   rtems_test_assert(out == EVENTS);
0226 }
0227 
0228 static const T_interrupt_test_config all_satisfy_before_timeout_config = {
0229   .action = all_satisfy_before_timeout_action,
0230   .interrupt = all_satisfy_before_timeout_interrupt,
0231   .max_iteration_count = MAX_ITERATION_COUNT
0232 };
0233 
0234 T_TEST_CASE(EventAllSatisfyBeforeTimeout)
0235 {
0236   test_context ctx;
0237   T_interrupt_test_state state;
0238 
0239   ctx.thread = _Thread_Get_executing();
0240   state = T_interrupt_test(&all_satisfy_before_timeout_config, &ctx);
0241   T_eq_int(state, T_INTERRUPT_TEST_DONE);
0242 }
0243 
0244 static T_interrupt_test_state timeout_before_satisfied_interrupt(void *arg)
0245 {
0246   rtems_status_code sc;
0247   test_context *ctx = arg;
0248   Thread_Control *thread = ctx->thread;
0249   Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
0250   T_interrupt_test_state state;
0251 
0252   if (blocks_for_event(flags)) {
0253     if (interrupts_blocking_op(flags)) {
0254       state = T_INTERRUPT_TEST_DONE;
0255     } else {
0256       state = T_INTERRUPT_TEST_LATE;
0257     }
0258 
0259     rtems_test_assert(
0260       *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
0261     );
0262     rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
0263 
0264     _Thread_Timeout(&thread->Timer.Watchdog);
0265 
0266     rtems_test_assert(
0267       *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
0268     );
0269     rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_TIMEOUT);
0270 
0271     sc = rtems_event_send(thread->Object.id, EVENTS);
0272     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0273 
0274     rtems_test_assert(
0275       *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
0276     );
0277     rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_TIMEOUT);
0278 
0279     if (state == T_INTERRUPT_TEST_DONE) {
0280       rtems_test_assert(
0281         _Thread_Wait_flags_get(thread) == THREAD_WAIT_STATE_READY
0282       );
0283     }
0284 
0285     rtems_test_assert(thread->Wait.count == EVENTS);
0286   } else {
0287     state = T_INTERRUPT_TEST_EARLY;
0288   }
0289 
0290   return state;
0291 }
0292 
0293 static void timeout_before_satisfied_action(void *arg)
0294 {
0295   rtems_event_set out;
0296   rtems_status_code sc;
0297 
0298   out = DEADBEEF;
0299   sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_WAIT, 1, &out);
0300   rtems_test_assert(sc == RTEMS_TIMEOUT);
0301   rtems_test_assert(out == DEADBEEF);
0302 
0303   out = DEADBEEF;
0304   sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_NO_WAIT, 0, &out);
0305   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0306   rtems_test_assert(out == EVENTS);
0307 }
0308 
0309 static const T_interrupt_test_config timeout_before_satisfied_config = {
0310   .action = timeout_before_satisfied_action,
0311   .interrupt = timeout_before_satisfied_interrupt,
0312   .max_iteration_count = MAX_ITERATION_COUNT
0313 };
0314 
0315 T_TEST_CASE(EventTimeoutBeforeSatisfied)
0316 {
0317   test_context ctx;
0318   T_interrupt_test_state state;
0319 
0320   ctx.thread = _Thread_Get_executing();
0321   state = T_interrupt_test(&timeout_before_satisfied_config, &ctx);
0322   T_eq_int(state, T_INTERRUPT_TEST_DONE);
0323 }
0324 
0325 static rtems_task Init( rtems_task_argument argument )
0326 {
0327   rtems_test_run( argument, TEST_STATE );
0328 }
0329 
0330 /* configuration information */
0331 
0332 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0333 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0334 
0335 #define CONFIGURE_MAXIMUM_TASKS       1
0336 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0337 
0338 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0339 #define CONFIGURE_MICROSECONDS_PER_TICK  1000
0340 
0341 #define CONFIGURE_INIT
0342 #include <rtems/confdefs.h>