Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup NewlibValSysLock
0007  */
0008 
0009 /*
0010  * Copyright (C) 2021 embedded brains GmbH & Co. KG
0011  *
0012  * Redistribution and use in source and binary forms, with or without
0013  * modification, are permitted provided that the following conditions
0014  * are met:
0015  * 1. Redistributions of source code must retain the above copyright
0016  *    notice, this list of conditions and the following disclaimer.
0017  * 2. Redistributions in binary form must reproduce the above copyright
0018  *    notice, this list of conditions and the following disclaimer in the
0019  *    documentation and/or other materials provided with the distribution.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0025  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0030  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0031  * POSSIBILITY OF SUCH DAMAGE.
0032  */
0033 
0034 /*
0035  * This file is part of the RTEMS quality process and was automatically
0036  * generated.  If you find something that needs to be fixed or
0037  * worded better please post a report or patch to an RTEMS mailing list
0038  * or raise a bug report:
0039  *
0040  * https://www.rtems.org/bugs.html
0041  *
0042  * For information on updating and regenerating please refer to the How-To
0043  * section in the Software Requirements Engineering chapter of the
0044  * RTEMS Software Engineering manual.  The manual is provided as a part of
0045  * a release.  For development sources please refer to the online
0046  * documentation at:
0047  *
0048  * https://docs.rtems.org
0049  */
0050 
0051 #ifdef HAVE_CONFIG_H
0052 #include "config.h"
0053 #endif
0054 
0055 #include <errno.h>
0056 #include <string.h>
0057 #include <sys/lock.h>
0058 
0059 #include "tr-mtx-seize-try.h"
0060 #include "tr-mtx-seize-wait.h"
0061 #include "tr-mtx-surrender.h"
0062 #include "tr-tq-timeout-priority-inherit.h"
0063 #include "tx-thread-queue.h"
0064 
0065 #include <rtems/test.h>
0066 
0067 /**
0068  * @defgroup NewlibValSysLock spec:/newlib/val/sys-lock
0069  *
0070  * @ingroup TestsuitesValidationNoClock0
0071  *
0072  * @brief Tests the <sys/lock.h> mutex directives.
0073  *
0074  * This test case performs the following actions:
0075  *
0076  * - Create a mutex and validate the mutex directives.
0077  *
0078  *   - Validate the _Mutex_Try_acquire() directive.
0079  *
0080  *   - Validate the _Mutex_Acquire_timed() directive for valid timeout
0081  *     parameters.
0082  *
0083  *   - Validate the _Mutex_Acquire_timed() directive for an invalid timeout
0084  *     parameter.
0085  *
0086  *   - Validate the _Mutex_Acquire_timed() timeout behaviour.
0087  *
0088  *   - Validate the _Mutex_Acquire() directive.
0089  *
0090  *   - Validate the _Mutex_Try_acquire() directive.
0091  *
0092  *   - Destroy the mutex.
0093  *
0094  * - Create a recursive mutex and validate the mutex directives.
0095  *
0096  *   - Validate the _Mutex_recursive_Try_acquire() directive.
0097  *
0098  *   - Validate the _Mutex_recursive_Acquire_timed() directive for valid
0099  *     timeout parameters.
0100  *
0101  *   - Validate the _Mutex_recursive_Acquire_timed() directive for an invalid
0102  *     timeout parameter.
0103  *
0104  *   - Validate the _Mutex_recursive_Acquire_timed() timeout behaviour.
0105  *
0106  *   - Validate the _Mutex_recursive_Acquire() directive.
0107  *
0108  *   - Validate the _Mutex_recursive_Try_acquire() directive.
0109  *
0110  *   - Destroy the mutex.
0111  *
0112  * @{
0113  */
0114 
0115 /**
0116  * @brief Test context for spec:/newlib/val/sys-lock test case.
0117  */
0118 typedef struct {
0119   /**
0120    * @brief This member contains the thread queue test context.
0121    */
0122   TQMtxContext tq_mtx_ctx;
0123 } NewlibValSysLock_Context;
0124 
0125 static NewlibValSysLock_Context
0126   NewlibValSysLock_Instance;
0127 
0128 static Status_Control Enqueue( TQContext *ctx, TQWait wait )
0129 {
0130   const struct timespec abstime = {
0131     .tv_sec = INT64_MAX,
0132     .tv_nsec = 0
0133   };
0134   int                   eno;
0135 
0136   switch ( wait ) {
0137     case TQ_NO_WAIT:
0138       eno = _Mutex_Try_acquire( ctx->thread_queue_object );
0139       break;
0140     case TQ_WAIT_FOREVER:
0141       _Mutex_Acquire( ctx->thread_queue_object );
0142       eno = 0;
0143       break;
0144     case TQ_WAIT_TIMED:
0145       eno = _Mutex_Acquire_timed( ctx->thread_queue_object, &abstime );
0146       break;
0147     default:
0148       T_unreachable();
0149       break;
0150   }
0151 
0152   return STATUS_BUILD( 0, eno );
0153 }
0154 
0155 static Status_Control Surrender( TQContext *ctx )
0156 {
0157   _Mutex_Release( ctx->thread_queue_object );
0158 
0159   return STATUS_SUCCESSFUL;
0160 }
0161 
0162 static rtems_tcb *GetOwner( TQContext *ctx )
0163 {
0164   const struct _Mutex_Control *mutex;
0165 
0166   mutex = ctx->thread_queue_object;
0167 
0168   return mutex->_Queue._owner;
0169 }
0170 
0171 static Status_Control RecursiveEnqueue( TQContext *ctx, TQWait wait )
0172 {
0173   const struct timespec abstime = {
0174     .tv_sec = INT64_MAX,
0175     .tv_nsec = 0
0176   };
0177   int                   eno;
0178 
0179   switch ( wait ) {
0180     case TQ_NO_WAIT:
0181       eno = _Mutex_recursive_Try_acquire( ctx->thread_queue_object );
0182       break;
0183     case TQ_WAIT_FOREVER:
0184       _Mutex_recursive_Acquire( ctx->thread_queue_object );
0185       eno = 0;
0186       break;
0187     case TQ_WAIT_TIMED:
0188       eno = _Mutex_recursive_Acquire_timed(
0189         ctx->thread_queue_object,
0190         &abstime
0191       );
0192       break;
0193     default:
0194       T_unreachable();
0195       break;
0196   }
0197 
0198   return STATUS_BUILD( 0, eno );
0199 }
0200 
0201 static Status_Control RecursiveSurrender( TQContext *ctx )
0202 {
0203   _Mutex_recursive_Release( ctx->thread_queue_object );
0204 
0205   return STATUS_SUCCESSFUL;
0206 }
0207 
0208 static rtems_tcb *RecursiveGetOwner( TQContext *ctx )
0209 {
0210   const struct _Mutex_recursive_Control *mutex;
0211 
0212   mutex = ctx->thread_queue_object;
0213 
0214   return mutex->_Mutex._Queue._owner;
0215 }
0216 
0217 static void NewlibValSysLock_Setup( NewlibValSysLock_Context *ctx )
0218 {
0219   memset( ctx, 0, sizeof( *ctx ) );
0220   ctx->tq_mtx_ctx.base.enqueue_variant = TQ_ENQUEUE_BLOCKS;
0221   ctx->tq_mtx_ctx.base.discipline = TQ_PRIORITY;
0222   ctx->tq_mtx_ctx.base.deadlock = TQ_DEADLOCK_FATAL;
0223   ctx->tq_mtx_ctx.base.convert_status = TQConvertStatusPOSIX;
0224   ctx->tq_mtx_ctx.protocol = TQ_MTX_PRIORITY_INHERIT;
0225   ctx->tq_mtx_ctx.owner_check = TQ_MTX_NO_OWNER_CHECK;
0226   ctx->tq_mtx_ctx.priority_ceiling = PRIO_INVALID;
0227   TQInitialize( &ctx->tq_mtx_ctx.base );
0228 }
0229 
0230 static void NewlibValSysLock_Setup_Wrap( void *arg )
0231 {
0232   NewlibValSysLock_Context *ctx;
0233 
0234   ctx = arg;
0235   NewlibValSysLock_Setup( ctx );
0236 }
0237 
0238 static void NewlibValSysLock_Teardown( NewlibValSysLock_Context *ctx )
0239 {
0240   TQDestroy( &ctx->tq_mtx_ctx.base );
0241   RestoreRunnerPriority();
0242 }
0243 
0244 static void NewlibValSysLock_Teardown_Wrap( void *arg )
0245 {
0246   NewlibValSysLock_Context *ctx;
0247 
0248   ctx = arg;
0249   NewlibValSysLock_Teardown( ctx );
0250 }
0251 
0252 static T_fixture NewlibValSysLock_Fixture = {
0253   .setup = NewlibValSysLock_Setup_Wrap,
0254   .stop = NULL,
0255   .teardown = NewlibValSysLock_Teardown_Wrap,
0256   .scope = NULL,
0257   .initial_context = &NewlibValSysLock_Instance
0258 };
0259 
0260 /**
0261  * @brief Create a mutex and validate the mutex directives.
0262  */
0263 static void NewlibValSysLock_Action_0( NewlibValSysLock_Context *ctx )
0264 {
0265   const struct timespec invalid_abstime = {
0266     .tv_sec = -1,
0267     .tv_nsec = -1
0268   };
0269   int                   eno;
0270   struct _Mutex_Control mutex;
0271 
0272   _Mutex_Initialize( &mutex );
0273 
0274   ctx->tq_mtx_ctx.base.thread_queue_object = &mutex;
0275   ctx->tq_mtx_ctx.base.enqueue_prepare = TQEnqueuePrepareDefault;
0276   ctx->tq_mtx_ctx.base.enqueue_done = TQEnqueueDoneDefault;
0277   ctx->tq_mtx_ctx.base.enqueue = Enqueue;
0278   ctx->tq_mtx_ctx.base.surrender = Surrender;
0279   ctx->tq_mtx_ctx.base.get_owner = GetOwner;
0280 
0281   /*
0282    * Validate the _Mutex_Try_acquire() directive.
0283    */
0284   ctx->tq_mtx_ctx.base.wait = TQ_NO_WAIT;
0285   ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_UNAVAILABLE;
0286   ScoreMtxReqSeizeTry_Run( &ctx->tq_mtx_ctx );
0287 
0288   /*
0289    * Validate the _Mutex_Acquire_timed() directive for valid timeout
0290    * parameters.
0291    */
0292   ctx->tq_mtx_ctx.base.wait = TQ_WAIT_TIMED;
0293   ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_DEADLOCK;
0294   ScoreMtxReqSeizeWait_Run( &ctx->tq_mtx_ctx );
0295 
0296   /*
0297    * Validate the _Mutex_Acquire_timed() directive for an invalid timeout
0298    * parameter.
0299    */
0300   TQSetScheduler(
0301     &ctx->tq_mtx_ctx.base,
0302     TQ_HELPER_A,
0303     SCHEDULER_A_ID,
0304     PRIO_HIGH
0305   );
0306   TQSend( &ctx->tq_mtx_ctx.base, TQ_HELPER_A, TQ_EVENT_ENQUEUE );
0307   eno = _Mutex_Acquire_timed( &mutex, &invalid_abstime );
0308   T_eq_int( eno, EINVAL );
0309   TQSend( &ctx->tq_mtx_ctx.base, TQ_HELPER_A, TQ_EVENT_SURRENDER );
0310 
0311   /*
0312    * Validate the _Mutex_Acquire_timed() timeout behaviour.
0313    */
0314   ctx->tq_mtx_ctx.base.wait = TQ_WAIT_FOREVER;
0315   ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_DEADLOCK;
0316   ScoreTqReqTimeoutPriorityInherit_Run(
0317     &ctx->tq_mtx_ctx.base
0318   );
0319 
0320   /*
0321    * Validate the _Mutex_Acquire() directive.
0322    */
0323   ctx->tq_mtx_ctx.base.wait = TQ_WAIT_FOREVER;
0324   ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_DEADLOCK;
0325   ScoreMtxReqSeizeWait_Run( &ctx->tq_mtx_ctx );
0326 
0327   /*
0328    * Validate the _Mutex_Try_acquire() directive.
0329    */
0330   ctx->tq_mtx_ctx.base.wait = TQ_WAIT_FOREVER;
0331   ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_DEADLOCK;
0332   ScoreMtxReqSurrender_Run( &ctx->tq_mtx_ctx );
0333 
0334   /*
0335    * Destroy the mutex.
0336    */
0337   _Mutex_Destroy( &mutex );
0338 }
0339 
0340 /**
0341  * @brief Create a recursive mutex and validate the mutex directives.
0342  */
0343 static void NewlibValSysLock_Action_1( NewlibValSysLock_Context *ctx )
0344 {
0345   const struct timespec invalid_abstime = {
0346     .tv_sec = -1,
0347     .tv_nsec = -1
0348   };
0349   int                             eno;
0350   struct _Mutex_recursive_Control mutex;
0351 
0352   _Mutex_recursive_Initialize( &mutex );
0353 
0354   ctx->tq_mtx_ctx.base.thread_queue_object = &mutex;
0355   ctx->tq_mtx_ctx.base.enqueue_prepare = TQEnqueuePrepareDefault;
0356   ctx->tq_mtx_ctx.base.enqueue_done = TQEnqueueDoneDefault;
0357   ctx->tq_mtx_ctx.base.enqueue = RecursiveEnqueue;
0358   ctx->tq_mtx_ctx.base.surrender = RecursiveSurrender;
0359   ctx->tq_mtx_ctx.base.get_owner = RecursiveGetOwner;
0360 
0361   /*
0362    * Validate the _Mutex_recursive_Try_acquire() directive.
0363    */
0364   ctx->tq_mtx_ctx.base.wait = TQ_NO_WAIT;
0365   ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_ALLOWED;
0366   ScoreMtxReqSeizeTry_Run( &ctx->tq_mtx_ctx );
0367 
0368   /*
0369    * Validate the _Mutex_recursive_Acquire_timed() directive for valid timeout
0370    * parameters.
0371    */
0372   ctx->tq_mtx_ctx.base.wait = TQ_WAIT_TIMED;
0373   ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_ALLOWED;
0374   ScoreMtxReqSeizeWait_Run( &ctx->tq_mtx_ctx );
0375 
0376   /*
0377    * Validate the _Mutex_recursive_Acquire_timed() directive for an invalid
0378    * timeout parameter.
0379    */
0380   TQSetScheduler(
0381     &ctx->tq_mtx_ctx.base,
0382     TQ_HELPER_A,
0383     SCHEDULER_A_ID,
0384     PRIO_HIGH
0385   );
0386   TQSend( &ctx->tq_mtx_ctx.base, TQ_HELPER_A, TQ_EVENT_ENQUEUE );
0387   eno = _Mutex_recursive_Acquire_timed( &mutex, &invalid_abstime );
0388   T_eq_int( eno, EINVAL );
0389   TQSend( &ctx->tq_mtx_ctx.base, TQ_HELPER_A, TQ_EVENT_SURRENDER );
0390 
0391   /*
0392    * Validate the _Mutex_recursive_Acquire_timed() timeout behaviour.
0393    */
0394   ctx->tq_mtx_ctx.base.wait = TQ_WAIT_FOREVER;
0395   ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_ALLOWED;
0396   ScoreTqReqTimeoutPriorityInherit_Run(
0397     &ctx->tq_mtx_ctx.base
0398   );
0399 
0400   /*
0401    * Validate the _Mutex_recursive_Acquire() directive.
0402    */
0403   ctx->tq_mtx_ctx.base.wait = TQ_WAIT_FOREVER;
0404   ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_ALLOWED;
0405   ScoreMtxReqSeizeWait_Run( &ctx->tq_mtx_ctx );
0406 
0407   /*
0408    * Validate the _Mutex_recursive_Try_acquire() directive.
0409    */
0410   ctx->tq_mtx_ctx.base.wait = TQ_WAIT_FOREVER;
0411   ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_ALLOWED;
0412   ScoreMtxReqSurrender_Run( &ctx->tq_mtx_ctx );
0413 
0414   /*
0415    * Destroy the mutex.
0416    */
0417   _Mutex_recursive_Destroy( &mutex );
0418 }
0419 
0420 /**
0421  * @fn void T_case_body_NewlibValSysLock( void )
0422  */
0423 T_TEST_CASE_FIXTURE( NewlibValSysLock, &NewlibValSysLock_Fixture )
0424 {
0425   NewlibValSysLock_Context *ctx;
0426 
0427   ctx = T_fixture_context();
0428 
0429   NewlibValSysLock_Action_0( ctx );
0430   NewlibValSysLock_Action_1( ctx );
0431 }
0432 
0433 /** @} */