/* * Copyright (c) 2014, 2017 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 * 82178 Puchheim * Germany * * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "tmacros.h" const char rtems_test_name[] = "SMPSCHEDULER 2"; #define SCHED_A rtems_build_name(' ', ' ', ' ', 'A') #define SCHED_B rtems_build_name(' ', ' ', ' ', 'B') #define SCHED_C rtems_build_name(' ', ' ', ' ', 'C') static rtems_id main_task_id; static rtems_id cmtx_id; static rtems_id imtx_id; static volatile bool ready; static void task(rtems_task_argument arg) { rtems_status_code sc; (void) arg; rtems_test_assert(rtems_scheduler_get_processor() == 1); rtems_test_assert(sched_get_priority_min(SCHED_RR) == 1); rtems_test_assert(sched_get_priority_max(SCHED_RR) == INT_MAX - 1); sc = rtems_semaphore_obtain(cmtx_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT); rtems_test_assert(sc == RTEMS_NOT_DEFINED); sc = rtems_event_transient_send(main_task_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_semaphore_obtain(imtx_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_semaphore_release(imtx_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_event_transient_send(main_task_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); while (1) { /* Do nothing */ } } static void sticky_task(rtems_task_argument arg) { rtems_status_code sc; rtems_id mtx_id; (void) arg; rtems_test_assert(rtems_scheduler_get_processor() == 0); sc = rtems_semaphore_create( rtems_build_name(' ', 'M', 'T', 'X'), 1, RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_MULTIPROCESSOR_RESOURCE_SHARING, 2, &mtx_id ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_semaphore_obtain(mtx_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT); rtems_test_assert(sc == RTEMS_SUCCESSFUL); ready = true; sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_semaphore_release(mtx_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_semaphore_delete(mtx_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_event_transient_send(main_task_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); while (1) { /* Do nothing */ } } static void test_scheduler_add_remove_processors(void) { rtems_status_code sc; rtems_id scheduler_a_id; rtems_id scheduler_c_id; sc = rtems_scheduler_ident(SCHED_A, &scheduler_a_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_scheduler_ident(SCHED_C, &scheduler_c_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_scheduler_add_processor(scheduler_c_id, 62); rtems_test_assert(sc == RTEMS_NOT_CONFIGURED); sc = rtems_scheduler_add_processor(scheduler_c_id, 63); rtems_test_assert(sc == RTEMS_INCORRECT_STATE); sc = rtems_scheduler_remove_processor(scheduler_c_id, 62); rtems_test_assert(sc == RTEMS_INVALID_NUMBER); sc = rtems_scheduler_remove_processor(scheduler_a_id, 0); rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE); if (rtems_scheduler_get_processor_maximum() > 1) { rtems_id scheduler_id; rtems_id scheduler_b_id; rtems_id task_id; cpu_set_t first_cpu; sc = rtems_scheduler_ident(SCHED_B, &scheduler_b_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_scheduler_remove_processor(scheduler_b_id, 1); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_scheduler_add_processor(scheduler_a_id, 1); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(rtems_scheduler_get_processor() == 0); sc = rtems_scheduler_remove_processor(scheduler_a_id, 0); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(rtems_scheduler_get_processor() == 1); CPU_ZERO(&first_cpu); CPU_SET(0, &first_cpu); sc = rtems_scheduler_ident_by_processor_set( sizeof(first_cpu), &first_cpu, &scheduler_id ); rtems_test_assert(sc == RTEMS_INCORRECT_STATE); sc = rtems_scheduler_add_processor(scheduler_a_id, 0); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(rtems_scheduler_get_processor() == 1); sc = rtems_task_create( rtems_build_name('T', 'A', 'S', 'K'), 2, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &task_id ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_start(task_id, sticky_task, 0); rtems_test_assert(sc == RTEMS_SUCCESSFUL); while (!ready) { /* Wait */ } sc = rtems_scheduler_remove_processor(scheduler_a_id, 1); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(rtems_scheduler_get_processor() == 0); sc = rtems_event_transient_send(task_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_delete(task_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_scheduler_add_processor(scheduler_b_id, 1); rtems_test_assert(sc == RTEMS_SUCCESSFUL); } } static void test(void) { rtems_status_code sc; rtems_id task_id; rtems_id scheduler_id; rtems_id scheduler_a_id; rtems_id scheduler_b_id; rtems_id scheduler_c_id; rtems_task_priority prio; cpu_set_t cpuset; cpu_set_t first_cpu; cpu_set_t second_cpu; cpu_set_t all_cpus; cpu_set_t online_cpus; uint32_t cpu_count; rtems_test_assert(rtems_scheduler_get_processor() == 0); cpu_count = rtems_scheduler_get_processor_maximum(); main_task_id = rtems_task_self(); CPU_ZERO(&first_cpu); CPU_SET(0, &first_cpu); CPU_ZERO(&second_cpu); CPU_SET(1, &second_cpu); CPU_FILL(&all_cpus); CPU_ZERO(&online_cpus); CPU_SET(0, &online_cpus); if (cpu_count > 1) { CPU_SET(1, &online_cpus); } sc = rtems_scheduler_ident(SCHED_A, &scheduler_a_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); if (cpu_count > 1) { sc = rtems_scheduler_ident(SCHED_B, &scheduler_b_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(scheduler_a_id != scheduler_b_id); } sc = rtems_scheduler_ident(SCHED_C, &scheduler_c_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_semaphore_create( rtems_build_name('C', 'M', 'T', 'X'), 1, RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING, 1, &cmtx_id ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_semaphore_create( rtems_build_name('I', 'M', 'T', 'X'), 1, RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 1, &imtx_id ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); prio = 2; sc = rtems_semaphore_set_priority(cmtx_id, scheduler_a_id, prio, &prio); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(prio == 1); if (cpu_count > 1) { prio = 1; sc = rtems_semaphore_set_priority(cmtx_id, scheduler_b_id, prio, &prio); rtems_test_assert(sc == RTEMS_NOT_DEFINED); rtems_test_assert(prio == 1); } CPU_ZERO(&cpuset); sc = rtems_scheduler_get_processor_set( scheduler_a_id, sizeof(cpuset), &cpuset ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(CPU_EQUAL(&cpuset, &first_cpu)); if (cpu_count > 1) { CPU_ZERO(&cpuset); sc = rtems_scheduler_get_processor_set( scheduler_b_id, sizeof(cpuset), &cpuset ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(CPU_EQUAL(&cpuset, &second_cpu)); } sc = rtems_task_create( rtems_build_name('T', 'A', 'S', 'K'), 1, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &task_id ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_get_scheduler(task_id, &scheduler_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(scheduler_id == scheduler_a_id); CPU_ZERO(&cpuset); sc = rtems_task_get_affinity(task_id, sizeof(cpuset), &cpuset); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(CPU_EQUAL(&cpuset, &online_cpus)); rtems_test_assert(sched_get_priority_min(SCHED_RR) == 1); rtems_test_assert(sched_get_priority_max(SCHED_RR) == 254); sc = rtems_task_set_scheduler(task_id, scheduler_c_id, 1); rtems_test_assert(sc == RTEMS_UNSATISFIED); sc = rtems_task_set_scheduler(task_id, scheduler_c_id + 1, 1); rtems_test_assert(sc == RTEMS_INVALID_ID); if (cpu_count > 1) { sc = rtems_task_set_scheduler(task_id, scheduler_b_id, 1); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_get_scheduler(task_id, &scheduler_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(scheduler_id == scheduler_b_id); CPU_ZERO(&cpuset); sc = rtems_task_get_affinity(task_id, sizeof(cpuset), &cpuset); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(CPU_EQUAL(&cpuset, &online_cpus)); sc = rtems_task_set_affinity(task_id, sizeof(all_cpus), &all_cpus); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_set_affinity(task_id, sizeof(first_cpu), &first_cpu); rtems_test_assert(sc == RTEMS_INVALID_NUMBER); sc = rtems_task_get_scheduler(task_id, &scheduler_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(scheduler_id == scheduler_b_id); sc = rtems_task_set_affinity(task_id, sizeof(online_cpus), &online_cpus); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_set_affinity(task_id, sizeof(second_cpu), &second_cpu); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_set_scheduler(task_id, scheduler_a_id, 1); rtems_test_assert(sc == RTEMS_UNSATISFIED); sc = rtems_task_get_scheduler(task_id, &scheduler_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(scheduler_id == scheduler_b_id); sc = rtems_semaphore_obtain(imtx_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_set_scheduler(task_id, scheduler_b_id, 1); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_start(task_id, task, 0); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); rtems_test_assert(sc == RTEMS_SUCCESSFUL); /* Ensure that the other task waits for the mutex owned by us */ sc = rtems_task_wake_after(2); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_set_scheduler(RTEMS_SELF, scheduler_b_id, 1); rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE); sc = rtems_semaphore_release(imtx_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); rtems_test_assert(sc == RTEMS_SUCCESSFUL); } sc = rtems_task_delete(task_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_semaphore_delete(cmtx_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_semaphore_delete(imtx_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); test_scheduler_add_remove_processors(); } static void Init(rtems_task_argument arg) { rtems_resource_snapshot snapshot; TEST_BEGIN(); rtems_resource_snapshot_take(&snapshot); test(); rtems_test_assert(rtems_resource_snapshot_check(&snapshot)); TEST_END(); rtems_test_exit(0); } #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER #define CONFIGURE_MAXIMUM_TASKS 2 #define CONFIGURE_MAXIMUM_SEMAPHORES 2 /* Lets see when the first RTEMS system hits this limit */ #define CONFIGURE_MAXIMUM_PROCESSORS 64 #define CONFIGURE_SCHEDULER_EDF_SMP #define CONFIGURE_SCHEDULER_PRIORITY_SMP #define CONFIGURE_SCHEDULER_SIMPLE_SMP #include RTEMS_SCHEDULER_PRIORITY_SMP(a, 256); RTEMS_SCHEDULER_EDF_SMP(b); RTEMS_SCHEDULER_SIMPLE_SMP(c); #define CONFIGURE_SCHEDULER_TABLE_ENTRIES \ RTEMS_SCHEDULER_TABLE_PRIORITY_SMP(a, SCHED_A), \ RTEMS_SCHEDULER_TABLE_EDF_SMP(b, SCHED_B), \ RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(c, SCHED_C) #define CONFIGURE_SCHEDULER_ASSIGNMENTS \ RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \ RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN(2, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL) #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION #define CONFIGURE_RTEMS_INIT_TASKS_TABLE #define CONFIGURE_INIT #include