diff options
Diffstat (limited to 'testsuites/validation/tx-preemption-intervention.c')
-rw-r--r-- | testsuites/validation/tx-preemption-intervention.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/testsuites/validation/tx-preemption-intervention.c b/testsuites/validation/tx-preemption-intervention.c new file mode 100644 index 0000000000..612190567e --- /dev/null +++ b/testsuites/validation/tx-preemption-intervention.c @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestSuites + * + * @brief This source file contains the implementation of + * SetPreemptionIntervention(). + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tx-support.h" + +#include <rtems/sysinit.h> +#include <rtems/score/chainimpl.h> +#include <rtems/score/percpu.h> +#include <rtems/score/threadimpl.h> + +#include <rtems/test.h> + +#if defined(RTEMS_SMP) +typedef struct { + void ( *handler )( void * ); + void *arg; + Scheduler_Context scheduler_context; + Scheduler_Node scheduler_node; + Thread_Control thread; +} PreemptionInterventionContext; + +static PreemptionInterventionContext preemption_intervention_instance; + +static bool PreemptionInterventionAskForHelp( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node +) +{ + PreemptionInterventionContext *ctx; + void ( *handler )( void * ); + void *arg; + + (void) scheduler; + (void) thread; + (void) node; + + ctx = &preemption_intervention_instance; + handler = ctx->handler; + arg = ctx->arg; + ctx->handler = NULL; + ctx->arg = NULL; + ( *handler )( arg ); + + return true; +} + +static const Scheduler_Control preemption_intervention_scheduler = { + .context = &preemption_intervention_instance.scheduler_context, + .Operations = { + .ask_for_help = PreemptionInterventionAskForHelp + } +}; + +static void PreemptionInterventionInitialize( void ) +{ + PreemptionInterventionContext *ctx; + + ctx = &preemption_intervention_instance; + + _Chain_Initialize_node( &ctx->thread.Scheduler.Help_node ); + _Thread_queue_Initialize( + &ctx->thread.Join_queue, + "Preemption Intervention" + ); + _ISR_lock_Initialize( + &ctx->scheduler_context.Lock, + "Preemption Intervention" + ); + _Scheduler_Node_do_initialize( + &preemption_intervention_scheduler, + &ctx->scheduler_node, + &ctx->thread, + 0 + ); + _Chain_Initialize_one( + &ctx->thread.Scheduler.Scheduler_nodes, + &ctx->scheduler_node.Thread.Scheduler_node.Chain + ); +} + +RTEMS_SYSINIT_ITEM( + PreemptionInterventionInitialize, + RTEMS_SYSINIT_DEVICE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); +#endif + +void SetPreemptionIntervention( + struct Per_CPU_Control *cpu, + void ( *handler )( void * ), + void *arg +) +{ +#if defined(RTEMS_SMP) + PreemptionInterventionContext *ctx; + rtems_interrupt_level level; + ISR_lock_Context lock_context; + + ctx = &preemption_intervention_instance; + T_quiet_assert_null( ctx->handler ); + ctx->handler = handler; + ctx->arg = arg; + + rtems_interrupt_local_disable( level ); + _Per_CPU_Acquire( cpu, &lock_context ); + _Chain_Append_unprotected( + &cpu->Threads_in_need_for_help, + &ctx->thread.Scheduler.Help_node + ); + _Per_CPU_Release( cpu, &lock_context ); + rtems_interrupt_local_enable( level ); +#else + (void) cpu; + (void) handler; + (void) arg; +#endif +} |