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 functions to test the
0009  *   @ref RTEMSScoreThreadQueue.
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_THREAD_QUEUE_H
0038 #define _TX_THREAD_QUEUE_H
0039 
0040 #include "tx-support.h"
0041 
0042 #include <rtems/test-scheduler.h>
0043 #include <rtems/score/atomic.h>
0044 #include <rtems/score/status.h>
0045 
0046 #include <setjmp.h>
0047 
0048 #ifdef __cplusplus
0049 extern "C" {
0050 #endif
0051 
0052 /**
0053  * @addtogroup RTEMSTestSuitesValidation
0054  *
0055  * @{
0056  */
0057 
0058 typedef enum {
0059   TQ_NODE_ONLY,
0060   TQ_NODE_VITAL,
0061   TQ_NODE_DISPENSABLE
0062 } TQNodeKind;
0063 
0064 typedef enum {
0065   TQ_WAIT_STATE_BLOCKED,
0066   TQ_WAIT_STATE_INTEND_TO_BLOCK,
0067   TQ_WAIT_STATE_READY_AGAIN
0068 } TQWaitState;
0069 
0070 typedef enum {
0071   TQ_BLOCKER_A,
0072   TQ_BLOCKER_B,
0073   TQ_BLOCKER_C,
0074   TQ_BLOCKER_D,
0075   TQ_BLOCKER_E,
0076   TQ_WORKER_F,
0077   TQ_HELPER_A,
0078   TQ_HELPER_B,
0079   TQ_HELPER_C,
0080   TQ_WORKER_COUNT
0081 } TQWorkerKind;
0082 
0083 typedef enum {
0084   TQ_MUTEX_A,
0085   TQ_MUTEX_B,
0086   TQ_MUTEX_C,
0087   TQ_MUTEX_D,
0088   TQ_MUTEX_NO_PROTOCOL,
0089   TQ_MUTEX_FIFO,
0090   TQ_MUTEX_COUNT
0091 } TQMutex;
0092 
0093 typedef enum {
0094   TQ_FIFO,
0095   TQ_PRIORITY
0096 } TQDiscipline;
0097 
0098 typedef enum {
0099   TQ_NO_WAIT,
0100   TQ_WAIT_FOREVER,
0101   TQ_WAIT_TIMED
0102 } TQWait;
0103 
0104 typedef enum {
0105   TQ_DEADLOCK_STATUS,
0106   TQ_DEADLOCK_FATAL
0107 } TQDeadlock;
0108 
0109 typedef enum {
0110   TQ_EVENT_ENQUEUE_PREPARE = RTEMS_EVENT_0,
0111   TQ_EVENT_ENQUEUE = RTEMS_EVENT_1,
0112   TQ_EVENT_ENQUEUE_DONE = RTEMS_EVENT_2,
0113   TQ_EVENT_SURRENDER = RTEMS_EVENT_3,
0114   TQ_EVENT_RUNNER_SYNC = RTEMS_EVENT_4,
0115   TQ_EVENT_RUNNER_SYNC_2 = RTEMS_EVENT_5,
0116   TQ_EVENT_HELPER_A_SYNC = RTEMS_EVENT_6,
0117   TQ_EVENT_HELPER_B_SYNC = RTEMS_EVENT_7,
0118   TQ_EVENT_MUTEX_A_OBTAIN = RTEMS_EVENT_8,
0119   TQ_EVENT_MUTEX_A_RELEASE = RTEMS_EVENT_9,
0120   TQ_EVENT_MUTEX_B_OBTAIN = RTEMS_EVENT_10,
0121   TQ_EVENT_MUTEX_B_RELEASE = RTEMS_EVENT_11,
0122   TQ_EVENT_BUSY_WAIT = RTEMS_EVENT_12,
0123   TQ_EVENT_FLUSH_ALL = RTEMS_EVENT_13,
0124   TQ_EVENT_FLUSH_PARTIAL = RTEMS_EVENT_14,
0125   TQ_EVENT_SCHEDULER_RECORD_START = RTEMS_EVENT_15,
0126   TQ_EVENT_SCHEDULER_RECORD_STOP = RTEMS_EVENT_16,
0127   TQ_EVENT_TIMEOUT = RTEMS_EVENT_17,
0128   TQ_EVENT_MUTEX_NO_PROTOCOL_OBTAIN = RTEMS_EVENT_18,
0129   TQ_EVENT_MUTEX_NO_PROTOCOL_RELEASE = RTEMS_EVENT_19,
0130   TQ_EVENT_ENQUEUE_FATAL = RTEMS_EVENT_20,
0131   TQ_EVENT_MUTEX_C_OBTAIN = RTEMS_EVENT_21,
0132   TQ_EVENT_MUTEX_C_RELEASE = RTEMS_EVENT_22,
0133   TQ_EVENT_MUTEX_FIFO_OBTAIN = RTEMS_EVENT_23,
0134   TQ_EVENT_MUTEX_FIFO_RELEASE = RTEMS_EVENT_24,
0135   TQ_EVENT_ENQUEUE_TIMED = RTEMS_EVENT_25,
0136   TQ_EVENT_MUTEX_D_OBTAIN = RTEMS_EVENT_26,
0137   TQ_EVENT_MUTEX_D_RELEASE = RTEMS_EVENT_27,
0138   TQ_EVENT_PIN = RTEMS_EVENT_28,
0139   TQ_EVENT_UNPIN = RTEMS_EVENT_29,
0140   TQ_EVENT_COUNT = RTEMS_EVENT_30
0141 } TQEvent;
0142 
0143 typedef enum {
0144   TQ_ENQUEUE_BLOCKS,
0145   TQ_ENQUEUE_STICKY
0146 } TQEnqueueVariant;
0147 
0148 typedef struct TQContext {
0149   /**
0150    * @brief This member defines the thread queue discipline.
0151    */
0152   TQDiscipline discipline;
0153 
0154   /**
0155    * @brief This member defines the enqueue wait behaviour.
0156    *
0157    * If TQ_NO_WAIT is used, then no thread queue enqueue shall be performed.
0158    */
0159   TQWait wait;
0160 
0161   /**
0162    * @brief This member defines the enqueue variant.
0163    */
0164   TQEnqueueVariant enqueue_variant;
0165 
0166   /**
0167    * @brief This member defines the deadlock enqueue behaviour.
0168    */
0169   TQDeadlock deadlock;
0170 
0171   /**
0172    * @brief This member contains the runner task identifier.
0173    */
0174   rtems_id runner_id;
0175 
0176   /**
0177    * @brief This member contains a reference to the runner task control block.
0178    */
0179   rtems_tcb *runner_tcb;
0180 
0181   /**
0182    * @brief This member contains the worker task identifiers.
0183    */
0184   rtems_id worker_id[ TQ_WORKER_COUNT ];
0185 
0186   /**
0187    * @brief This member contains references to the worker task control
0188    *   blocks.
0189    */
0190   rtems_tcb *worker_tcb[ TQ_WORKER_COUNT ];
0191 
0192   /**
0193    * @brief When a worker received an event, the corresponding element shall be
0194    *   set to true.
0195    */
0196   volatile bool event_received[ TQ_WORKER_COUNT ];
0197 
0198   /**
0199    * @brief If this member is true, then the worker shall busy wait on request.
0200    */
0201   volatile bool busy_wait[ TQ_WORKER_COUNT ];
0202 
0203   /**
0204    * @brief When a worker is done processing its current event set, the
0205    *   corresponding element shall be set to true.
0206    */
0207   volatile bool done[ TQ_WORKER_COUNT ];
0208 
0209   /**
0210    * @brief This member provides the counter used for the worker counters.
0211    */
0212   Atomic_Uint counter;
0213 
0214   /**
0215    * @brief When a worker returned from TQEnqueue() the counter is incremented
0216    * and stored in this member.
0217    */
0218   uint32_t worker_counter[ TQ_WORKER_COUNT ];
0219 
0220   /**
0221    * @brief This member contains the last return status of a TQEnqueue() of the
0222    *   corresponding worker.
0223    */
0224   Status_Control status[ TQ_WORKER_COUNT ];
0225 
0226   union {
0227     /**
0228      * @brief This member contains the identifier of an object providing the
0229      *   thread queue under test.
0230      */
0231     rtems_id thread_queue_id;
0232 
0233     /**
0234      * @brief This member contains the reference to object containing the
0235      *   thread queue under test.
0236      */
0237     void *thread_queue_object;
0238   };
0239 
0240   /**
0241    * @brief This member contains the identifier of priority inheritance
0242    *   mutexes.
0243    */
0244   rtems_id mutex_id[ TQ_MUTEX_COUNT ];
0245 
0246   /**
0247    * @brief This member provides the scheduler log.
0248    */
0249   T_scheduler_log_40 scheduler_log;
0250 
0251   /**
0252    * @brief This member provides the get properties handler.
0253    */
0254   void ( *get_properties )( struct TQContext *, TQWorkerKind );
0255 
0256   /**
0257    * @brief This member provides the status convert handler.
0258    */
0259   Status_Control ( *convert_status )( Status_Control );
0260 
0261   /**
0262    * @brief This this member specifies how many threads shall be enqueued.
0263    */
0264   uint32_t how_many;
0265 
0266   /**
0267    * @brief This this member contains the count of the least recently flushed
0268    *   threads.
0269    */
0270   uint32_t flush_count;
0271 
0272   /**
0273    * @brief This this member provides a context to jump back to before the
0274    *   enqueue.
0275    */
0276   jmp_buf before_enqueue;
0277 
0278   /**
0279    * @brief This member provides the thread queue enqueue prepare handler.
0280    */
0281   void ( *enqueue_prepare )( struct TQContext * );
0282 
0283   /**
0284    * @brief This member provides the thread queue enqueue handler.
0285    */
0286   Status_Control ( *enqueue )( struct TQContext *, TQWait );
0287 
0288   /**
0289    * @brief This member provides the thread queue enqueue done handler.
0290    */
0291   void ( *enqueue_done )( struct TQContext * );
0292 
0293   /**
0294    * @brief This member provides the thread queue surrender handler.
0295    */
0296   Status_Control ( *surrender )( struct TQContext * );
0297 
0298   /**
0299    * @brief This member provides the thread queue flush handler.
0300    *
0301    * The second parameter specifies the count of enqueued threads.  While the
0302    * third parameter is true, all enqueued threads shall be extracted,
0303    * otherwise the thread queue shall be partially flushed.  The handler shall
0304    * return the count of flushed threads.
0305    */
0306   uint32_t ( *flush )( struct TQContext *, uint32_t, bool );
0307 
0308   /**
0309    * @brief This member provides the get owner handler.
0310    */
0311   rtems_tcb *( *get_owner )( struct TQContext * );
0312 } TQContext;
0313 
0314 void TQSend(
0315   TQContext      *ctx,
0316   TQWorkerKind    worker,
0317   rtems_event_set events
0318 );
0319 
0320 void TQSendAndWaitForExecutionStop(
0321   TQContext      *ctx,
0322   TQWorkerKind    worker,
0323   rtems_event_set events
0324 );
0325 
0326 void TQSendAndWaitForIntendToBlock(
0327   TQContext      *ctx,
0328   TQWorkerKind    worker,
0329   rtems_event_set events
0330 );
0331 
0332 void TQSendAndWaitForExecutionStopOrIntendToBlock(
0333   TQContext      *ctx,
0334   TQWorkerKind    worker,
0335   rtems_event_set events
0336 );
0337 
0338 void TQSendAndSynchronizeRunner(
0339   TQContext      *ctx,
0340   TQWorkerKind    worker,
0341   rtems_event_set events
0342 );
0343 
0344 void TQWaitForEventsReceived( const TQContext *ctx, TQWorkerKind worker );
0345 
0346 void TQWaitForIntendToBlock( const TQContext *ctx, TQWorkerKind worker );
0347 
0348 void TQWaitForExecutionStop( const TQContext *ctx, TQWorkerKind worker );
0349 
0350 void TQClearDone( TQContext *ctx, TQWorkerKind worker );
0351 
0352 void TQWaitForDone( const TQContext *ctx, TQWorkerKind worker );
0353 
0354 void TQSynchronizeRunner( void );
0355 
0356 void TQSynchronizeRunner2( void );
0357 
0358 void TQResetCounter( TQContext *ctx );
0359 
0360 uint32_t TQGetCounter( const TQContext *ctx );
0361 
0362 uint32_t TQGetWorkerCounter( const TQContext *ctx, TQWorkerKind worker );
0363 
0364 void TQMutexObtain( const TQContext *ctx, TQMutex mutex );
0365 
0366 void TQMutexRelease( const TQContext *ctx, TQMutex mutex );
0367 
0368 void TQSetPriority(
0369   const TQContext *ctx,
0370   TQWorkerKind     worker,
0371   Priority         priority
0372 );
0373 
0374 Priority TQGetPriority( const TQContext *ctx, TQWorkerKind worker );
0375 
0376 void TQSetScheduler(
0377   const TQContext *ctx,
0378   TQWorkerKind     worker,
0379   rtems_id         scheduler_id,
0380   Priority         priority
0381 );
0382 
0383 void TQInitialize( TQContext *ctx );
0384 
0385 void TQDestroy( TQContext *ctx );
0386 
0387 void TQReset( TQContext *ctx );
0388 
0389 void TQSortMutexesByID( TQContext *ctx );
0390 
0391 void TQGetProperties( TQContext *ctx, TQWorkerKind enqueued_worker );
0392 
0393 Status_Control TQConvertStatus( TQContext *ctx, Status_Control status );
0394 
0395 void TQEnqueuePrepare( TQContext *ctx );
0396 
0397 Status_Control TQEnqueue( TQContext *ctx, TQWait wait );
0398 
0399 Status_Control TQEnqueueFatal( TQContext *ctx );
0400 
0401 void TQEnqueueDone( TQContext *ctx );
0402 
0403 Status_Control TQSurrender( TQContext *ctx );
0404 
0405 void TQFlush( TQContext *ctx, bool flush_all );
0406 
0407 rtems_tcb *TQGetOwner( TQContext *ctx );
0408 
0409 void TQSchedulerRecordStart( TQContext *ctx );
0410 
0411 void TQSchedulerRecordStop( TQContext *ctx );
0412 
0413 const T_scheduler_event *TQGetNextAny( TQContext *ctx, size_t *index );
0414 
0415 const T_scheduler_event *TQGetNextBlock( TQContext *ctx, size_t *index );
0416 
0417 const T_scheduler_event *TQGetNextUnblock( TQContext *ctx, size_t *index );
0418 
0419 const T_scheduler_event *TQGetNextUpdatePriority(
0420   TQContext *ctx,
0421   size_t    *index
0422 );
0423 
0424 const T_scheduler_event *TQGetNextAskForHelp( TQContext *ctx, size_t *index );
0425 
0426 void TQDoNothing( TQContext *ctx );
0427 
0428 Status_Control TQDoNothingSuccessfully( TQContext *ctx );
0429 
0430 Status_Control TQConvertStatusClassic( Status_Control status );
0431 
0432 Status_Control TQConvertStatusPOSIX( Status_Control status );
0433 
0434 void TQEnqueuePrepareDefault( TQContext *ctx );
0435 
0436 void TQEnqueueDoneDefault( TQContext *ctx );
0437 
0438 Status_Control TQEnqueueClassicSem( TQContext *ctx, TQWait wait );
0439 
0440 Status_Control TQSurrenderClassicSem( TQContext *ctx );
0441 
0442 rtems_tcb *TQGetOwnerClassicSem( TQContext *ctx );
0443 
0444 typedef enum {
0445   TQ_SEM_BINARY,
0446   TQ_SEM_COUNTING
0447 } TQSemVariant;
0448 
0449 typedef struct TQSemContext {
0450   /**
0451    * @brief This member contains the base thread queue test context.
0452    */
0453   TQContext base;
0454 
0455   /**
0456    * @brief This member defines the semaphore variant.
0457    */
0458   TQSemVariant variant;
0459 
0460   /**
0461    * @brief This member provides the semaphore get count handler.
0462    */
0463   uint32_t ( *get_count )( struct TQSemContext * );
0464 
0465   /**
0466    * @brief This member provides the semaphore set count handler.
0467    */
0468   void ( *set_count )( struct TQSemContext *, uint32_t );
0469 } TQSemContext;
0470 
0471 Status_Control TQSemSurrender( TQSemContext *ctx );
0472 
0473 uint32_t TQSemGetCount( TQSemContext *ctx );
0474 
0475 void TQSemSetCount( TQSemContext *ctx, uint32_t count );
0476 
0477 Status_Control TQSemSurrenderClassic( TQSemContext *ctx );
0478 
0479 uint32_t TQSemGetCountClassic( TQSemContext *ctx );
0480 
0481 void TQSemSetCountClassic( TQSemContext *ctx, uint32_t count );
0482 
0483 typedef enum {
0484   TQ_MTX_NO_PROTOCOL,
0485   TQ_MTX_PRIORITY_INHERIT,
0486   TQ_MTX_PRIORITY_CEILING,
0487   TQ_MTX_MRSP
0488 } TQMtxProtocol;
0489 
0490 typedef enum {
0491   TQ_MTX_RECURSIVE_ALLOWED,
0492   TQ_MTX_RECURSIVE_DEADLOCK,
0493   TQ_MTX_RECURSIVE_UNAVAILABLE
0494 } TQMtxRecursive;
0495 
0496 typedef enum {
0497   TQ_MTX_NO_OWNER_CHECK,
0498   TQ_MTX_CHECKS_OWNER
0499 } TQMtxOwnerCheck;
0500 
0501 typedef struct TQMtxContext {
0502   /**
0503    * @brief This member contains the base thread queue test context.
0504    */
0505   TQContext base;
0506 
0507   /**
0508    * @brief This member defines the locking protocol.
0509    */
0510   TQMtxProtocol protocol;
0511 
0512   /**
0513    * @brief This member defines the recursive seize behaviour.
0514    */
0515   TQMtxRecursive recursive;
0516 
0517   /**
0518    * @brief This member defines the owner check behaviour.
0519    */
0520   TQMtxOwnerCheck owner_check;
0521 
0522   /**
0523    * @brief This member defines the priority ceiling of the mutex.
0524    *
0525    * Use PRIO_INVALID to indicate that the mutex does not provide a priority
0526    * ceiling.
0527    */
0528   rtems_task_priority priority_ceiling;
0529 } TQMtxContext;
0530 
0531 /** @} */
0532 
0533 #ifdef __cplusplus
0534 }
0535 #endif
0536 
0537 #endif /* _TX_THREAD_QUEUE_H */