Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2013, 2015 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/score/cpuimpl.h>
0033 
0034 #include <tmacros.h>
0035 
0036 const char rtems_test_name[] = "SPCONTEXT 1";
0037 
0038 #define ITERATION_COUNT 2000
0039 
0040 #define PRIORITY_HIGH 2
0041 
0042 #define PRIORITY_LOW 3
0043 
0044 #define FINISH_EVENT RTEMS_EVENT_0
0045 
0046 typedef struct {
0047   rtems_id control_task;
0048   rtems_id validate_tasks[3];
0049   rtems_id timer;
0050   size_t task_index;
0051   int iteration_counter;
0052 } test_context;
0053 
0054 static test_context test_instance;
0055 
0056 static void validate_task(rtems_task_argument arg)
0057 {
0058   _CPU_Context_validate(arg);
0059   rtems_test_assert(0);
0060 }
0061 
0062 static void start_validate_task(
0063   rtems_id *id,
0064   uintptr_t pattern,
0065   rtems_task_priority priority,
0066   bool fp_unit
0067 )
0068 {
0069   rtems_status_code sc;
0070   rtems_attribute fpu_state;
0071 
0072   fpu_state = fp_unit ? RTEMS_FLOATING_POINT : RTEMS_DEFAULT_ATTRIBUTES;
0073 
0074   sc = rtems_task_create(
0075     rtems_build_name('V', 'A', 'L', 'I'),
0076     priority,
0077     RTEMS_MINIMUM_STACK_SIZE,
0078     RTEMS_DEFAULT_MODES,
0079     fpu_state,
0080     id
0081   );
0082   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0083 
0084   sc = rtems_task_start(*id, validate_task, pattern);
0085   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0086 }
0087 
0088 static void reset_timer_or_finish(test_context *self, rtems_id timer)
0089 {
0090   rtems_status_code sc;
0091   int i = self->iteration_counter;
0092 
0093   if (i < ITERATION_COUNT) {
0094     self->iteration_counter = i + 1;
0095 
0096     sc = rtems_timer_reset(timer);
0097     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0098   } else {
0099     sc = rtems_event_send(self->control_task, FINISH_EVENT);
0100     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0101   }
0102 }
0103 
0104 static void switch_priorities(test_context *self)
0105 {
0106   rtems_status_code sc;
0107   size_t index = self->task_index;
0108   size_t next = (index + 1) % RTEMS_ARRAY_SIZE(self->validate_tasks);
0109   size_t task_current_high = index;
0110   size_t task_next_high = next;
0111   rtems_task_priority priority;
0112 
0113   self->task_index = next;
0114 
0115   sc = rtems_task_set_priority(
0116     self->validate_tasks[task_next_high],
0117     PRIORITY_HIGH,
0118     &priority
0119   );
0120   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0121 
0122   sc = rtems_task_set_priority(
0123     self->validate_tasks[task_current_high],
0124     PRIORITY_LOW,
0125     &priority
0126   );
0127   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0128 }
0129 
0130 static void clobber_and_switch_timer(rtems_id timer, void *arg)
0131 {
0132   uintptr_t pattern = (uintptr_t) 0xffffffffffffffffU;
0133   test_context *self = arg;
0134 
0135   reset_timer_or_finish(self, self->timer);
0136   switch_priorities(self);
0137 
0138   _CPU_Context_volatile_clobber(pattern);
0139 }
0140 
0141 static void start_timer(test_context *self)
0142 {
0143   rtems_status_code sc;
0144 
0145   sc = rtems_timer_create(rtems_build_name('C', 'L', 'S', 'W'), &self->timer);
0146   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0147 
0148   sc = rtems_timer_fire_after(self->timer, 2, clobber_and_switch_timer, self);
0149   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0150 }
0151 
0152 static void wait_for_finish(void)
0153 {
0154   rtems_status_code sc;
0155   rtems_event_set out;
0156 
0157   sc = rtems_event_receive(
0158     FINISH_EVENT,
0159     RTEMS_WAIT | RTEMS_EVENT_ALL,
0160     RTEMS_NO_TIMEOUT,
0161     &out
0162   );
0163   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0164   rtems_test_assert(out == FINISH_EVENT);
0165 }
0166 
0167 static void test(
0168   test_context *self,
0169   bool task_0_fpu,
0170   bool task_1_fpu,
0171   bool task_2_fpu
0172 )
0173 {
0174   rtems_status_code sc;
0175   uintptr_t pattern_0 = (uintptr_t) 0xaaaaaaaaaaaaaaaaU;
0176   uintptr_t pattern_1 = (uintptr_t) 0x5555555555555555U;
0177   uintptr_t pattern_2 = (uintptr_t) 0x0000000000000000U;
0178 
0179   memset(self, 0, sizeof(*self));
0180 
0181   self->control_task = rtems_task_self();
0182   start_validate_task(
0183     &self->validate_tasks[0],
0184     pattern_0,
0185     PRIORITY_HIGH,
0186     task_0_fpu
0187   );
0188   start_validate_task(
0189     &self->validate_tasks[1],
0190     pattern_1,
0191     PRIORITY_LOW,
0192     task_1_fpu
0193   );
0194   start_validate_task(
0195     &self->validate_tasks[2],
0196     pattern_2,
0197     PRIORITY_LOW,
0198     task_2_fpu
0199   );
0200   start_timer(self);
0201   wait_for_finish();
0202 
0203   sc = rtems_task_delete(self->validate_tasks[0]);
0204   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0205 
0206   sc = rtems_task_delete(self->validate_tasks[1]);
0207   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0208 
0209   sc = rtems_task_delete(self->validate_tasks[2]);
0210   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0211 
0212   sc = rtems_timer_delete(self->timer);
0213   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0214 }
0215 
0216 static void test_context_is_executing(void)
0217 {
0218 #if defined(RTEMS_SMP)
0219   /*
0220    * Provide a stack area, since on some architectures the top/bottom of stack
0221    * is initialized by _CPU_Context_Initialize().
0222    */
0223   static char stack[1024];
0224 
0225   Context_Control context;
0226   bool is_executing;
0227 
0228   memset(&context, 0, sizeof(context));
0229 
0230   is_executing = _CPU_Context_Get_is_executing(&context);
0231   rtems_test_assert(!is_executing);
0232 
0233   _CPU_Context_Set_is_executing(&context, true);
0234   is_executing = _CPU_Context_Get_is_executing(&context);
0235   rtems_test_assert(is_executing);
0236 
0237   _CPU_Context_Set_is_executing(&context, false);
0238   is_executing = _CPU_Context_Get_is_executing(&context);
0239   rtems_test_assert(!is_executing);
0240 
0241   _CPU_Context_Set_is_executing(&context, true);
0242   _CPU_Context_Initialize(
0243     &context,
0244     (void *) &stack[0],
0245     sizeof(stack),
0246     0,
0247     NULL,
0248     false,
0249     NULL
0250   );
0251   is_executing = _CPU_Context_Get_is_executing(&context);
0252   rtems_test_assert(is_executing);
0253 #endif
0254 }
0255 
0256 static bool is_fp(int i)
0257 {
0258   return i != 0;
0259 }
0260 
0261 static const char *desc(int i)
0262 {
0263   return is_fp(i) ? "F" : "N";
0264 }
0265 
0266 static void Init(rtems_task_argument arg)
0267 {
0268   test_context *self = &test_instance;
0269   int i;
0270   int j;
0271   int k;
0272 
0273   TEST_BEGIN();
0274 
0275   test_context_is_executing();
0276 
0277   for (i = 0; i < 2; ++i) {
0278     for (j = 0; j < 2; ++j) {
0279       for (k = 0; k < 2; ++k) {
0280         printf("Test configuration %s %s %s... ", desc(i), desc(j), desc(k));
0281         test(self, is_fp(i), is_fp(j), is_fp(k));
0282         printf("done\n");
0283       }
0284     }
0285   }
0286 
0287   TEST_END();
0288 
0289   rtems_test_exit(0);
0290 }
0291 
0292 static void switch_extension(Thread_Control *executing, Thread_Control *heir)
0293 {
0294   uintptr_t pattern = (uintptr_t) 0xffffffffffffffffU;
0295 
0296   _CPU_Context_volatile_clobber(pattern);
0297 }
0298 
0299 #define CONFIGURE_MICROSECONDS_PER_TICK 1000
0300 
0301 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0302 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0303 
0304 #define CONFIGURE_MAXIMUM_TASKS 4
0305 #define CONFIGURE_MAXIMUM_TIMERS 1
0306 
0307 #define CONFIGURE_INITIAL_EXTENSIONS \
0308   { .thread_switch = switch_extension }, \
0309   RTEMS_TEST_INITIAL_EXTENSION
0310 
0311 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0312 
0313 #define CONFIGURE_INIT
0314 
0315 #include <rtems/confdefs.h>