File indexing completed on 2025-05-11 08:24:47
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
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>