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) 2013, 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 <string.h>
0033 
0034 #include <rtems/test.h>
0035 #include <rtems/test-info.h>
0036 
0037 #include <rtems/score/threadimpl.h>
0038 #include <rtems/score/threadqimpl.h>
0039 #include <rtems/rtems/semimpl.h>
0040 
0041 const char rtems_test_name[] = "SPINTRCRITICAL 20";
0042 
0043 #define PRIORITY_MASTER 2
0044 
0045 #define PRIORITY_SEMAPHORE 1
0046 
0047 typedef struct {
0048   rtems_id master_task;
0049   rtems_id semaphore_task;
0050   rtems_id semaphore_id;
0051   Thread_Control *semaphore_task_tcb;
0052   bool thread_queue_was_null;
0053   bool status_was_successful;
0054   bool status_was_timeout;
0055   volatile bool early;
0056   volatile bool late;
0057 } test_context;
0058 
0059 static void semaphore_task(rtems_task_argument arg)
0060 {
0061   test_context *ctx = (test_context *) arg;
0062 
0063   ctx->semaphore_task_tcb = _Thread_Get_executing();
0064 
0065   while (true) {
0066     rtems_status_code sc = rtems_semaphore_obtain(
0067       ctx->semaphore_id,
0068       RTEMS_WAIT,
0069       RTEMS_NO_TIMEOUT
0070     );
0071     T_quiet_true(sc == RTEMS_SUCCESSFUL || sc == RTEMS_TIMEOUT);
0072   }
0073 }
0074 
0075 static T_interrupt_test_state interrupt(void *arg)
0076 {
0077   test_context *ctx = arg;
0078   T_interrupt_test_state state;
0079   rtems_status_code sc;
0080 
0081   state = T_interrupt_test_get_state();
0082 
0083   if (state != T_INTERRUPT_TEST_ACTION) {
0084     return T_INTERRUPT_TEST_CONTINUE;
0085   }
0086 
0087   sc = rtems_semaphore_release(ctx->semaphore_id);
0088   T_quiet_rsc_success(sc);
0089 
0090   if ( ctx->early ) {
0091     state = T_INTERRUPT_TEST_EARLY;
0092   } else if ( ctx->late ) {
0093     state = T_INTERRUPT_TEST_LATE;
0094   } else if (
0095     ctx->thread_queue_was_null
0096       && ctx->status_was_successful
0097       && ctx->status_was_timeout
0098   ) {
0099     state = T_INTERRUPT_TEST_DONE;
0100   } else {
0101     state = T_INTERRUPT_TEST_CONTINUE;
0102   }
0103 
0104   return state;
0105 }
0106 
0107 static void prepare(void *arg)
0108 {
0109   test_context *ctx = arg;
0110 
0111   ctx->early = true;
0112   ctx->late = false;
0113 }
0114 
0115 static void action(void *arg)
0116 {
0117   test_context *ctx = arg;
0118   Per_CPU_Control *cpu_self;
0119 
0120   cpu_self = _Thread_Dispatch_disable();
0121   ctx->early = false;
0122 
0123   T_quiet_rsc_success(_Thread_Wait_get_status( ctx->semaphore_task_tcb ));
0124 
0125   if (ctx->semaphore_task_tcb->Wait.queue == NULL) {
0126     ctx->thread_queue_was_null = true;
0127   }
0128 
0129   _Thread_Timeout(&ctx->semaphore_task_tcb->Timer.Watchdog);
0130 
0131   switch (_Thread_Wait_get_status(ctx->semaphore_task_tcb)) {
0132     case STATUS_SUCCESSFUL:
0133       ctx->status_was_successful = true;
0134       break;
0135     case STATUS_TIMEOUT:
0136       ctx->status_was_timeout = true;
0137       break;
0138     default:
0139       T_unreachable();
0140       break;
0141   }
0142 
0143   ctx->late = true;
0144   _Thread_Dispatch_enable(cpu_self);
0145 
0146   T_interrupt_test_busy_wait_for_interrupt();
0147 }
0148 
0149 static const T_interrupt_test_config config = {
0150   .prepare = prepare,
0151   .action = action,
0152   .interrupt = interrupt,
0153   .max_iteration_count = 10000
0154 };
0155 
0156 T_TEST_CASE(SemaphoreObtainTimeoutInterrupt)
0157 {
0158   test_context ctx;
0159   rtems_status_code sc;
0160   T_interrupt_test_state state;
0161 
0162   memset(&ctx, 0, sizeof(ctx));
0163   ctx.master_task = rtems_task_self();
0164 
0165   sc = rtems_semaphore_create(
0166     rtems_build_name('S', 'E', 'M', 'A'),
0167     1,
0168     RTEMS_COUNTING_SEMAPHORE,
0169     0,
0170     &ctx.semaphore_id
0171   );
0172   T_assert_rsc_success(sc);
0173 
0174   sc = rtems_task_create(
0175     rtems_build_name('S', 'E', 'M', 'A'),
0176     PRIORITY_SEMAPHORE,
0177     RTEMS_MINIMUM_STACK_SIZE,
0178     RTEMS_DEFAULT_MODES,
0179     RTEMS_DEFAULT_ATTRIBUTES,
0180     &ctx.semaphore_task
0181   );
0182   T_assert_rsc_success(sc);
0183 
0184   sc = rtems_task_start(
0185     ctx.semaphore_task,
0186     semaphore_task,
0187     (rtems_task_argument) &ctx
0188   );
0189   T_assert_rsc_success(sc);
0190 
0191   state = T_interrupt_test(&config, &ctx);
0192   T_eq_int(state, T_INTERRUPT_TEST_DONE);
0193 
0194   T_true(ctx.thread_queue_was_null);
0195   T_true(ctx.status_was_successful);
0196   T_true(ctx.status_was_timeout);
0197 
0198   sc = rtems_task_delete(ctx.semaphore_task);
0199   T_rsc_success(sc);
0200 
0201   sc = rtems_semaphore_delete(ctx.semaphore_id);
0202   T_rsc_success(sc);
0203 }
0204 
0205 static rtems_task Init(rtems_task_argument argument)
0206 {
0207   rtems_test_run(argument, TEST_STATE);
0208 }
0209 
0210 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0211 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0212 
0213 #define CONFIGURE_MICROSECONDS_PER_TICK 1000
0214 
0215 #define CONFIGURE_MAXIMUM_SEMAPHORES 1
0216 #define CONFIGURE_MAXIMUM_TASKS 2
0217 
0218 #define CONFIGURE_INIT_TASK_PRIORITY PRIORITY_MASTER
0219 #define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES
0220 #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
0221 
0222 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0223 
0224 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0225 
0226 #define CONFIGURE_INIT
0227 
0228 #include <rtems/confdefs.h>