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 <rtems/test.h>
0033 #include <rtems/test-info.h>
0034
0035 #include <string.h>
0036
0037 #include <rtems.h>
0038 #include <rtems/score/schedulerpriorityimpl.h>
0039 #include <rtems/score/threadimpl.h>
0040
0041 const char rtems_test_name[] = "SPINTRCRITICAL 23";
0042
0043 typedef struct {
0044 RTEMS_INTERRUPT_LOCK_MEMBER(lock)
0045 rtems_id task_id;
0046 Scheduler_priority_Node *scheduler_node;
0047 rtems_task_priority priority_task;
0048 rtems_task_priority priority_interrupt;
0049 volatile bool early;
0050 volatile bool late;
0051 } test_context;
0052
0053 static T_interrupt_test_state interrupt(void *arg)
0054 {
0055 test_context *ctx = arg;
0056 T_interrupt_test_state state;
0057 rtems_interrupt_lock_context lock_context;
0058 unsigned int next_priority;
0059
0060 state = T_interrupt_test_get_state();
0061
0062 if (state != T_INTERRUPT_TEST_ACTION) {
0063 return T_INTERRUPT_TEST_CONTINUE;
0064 }
0065
0066 rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
0067
0068 next_priority = SCHEDULER_PRIORITY_UNMAP(
0069 (unsigned int) ctx->scheduler_node->Base.Priority.value
0070 );
0071
0072 if ( ctx->scheduler_node->Ready_queue.current_priority != next_priority ) {
0073 rtems_task_priority priority_interrupt;
0074 rtems_task_priority priority_task;
0075 rtems_task_priority previous;
0076 rtems_status_code sc;
0077
0078 priority_interrupt = ctx->priority_interrupt;
0079 priority_task = ctx->priority_task;
0080
0081 rtems_interrupt_lock_release(&ctx->lock, &lock_context);
0082
0083 sc = rtems_task_set_priority(
0084 ctx->task_id,
0085 priority_interrupt,
0086 &previous
0087 );
0088 T_quiet_rsc_success(sc);
0089 T_quiet_eq_u32(previous, priority_task);
0090
0091 state = T_INTERRUPT_TEST_DONE;
0092 } else {
0093 rtems_interrupt_lock_release(&ctx->lock, &lock_context);
0094
0095 if ( ctx->early ) {
0096 state = T_INTERRUPT_TEST_EARLY;
0097 } else if ( ctx->late ) {
0098 state = T_INTERRUPT_TEST_LATE;
0099 } else {
0100 state = T_INTERRUPT_TEST_CONTINUE;
0101 }
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 rtems_status_code sc;
0119 rtems_interrupt_lock_context lock_context;
0120 rtems_task_priority priority_last;
0121 rtems_task_priority priority_task;
0122 rtems_task_priority priority_interrupt;
0123 rtems_task_priority previous;
0124
0125 rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
0126
0127 priority_last = ctx->priority_task;
0128 priority_task = 1 + (priority_last + 1) % 3;
0129 priority_interrupt = 1 + (priority_task + 1) % 3;
0130 ctx->priority_task = priority_task;
0131 ctx->priority_interrupt = priority_interrupt;
0132
0133 rtems_interrupt_lock_release(&ctx->lock, &lock_context);
0134
0135 ctx->early = false;
0136 sc = rtems_task_set_priority(
0137 ctx->task_id,
0138 priority_task,
0139 &previous
0140 );
0141 T_quiet_rsc_success(RTEMS_SUCCESSFUL);
0142 T_quiet_eq_u32(previous, priority_last);
0143 ctx->late = true;
0144
0145 if (T_interrupt_test_get_state() == T_INTERRUPT_TEST_DONE) {
0146 sc = rtems_task_set_priority(
0147 ctx->task_id,
0148 RTEMS_CURRENT_PRIORITY,
0149 &previous
0150 );
0151 T_quiet_rsc_success(sc);
0152 T_quiet_eq_u32(previous, priority_interrupt);
0153 }
0154 }
0155
0156 static const T_interrupt_test_config config = {
0157 .prepare = prepare,
0158 .action = action,
0159 .interrupt = interrupt,
0160 .max_iteration_count = 10000
0161 };
0162
0163 T_TEST_CASE(TaskSetPriorityInterrupt)
0164 {
0165 test_context ctx;
0166 T_interrupt_test_state state;
0167 rtems_status_code sc;
0168 rtems_task_priority prio;
0169
0170 sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &prio);
0171 T_rsc_success(sc);
0172
0173 memset(&ctx, 0, sizeof(ctx));
0174 rtems_interrupt_lock_initialize(&ctx.lock, "Test");
0175 ctx.priority_task = 1;
0176 ctx.task_id = rtems_task_self();
0177 ctx.scheduler_node =
0178 _Scheduler_priority_Thread_get_node(_Thread_Get_executing());
0179
0180 state = T_interrupt_test(&config, &ctx);
0181 T_eq_int(state, T_INTERRUPT_TEST_DONE);
0182
0183 rtems_interrupt_lock_destroy(&ctx.lock);
0184
0185 sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
0186 T_rsc_success(sc);
0187 }
0188
0189 static rtems_task Init(rtems_task_argument argument)
0190 {
0191 rtems_test_run(argument, TEST_STATE);
0192 }
0193
0194 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0195 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0196
0197 #define CONFIGURE_MICROSECONDS_PER_TICK 1000
0198
0199 #define CONFIGURE_MAXIMUM_TASKS 1
0200
0201
0202 #define CONFIGURE_SCHEDULER_PRIORITY
0203
0204 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0205
0206 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0207
0208 #define CONFIGURE_INIT
0209
0210 #include <rtems/confdefs.h>