forked from Imagelibrary/rtems
600 lines
15 KiB
C
600 lines
15 KiB
C
/* SPDX-License-Identifier: BSD-2-Clause */
|
|
|
|
/**
|
|
* @file
|
|
*
|
|
* @ingroup RTEMSTestSuites
|
|
*
|
|
* @brief This header file provides the support functions for the validation
|
|
* test cases.
|
|
*/
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
|
|
#ifndef _TX_SUPPORT_H
|
|
#define _TX_SUPPORT_H
|
|
|
|
#include <rtems.h>
|
|
#include <rtems/irq-extension.h>
|
|
#include <rtems/score/atomic.h>
|
|
#include <rtems/score/threadq.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @addtogroup RTEMSTestSuites
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
typedef enum {
|
|
PRIO_PSEUDO_ISR,
|
|
PRIO_VERY_ULTRA_HIGH,
|
|
PRIO_ULTRA_HIGH,
|
|
PRIO_VERY_HIGH,
|
|
PRIO_HIGH,
|
|
PRIO_NORMAL,
|
|
PRIO_LOW,
|
|
PRIO_VERY_LOW,
|
|
PRIO_ULTRA_LOW
|
|
} Priority;
|
|
|
|
/**
|
|
* @brief This constants represents the default priority of the runner task.
|
|
*/
|
|
#define PRIO_DEFAULT 1
|
|
|
|
/**
|
|
* @brief This constants represents an invalid RTEMS task priority value.
|
|
*
|
|
* It should be an invalid priority value which is not equal to
|
|
* RTEMS_CURRENT_PRIORITY and RTEMS_TIMER_SERVER_DEFAULT_PRIORITY.
|
|
*/
|
|
#define PRIO_INVALID 0xfffffffe
|
|
|
|
/**
|
|
* @brief This constants represents a priority which is close to the priority
|
|
* of the idle thread.
|
|
*
|
|
* It may be used for the runner thread together with PRIO_FLEXIBLE for worker
|
|
* threads.
|
|
*/
|
|
#define PRIO_NEARLY_IDLE 126
|
|
|
|
/**
|
|
* @brief This constants represents a priority with a wider range of higher and
|
|
* lower priorities around it.
|
|
*
|
|
* It may be used for the worker threads together with PRIO_NEARLY_IDLE for the
|
|
* runner thread.
|
|
*/
|
|
#define PRIO_FLEXIBLE 64
|
|
|
|
/**
|
|
* @brief This constants represents an invalid RTEMS object identifier.
|
|
*/
|
|
#define INVALID_ID 0xfffffffd
|
|
|
|
/**
|
|
* @brief This constants represents an object name for tests.
|
|
*/
|
|
#define OBJECT_NAME rtems_build_name( 'T', 'E', 'S', 'T' )
|
|
|
|
#define CreateTask( name, priority ) \
|
|
DoCreateTask( \
|
|
rtems_build_name( name[ 0 ], name[ 1 ], name[ 2 ], name[ 3 ] ), \
|
|
priority \
|
|
)
|
|
|
|
#define SCHEDULER_A_ID 0xf010001
|
|
|
|
#define SCHEDULER_B_ID 0xf010002
|
|
|
|
#define SCHEDULER_C_ID 0xf010003
|
|
|
|
#define SCHEDULER_D_ID 0xf010004
|
|
|
|
rtems_id DoCreateTask( rtems_name name, rtems_task_priority priority );
|
|
|
|
void StartTask( rtems_id id, rtems_task_entry entry, void *arg );
|
|
|
|
void DeleteTask( rtems_id id );
|
|
|
|
void SuspendTask( rtems_id id );
|
|
|
|
void SuspendSelf( void );
|
|
|
|
void ResumeTask( rtems_id id );
|
|
|
|
bool IsTaskSuspended( rtems_id id );
|
|
|
|
rtems_event_set QueryPendingEvents( void );
|
|
|
|
rtems_event_set PollAnyEvents( void );
|
|
|
|
rtems_event_set ReceiveAnyEvents( void );
|
|
|
|
rtems_event_set ReceiveAnyEventsTimed( rtems_interval ticks );
|
|
|
|
void ReceiveAllEvents( rtems_event_set events );
|
|
|
|
void SendEvents( rtems_id id, rtems_event_set events );
|
|
|
|
rtems_mode GetMode( void );
|
|
|
|
rtems_mode SetMode( rtems_mode set, rtems_mode mask );
|
|
|
|
rtems_task_priority GetPriority( rtems_id id );
|
|
|
|
rtems_task_priority GetPriorityByScheduler(
|
|
rtems_id task_id,
|
|
rtems_id scheduler_id
|
|
);
|
|
|
|
rtems_task_priority SetPriority( rtems_id id, rtems_task_priority priority );
|
|
|
|
rtems_task_priority GetSelfPriority( void );
|
|
|
|
rtems_task_priority SetSelfPriority( rtems_task_priority priority );
|
|
|
|
rtems_task_priority SetSelfPriorityNoYield( rtems_task_priority priority );
|
|
|
|
rtems_id GetScheduler( rtems_id id );
|
|
|
|
rtems_id GetSelfScheduler( void );
|
|
|
|
void SetScheduler(
|
|
rtems_id task_id,
|
|
rtems_id scheduler_id,
|
|
rtems_task_priority priority
|
|
);
|
|
|
|
void SetSelfScheduler( rtems_id scheduler_id, rtems_task_priority priority );
|
|
|
|
void GetAffinity( rtems_id id, cpu_set_t *set );
|
|
|
|
void GetSelfAffinity( cpu_set_t *set );
|
|
|
|
void SetAffinity( rtems_id id, const cpu_set_t *set );
|
|
|
|
void SetSelfAffinity( const cpu_set_t *set );
|
|
|
|
void SetAffinityOne( rtems_id id, uint32_t cpu_index );
|
|
|
|
void SetSelfAffinityOne( uint32_t cpu_index );
|
|
|
|
void SetAffinityAll( rtems_id id );
|
|
|
|
void SetSelfAffinityAll( void );
|
|
|
|
void Yield( void );
|
|
|
|
void YieldTask( rtems_id id );
|
|
|
|
void AddProcessor( rtems_id scheduler_id, uint32_t cpu_index );
|
|
|
|
void RemoveProcessor( rtems_id scheduler_id, uint32_t cpu_index );
|
|
|
|
rtems_id CreateMutex( void );
|
|
|
|
rtems_id CreateMutexNoProtocol( void );
|
|
|
|
rtems_id CreateMutexFIFO( void );
|
|
|
|
bool IsMutexOwner( rtems_id id );
|
|
|
|
void DeleteMutex( rtems_id id );
|
|
|
|
void ObtainMutex( rtems_id id );
|
|
|
|
void ObtainMutexTimed( rtems_id id, rtems_interval ticks );
|
|
|
|
void ObtainMutexDeadlock( rtems_id id );
|
|
|
|
void ReleaseMutex( rtems_id id );
|
|
|
|
struct Thread_queue_Queue;
|
|
|
|
struct Thread_queue_Queue *GetMutexThreadQueue( rtems_id id );
|
|
|
|
void RestoreRunnerASR( void );
|
|
|
|
void RestoreRunnerMode( void );
|
|
|
|
void RestoreRunnerPriority( void );
|
|
|
|
struct _Thread_Control;
|
|
|
|
struct _Thread_Control *GetThread( rtems_id id );
|
|
|
|
struct _Thread_Control *GetExecuting( void );
|
|
|
|
void KillZombies( void );
|
|
|
|
void WaitForExecutionStop( rtems_id task_id );
|
|
|
|
void WaitForIntendToBlock( rtems_id task_id );
|
|
|
|
void WaitForHeir( uint32_t cpu_index, rtems_id task_id );
|
|
|
|
void WaitForNextTask( uint32_t cpu_index, rtems_id task_id );
|
|
|
|
typedef enum {
|
|
TASK_TIMER_INVALID,
|
|
TASK_TIMER_INACTIVE,
|
|
TASK_TIMER_TICKS,
|
|
TASK_TIMER_REALTIME,
|
|
TASK_TIMER_MONOTONIC
|
|
} TaskTimerState;
|
|
|
|
typedef struct {
|
|
TaskTimerState state;
|
|
uint64_t expire_ticks;
|
|
struct timespec expire_timespec;
|
|
} TaskTimerInfo;
|
|
|
|
void GetTaskTimerInfo( rtems_id id, TaskTimerInfo *info );
|
|
|
|
void GetTaskTimerInfoByThread(
|
|
struct _Thread_Control *thread,
|
|
TaskTimerInfo *info
|
|
);
|
|
|
|
void ClockTick( void );
|
|
|
|
/**
|
|
* @brief Simulates a clock tick with the final expire time point of
|
|
* UINT64_MAX for all clocks.
|
|
*
|
|
* This function does not update the clock ticks counter.
|
|
*/
|
|
void FinalClockTick( void );
|
|
|
|
/**
|
|
* @brief Simulates a single clock tick using the software timecounter.
|
|
*
|
|
* In contrast to ClockTick(), this function updates also CLOCK_MONOTONIC and
|
|
* CLOCK_REALTIME to the next software timecounter clock tick time point.
|
|
*
|
|
* This function is designed for test suites not having a clock driver.
|
|
*/
|
|
void TimecounterTick( void );
|
|
|
|
typedef uint32_t ( *GetTimecountHandler )( void );
|
|
|
|
/**
|
|
* @brief Sets the get timecount handler.
|
|
*
|
|
* Using this function will replace the timecounter of the clock driver.
|
|
*
|
|
* @return Returns the previous get timecount handler.
|
|
*/
|
|
GetTimecountHandler SetGetTimecountHandler( GetTimecountHandler handler );
|
|
|
|
/**
|
|
* @brief This constant represents the fake frequency of the software
|
|
* timecounter.
|
|
*/
|
|
#define SOFTWARE_TIMECOUNTER_FREQUENCY 1000000
|
|
|
|
/**
|
|
* @brief Gets the software timecount counter value.
|
|
*
|
|
* @return Returns the current software timecounter counter value.
|
|
*/
|
|
uint32_t GetTimecountCounter( void );
|
|
|
|
/**
|
|
* @brief Sets and gets the software timecount counter value.
|
|
*
|
|
* @param counter is the new software timecounter counter value.
|
|
*
|
|
* @return Returns the previous software timecounter counter value.
|
|
*/
|
|
uint32_t SetTimecountCounter( uint32_t counter );
|
|
|
|
/**
|
|
* @brief Return the task id of the timer server task
|
|
*
|
|
* This function is an attempt to avoid using RTEMS internal global
|
|
* _Timer_server throughout the validation test code.
|
|
*
|
|
* @return Returns the task id of the timer server task, if
|
|
* rtems_timer_initiate_server() has been invoked before,
|
|
* otherwise - if the timer server task does not exist -
|
|
* RTEMS_INVALID_ID is returned.
|
|
*/
|
|
rtems_id GetTimerServerTaskId( void );
|
|
|
|
/**
|
|
* @brief Undo the effects of rtems_timer_initiate_server()
|
|
*
|
|
* If rtems_timer_initiate_server() was never called before,
|
|
* nothing is done.
|
|
*
|
|
* If rtems_timer_initiate_server() was called before, the
|
|
* created thread and other resources are freed so that
|
|
* rtems_timer_initiate_server() can be called again.
|
|
* There should be no pending timers which are not yet executed
|
|
* by the server task. Naturally, there should be no
|
|
* timer server timers scheduled for execution.
|
|
*
|
|
* @return Returns true, if rtems_timer_initiate_server() has been
|
|
* invoked before and the timer server task has indeed been deleted,
|
|
* otherwise false.
|
|
*/
|
|
bool DeleteTimerServer( void );
|
|
|
|
typedef struct {
|
|
struct {
|
|
const void *begin;
|
|
void *free_begin;
|
|
const void *end;
|
|
} areas[ 2 ];
|
|
size_t count;
|
|
} MemoryContext;
|
|
|
|
void MemorySave( MemoryContext *ctx );
|
|
|
|
void MemoryRestore( const MemoryContext *ctx );
|
|
|
|
/**
|
|
* @brief Fails a dynamic memory allocation when the counter reaches zero.
|
|
*
|
|
* This function initializes an internal counter which is decremented before
|
|
* each dynamic memory allocation though the rtems_malloc() directive. When
|
|
* the counter decrements from one to zero, the allocation fails and NULL will
|
|
* be returned.
|
|
*
|
|
* @param counter is the initial counter value.
|
|
*/
|
|
void MemoryAllocationFailWhen( uint32_t counter );
|
|
|
|
typedef struct {
|
|
Chain_Node node;
|
|
void ( *handler )( void * );
|
|
void *arg;
|
|
Atomic_Uint done;
|
|
} CallWithinISRRequest;
|
|
|
|
void CallWithinISR( void ( *handler )( void * ), void *arg );
|
|
|
|
void CallWithinISRSubmit( CallWithinISRRequest *request );
|
|
|
|
void CallWithinISRWait( const CallWithinISRRequest *request );
|
|
|
|
typedef struct {
|
|
Thread_queue_Operations tq_ops;
|
|
const Thread_queue_Operations *wrapped_ops;
|
|
Thread_queue_Control thread_queue;
|
|
CallWithinISRRequest isr_request;
|
|
} WrapThreadQueueContext;
|
|
|
|
void WrapThreadQueueInitialize(
|
|
WrapThreadQueueContext *ctx,
|
|
void ( *handler )( void * ),
|
|
void *arg
|
|
);
|
|
|
|
void WrapThreadQueueExtract(
|
|
WrapThreadQueueContext *ctx,
|
|
struct _Thread_Control *thread
|
|
);
|
|
|
|
void WrapThreadQueueExtractDirect(
|
|
WrapThreadQueueContext *ctx,
|
|
Thread_Control *thread
|
|
);
|
|
|
|
void WrapThreadQueueDestroy( WrapThreadQueueContext *ctx );
|
|
|
|
struct Per_CPU_Control;
|
|
|
|
void SetPreemptionIntervention(
|
|
struct Per_CPU_Control *cpu,
|
|
void ( *handler )( void * ),
|
|
void *arg
|
|
);
|
|
|
|
rtems_vector_number GetValidInterruptVectorNumber(
|
|
const rtems_interrupt_attributes *required
|
|
);
|
|
|
|
rtems_vector_number GetTestableInterruptVector(
|
|
const rtems_interrupt_attributes *required
|
|
);
|
|
|
|
bool HasInterruptVectorEntriesInstalled( rtems_vector_number vector );
|
|
|
|
/**
|
|
* @brief Get the clock and context of a timer from RTEMS internal data.
|
|
*
|
|
* With exception of TIMER_DORMANT, the return values are bits or-ed together.
|
|
*
|
|
* @param id The timer ID.
|
|
*
|
|
* @retval TIMER_DORMANT Either the id argument is invalid or the timer has
|
|
* never been used before.
|
|
* @return The TIMER_CLASS_BIT_ON_TASK is set, if the timer server routine
|
|
* was or will be executed in task context, otherwise it was or will be
|
|
* executed in interrupt context.
|
|
*
|
|
* The TIMER_CLASS_BIT_TIME_OF_DAY is set, if the clock used is or was the
|
|
* ${/glossary/clock-realtime:/term}, otherwise the
|
|
* ${/glossary/clock-tick:/term} based clock is or was used.
|
|
*/
|
|
Timer_Classes GetTimerClass( rtems_id id );
|
|
|
|
/**
|
|
* @brief This structure provides data used by RTEMS to schedule a timer
|
|
* service routine.
|
|
*/
|
|
typedef struct {
|
|
/**
|
|
* @brief This member contains a reference to the timer service routine.
|
|
*/
|
|
rtems_timer_service_routine_entry routine;
|
|
/**
|
|
* @brief This member contains a reference to the user data to be provided
|
|
* to the timer service routine.
|
|
*/
|
|
void *user_data;
|
|
/**
|
|
* @brief This member contains the timer interval in ticks or seconds.
|
|
*/
|
|
Watchdog_Interval interval;
|
|
} Timer_Scheduling_Data;
|
|
|
|
/**
|
|
* @brief Get data related to scheduling a timer service routine
|
|
* from RTEMS internal structures.
|
|
*
|
|
* @param id The timer ID.
|
|
* @param[out] data If the reference is not NULL, the data retrieved from
|
|
* internal RTEMS structures is stored here.
|
|
*/
|
|
void GetTimerSchedulingData(
|
|
rtems_id id,
|
|
Timer_Scheduling_Data *data
|
|
);
|
|
|
|
/**
|
|
* @brief The various states of a timer.
|
|
*/
|
|
typedef enum {
|
|
TIMER_INVALID,
|
|
TIMER_INACTIVE,
|
|
TIMER_SCHEDULED,
|
|
TIMER_PENDING
|
|
} Timer_States;
|
|
|
|
/**
|
|
* @brief Get the state of a timer from RTEMS internal data.
|
|
*
|
|
* @param id The timer ID.
|
|
*
|
|
* @retval TIMER_INVALID The id argument is invalid.
|
|
* @retval TIMER_INACTIVE The timer is not scheduled (i.e. it is
|
|
* new, run off, or canceled).
|
|
* @retval TIMER_SCHEDULED The timer is scheduled.
|
|
* @retval TIMER_PENDING The timer is pending.
|
|
*/
|
|
Timer_States GetTimerState( rtems_id id );
|
|
|
|
/**
|
|
* @brief Mark the realtime clock as never set.
|
|
*
|
|
* This function manipulates RTEMS internal data structures to undo the
|
|
* effect of rtems_clock_set(). If the clock is not set, the function has no
|
|
* effect.
|
|
*/
|
|
void UnsetClock( void );
|
|
|
|
void FatalInitialExtension(
|
|
rtems_fatal_source source,
|
|
bool always_set_to_false,
|
|
rtems_fatal_code code
|
|
);
|
|
|
|
typedef void ( *FatalHandler )(
|
|
rtems_fatal_source source,
|
|
rtems_fatal_code code,
|
|
void *arg
|
|
);
|
|
|
|
void SetFatalHandler( FatalHandler fatal, void *arg );
|
|
|
|
void SetTaskSwitchExtension( rtems_task_switch_extension task_switch );
|
|
|
|
typedef struct {
|
|
uint32_t fatal;
|
|
uint32_t thread_begin;
|
|
uint32_t thread_create;
|
|
uint32_t thread_delete;
|
|
uint32_t thread_exitted;
|
|
uint32_t thread_restart;
|
|
uint32_t thread_start;
|
|
uint32_t thread_switch;
|
|
uint32_t thread_terminate;
|
|
} ExtensionCalls;
|
|
|
|
void ClearExtensionCalls( ExtensionCalls *calls );
|
|
|
|
void CopyExtensionCalls( const ExtensionCalls *from, ExtensionCalls *to );
|
|
|
|
void SetIORelaxHandler( void ( *handler )( void * ), void *arg );
|
|
|
|
void StartDelayThreadDispatch( uint32_t cpu_index );
|
|
|
|
void StopDelayThreadDispatch( uint32_t cpu_index );
|
|
|
|
bool AreInterruptsEnabled( void );
|
|
|
|
bool IsWhiteSpaceOnly( const char *s );
|
|
|
|
bool IsEqualIgnoreWhiteSpace( const char *a, const char *b );
|
|
|
|
#if defined(RTEMS_SMP)
|
|
bool TicketLockIsAvailable( const SMP_ticket_lock_Control *lock );
|
|
|
|
void TicketLockWaitForOwned( const SMP_ticket_lock_Control *lock );
|
|
|
|
void TicketLockWaitForOthers(
|
|
const SMP_ticket_lock_Control *lock,
|
|
unsigned int others
|
|
);
|
|
|
|
static inline bool ISRLockIsAvailable( const ISR_lock_Control *lock )
|
|
{
|
|
return TicketLockIsAvailable( &lock->Lock.Ticket_lock );
|
|
}
|
|
|
|
static inline void ISRLockWaitForOwned( const ISR_lock_Control *lock )
|
|
{
|
|
TicketLockWaitForOwned( &lock->Lock.Ticket_lock );
|
|
}
|
|
|
|
static inline void ISRLockWaitForOthers(
|
|
const ISR_lock_Control *lock,
|
|
unsigned int others
|
|
)
|
|
{
|
|
TicketLockWaitForOthers( &lock->Lock.Ticket_lock, others );
|
|
}
|
|
#endif
|
|
|
|
void *IdleBody( uintptr_t ignored );
|
|
|
|
/** @} */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _TX_SUPPORT_H */
|