Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RtemsUserextValUserext
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 <string.h>
0056 #include <rtems/score/apimutex.h>
0057 #include <rtems/score/atomic.h>
0058 
0059 #include "tc-userext.h"
0060 #include "tx-support.h"
0061 
0062 #include <rtems/test.h>
0063 
0064 /**
0065  * @defgroup RtemsUserextValUserext spec:/rtems/userext/val/userext
0066  *
0067  * @ingroup TestsuitesUserext
0068  *
0069  * @brief Tests the thread user extensions.
0070  *
0071  * This test case performs the following actions:
0072  *
0073  * - Create five dynamic extensions.  Switch to a started thread.  Delete three
0074  *   dynamic extension during the thread begin invocation.  Clean up the used
0075  *   resources.
0076  *
0077  *   - Check that the thread switch extensions were invoked in the right order
0078  *     before the thread begin extensions.
0079  *
0080  *   - Check that the thread begin extensions were invoked in the right order.
0081  *
0082  *   - Check that the other extensions were not invoked.
0083  *
0084  *   - Check that the thread begin extension of the extension set deleted
0085  *     before its turn in the invocation was not invoked.
0086  *
0087  * - Create five dynamic extensions.  Create a thread.  Delete three dynamic
0088  *   extension during the thread create invocation.  Clean up the used
0089  *   resources.
0090  *
0091  *   - Check that the thread create extensions were invoked in the right order.
0092  *
0093  *   - Check that the thread create extensions were invoked under protection of
0094  *     the allocator mutex.
0095  *
0096  *   - Check that the other extensions were not invoked.
0097  *
0098  *   - Check that the thread create extension of the extension set deleted
0099  *     before its turn in the invocation was not invoked.
0100  *
0101  * - Create five dynamic extensions.  Delete a thread.  Delete three dynamic
0102  *   extension during the thread delete invocation.  Clean up the used
0103  *   resources.
0104  *
0105  *   - Check that the thread delete extensions were invoked in the right order.
0106  *
0107  *   - Check that the thread delete extensions were invoked under protection of
0108  *     the allocator mutex.
0109  *
0110  *   - Check that the other extensions were not invoked.
0111  *
0112  *   - Check that the thread delete extension of the extension set deleted
0113  *     before its turn in the invocation was not invoked.
0114  *
0115  * - Create five dynamic extensions.  Return from a thread entry.  Delete three
0116  *   dynamic extension during the thread exitted invocation.  Clean up the used
0117  *   resources.
0118  *
0119  *   - Check that the thread exitted extensions were invoked in the right
0120  *     order.
0121  *
0122  *   - Check that the other extensions were not invoked.
0123  *
0124  *   - Check that the thread exitted extension of the extension set deleted
0125  *     before its turn in the invocation was not invoked.
0126  *
0127  * - Create five dynamic extensions.  Restart a thread.  Delete three dynamic
0128  *   extension during the thread restart invocation.  Clean up the used
0129  *   resources.
0130  *
0131  *   - Check that the thread restart extensions were invoked in the right
0132  *     order.
0133  *
0134  *   - Check that the other extensions were not invoked.
0135  *
0136  *   - Check that the thread restart extension of the extension set deleted
0137  *     before its turn in the invocation was not invoked.
0138  *
0139  * - Create five dynamic extensions.  Start a thread.  Delete three dynamic
0140  *   extension during the thread start invocation.  Clean up the used
0141  *   resources.
0142  *
0143  *   - Check that the thread start extensions were invoked in the right order.
0144  *
0145  *   - Check that the other extensions were not invoked.
0146  *
0147  *   - Check that the thread start extension of the extension set deleted
0148  *     before its turn in the invocation was not invoked.
0149  *
0150  * - Create five dynamic extensions.  Terminate a thread.  Delete three dynamic
0151  *   extension during the thread terminate invocation.  Clean up the used
0152  *   resources.
0153  *
0154  *   - Check that the thread terminate extensions were invoked in the right
0155  *     order.
0156  *
0157  *   - Check that the other extensions were not invoked.
0158  *
0159  *   - Check that the thread terminate extension of the extension set deleted
0160  *     before its turn in the invocation was not invoked.
0161  *
0162  * - Create five dynamic extensions.  Let an idle thread return from its entry.
0163  *   Delete three dynamic extension during the thread exitted invocation.
0164  *   Clean up the used resources.
0165  *
0166  *   - Check that the thread exitted extensions were invoked in the right
0167  *     order.
0168  *
0169  *   - Check that the other extensions were not invoked.
0170  *
0171  *   - Check that the thread exitted extension of the extension set deleted
0172  *     before its turn in the invocation was not invoked.
0173  *
0174  * @{
0175  */
0176 
0177 typedef struct {
0178   unsigned int counter;
0179   rtems_tcb   *executing;
0180   rtems_tcb   *thread;
0181 } ExtensionEvent;
0182 
0183 typedef enum {
0184   THREAD_BEGIN,
0185   THREAD_CREATE,
0186   THREAD_DELETE,
0187   THREAD_EXITTED,
0188   THREAD_RESTART,
0189   THREAD_START,
0190   THREAD_SWITCH,
0191   THREAD_TERMINATE,
0192   EXTENSION_KIND_COUNT
0193 } ExtensionKind;
0194 
0195 static rtems_id extension_ids[ 7 ];
0196 
0197 static Atomic_Uint extension_counter[ RTEMS_ARRAY_SIZE( extension_ids ) ]
0198   [ EXTENSION_KIND_COUNT ];
0199 
0200 static ExtensionEvent extension_events[ RTEMS_ARRAY_SIZE( extension_ids ) ]
0201   [ EXTENSION_KIND_COUNT ][ 3 ];
0202 
0203 static Atomic_Uint global_counter;
0204 
0205 static ExtensionKind extension_under_test = EXTENSION_KIND_COUNT;
0206 
0207 static uint32_t thread_create_allocator_owner_count;
0208 
0209 static uint32_t thread_delete_allocator_owner_count;
0210 
0211 static void StopTestCase( void )
0212 {
0213   ExtensionKind     kind;
0214   rtems_status_code sc;
0215 
0216   kind = extension_under_test;
0217   extension_under_test = EXTENSION_KIND_COUNT;
0218 
0219   sc = rtems_extension_delete( extension_ids[ 2 ] );
0220   T_rsc_success( sc );
0221 
0222   if ( kind == THREAD_SWITCH ) {
0223     sc = rtems_extension_delete( extension_ids[ 3 ] );
0224     T_rsc_success( sc );
0225 
0226     sc = rtems_extension_delete( extension_ids[ 4 ] );
0227     T_rsc_success( sc );
0228 
0229     sc = rtems_extension_delete( extension_ids[ 5 ] );
0230     T_rsc_success( sc );
0231   }
0232 
0233   sc = rtems_extension_delete( extension_ids[ 6 ] );
0234   T_rsc_success( sc );
0235 }
0236 
0237 static void Extension(
0238   size_t        index,
0239   ExtensionKind kind,
0240   rtems_tcb    *executing,
0241   rtems_tcb    *thread
0242 )
0243 {
0244   unsigned int      gc;
0245   unsigned int      c;
0246   rtems_status_code sc;
0247 
0248   if ( extension_under_test == EXTENSION_KIND_COUNT ) {
0249     return;
0250   }
0251 
0252   if ( kind == THREAD_CREATE && _RTEMS_Allocator_is_owner() ) {
0253     ++thread_create_allocator_owner_count;
0254   }
0255 
0256   if ( kind == THREAD_DELETE && _RTEMS_Allocator_is_owner() ) {
0257     ++thread_delete_allocator_owner_count;
0258   }
0259 
0260   gc = _Atomic_Fetch_add_uint( &global_counter, 1, ATOMIC_ORDER_RELAXED ) + 1;
0261   c = _Atomic_Fetch_add_uint(
0262     &extension_counter[ index ][ kind ],
0263     1,
0264     ATOMIC_ORDER_RELAXED
0265   );
0266 
0267   if ( c < RTEMS_ARRAY_SIZE( extension_events[ index ][ kind ] ) ) {
0268     extension_events[ index ][ kind ][ c ].counter = gc;
0269     extension_events[ index ][ kind ][ c ].executing = executing;
0270     extension_events[ index ][ kind ][ c ].thread = thread;
0271   }
0272 
0273   if ( kind == THREAD_SWITCH ) {
0274     /* Extension set deletion is not allowed in thread switch extensions */
0275     return;
0276   }
0277 
0278   if ( kind != extension_under_test ) {
0279     return;
0280   }
0281 
0282   if ( kind == THREAD_DELETE || kind == THREAD_TERMINATE ) {
0283     if ( index == 6 ) {
0284       sc = rtems_extension_delete( extension_ids[ 5 ] );
0285       T_rsc_success( sc );
0286     } else if ( index == 3 ) {
0287       sc = rtems_extension_delete( extension_ids[ 3 ] );
0288       T_rsc_success( sc );
0289     } else if ( index == 2 ) {
0290       sc = rtems_extension_delete( extension_ids[ 4 ] );
0291       T_rsc_success( sc );
0292     }
0293   } else {
0294     if ( index == 2 ) {
0295       sc = rtems_extension_delete( extension_ids[ 3 ] );
0296       T_rsc_success( sc );
0297     } else if ( index == 5 ) {
0298       sc = rtems_extension_delete( extension_ids[ 5 ] );
0299       T_rsc_success( sc );
0300     } else if ( index == 6 ) {
0301       sc = rtems_extension_delete( extension_ids[ 4 ] );
0302       T_rsc_success( sc );
0303     }
0304   }
0305 
0306   if ( index == 6 && ( kind == THREAD_EXITTED || kind == THREAD_RESTART ) ) {
0307     StopTestCase();
0308 
0309     if ( GetExecuting()->is_idle ) {
0310       SetSelfPriority( RTEMS_MAXIMUM_PRIORITY );
0311       _CPU_Thread_Idle_body( 0 );
0312     } else {
0313       rtems_task_exit();
0314     }
0315   }
0316 
0317   if ( index == 0 && kind == THREAD_TERMINATE ) {
0318     StopTestCase();
0319   }
0320 }
0321 
0322 #define DEFINE_EXTENSIONS( index, linkage ) \
0323   linkage void ThreadBeginExtension##index( rtems_tcb *executing ) \
0324   { \
0325     Extension( index, THREAD_BEGIN, executing, NULL ); \
0326   } \
0327   linkage bool ThreadCreateExtension##index( \
0328     rtems_tcb *executing, \
0329     rtems_tcb *created \
0330   ) \
0331   { \
0332     Extension( index, THREAD_CREATE, executing, created ); \
0333     return true; \
0334   } \
0335   linkage void ThreadDeleteExtension##index( \
0336     rtems_tcb *executing, \
0337     rtems_tcb *deleted \
0338   ) \
0339   { \
0340     Extension( index, THREAD_DELETE, executing, deleted ); \
0341   } \
0342   linkage void ThreadExittedExtension##index( rtems_tcb *executing ) \
0343   { \
0344     Extension( index, THREAD_EXITTED, executing, NULL ); \
0345   } \
0346   linkage void ThreadRestartExtension##index( \
0347     rtems_tcb *executing, \
0348     rtems_tcb *restarted \
0349   ) \
0350   { \
0351     Extension( index, THREAD_RESTART, executing, restarted ); \
0352   } \
0353   linkage void ThreadStartExtension##index( \
0354     rtems_tcb *executing, \
0355     rtems_tcb *started \
0356   ) \
0357   { \
0358     Extension( index, THREAD_START, executing, started ); \
0359   } \
0360   linkage void ThreadSwitchExtension##index( \
0361     rtems_tcb *executing, \
0362     rtems_tcb *heir \
0363   ) \
0364   { \
0365     Extension( index, THREAD_SWITCH, executing, heir ); \
0366   } \
0367   linkage void ThreadTerminateExtension##index( rtems_tcb *executing ) \
0368   { \
0369     Extension( index, THREAD_TERMINATE, executing, NULL ); \
0370   }
0371 
0372 DEFINE_EXTENSIONS( 0, )
0373 DEFINE_EXTENSIONS( 1, )
0374 
0375 #define DEFINE_EXTENSIONS_AND_TABLE( index ) \
0376   DEFINE_EXTENSIONS( index, static ) \
0377   static const rtems_extensions_table table_##index = { \
0378     .thread_begin = ThreadBeginExtension##index, \
0379     .thread_create = ThreadCreateExtension##index, \
0380     .thread_delete = ThreadDeleteExtension##index, \
0381     .thread_exitted = ThreadExittedExtension##index, \
0382     .thread_restart = ThreadRestartExtension##index, \
0383     .thread_start = ThreadStartExtension##index, \
0384     .thread_switch = ThreadSwitchExtension##index, \
0385     .thread_terminate = ThreadTerminateExtension##index \
0386   }
0387 
0388 DEFINE_EXTENSIONS_AND_TABLE( 2 );
0389 DEFINE_EXTENSIONS_AND_TABLE( 3 );
0390 DEFINE_EXTENSIONS_AND_TABLE( 4 );
0391 DEFINE_EXTENSIONS_AND_TABLE( 5 );
0392 DEFINE_EXTENSIONS_AND_TABLE( 6 );
0393 
0394 static const rtems_extensions_table * const tables[] = {
0395   NULL,
0396   NULL,
0397   &table_2,
0398   &table_3,
0399   &table_4,
0400   &table_5,
0401   &table_6
0402 };
0403 
0404 static rtems_tcb *StartTestCase( ExtensionKind kind )
0405 {
0406   size_t i;
0407 
0408   thread_create_allocator_owner_count = 0;
0409   thread_delete_allocator_owner_count = 0;
0410   _Atomic_Store_uint( &global_counter, 0, ATOMIC_ORDER_RELAXED );
0411   memset( extension_counter, 0, sizeof( extension_counter ) );
0412   memset( extension_events, 0, sizeof( extension_events ) );
0413 
0414   extension_under_test = kind;
0415 
0416   for ( i = 2; i < RTEMS_ARRAY_SIZE( extension_ids ); ++i ) {
0417     rtems_status_code sc;
0418 
0419     sc = rtems_extension_create(
0420       rtems_build_name( ' ', ' ', ' ', '2' + i ),
0421       tables[ i ],
0422       &extension_ids[ i ]
0423     );
0424     T_rsc_success( sc );
0425   }
0426 
0427   return GetExecuting();
0428 }
0429 
0430 static void CheckForward(
0431   ExtensionKind kind,
0432   unsigned int  counter,
0433   unsigned int  increment,
0434   rtems_tcb    *executing,
0435   rtems_tcb    *thread
0436 )
0437 {
0438   size_t i;
0439 
0440   for ( i = 0; i < RTEMS_ARRAY_SIZE( extension_ids ); ++i ) {
0441     if ( i == 3 && kind != THREAD_SWITCH ) {
0442       continue;
0443     }
0444 
0445     if ( counter == 0 ) {
0446       T_eq_uint( extension_counter[ i ][ kind ], 0 );
0447     } else {
0448       T_eq_uint( extension_counter[ i ][ kind ], 1 );
0449       T_eq_uint( extension_events[ i ][ kind ][ 0 ].counter, counter );
0450       T_eq_ptr( extension_events[ i ][ kind ][ 0 ].executing, executing );
0451       T_eq_ptr( extension_events[ i ][ kind ][ 0 ].thread, thread );
0452 
0453       counter += increment;
0454     }
0455   }
0456 }
0457 
0458 static void CheckReverse(
0459   ExtensionKind kind,
0460   unsigned int  counter,
0461   unsigned int  increment,
0462   rtems_tcb    *executing,
0463   rtems_tcb    *thread
0464 )
0465 {
0466   size_t i;
0467 
0468   for ( i = 0; i < RTEMS_ARRAY_SIZE( extension_ids ); ++i ) {
0469     if ( i == 5 && kind != THREAD_SWITCH ) {
0470       continue;
0471     }
0472 
0473     if ( counter == 0 ) {
0474       T_eq_uint( extension_counter[ i ][ kind ], 0 );
0475     } else {
0476       T_eq_uint( extension_counter[ i ][ kind ], 1 );
0477       T_eq_uint(
0478         extension_events[ i ][ kind ][ 0 ].counter,
0479         7 - counter
0480       );
0481       T_eq_ptr( extension_events[ i ][ kind ][ 0 ].executing, executing );
0482       T_eq_ptr( extension_events[ i ][ kind ][ 0 ].thread, thread );
0483 
0484       counter += increment;
0485     }
0486   }
0487 }
0488 
0489 static void CheckDeletedNotInvoked( ExtensionKind kind )
0490 {
0491   size_t index;
0492 
0493   if ( kind == THREAD_DELETE || kind == THREAD_TERMINATE ) {
0494     index = 5;
0495   } else {
0496     index = 3;
0497   }
0498 
0499   T_eq_uint( extension_events[ index ][ kind ][ 0 ].counter, 0 );
0500   T_null( extension_events[ index ][ kind ][ 0 ].executing );
0501   T_null( extension_events[ index ][ kind ][ 0 ].thread );
0502 }
0503 
0504 static void BeginWorker( rtems_task_argument arg )
0505 {
0506   T_eq_u32( arg, 0 );
0507   StopTestCase();
0508   rtems_task_exit();
0509 }
0510 
0511 static void ExittedWorker( rtems_task_argument arg )
0512 {
0513   T_eq_u32( arg, 0 );
0514   (void) StartTestCase( THREAD_EXITTED );
0515 }
0516 
0517 static void RestartWorker( rtems_task_argument arg )
0518 {
0519   T_eq_u32( arg, 0 );
0520   (void) StartTestCase( THREAD_RESTART );
0521   (void) rtems_task_restart( RTEMS_SELF, 1 );
0522 }
0523 
0524 static void StartWorker( rtems_task_argument arg )
0525 {
0526   (void) arg;
0527   T_unreachable();
0528 }
0529 
0530 static void TerminateWorker( rtems_task_argument arg )
0531 {
0532   T_eq_u32( arg, 0 );
0533   (void) StartTestCase( THREAD_TERMINATE );
0534   rtems_task_exit();
0535 }
0536 
0537 void *IdleBody( uintptr_t arg )
0538 {
0539   rtems_event_set events;
0540 
0541   do {
0542     events = PollAnyEvents();
0543   } while ( events == 0 );
0544 
0545   (void) StartTestCase( THREAD_EXITTED );
0546   return (void *) arg;
0547 }
0548 
0549 static void RtemsUserextValUserext_Setup( void *ctx )
0550 {
0551   SetSelfPriority( PRIO_NORMAL );
0552 }
0553 
0554 static void RtemsUserextValUserext_Teardown( void *ctx )
0555 {
0556   RestoreRunnerPriority();
0557 }
0558 
0559 static T_fixture RtemsUserextValUserext_Fixture = {
0560   .setup = RtemsUserextValUserext_Setup,
0561   .stop = NULL,
0562   .teardown = RtemsUserextValUserext_Teardown,
0563   .scope = NULL,
0564   .initial_context = NULL
0565 };
0566 
0567 /**
0568  * @brief Create five dynamic extensions.  Switch to a started thread.  Delete
0569  *   three dynamic extension during the thread begin invocation.  Clean up the
0570  *   used resources.
0571  */
0572 static void RtemsUserextValUserext_Action_0( void )
0573 {
0574   rtems_tcb *executing;
0575   rtems_tcb *thread;
0576   rtems_id   id;
0577 
0578   id = CreateTask( "WORK", PRIO_LOW );
0579   thread = GetThread( id );
0580   StartTask( id, BeginWorker, NULL );
0581   executing = StartTestCase( THREAD_BEGIN );
0582   SetPriority( id, PRIO_HIGH );
0583   KillZombies();
0584 
0585   /*
0586    * Check that the thread switch extensions were invoked in the right order
0587    * before the thread begin extensions.
0588    */
0589   CheckForward( THREAD_SWITCH, 1, 1, executing, thread );
0590 
0591   /*
0592    * Check that the thread begin extensions were invoked in the right order.
0593    */
0594   CheckForward( THREAD_BEGIN, 8, 1, thread, NULL );
0595 
0596   /*
0597    * Check that the other extensions were not invoked.
0598    */
0599   CheckForward( THREAD_CREATE, 0, 0, NULL, NULL );
0600   CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL );
0601   CheckForward( THREAD_EXITTED, 0, 0, NULL, NULL );
0602   CheckForward( THREAD_RESTART, 0, 0, NULL, NULL );
0603   CheckForward( THREAD_START, 0, 0, NULL, NULL );
0604   CheckReverse( THREAD_TERMINATE, 0, 0, NULL, NULL );
0605 
0606   /*
0607    * Check that the thread begin extension of the extension set deleted before
0608    * its turn in the invocation was not invoked.
0609    */
0610   CheckDeletedNotInvoked( THREAD_BEGIN );
0611 }
0612 
0613 /**
0614  * @brief Create five dynamic extensions.  Create a thread.  Delete three
0615  *   dynamic extension during the thread create invocation.  Clean up the used
0616  *   resources.
0617  */
0618 static void RtemsUserextValUserext_Action_1( void )
0619 {
0620   rtems_tcb *executing;
0621   rtems_tcb *thread;
0622   rtems_id   id;
0623 
0624   executing = StartTestCase( THREAD_CREATE );
0625   id = CreateTask( "WORK", PRIO_NORMAL );
0626   thread = GetThread( id );
0627   StopTestCase();
0628   DeleteTask( id );
0629   KillZombies();
0630 
0631   /*
0632    * Check that the thread create extensions were invoked in the right order.
0633    */
0634   CheckForward( THREAD_CREATE, 1, 1, executing, thread );
0635 
0636   /*
0637    * Check that the thread create extensions were invoked under protection of
0638    * the allocator mutex.
0639    */
0640   T_eq_u32( thread_create_allocator_owner_count, 6 );
0641 
0642   /*
0643    * Check that the other extensions were not invoked.
0644    */
0645   CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL );
0646   CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL );
0647   CheckForward( THREAD_EXITTED, 0, 0, NULL, NULL );
0648   CheckForward( THREAD_RESTART, 0, 0, NULL, NULL );
0649   CheckForward( THREAD_START, 0, 0, NULL, NULL );
0650   CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL );
0651   CheckReverse( THREAD_TERMINATE, 0, 0, NULL, NULL );
0652 
0653   /*
0654    * Check that the thread create extension of the extension set deleted before
0655    * its turn in the invocation was not invoked.
0656    */
0657   CheckDeletedNotInvoked( THREAD_CREATE );
0658 }
0659 
0660 /**
0661  * @brief Create five dynamic extensions.  Delete a thread.  Delete three
0662  *   dynamic extension during the thread delete invocation.  Clean up the used
0663  *   resources.
0664  */
0665 static void RtemsUserextValUserext_Action_2( void )
0666 {
0667   rtems_tcb *executing;
0668   rtems_tcb *thread;
0669   rtems_id   id;
0670 
0671   id = CreateTask( "WORK", PRIO_NORMAL );
0672   thread = GetThread( id );
0673   DeleteTask( id );
0674   executing = StartTestCase( THREAD_DELETE );
0675   KillZombies();
0676   StopTestCase();
0677 
0678   /*
0679    * Check that the thread delete extensions were invoked in the right order.
0680    */
0681   CheckReverse( THREAD_DELETE, 1, 1, executing, thread );
0682 
0683   /*
0684    * Check that the thread delete extensions were invoked under protection of
0685    * the allocator mutex.
0686    */
0687   T_eq_u32( thread_delete_allocator_owner_count, 6 );
0688 
0689   /*
0690    * Check that the other extensions were not invoked.
0691    */
0692   CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL );
0693   CheckForward( THREAD_CREATE, 0, 0, NULL, NULL );
0694   CheckForward( THREAD_EXITTED, 0, 0, NULL, NULL );
0695   CheckForward( THREAD_RESTART, 0, 0, NULL, NULL );
0696   CheckForward( THREAD_START, 0, 0, NULL, NULL );
0697   CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL );
0698   CheckReverse( THREAD_TERMINATE, 0, 0, NULL, NULL );
0699 
0700   /*
0701    * Check that the thread delete extension of the extension set deleted before
0702    * its turn in the invocation was not invoked.
0703    */
0704   CheckDeletedNotInvoked( THREAD_DELETE );
0705 }
0706 
0707 /**
0708  * @brief Create five dynamic extensions.  Return from a thread entry.  Delete
0709  *   three dynamic extension during the thread exitted invocation.  Clean up
0710  *   the used resources.
0711  */
0712 static void RtemsUserextValUserext_Action_3( void )
0713 {
0714   rtems_tcb *thread;
0715   rtems_id   id;
0716 
0717   id = CreateTask( "WORK", PRIO_HIGH );
0718   thread = GetThread( id );
0719   StartTask( id, ExittedWorker, NULL );
0720   KillZombies();
0721 
0722   /*
0723    * Check that the thread exitted extensions were invoked in the right order.
0724    */
0725   CheckForward( THREAD_EXITTED, 1, 1, thread, NULL );
0726 
0727   /*
0728    * Check that the other extensions were not invoked.
0729    */
0730   CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL );
0731   CheckForward( THREAD_CREATE, 0, 0, NULL, NULL );
0732   CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL );
0733   CheckForward( THREAD_RESTART, 0, 0, NULL, NULL );
0734   CheckForward( THREAD_START, 0, 0, NULL, NULL );
0735   CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL );
0736   CheckReverse( THREAD_TERMINATE, 0, 0, NULL, NULL );
0737 
0738   /*
0739    * Check that the thread exitted extension of the extension set deleted
0740    * before its turn in the invocation was not invoked.
0741    */
0742   CheckDeletedNotInvoked( THREAD_EXITTED );
0743 }
0744 
0745 /**
0746  * @brief Create five dynamic extensions.  Restart a thread.  Delete three
0747  *   dynamic extension during the thread restart invocation.  Clean up the used
0748  *   resources.
0749  */
0750 static void RtemsUserextValUserext_Action_4( void )
0751 {
0752   rtems_tcb *thread;
0753   rtems_id   id;
0754 
0755   id = CreateTask( "WORK", PRIO_HIGH );
0756   thread = GetThread( id );
0757   StartTask( id, RestartWorker, NULL );
0758   KillZombies();
0759 
0760   /*
0761    * Check that the thread restart extensions were invoked in the right order.
0762    */
0763   CheckForward( THREAD_RESTART, 1, 1, thread, thread );
0764 
0765   /*
0766    * Check that the other extensions were not invoked.
0767    */
0768   CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL );
0769   CheckForward( THREAD_EXITTED, 0, 0, NULL, NULL );
0770   CheckForward( THREAD_CREATE, 0, 0, NULL, NULL );
0771   CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL );
0772   CheckForward( THREAD_START, 0, 0, NULL, NULL );
0773   CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL );
0774   CheckForward( THREAD_TERMINATE, 0, 0, NULL, NULL );
0775 
0776   /*
0777    * Check that the thread restart extension of the extension set deleted
0778    * before its turn in the invocation was not invoked.
0779    */
0780   CheckDeletedNotInvoked( THREAD_RESTART );
0781 }
0782 
0783 /**
0784  * @brief Create five dynamic extensions.  Start a thread.  Delete three
0785  *   dynamic extension during the thread start invocation.  Clean up the used
0786  *   resources.
0787  */
0788 static void RtemsUserextValUserext_Action_5( void )
0789 {
0790   rtems_tcb *executing;
0791   rtems_tcb *thread;
0792   rtems_id   id;
0793 
0794   id = CreateTask( "WORK", PRIO_LOW );
0795   thread = GetThread( id );
0796   executing = StartTestCase( THREAD_START );
0797   StartTask( id, StartWorker, NULL );
0798   StopTestCase();
0799   DeleteTask( id );
0800   KillZombies();
0801 
0802   /*
0803    * Check that the thread start extensions were invoked in the right order.
0804    */
0805   CheckForward( THREAD_START, 1, 1, executing, thread );
0806 
0807   /*
0808    * Check that the other extensions were not invoked.
0809    */
0810   CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL );
0811   CheckForward( THREAD_EXITTED, 0, 0, NULL, NULL );
0812   CheckForward( THREAD_CREATE, 0, 0, NULL, NULL );
0813   CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL );
0814   CheckForward( THREAD_RESTART, 0, 0, NULL, NULL );
0815   CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL );
0816   CheckForward( THREAD_TERMINATE, 0, 0, NULL, NULL );
0817 
0818   /*
0819    * Check that the thread start extension of the extension set deleted before
0820    * its turn in the invocation was not invoked.
0821    */
0822   CheckDeletedNotInvoked( THREAD_START );
0823 }
0824 
0825 /**
0826  * @brief Create five dynamic extensions.  Terminate a thread.  Delete three
0827  *   dynamic extension during the thread terminate invocation.  Clean up the
0828  *   used resources.
0829  */
0830 static void RtemsUserextValUserext_Action_6( void )
0831 {
0832   rtems_tcb *thread;
0833   rtems_id   id;
0834 
0835   id = CreateTask( "WORK", PRIO_HIGH );
0836   thread = GetThread( id );
0837   StartTask( id, TerminateWorker, NULL );
0838   KillZombies();
0839 
0840   /*
0841    * Check that the thread terminate extensions were invoked in the right
0842    * order.
0843    */
0844   CheckReverse( THREAD_TERMINATE, 1, 1, thread, NULL );
0845 
0846   /*
0847    * Check that the other extensions were not invoked.
0848    */
0849   CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL );
0850   CheckForward( THREAD_EXITTED, 0, 0, NULL, NULL );
0851   CheckForward( THREAD_CREATE, 0, 0, NULL, NULL );
0852   CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL );
0853   CheckForward( THREAD_RESTART, 0, 0, NULL, NULL );
0854   CheckForward( THREAD_START, 0, 0, NULL, NULL );
0855   CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL );
0856 
0857   /*
0858    * Check that the thread terminate extension of the extension set deleted
0859    * before its turn in the invocation was not invoked.
0860    */
0861   CheckDeletedNotInvoked( THREAD_TERMINATE );
0862 }
0863 
0864 /**
0865  * @brief Create five dynamic extensions.  Let an idle thread return from its
0866  *   entry. Delete three dynamic extension during the thread exitted
0867  *   invocation.  Clean up the used resources.
0868  */
0869 static void RtemsUserextValUserext_Action_7( void )
0870 {
0871   rtems_tcb *thread;
0872   rtems_id   id;
0873 
0874   /* ID of idle thread of processor 0 */
0875   id = 0x09010001;
0876   thread = GetThread( id );
0877   SendEvents( id, RTEMS_EVENT_0 );
0878   SetPriority( id, PRIO_HIGH );
0879 
0880   /*
0881    * Check that the thread exitted extensions were invoked in the right order.
0882    */
0883   CheckForward( THREAD_EXITTED, 1, 1, thread, NULL );
0884 
0885   /*
0886    * Check that the other extensions were not invoked.
0887    */
0888   CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL );
0889   CheckForward( THREAD_CREATE, 0, 0, NULL, NULL );
0890   CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL );
0891   CheckForward( THREAD_RESTART, 0, 0, NULL, NULL );
0892   CheckForward( THREAD_START, 0, 0, NULL, NULL );
0893   CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL );
0894   CheckReverse( THREAD_TERMINATE, 0, 0, NULL, NULL );
0895 
0896   /*
0897    * Check that the thread exitted extension of the extension set deleted
0898    * before its turn in the invocation was not invoked.
0899    */
0900   CheckDeletedNotInvoked( THREAD_EXITTED );
0901 }
0902 
0903 /**
0904  * @fn void T_case_body_RtemsUserextValUserext( void )
0905  */
0906 T_TEST_CASE_FIXTURE( RtemsUserextValUserext, &RtemsUserextValUserext_Fixture )
0907 {
0908   RtemsUserextValUserext_Action_0();
0909   RtemsUserextValUserext_Action_1();
0910   RtemsUserextValUserext_Action_2();
0911   RtemsUserextValUserext_Action_3();
0912   RtemsUserextValUserext_Action_4();
0913   RtemsUserextValUserext_Action_5();
0914   RtemsUserextValUserext_Action_6();
0915   RtemsUserextValUserext_Action_7();
0916 }
0917 
0918 /** @} */