Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSTestSuitesValidation
0007  *
0008  * @brief This header file provides the support functions for the validation
0009  *   test cases.
0010  */
0011 
0012 /*
0013  * Copyright (C) 2021 embedded brains GmbH & Co. KG
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #ifndef _TX_SUPPORT_H
0038 #define _TX_SUPPORT_H
0039 
0040 #include <rtems.h>
0041 #include <rtems/irq-extension.h>
0042 #include <rtems/score/atomic.h>
0043 #include <rtems/score/threadq.h>
0044 
0045 #ifdef __cplusplus
0046 extern "C" {
0047 #endif
0048 
0049 /**
0050  * @addtogroup RTEMSTestSuitesValidation
0051  *
0052  * @{
0053  */
0054 
0055 typedef enum {
0056   PRIO_PSEUDO_ISR,
0057   PRIO_VERY_ULTRA_HIGH,
0058   PRIO_ULTRA_HIGH,
0059   PRIO_VERY_HIGH,
0060   PRIO_HIGH,
0061   PRIO_NORMAL,
0062   PRIO_LOW,
0063   PRIO_VERY_LOW,
0064   PRIO_ULTRA_LOW
0065 } Priority;
0066 
0067 /**
0068  * @brief This constants represents the default priority of the runner task.
0069  */
0070 #define PRIO_DEFAULT 1
0071 
0072 /**
0073  * @brief This constants represents an invalid RTEMS task priority value.
0074  *
0075  * It should be an invalid priority value which is not equal to
0076  * RTEMS_CURRENT_PRIORITY and RTEMS_TIMER_SERVER_DEFAULT_PRIORITY.
0077  */
0078 #define PRIO_INVALID 0xfffffffe
0079 
0080 /**
0081  * @brief This constants represents a priority which is close to the priority
0082  *   of the idle thread.
0083  *
0084  * It may be used for the runner thread together with PRIO_FLEXIBLE for worker
0085  * threads.
0086  */
0087 #define PRIO_NEARLY_IDLE 126
0088 
0089 /**
0090  * @brief This constants represents a priority with a wider range of higher and
0091  *   lower priorities around it.
0092  *
0093  * It may be used for the worker threads together with PRIO_NEARLY_IDLE for the
0094  * runner thread.
0095  */
0096 #define PRIO_FLEXIBLE 64
0097 
0098 /**
0099  * @brief This constants represents an invalid RTEMS object identifier.
0100  */
0101 #define INVALID_ID 0xfffffffd
0102 
0103 /**
0104  * @brief This constants represents an object name for tests.
0105  */
0106 #define OBJECT_NAME rtems_build_name( 'T', 'E', 'S', 'T' )
0107 
0108 #define CreateTask( name, priority ) \
0109   DoCreateTask( \
0110     rtems_build_name( name[ 0 ], name[ 1 ], name[ 2 ], name[ 3 ] ), \
0111     priority \
0112   )
0113 
0114 #define SCHEDULER_A_ID 0xf010001
0115 
0116 #define SCHEDULER_B_ID 0xf010002
0117 
0118 #define SCHEDULER_C_ID 0xf010003
0119 
0120 #define SCHEDULER_D_ID 0xf010004
0121 
0122 rtems_id DoCreateTask( rtems_name name, rtems_task_priority priority );
0123 
0124 void StartTask( rtems_id id, rtems_task_entry entry, void *arg );
0125 
0126 void DeleteTask( rtems_id id );
0127 
0128 void SuspendTask( rtems_id id );
0129 
0130 void SuspendSelf( void );
0131 
0132 void ResumeTask( rtems_id id );
0133 
0134 bool IsTaskSuspended( rtems_id id );
0135 
0136 rtems_event_set QueryPendingEvents( void );
0137 
0138 rtems_event_set PollAnyEvents( void );
0139 
0140 rtems_event_set ReceiveAnyEvents( void );
0141 
0142 rtems_event_set ReceiveAnyEventsTimed( rtems_interval ticks );
0143 
0144 void ReceiveAllEvents( rtems_event_set events );
0145 
0146 void SendEvents( rtems_id id, rtems_event_set events );
0147 
0148 rtems_mode GetMode( void );
0149 
0150 rtems_mode SetMode( rtems_mode set, rtems_mode mask );
0151 
0152 rtems_task_priority GetPriority( rtems_id id );
0153 
0154 rtems_task_priority GetPriorityByScheduler(
0155   rtems_id task_id,
0156   rtems_id scheduler_id
0157 );
0158 
0159 rtems_task_priority SetPriority( rtems_id id, rtems_task_priority priority );
0160 
0161 rtems_task_priority GetSelfPriority( void );
0162 
0163 rtems_task_priority SetSelfPriority( rtems_task_priority priority );
0164 
0165 rtems_task_priority SetSelfPriorityNoYield( rtems_task_priority priority );
0166 
0167 rtems_id GetScheduler( rtems_id id );
0168 
0169 rtems_id GetSelfScheduler( void );
0170 
0171 void SetScheduler(
0172   rtems_id            task_id,
0173   rtems_id            scheduler_id,
0174   rtems_task_priority priority
0175 );
0176 
0177 void SetSelfScheduler( rtems_id scheduler_id, rtems_task_priority priority );
0178 
0179 void GetAffinity( rtems_id id, cpu_set_t *set );
0180 
0181 void GetSelfAffinity( cpu_set_t *set );
0182 
0183 void SetAffinity( rtems_id id, const cpu_set_t *set );
0184 
0185 void SetSelfAffinity( const cpu_set_t *set );
0186 
0187 void SetAffinityOne( rtems_id id, uint32_t cpu_index );
0188 
0189 void SetSelfAffinityOne( uint32_t cpu_index );
0190 
0191 void SetAffinityAll( rtems_id id );
0192 
0193 void SetSelfAffinityAll( void );
0194 
0195 void Yield( void );
0196 
0197 void YieldTask( rtems_id id );
0198 
0199 void AddProcessor( rtems_id scheduler_id, uint32_t cpu_index );
0200 
0201 void RemoveProcessor( rtems_id scheduler_id, uint32_t cpu_index );
0202 
0203 rtems_id CreateMutex( void );
0204 
0205 rtems_id CreateMutexNoProtocol( void );
0206 
0207 rtems_id CreateMutexFIFO( void );
0208 
0209 bool IsMutexOwner( rtems_id id );
0210 
0211 void DeleteMutex( rtems_id id );
0212 
0213 void ObtainMutex( rtems_id id );
0214 
0215 void ObtainMutexTimed( rtems_id id, rtems_interval ticks );
0216 
0217 void ObtainMutexDeadlock( rtems_id id );
0218 
0219 void ReleaseMutex( rtems_id id );
0220 
0221 struct Thread_queue_Queue;
0222 
0223 struct Thread_queue_Queue *GetMutexThreadQueue( rtems_id id );
0224 
0225 void RestoreRunnerASR( void );
0226 
0227 void RestoreRunnerMode( void );
0228 
0229 void RestoreRunnerPriority( void );
0230 
0231 void RestoreRunnerScheduler( void );
0232 
0233 struct _Thread_Control;
0234 
0235 struct _Thread_Control *GetThread( rtems_id id );
0236 
0237 struct _Thread_Control *GetExecuting( void );
0238 
0239 void KillZombies( void );
0240 
0241 void WaitForExecutionStop( rtems_id task_id );
0242 
0243 void WaitForIntendToBlock( rtems_id task_id );
0244 
0245 void WaitForHeir( uint32_t cpu_index, rtems_id task_id );
0246 
0247 void WaitForNextTask( uint32_t cpu_index, rtems_id task_id );
0248 
0249 typedef enum {
0250   TASK_TIMER_INVALID,
0251   TASK_TIMER_INACTIVE,
0252   TASK_TIMER_TICKS,
0253   TASK_TIMER_REALTIME,
0254   TASK_TIMER_MONOTONIC
0255 } TaskTimerState;
0256 
0257 typedef struct {
0258   TaskTimerState state;
0259   uint64_t expire_ticks;
0260   struct timespec expire_timespec;
0261 } TaskTimerInfo;
0262 
0263 void GetTaskTimerInfo( rtems_id id, TaskTimerInfo *info );
0264 
0265 void GetTaskTimerInfoByThread(
0266   struct _Thread_Control *thread,
0267   TaskTimerInfo          *info
0268 );
0269 
0270 void ClockTick( void );
0271 
0272 /**
0273  * @brief Simulates a clock tick with the final expire time point of
0274  *   UINT64_MAX for all clocks.
0275  *
0276  * This function does not update the clock ticks counter.
0277  */
0278 void FinalClockTick( void );
0279 
0280 /**
0281  * @brief Simulates a single clock tick using the software timecounter.
0282  *
0283  * In contrast to ClockTick(), this function updates also CLOCK_MONOTONIC and
0284  * CLOCK_REALTIME to the next software timecounter clock tick time point.
0285  *
0286  * This function is designed for test suites not having a clock driver.
0287  */
0288 void TimecounterTick( void );
0289 
0290 typedef uint32_t ( *GetTimecountHandler )( void );
0291 
0292 /**
0293  * @brief Sets the get timecount handler.
0294  *
0295  * Using this function will replace the timecounter of the clock driver.
0296  *
0297  * @return Returns the previous get timecount handler.
0298  */
0299 GetTimecountHandler SetGetTimecountHandler( GetTimecountHandler handler );
0300 
0301 /**
0302  * @brief This constant represents the fake frequency of the software
0303  *   timecounter.
0304  */
0305 #define SOFTWARE_TIMECOUNTER_FREQUENCY 1000000
0306 
0307 /**
0308  * @brief Gets the software timecount counter value.
0309  *
0310  * @return Returns the current software timecounter counter value.
0311  */
0312 uint32_t GetTimecountCounter( void );
0313 
0314 /**
0315  * @brief Sets and gets the software timecount counter value.
0316  *
0317  * @param counter is the new software timecounter counter value.
0318  *
0319  * @return Returns the previous software timecounter counter value.
0320  */
0321 uint32_t SetTimecountCounter( uint32_t counter );
0322 
0323 /**
0324  * @brief Return the task id of the timer server task
0325  *
0326  * This function is an attempt to avoid using RTEMS internal global
0327  * _Timer_server throughout the validation test code.
0328  *
0329  * @return Returns the task id of the timer server task, if
0330  *   rtems_timer_initiate_server() has been invoked before,
0331  *   otherwise - if the timer server task does not exist -
0332  *   RTEMS_INVALID_ID is returned.
0333  */
0334 rtems_id GetTimerServerTaskId( void );
0335 
0336 /**
0337  * @brief Undo the effects of rtems_timer_initiate_server()
0338  *
0339  * If rtems_timer_initiate_server() was never called before,
0340  * nothing is done.
0341  *
0342  * If rtems_timer_initiate_server() was called before, the
0343  * created thread and other resources are freed so that
0344  * rtems_timer_initiate_server() can be called again.
0345  * There should be no pending timers which are not yet executed
0346  * by the server task. Naturally, there should be no
0347  * timer server timers scheduled for execution.
0348  *
0349  * @return Returns true, if rtems_timer_initiate_server() has been
0350  *   invoked before and the timer server task has indeed been deleted,
0351  *   otherwise false.
0352  */
0353 bool DeleteTimerServer( void );
0354 
0355 typedef struct {
0356   struct {
0357     const void *begin;
0358     void *free_begin;
0359     const void *end;
0360   } areas[ 2 ];
0361   size_t count;
0362 } MemoryContext;
0363 
0364 void MemorySave( MemoryContext *ctx );
0365 
0366 void MemoryRestore( const MemoryContext *ctx );
0367 
0368 /**
0369  * @brief Fails a dynamic memory allocation when the counter reaches zero.
0370  *
0371  * This function initializes an internal counter which is decremented before
0372  * each dynamic memory allocation though the rtems_malloc() directive.  When
0373  * the counter decrements from one to zero, the allocation fails and NULL will
0374  * be returned.
0375  *
0376  * @param counter is the initial counter value.
0377  */
0378 void MemoryAllocationFailWhen( uint32_t counter );
0379 
0380 typedef struct {
0381   Chain_Node node;
0382   void ( *handler )( void * );
0383   void *arg;
0384   Atomic_Uint done;
0385 } CallWithinISRRequest;
0386 
0387 void CallWithinISR( void ( *handler )( void * ), void *arg );
0388 
0389 void CallWithinISRSubmit( CallWithinISRRequest *request );
0390 
0391 void CallWithinISRWait( const CallWithinISRRequest *request );
0392 
0393 void CallWithinISRRaise( void );
0394 
0395 void CallWithinISRClear( void );
0396 
0397 rtems_vector_number CallWithinISRGetVector( void );
0398 
0399 rtems_vector_number GetSoftwareInterruptVector( void );
0400 
0401 typedef struct {
0402   Thread_queue_Operations        tq_ops;
0403   const Thread_queue_Operations *wrapped_ops;
0404   Thread_queue_Control           thread_queue;
0405   CallWithinISRRequest           isr_request;
0406 } WrapThreadQueueContext;
0407 
0408 void WrapThreadQueueInitialize(
0409   WrapThreadQueueContext *ctx,
0410   void                 ( *handler )( void * ),
0411   void                   *arg
0412 );
0413 
0414 void WrapThreadQueueExtract(
0415   WrapThreadQueueContext *ctx,
0416   struct _Thread_Control *thread
0417 );
0418 
0419 void WrapThreadQueueExtractDirect(
0420   WrapThreadQueueContext *ctx,
0421   Thread_Control         *thread
0422 );
0423 
0424 void WrapThreadQueueDestroy( WrapThreadQueueContext *ctx );
0425 
0426 struct Per_CPU_Control;
0427 
0428 void SetPreemptionIntervention(
0429   struct Per_CPU_Control *cpu,
0430   void                 ( *handler )( void * ),
0431   void                   *arg
0432 );
0433 
0434 rtems_vector_number GetValidInterruptVectorNumber(
0435   const rtems_interrupt_attributes *required
0436 );
0437 
0438 rtems_vector_number GetTestableInterruptVector(
0439   const rtems_interrupt_attributes *required
0440 );
0441 
0442 rtems_status_code RaiseSoftwareInterrupt( rtems_vector_number vector );
0443 
0444 rtems_status_code ClearSoftwareInterrupt( rtems_vector_number vector );
0445 
0446 bool HasInterruptVectorEntriesInstalled( rtems_vector_number vector );
0447 
0448 /**
0449  * @brief Get the clock and context of a timer from RTEMS internal data.
0450  *
0451  * With exception of TIMER_DORMANT, the return values are bits or-ed together.
0452  *
0453  * @param id The timer ID.
0454  *
0455  * @retval TIMER_DORMANT Either the id argument is invalid or the timer has
0456  *   never been used before.
0457  * @return The TIMER_CLASS_BIT_ON_TASK is set, if the timer server routine
0458  *   was or will be executed in task context, otherwise it was or will be
0459  *   executed in interrupt context.
0460  *
0461  *   The TIMER_CLASS_BIT_TIME_OF_DAY is set, if the clock used is or was the
0462  *   ${/glossary/clock-realtime:/term}, otherwise the
0463  *   ${/glossary/clock-tick:/term} based clock is or was used.
0464  */
0465 Timer_Classes GetTimerClass( rtems_id id );
0466 
0467 /**
0468  * @brief This structure provides data used by RTEMS to schedule a timer
0469  *   service routine.
0470  */
0471 typedef struct {
0472   /**
0473     * @brief This member contains a reference to the timer service routine.
0474     */
0475   rtems_timer_service_routine_entry routine;
0476   /**
0477    * @brief This member contains a reference to the user data to be provided
0478    * to the timer service routine.
0479    */
0480   void *user_data;
0481   /**
0482    * @brief This member contains the timer interval in ticks or seconds.
0483    */
0484   Watchdog_Interval interval;
0485 } Timer_Scheduling_Data;
0486 
0487 /**
0488  * @brief Get data related to scheduling a timer service routine
0489  *   from RTEMS internal structures.
0490  *
0491  * @param id The timer ID.
0492  * @param[out] data If the reference is not NULL, the data retrieved from
0493  *   internal RTEMS structures is stored here.
0494  */
0495 void GetTimerSchedulingData(
0496   rtems_id id,
0497   Timer_Scheduling_Data *data
0498 );
0499 
0500 /**
0501  * @brief The various states of a timer.
0502  */
0503 typedef enum {
0504   TIMER_INVALID,
0505   TIMER_INACTIVE,
0506   TIMER_SCHEDULED,
0507   TIMER_PENDING
0508 } Timer_States;
0509 
0510 /**
0511  * @brief Get the state of a timer from RTEMS internal data.
0512  *
0513  * @param id The timer ID.
0514  *
0515  * @retval TIMER_INVALID The id argument is invalid.
0516  * @retval TIMER_INACTIVE The timer is not scheduled (i.e. it is
0517  *   new, run off, or canceled).
0518  * @retval TIMER_SCHEDULED The timer is scheduled.
0519  * @retval TIMER_PENDING The timer is pending.
0520  */
0521 Timer_States GetTimerState( rtems_id id );
0522 
0523 /**
0524  * @brief Mark the realtime clock as never set.
0525  *
0526  * This function manipulates RTEMS internal data structures to undo the
0527  * effect of rtems_clock_set(). If the clock is not set, the function has no
0528  * effect.
0529  */
0530 void UnsetClock( void );
0531 
0532 void FatalInitialExtension(
0533   rtems_fatal_source source,
0534   bool               always_set_to_false,
0535   rtems_fatal_code   code
0536 );
0537 
0538 typedef void ( *FatalHandler )(
0539   rtems_fatal_source source,
0540   rtems_fatal_code   code,
0541   void              *arg
0542 );
0543 
0544 void SetFatalHandler( FatalHandler fatal, void *arg );
0545 
0546 void SetTaskSwitchExtension( rtems_task_switch_extension task_switch );
0547 
0548 typedef struct {
0549   uint32_t fatal;
0550   uint32_t thread_begin;
0551   uint32_t thread_create;
0552   uint32_t thread_delete;
0553   uint32_t thread_exitted;
0554   uint32_t thread_restart;
0555   uint32_t thread_start;
0556   uint32_t thread_switch;
0557   uint32_t thread_terminate;
0558 } ExtensionCalls;
0559 
0560 void ClearExtensionCalls( ExtensionCalls *calls );
0561 
0562 void CopyExtensionCalls( const ExtensionCalls *from, ExtensionCalls *to );
0563 
0564 void SetIORelaxHandler( void ( *handler )( void * ), void *arg );
0565 
0566 void StartDelayThreadDispatch( uint32_t cpu_index );
0567 
0568 void StopDelayThreadDispatch( uint32_t cpu_index );
0569 
0570 bool AreInterruptsEnabled( void );
0571 
0572 bool IsWhiteSpaceOnly( const char *s );
0573 
0574 bool IsEqualIgnoreWhiteSpace( const char *a, const char *b );
0575 
0576 #if defined(RTEMS_SMP)
0577 bool TicketLockIsAvailable( const SMP_ticket_lock_Control *lock );
0578 
0579 void TicketLockWaitForOwned( const SMP_ticket_lock_Control *lock );
0580 
0581 void TicketLockWaitForOthers(
0582   const SMP_ticket_lock_Control *lock,
0583   unsigned int                   others
0584 );
0585 
0586 typedef struct {
0587   const SMP_ticket_lock_Control *lock;
0588   unsigned int                   next_ticket;
0589 } TicketLockState;
0590 
0591 void TicketLockGetState(
0592   const SMP_ticket_lock_Control *lock,
0593   TicketLockState               *state
0594 );
0595 
0596 void TicketLockWaitForAcquires(
0597   const TicketLockState *state,
0598   unsigned int           acquire_count
0599 );
0600 
0601 void TicketLockWaitForReleases(
0602   const TicketLockState *state,
0603   unsigned int           release_count
0604 );
0605 
0606 static inline bool ISRLockIsAvailable( const ISR_lock_Control *lock )
0607 {
0608   return TicketLockIsAvailable( &lock->Lock.Ticket_lock );
0609 }
0610 
0611 static inline void ISRLockWaitForOwned( const ISR_lock_Control *lock )
0612 {
0613   TicketLockWaitForOwned( &lock->Lock.Ticket_lock );
0614 }
0615 
0616 static inline void ISRLockWaitForOthers(
0617   const ISR_lock_Control *lock,
0618   unsigned int            others
0619 )
0620 {
0621   TicketLockWaitForOthers( &lock->Lock.Ticket_lock, others );
0622 }
0623 #endif
0624 
0625 void *IdleBody( uintptr_t ignored );
0626 
0627 /**
0628  * @brief This task configurations may be used to construct a task during
0629  *   tests.
0630  *
0631  * Only one task shall use this configuration at a time, otherwise two tasks
0632  * would share a stack.
0633  */
0634 extern const rtems_task_config DefaultTaskConfig;
0635 
0636 /** @} */
0637 
0638 #ifdef __cplusplus
0639 }
0640 #endif
0641 
0642 #endif /* _TX_SUPPORT_H */