Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  COPYRIGHT (c) 2014.
0005  *  On-Line Applications Research Corporation (OAR).
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0026  * POSSIBILITY OF SUCH DAMAGE.
0027  */
0028 
0029 /*
0030  * Start 4 tasks with affinity for each of the 4 cpus.
0031  * Allow tasks to set their actual cpu value and delete themselves.
0032  * Verify the actual cpu values match the expected cpu values.
0033  *
0034  * Init task is at a lower priority 8 and the threads
0035  * with affinity are at priority 4, so the affinity task
0036  * on the core init is running on will preempt it.
0037  *
0038  * Test tasks run and delete themselves.
0039  * Init task never blocks.
0040  */
0041 
0042 #ifdef HAVE_CONFIG_H
0043 #include "config.h"
0044 #endif
0045 
0046 #include <rtems.h>
0047 #include <inttypes.h>
0048 
0049 #include "tmacros.h"
0050 
0051 const char rtems_test_name[] = "SMPSCHEDAFFINITY 5";
0052 
0053 #define NUM_CPUS   4
0054 #define TASK_COUNT 5
0055 
0056 struct task_data_t {
0057   rtems_id            id;
0058   cpu_set_t           cpuset;
0059   rtems_task_priority priority;
0060   bool                ran;
0061   int                 expected_cpu;
0062   int                 actual_cpu;
0063   int                 migrate_cpu;
0064 };
0065 
0066 static struct task_data_t task_data[TASK_COUNT] = {
0067   {0x0, {{0xc}}, 7, false,  3, -1,  2},
0068   {0x0, {{0xf}}, 8, false,  2, -1, -1},
0069   {0x0, {{0x3}}, 5, false,  1, -1,  0},
0070   {0x0, {{0x9}}, 6, false,  0, -1,  3},
0071   {0x0, {{0x2}}, 9, false, -1, -1,  1}
0072 };
0073 
0074 rtems_id           task_sem;
0075 
0076 static void verify_tasks(void);
0077 
0078 /*
0079  * Spin loop to allow tasks to delay without yeilding the
0080  * processor.
0081  */
0082 static void test_delay(int ticks)
0083 {
0084   rtems_interval start, stop;
0085   start = rtems_clock_get_ticks_since_boot();
0086   do {
0087     stop = rtems_clock_get_ticks_since_boot();
0088   } while ( (stop - start) < ticks );
0089 }
0090 
0091 static void task(rtems_task_argument arg)
0092 {
0093   rtems_status_code   sc;
0094 
0095   while (true) {
0096     sc = rtems_semaphore_obtain (task_sem, RTEMS_NO_WAIT, 0);
0097     if (sc == RTEMS_SUCCESSFUL) {
0098       task_data[arg].ran = true;
0099       task_data[arg].actual_cpu = rtems_scheduler_get_processor();
0100       rtems_semaphore_release(task_sem);
0101     }
0102   }
0103 }
0104 static void verify_tasks(void)
0105 {
0106   int i;
0107 
0108   printf("Verify Tasks Ran\n");
0109 
0110   while( rtems_semaphore_obtain (task_sem, RTEMS_NO_WAIT, 0) != RTEMS_SUCCESSFUL );
0111 
0112   /* Set Init task data */
0113   task_data[0].ran = true;
0114   task_data[0].actual_cpu = rtems_scheduler_get_processor();
0115 
0116   /* Verify all tasks */
0117   for (i = 0; i < NUM_CPUS; i++) {
0118     if (i==0)
0119       printf("Init(%" PRIu32 "): ran=%d expected=%d actual=%d\n",
0120         task_data[i].priority,
0121         task_data[i].ran,
0122         task_data[i].expected_cpu,
0123         task_data[i].actual_cpu
0124       );
0125     else
0126       printf( "TA0%d(%" PRIu32 "): ran=%d expected=%d actual=%d\n",
0127         i,
0128         task_data[i].priority,
0129         task_data[i].ran,
0130         task_data[i].expected_cpu,
0131         task_data[i].actual_cpu
0132       );
0133 
0134     /*  Abort test if values are not as expected */
0135     if ( task_data[i].expected_cpu == -1 )
0136       rtems_test_assert( task_data[i].ran == false );
0137     else {
0138       rtems_test_assert( task_data[i].ran == true );
0139       rtems_test_assert( task_data[i].expected_cpu == task_data[i].actual_cpu );
0140     }
0141   }
0142 
0143   rtems_semaphore_release(task_sem);
0144 }
0145 
0146 static void test(void)
0147 {
0148   rtems_status_code   sc;
0149   rtems_task_argument i;
0150   size_t              size;
0151   uint32_t            cpu_count;
0152   rtems_task_priority priority;
0153 
0154   /* Get the number of processors that we are using. */
0155   cpu_count = rtems_scheduler_get_processor_maximum();
0156   if (cpu_count != 4) {
0157     printf("Test requires a minimum of 4 cores\n");
0158     return;
0159   }
0160 
0161   size = sizeof(cpu_set_t);
0162   task_data[0].id = rtems_task_self();
0163   printf("Create Semaphore\n");
0164 
0165   sc = rtems_semaphore_create(
0166     rtems_build_name('S', 'E', 'M', '0'),
0167     1,                                               /* initial count = 1 */
0168     RTEMS_BINARY_SEMAPHORE |
0169     RTEMS_PRIORITY |
0170     RTEMS_PRIORITY_CEILING,
0171     0,
0172     &task_sem
0173   );
0174   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0175 
0176 
0177   /* Create and start tasks on each cpu with the appropriate affinity. */
0178   for (i = 1; i < TASK_COUNT; i++) {
0179 
0180       sc = rtems_task_create(
0181         rtems_build_name('T', 'A', '0', '0'+i),
0182         task_data[ i ].priority,
0183         RTEMS_MINIMUM_STACK_SIZE,
0184         RTEMS_DEFAULT_MODES,
0185         RTEMS_DEFAULT_ATTRIBUTES,
0186         &task_data[ i ].id
0187       );
0188       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0189 
0190       sc = rtems_task_set_affinity(
0191         task_data[ i ].id,
0192         size,
0193         &task_data[i].cpuset
0194       );
0195       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0196 
0197       printf(
0198         "Start TA%" PRIdrtems_task_argument " at priority %"
0199           PRIu32 " on cpu %d\n",
0200          i,
0201          task_data[i].priority,
0202          task_data[i].expected_cpu
0203       );
0204       sc = rtems_task_start( task_data[ i ].id, task, i );
0205       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0206   }
0207 
0208   /* spin for 100 ticks */
0209   test_delay(100);
0210 
0211   verify_tasks();
0212 
0213   i = TASK_COUNT - 1;
0214   task_data[ i ].priority = 4;
0215   printf(
0216     "Set TA%" PRIdrtems_task_argument " priority %" PRIu32 "\n",
0217     i,
0218     task_data[i].priority
0219   );
0220   sc = rtems_task_set_priority(
0221     task_data[ i ].id,
0222     task_data[ i ].priority,
0223     &priority
0224   );
0225   test_delay(25);
0226 
0227   while( rtems_semaphore_obtain (task_sem, RTEMS_NO_WAIT, 0) != RTEMS_SUCCESSFUL );
0228   for (i = 0; i < TASK_COUNT; i++) {
0229     task_data[ i ].expected_cpu = task_data[ i ].migrate_cpu;
0230     task_data[ i ].actual_cpu = -1;
0231     task_data[ i ].ran = false;
0232   }
0233   rtems_semaphore_release(task_sem);
0234   test_delay(25);
0235   verify_tasks();
0236 }
0237 
0238 static void Init(rtems_task_argument arg)
0239 {
0240   TEST_BEGIN();
0241 
0242   test();
0243 
0244   TEST_END();
0245   rtems_test_exit(0);
0246 }
0247 
0248 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0249 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0250 
0251 #define CONFIGURE_SCHEDULER_PRIORITY_AFFINITY_SMP
0252 
0253 #define CONFIGURE_MAXIMUM_PROCESSORS NUM_CPUS
0254 
0255 #define CONFIGURE_MAXIMUM_TASKS          TASK_COUNT
0256 
0257 #define CONFIGURE_MAXIMUM_SEMAPHORES 1
0258 
0259 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0260 
0261 #define CONFIGURE_INIT_TASK_PRIORITY       7
0262 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0263 
0264 #define CONFIGURE_INIT
0265 
0266 #include <rtems/confdefs.h>