diff options
Diffstat (limited to 'testsuites/validation/tx-support.h')
-rw-r--r-- | testsuites/validation/tx-support.h | 499 |
1 files changed, 495 insertions, 4 deletions
diff --git a/testsuites/validation/tx-support.h b/testsuites/validation/tx-support.h index b0e466fda1..378bc4c466 100644 --- a/testsuites/validation/tx-support.h +++ b/testsuites/validation/tx-support.h @@ -3,14 +3,14 @@ /** * @file * - * @ingroup RTEMSTestSuites + * @ingroup RTEMSTestSuitesValidation * * @brief This header file provides the support functions for the validation * test cases. */ /* - * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * Copyright (C) 2021 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,19 +40,21 @@ #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 + * @addtogroup RTEMSTestSuitesValidation * * @{ */ typedef enum { PRIO_PSEUDO_ISR, + PRIO_VERY_ULTRA_HIGH, PRIO_ULTRA_HIGH, PRIO_VERY_HIGH, PRIO_HIGH, @@ -63,24 +65,84 @@ typedef enum { } 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 ); @@ -89,18 +151,232 @@ 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 ); +void RestoreRunnerScheduler( 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 * ); @@ -114,14 +390,229 @@ void CallWithinISRSubmit( CallWithinISRRequest *request ); void CallWithinISRWait( const CallWithinISRRequest *request ); +void CallWithinISRRaise( void ); + +void CallWithinISRClear( void ); + +rtems_vector_number CallWithinISRGetVector( void ); + +rtems_vector_number GetSoftwareInterruptVector( void ); + +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( void ); +rtems_vector_number GetTestableInterruptVector( + const rtems_interrupt_attributes *required +); + +rtems_status_code RaiseSoftwareInterrupt( rtems_vector_number vector ); + +rtems_status_code ClearSoftwareInterrupt( rtems_vector_number vector ); 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 ); + +/** + * @brief This task configurations may be used to construct a task during + * tests. + * + * Only one task shall use this configuration at a time, otherwise two tasks + * would share a stack. + */ +extern const rtems_task_config DefaultTaskConfig; + /** @} */ #ifdef __cplusplus |