Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (c) 2016 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 "tmacros.h"
0033 
0034 #include <rtems.h>
0035 #include <rtems/libcsupport.h>
0036 #include <rtems/score/percpu.h>
0037 #include <rtems/score/smpbarrier.h>
0038 
0039 #include <test_support.h>
0040 
0041 #define CPU_COUNT 2
0042 
0043 #define SCHEDULER_A rtems_build_name(' ', ' ', ' ', 'A')
0044 
0045 #define SCHEDULER_B rtems_build_name(' ', ' ', ' ', 'B')
0046 
0047 const char rtems_test_name[] = "SMPCLOCK 1";
0048 
0049 typedef struct {
0050   SMP_barrier_Control barrier;
0051   SMP_barrier_State delay_barrier_state;
0052   SMP_barrier_State timer_barrier_state;
0053 } test_context;
0054 
0055 static test_context test_instance = {
0056   .barrier = SMP_BARRIER_CONTROL_INITIALIZER,
0057   .delay_barrier_state = SMP_BARRIER_STATE_INITIALIZER,
0058   .timer_barrier_state = SMP_BARRIER_STATE_INITIALIZER
0059 };
0060 
0061 static void wait(test_context *ctx, SMP_barrier_State *bs)
0062 {
0063   _SMP_barrier_Wait(&ctx->barrier, bs, CPU_COUNT);
0064 }
0065 
0066 static void timer_isr(rtems_id id, void *arg)
0067 {
0068   test_context *ctx = arg;
0069 
0070   /* (B) */
0071   wait(ctx, &ctx->timer_barrier_state);
0072 }
0073 
0074 static void timer_task(rtems_task_argument arg)
0075 {
0076   test_context *ctx = (test_context *) arg;
0077   rtems_status_code sc;
0078   rtems_id timer_id;
0079 
0080   rtems_test_assert(rtems_scheduler_get_processor() == 1);
0081 
0082   sc = rtems_timer_create(SCHEDULER_B, &timer_id);
0083   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0084 
0085   /* (A) */
0086   wait(ctx, &ctx->timer_barrier_state);
0087 
0088   sc = rtems_timer_fire_after(timer_id, 1, timer_isr, ctx);
0089   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0090 
0091   sc = rtems_task_wake_after(1);
0092   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0093 
0094   sc = rtems_timer_delete(timer_id);
0095   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0096 
0097   /* (C) */
0098   wait(ctx, &ctx->timer_barrier_state);
0099 
0100   while (true) {
0101     /* Wait for deletion */
0102   }
0103 }
0104 
0105 static void delay_clock_tick(test_context *ctx)
0106 {
0107   rtems_interrupt_level level;
0108   const Per_CPU_Control *cpu_self = _Per_CPU_Get_by_index(0);
0109   const Per_CPU_Control *cpu_other = _Per_CPU_Get_by_index(1);
0110   uint64_t ticks;
0111 
0112   rtems_test_assert(rtems_scheduler_get_processor() == 0);
0113 
0114   rtems_test_spin_until_next_tick();
0115   ticks = cpu_self->Watchdog.ticks;
0116 
0117   rtems_interrupt_local_disable(level);
0118 
0119   /* (A) */
0120   wait(ctx, &ctx->delay_barrier_state);
0121 
0122   /* (B) */
0123   wait(ctx, &ctx->delay_barrier_state);
0124 
0125   rtems_test_assert(cpu_self->Watchdog.ticks == ticks);
0126   rtems_test_assert(cpu_other->Watchdog.ticks == ticks + 1);
0127 
0128   rtems_interrupt_local_enable(level);
0129 
0130   rtems_test_assert(cpu_self->Watchdog.ticks == ticks + 1);
0131   rtems_test_assert(cpu_other->Watchdog.ticks == ticks + 1);
0132 
0133   /* (C) */
0134   wait(ctx, &ctx->delay_barrier_state);
0135 }
0136 
0137 static void test(void)
0138 {
0139   test_context *ctx = &test_instance;
0140   rtems_status_code sc;
0141   rtems_id scheduler_b_id;
0142   rtems_id task_id;
0143 
0144   sc = rtems_scheduler_ident(SCHEDULER_B, &scheduler_b_id);
0145   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0146 
0147   sc = rtems_task_create(
0148     SCHEDULER_B,
0149     255,
0150     RTEMS_MINIMUM_STACK_SIZE,
0151     RTEMS_DEFAULT_MODES,
0152     RTEMS_DEFAULT_ATTRIBUTES,
0153     &task_id
0154   );
0155   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0156 
0157   sc = rtems_task_set_scheduler(task_id, scheduler_b_id, 1);
0158   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0159 
0160   sc = rtems_task_start(task_id, timer_task, (rtems_task_argument) ctx);
0161   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0162 
0163   delay_clock_tick(ctx);
0164 
0165   sc = rtems_task_delete(task_id);
0166   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0167 }
0168 
0169 static void Init(rtems_task_argument arg)
0170 {
0171   rtems_resource_snapshot snapshot;
0172 
0173   TEST_BEGIN();
0174 
0175   rtems_resource_snapshot_take(&snapshot);
0176 
0177   if (rtems_scheduler_get_processor_maximum() == CPU_COUNT) {
0178     test();
0179   }
0180 
0181   rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0182 
0183   TEST_END();
0184   rtems_test_exit(0);
0185 }
0186 
0187 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0188 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0189 
0190 #define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
0191 
0192 #define CONFIGURE_SCHEDULER_SIMPLE_SMP
0193 
0194 #include <rtems/scheduler.h>
0195 
0196 RTEMS_SCHEDULER_SIMPLE_SMP(a);
0197 RTEMS_SCHEDULER_SIMPLE_SMP(b);
0198 
0199 #define CONFIGURE_SCHEDULER_TABLE_ENTRIES \
0200   RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(a, SCHEDULER_A), \
0201   RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(b, SCHEDULER_B)
0202 
0203 #define CONFIGURE_SCHEDULER_ASSIGNMENTS \
0204   RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
0205   RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
0206 
0207 #define CONFIGURE_MAXIMUM_TASKS CPU_COUNT
0208 
0209 #define CONFIGURE_MAXIMUM_TIMERS 1
0210 
0211 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0212 
0213 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0214 
0215 #define CONFIGURE_INIT
0216 
0217 #include <rtems/confdefs.h>