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) 2013 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.h>
0033 #include <rtems/score/threadimpl.h>
0034 
0035 #include "tmacros.h"
0036 
0037 const char rtems_test_name[] = "SMPSCHEDULER 1";
0038 
0039 #define CPU_COUNT 2
0040 
0041 #define TASK_COUNT 4
0042 
0043 #define FIRST_TASK_PRIORITY 1
0044 
0045 #define SECOND_TASK_READY RTEMS_EVENT_0
0046 
0047 static rtems_id task_ids[TASK_COUNT];
0048 
0049 static void suspend(size_t i)
0050 {
0051   rtems_status_code sc = rtems_task_suspend(task_ids[i]);
0052   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0053 }
0054 
0055 static void resume(size_t i)
0056 {
0057   rtems_status_code sc = rtems_task_resume(task_ids[i]);
0058   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0059 }
0060 
0061 static void task(rtems_task_argument arg)
0062 {
0063   rtems_task_priority task_priority;
0064   rtems_status_code sc;
0065 
0066   sc = rtems_task_set_priority(
0067     RTEMS_SELF,
0068     RTEMS_CURRENT_PRIORITY,
0069     &task_priority
0070   );
0071   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0072 
0073   if (arg == 1) {
0074     sc = rtems_event_send(task_ids[0], SECOND_TASK_READY);
0075     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0076   }
0077 
0078   while (true) {
0079     /* Do nothing */
0080   }
0081 }
0082 
0083 static bool is_per_cpu_state_ok(void)
0084 {
0085   bool ok = true;
0086   uint32_t n = rtems_scheduler_get_processor_maximum();
0087   uint32_t i;
0088 
0089   for (i = 0; i < n; ++i) {
0090     const Thread_Control *thread = _Per_CPU_Get_by_index(i)->executing;
0091     uint32_t count = 0;
0092     uint32_t j;
0093 
0094     for (j = 0; j < n; ++j) {
0095       const Per_CPU_Control *cpu = _Per_CPU_Get_by_index(j);
0096       const Thread_Control *executing = cpu->executing;
0097       const Thread_Control *heir = cpu->heir;
0098 
0099       if (i != j) {
0100         count += executing == thread;
0101         count += heir == thread;
0102       } else {
0103         ++count;
0104       }
0105 
0106       ok = ok && _Thread_Get_CPU( executing ) == cpu;
0107       ok = ok && _Thread_Get_CPU( heir ) == cpu;
0108     }
0109 
0110     ok = ok && (count == 1);
0111   }
0112 
0113   return ok;
0114 }
0115 
0116 static void test_scheduler_cross(void)
0117 {
0118   bool per_cpu_state_ok;
0119   Per_CPU_Control *cpu_self;
0120 
0121   cpu_self = _Thread_Dispatch_disable();
0122 
0123   suspend(0);
0124   suspend(1);
0125   resume(0);
0126   resume(1);
0127 
0128   per_cpu_state_ok = is_per_cpu_state_ok();
0129 
0130   _Thread_Dispatch_enable( cpu_self );
0131 
0132   rtems_test_assert(per_cpu_state_ok);
0133 }
0134 
0135 static void test_scheduler_move_heir(void)
0136 {
0137   bool per_cpu_state_ok;
0138   Per_CPU_Control *cpu_self;
0139 
0140   cpu_self = _Thread_Dispatch_disable();
0141 
0142   suspend(2);
0143   suspend(3);
0144   suspend(0);
0145   resume(2);
0146   suspend(1);
0147   resume(3);
0148   resume(0);
0149 
0150   per_cpu_state_ok = is_per_cpu_state_ok();
0151 
0152   resume(1);
0153 
0154   _Thread_Dispatch_enable( cpu_self );
0155 
0156   rtems_test_assert(per_cpu_state_ok);
0157 }
0158 
0159 static void test(void)
0160 {
0161   rtems_event_set events;
0162   rtems_status_code sc;
0163   rtems_task_argument task_index;
0164 
0165   task_ids[0] = rtems_task_self();
0166 
0167   for (task_index = 1; task_index < TASK_COUNT; ++task_index) {
0168       rtems_id task_id;
0169 
0170       sc = rtems_task_create(
0171         rtems_build_name('T', 'A', 'S', 'K'),
0172         FIRST_TASK_PRIORITY + task_index,
0173         RTEMS_MINIMUM_STACK_SIZE,
0174         RTEMS_DEFAULT_MODES,
0175         RTEMS_DEFAULT_ATTRIBUTES,
0176         &task_id
0177       );
0178       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0179 
0180       sc = rtems_task_start(task_id, task, task_index);
0181       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0182 
0183       task_ids[task_index] = task_id;
0184   }
0185 
0186   sc = rtems_event_receive(
0187     SECOND_TASK_READY,
0188     RTEMS_EVENT_ALL | RTEMS_WAIT,
0189     RTEMS_NO_TIMEOUT,
0190     &events
0191   );
0192   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0193   rtems_test_assert(events == SECOND_TASK_READY);
0194 
0195   test_scheduler_cross();
0196   test_scheduler_move_heir();
0197 }
0198 
0199 static void Init(rtems_task_argument arg)
0200 {
0201   TEST_BEGIN();
0202 
0203   test();
0204 
0205   TEST_END();
0206   rtems_test_exit(0);
0207 }
0208 
0209 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0210 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0211 
0212 #define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
0213 
0214 #define CONFIGURE_MAXIMUM_TASKS TASK_COUNT
0215 
0216 /* We need a scheduler with lazy processor allocation for this test */
0217 #define CONFIGURE_SCHEDULER_SIMPLE_SMP
0218 
0219 #define CONFIGURE_INIT_TASK_PRIORITY FIRST_TASK_PRIORITY
0220 #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
0221 #define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES
0222 
0223 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0224 
0225 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0226 
0227 #define CONFIGURE_INIT
0228 
0229 #include <rtems/confdefs.h>