forked from Imagelibrary/rtems
526 lines
13 KiB
C
526 lines
13 KiB
C
/* SPDX-License-Identifier: BSD-2-Clause */
|
|
|
|
/**
|
|
* @file
|
|
*
|
|
* @ingroup RTEMSTestSuites
|
|
*
|
|
* @brief This header file provides the functions to test the
|
|
* @ref RTEMSScoreThreadQueue.
|
|
*/
|
|
|
|
/*
|
|
* 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_THREAD_QUEUE_H
|
|
#define _TX_THREAD_QUEUE_H
|
|
|
|
#include "tx-support.h"
|
|
|
|
#include <rtems/test-scheduler.h>
|
|
#include <rtems/score/atomic.h>
|
|
#include <rtems/score/status.h>
|
|
|
|
#include <setjmp.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @addtogroup RTEMSTestSuites
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
typedef enum {
|
|
TQ_NODE_ONLY,
|
|
TQ_NODE_VITAL,
|
|
TQ_NODE_DISPENSABLE
|
|
} TQNodeKind;
|
|
|
|
typedef enum {
|
|
TQ_WAIT_STATE_BLOCKED,
|
|
TQ_WAIT_STATE_INTEND_TO_BLOCK,
|
|
TQ_WAIT_STATE_READY_AGAIN
|
|
} TQWaitState;
|
|
|
|
typedef enum {
|
|
TQ_BLOCKER_A,
|
|
TQ_BLOCKER_B,
|
|
TQ_BLOCKER_C,
|
|
TQ_BLOCKER_D,
|
|
TQ_BLOCKER_E,
|
|
TQ_WORKER_F,
|
|
TQ_HELPER_A,
|
|
TQ_HELPER_B,
|
|
TQ_HELPER_C,
|
|
TQ_WORKER_COUNT
|
|
} TQWorkerKind;
|
|
|
|
typedef enum {
|
|
TQ_MUTEX_A,
|
|
TQ_MUTEX_B,
|
|
TQ_MUTEX_C,
|
|
TQ_MUTEX_D,
|
|
TQ_MUTEX_NO_PROTOCOL,
|
|
TQ_MUTEX_FIFO,
|
|
TQ_MUTEX_COUNT
|
|
} TQMutex;
|
|
|
|
typedef enum {
|
|
TQ_FIFO,
|
|
TQ_PRIORITY
|
|
} TQDiscipline;
|
|
|
|
typedef enum {
|
|
TQ_NO_WAIT,
|
|
TQ_WAIT_FOREVER,
|
|
TQ_WAIT_TIMED
|
|
} TQWait;
|
|
|
|
typedef enum {
|
|
TQ_DEADLOCK_STATUS,
|
|
TQ_DEADLOCK_FATAL
|
|
} TQDeadlock;
|
|
|
|
typedef enum {
|
|
TQ_EVENT_ENQUEUE_PREPARE = RTEMS_EVENT_0,
|
|
TQ_EVENT_ENQUEUE = RTEMS_EVENT_1,
|
|
TQ_EVENT_ENQUEUE_DONE = RTEMS_EVENT_2,
|
|
TQ_EVENT_SURRENDER = RTEMS_EVENT_3,
|
|
TQ_EVENT_RUNNER_SYNC = RTEMS_EVENT_4,
|
|
TQ_EVENT_RUNNER_SYNC_2 = RTEMS_EVENT_5,
|
|
TQ_EVENT_HELPER_A_SYNC = RTEMS_EVENT_6,
|
|
TQ_EVENT_HELPER_B_SYNC = RTEMS_EVENT_7,
|
|
TQ_EVENT_MUTEX_A_OBTAIN = RTEMS_EVENT_8,
|
|
TQ_EVENT_MUTEX_A_RELEASE = RTEMS_EVENT_9,
|
|
TQ_EVENT_MUTEX_B_OBTAIN = RTEMS_EVENT_10,
|
|
TQ_EVENT_MUTEX_B_RELEASE = RTEMS_EVENT_11,
|
|
TQ_EVENT_BUSY_WAIT = RTEMS_EVENT_12,
|
|
TQ_EVENT_FLUSH = RTEMS_EVENT_13,
|
|
TQ_EVENT_SCHEDULER_RECORD_START = RTEMS_EVENT_14,
|
|
TQ_EVENT_SCHEDULER_RECORD_STOP = RTEMS_EVENT_15,
|
|
TQ_EVENT_TIMEOUT = RTEMS_EVENT_16,
|
|
TQ_EVENT_MUTEX_NO_PROTOCOL_OBTAIN = RTEMS_EVENT_17,
|
|
TQ_EVENT_MUTEX_NO_PROTOCOL_RELEASE = RTEMS_EVENT_18,
|
|
TQ_EVENT_ENQUEUE_FATAL = RTEMS_EVENT_19,
|
|
TQ_EVENT_MUTEX_C_OBTAIN = RTEMS_EVENT_20,
|
|
TQ_EVENT_MUTEX_C_RELEASE = RTEMS_EVENT_21,
|
|
TQ_EVENT_MUTEX_FIFO_OBTAIN = RTEMS_EVENT_22,
|
|
TQ_EVENT_MUTEX_FIFO_RELEASE = RTEMS_EVENT_23,
|
|
TQ_EVENT_ENQUEUE_TIMED = RTEMS_EVENT_24,
|
|
TQ_EVENT_MUTEX_D_OBTAIN = RTEMS_EVENT_25,
|
|
TQ_EVENT_MUTEX_D_RELEASE = RTEMS_EVENT_26,
|
|
TQ_EVENT_PIN = RTEMS_EVENT_27,
|
|
TQ_EVENT_UNPIN = RTEMS_EVENT_28,
|
|
TQ_EVENT_COUNT = RTEMS_EVENT_29
|
|
} TQEvent;
|
|
|
|
typedef enum {
|
|
TQ_ENQUEUE_BLOCKS,
|
|
TQ_ENQUEUE_STICKY
|
|
} TQEnqueueVariant;
|
|
|
|
typedef struct TQContext {
|
|
/**
|
|
* @brief This member defines the thread queue discipline.
|
|
*/
|
|
TQDiscipline discipline;
|
|
|
|
/**
|
|
* @brief This member defines the enqueue wait behaviour.
|
|
*
|
|
* If TQ_NO_WAIT is used, then no thread queue enqueue shall be performed.
|
|
*/
|
|
TQWait wait;
|
|
|
|
/**
|
|
* @brief This member defines the enqueue variant.
|
|
*/
|
|
TQEnqueueVariant enqueue_variant;
|
|
|
|
/**
|
|
* @brief This member defines the deadlock enqueue behaviour.
|
|
*/
|
|
TQDeadlock deadlock;
|
|
|
|
/**
|
|
* @brief This member contains the runner task identifier.
|
|
*/
|
|
rtems_id runner_id;
|
|
|
|
/**
|
|
* @brief This member contains a reference to the runner task control block.
|
|
*/
|
|
rtems_tcb *runner_tcb;
|
|
|
|
/**
|
|
* @brief This member contains the worker task identifiers.
|
|
*/
|
|
rtems_id worker_id[ TQ_WORKER_COUNT ];
|
|
|
|
/**
|
|
* @brief This member contains references to the worker task control
|
|
* blocks.
|
|
*/
|
|
rtems_tcb *worker_tcb[ TQ_WORKER_COUNT ];
|
|
|
|
/**
|
|
* @brief When a worker received an event, the corresponding element shall be
|
|
* set to true.
|
|
*/
|
|
volatile bool event_received[ TQ_WORKER_COUNT ];
|
|
|
|
/**
|
|
* @brief If this member is true, then the worker shall busy wait on request.
|
|
*/
|
|
volatile bool busy_wait[ TQ_WORKER_COUNT ];
|
|
|
|
/**
|
|
* @brief When a worker is done processing its current event set, the
|
|
* corresponding element shall be set to true.
|
|
*/
|
|
volatile bool done[ TQ_WORKER_COUNT ];
|
|
|
|
/**
|
|
* @brief This member provides the counter used for the worker counters.
|
|
*/
|
|
Atomic_Uint counter;
|
|
|
|
/**
|
|
* @brief When a worker returned from TQEnqueue() the counter is incremented
|
|
* and stored in this member.
|
|
*/
|
|
uint32_t worker_counter[ TQ_WORKER_COUNT ];
|
|
|
|
/**
|
|
* @brief This member contains the last return status of a TQEnqueue() of the
|
|
* corresponding worker.
|
|
*/
|
|
Status_Control status[ TQ_WORKER_COUNT ];
|
|
|
|
union {
|
|
/**
|
|
* @brief This member contains the identifier of an object providing the
|
|
* thread queue under test.
|
|
*/
|
|
rtems_id thread_queue_id;
|
|
|
|
/**
|
|
* @brief This member contains the reference to object containing the
|
|
* thread queue under test.
|
|
*/
|
|
void *thread_queue_object;
|
|
};
|
|
|
|
/**
|
|
* @brief This member contains the identifier of priority inheritance
|
|
* mutexes.
|
|
*/
|
|
rtems_id mutex_id[ TQ_MUTEX_COUNT ];
|
|
|
|
/**
|
|
* @brief This member provides the scheduler log.
|
|
*/
|
|
T_scheduler_log_40 scheduler_log;
|
|
|
|
/**
|
|
* @brief This member provides the get properties handler.
|
|
*/
|
|
void ( *get_properties )( struct TQContext *, TQWorkerKind );
|
|
|
|
/**
|
|
* @brief This member provides the status convert handler.
|
|
*/
|
|
Status_Control ( *convert_status )( Status_Control );
|
|
|
|
/**
|
|
* @brief This this member specifies how many threads shall be enqueued.
|
|
*/
|
|
uint32_t how_many;
|
|
|
|
/**
|
|
* @brief This this member provides a context to jump back to before the
|
|
* enqueue.
|
|
*/
|
|
jmp_buf before_enqueue;
|
|
|
|
/**
|
|
* @brief This member provides the thread queue enqueue prepare handler.
|
|
*/
|
|
void ( *enqueue_prepare )( struct TQContext * );
|
|
|
|
/**
|
|
* @brief This member provides the thread queue enqueue handler.
|
|
*/
|
|
Status_Control ( *enqueue )( struct TQContext *, TQWait );
|
|
|
|
/**
|
|
* @brief This member provides the thread queue enqueue done handler.
|
|
*/
|
|
void ( *enqueue_done )( struct TQContext * );
|
|
|
|
/**
|
|
* @brief This member provides the thread queue surrender handler.
|
|
*/
|
|
Status_Control ( *surrender )( struct TQContext * );
|
|
|
|
/**
|
|
* @brief This member provides the thread queue flush handler.
|
|
*/
|
|
void ( *flush )( struct TQContext * );
|
|
|
|
/**
|
|
* @brief This member provides the get owner handler.
|
|
*/
|
|
rtems_tcb *( *get_owner )( struct TQContext * );
|
|
} TQContext;
|
|
|
|
void TQSend(
|
|
TQContext *ctx,
|
|
TQWorkerKind worker,
|
|
rtems_event_set events
|
|
);
|
|
|
|
void TQSendAndWaitForExecutionStop(
|
|
TQContext *ctx,
|
|
TQWorkerKind worker,
|
|
rtems_event_set events
|
|
);
|
|
|
|
void TQSendAndWaitForIntendToBlock(
|
|
TQContext *ctx,
|
|
TQWorkerKind worker,
|
|
rtems_event_set events
|
|
);
|
|
|
|
void TQSendAndWaitForExecutionStopOrIntendToBlock(
|
|
TQContext *ctx,
|
|
TQWorkerKind worker,
|
|
rtems_event_set events
|
|
);
|
|
|
|
void TQSendAndSynchronizeRunner(
|
|
TQContext *ctx,
|
|
TQWorkerKind worker,
|
|
rtems_event_set events
|
|
);
|
|
|
|
void TQWaitForEventsReceived( const TQContext *ctx, TQWorkerKind worker );
|
|
|
|
void TQWaitForIntendToBlock( const TQContext *ctx, TQWorkerKind worker );
|
|
|
|
void TQWaitForExecutionStop( const TQContext *ctx, TQWorkerKind worker );
|
|
|
|
void TQClearDone( TQContext *ctx, TQWorkerKind worker );
|
|
|
|
void TQWaitForDone( const TQContext *ctx, TQWorkerKind worker );
|
|
|
|
void TQSynchronizeRunner( void );
|
|
|
|
void TQSynchronizeRunner2( void );
|
|
|
|
void TQResetCounter( TQContext *ctx );
|
|
|
|
uint32_t TQGetCounter( const TQContext *ctx );
|
|
|
|
uint32_t TQGetWorkerCounter( const TQContext *ctx, TQWorkerKind worker );
|
|
|
|
void TQMutexObtain( const TQContext *ctx, TQMutex mutex );
|
|
|
|
void TQMutexRelease( const TQContext *ctx, TQMutex mutex );
|
|
|
|
void TQSetPriority(
|
|
const TQContext *ctx,
|
|
TQWorkerKind worker,
|
|
Priority priority
|
|
);
|
|
|
|
Priority TQGetPriority( const TQContext *ctx, TQWorkerKind worker );
|
|
|
|
void TQSetScheduler(
|
|
const TQContext *ctx,
|
|
TQWorkerKind worker,
|
|
rtems_id scheduler_id,
|
|
Priority priority
|
|
);
|
|
|
|
void TQInitialize( TQContext *ctx );
|
|
|
|
void TQDestroy( TQContext *ctx );
|
|
|
|
void TQReset( TQContext *ctx );
|
|
|
|
void TQSortMutexesByID( TQContext *ctx );
|
|
|
|
void TQGetProperties( TQContext *ctx, TQWorkerKind enqueued_worker );
|
|
|
|
Status_Control TQConvertStatus( TQContext *ctx, Status_Control status );
|
|
|
|
void TQEnqueuePrepare( TQContext *ctx );
|
|
|
|
Status_Control TQEnqueue( TQContext *ctx, TQWait wait );
|
|
|
|
Status_Control TQEnqueueFatal( TQContext *ctx );
|
|
|
|
void TQEnqueueDone( TQContext *ctx );
|
|
|
|
Status_Control TQSurrender( TQContext *ctx );
|
|
|
|
void TQFlush( TQContext *ctx );
|
|
|
|
rtems_tcb *TQGetOwner( TQContext *ctx );
|
|
|
|
void TQSchedulerRecordStart( TQContext *ctx );
|
|
|
|
void TQSchedulerRecordStop( TQContext *ctx );
|
|
|
|
const T_scheduler_event *TQGetNextAny( TQContext *ctx, size_t *index );
|
|
|
|
const T_scheduler_event *TQGetNextBlock( TQContext *ctx, size_t *index );
|
|
|
|
const T_scheduler_event *TQGetNextUnblock( TQContext *ctx, size_t *index );
|
|
|
|
const T_scheduler_event *TQGetNextUpdatePriority(
|
|
TQContext *ctx,
|
|
size_t *index
|
|
);
|
|
|
|
const T_scheduler_event *TQGetNextAskForHelp( TQContext *ctx, size_t *index );
|
|
|
|
void TQDoNothing( TQContext *ctx );
|
|
|
|
Status_Control TQDoNothingSuccessfully( TQContext *ctx );
|
|
|
|
Status_Control TQConvertStatusClassic( Status_Control status );
|
|
|
|
Status_Control TQConvertStatusPOSIX( Status_Control status );
|
|
|
|
void TQEnqueuePrepareDefault( TQContext *ctx );
|
|
|
|
void TQEnqueueDoneDefault( TQContext *ctx );
|
|
|
|
Status_Control TQEnqueueClassicSem( TQContext *ctx, TQWait wait );
|
|
|
|
Status_Control TQSurrenderClassicSem( TQContext *ctx );
|
|
|
|
rtems_tcb *TQGetOwnerClassicSem( TQContext *ctx );
|
|
|
|
typedef enum {
|
|
TQ_SEM_BINARY,
|
|
TQ_SEM_COUNTING
|
|
} TQSemVariant;
|
|
|
|
typedef struct TQSemContext {
|
|
/**
|
|
* @brief This member contains the base thread queue test context.
|
|
*/
|
|
TQContext base;
|
|
|
|
/**
|
|
* @brief This member defines the semaphore variant.
|
|
*/
|
|
TQSemVariant variant;
|
|
|
|
/**
|
|
* @brief This member provides the semaphore get count handler.
|
|
*/
|
|
uint32_t ( *get_count )( struct TQSemContext * );
|
|
|
|
/**
|
|
* @brief This member provides the semaphore set count handler.
|
|
*/
|
|
void ( *set_count )( struct TQSemContext *, uint32_t );
|
|
} TQSemContext;
|
|
|
|
Status_Control TQSemSurrender( TQSemContext *ctx );
|
|
|
|
uint32_t TQSemGetCount( TQSemContext *ctx );
|
|
|
|
void TQSemSetCount( TQSemContext *ctx, uint32_t count );
|
|
|
|
Status_Control TQSemSurrenderClassic( TQSemContext *ctx );
|
|
|
|
uint32_t TQSemGetCountClassic( TQSemContext *ctx );
|
|
|
|
void TQSemSetCountClassic( TQSemContext *ctx, uint32_t count );
|
|
|
|
typedef enum {
|
|
TQ_MTX_NO_PROTOCOL,
|
|
TQ_MTX_PRIORITY_INHERIT,
|
|
TQ_MTX_PRIORITY_CEILING,
|
|
TQ_MTX_MRSP
|
|
} TQMtxProtocol;
|
|
|
|
typedef enum {
|
|
TQ_MTX_RECURSIVE_ALLOWED,
|
|
TQ_MTX_RECURSIVE_DEADLOCK,
|
|
TQ_MTX_RECURSIVE_UNAVAILABLE
|
|
} TQMtxRecursive;
|
|
|
|
typedef enum {
|
|
TQ_MTX_NO_OWNER_CHECK,
|
|
TQ_MTX_CHECKS_OWNER
|
|
} TQMtxOwnerCheck;
|
|
|
|
typedef struct TQMtxContext {
|
|
/**
|
|
* @brief This member contains the base thread queue test context.
|
|
*/
|
|
TQContext base;
|
|
|
|
/**
|
|
* @brief This member defines the locking protocol.
|
|
*/
|
|
TQMtxProtocol protocol;
|
|
|
|
/**
|
|
* @brief This member defines the recursive seize behaviour.
|
|
*/
|
|
TQMtxRecursive recursive;
|
|
|
|
/**
|
|
* @brief This member defines the owner check behaviour.
|
|
*/
|
|
TQMtxOwnerCheck owner_check;
|
|
|
|
/**
|
|
* @brief This member defines the priority ceiling of the mutex.
|
|
*
|
|
* Use PRIO_INVALID to indicate that the mutex does not provide a priority
|
|
* ceiling.
|
|
*/
|
|
rtems_task_priority priority_ceiling;
|
|
} TQMtxContext;
|
|
|
|
/** @} */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _TX_THREAD_QUEUE_H */
|