Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Redistribution and use in source and binary forms, with or without
0005  * modification, are permitted provided that the following conditions
0006  * are met:
0007  * 1. Redistributions of source code must retain the above copyright
0008  *    notice, this list of conditions and the following disclaimer.
0009  * 2. Redistributions in binary form must reproduce the above copyright
0010  *    notice, this list of conditions and the following disclaimer in the
0011  *    documentation and/or other materials provided with the distribution.
0012  *
0013  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0014  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0015  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0016  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0017  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0018  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0019  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0020  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0021  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0022  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0023  * POSSIBILITY OF SUCH DAMAGE.
0024  */
0025 
0026 #ifdef HAVE_CONFIG_H
0027 #include "config.h"
0028 #endif
0029 
0030 #include <stdio.h>
0031 #include <stdlib.h>
0032 #include <pthread.h>
0033 #include <sys/time.h>
0034 #include <unistd.h>
0035 #include <errno.h>
0036 #include <sched.h>
0037 #include <semaphore.h>
0038 
0039 #if defined(__rtems__)
0040   #include <rtems.h>
0041   #include <rtems/libcsupport.h>
0042   #include <pmacros.h>
0043 #endif
0044 
0045 const char rtems_test_name[] = "PSXCANCEL";
0046 
0047 /* forward declarations to avoid warnings */
0048 void *POSIX_Init(void *argument);
0049 
0050 #if defined(__rtems__)
0051 static rtems_resource_snapshot initialSnapshot;
0052 #endif
0053 
0054 static volatile bool countTask_handler;
0055 
0056 static sem_t masterSem;
0057 
0058 static sem_t workerSem;
0059 
0060 static void countTask_cancel_handler(void *ignored)
0061 {
0062   countTask_handler = true;
0063 }
0064 
0065 static void *countTaskDeferred(void *ignored)
0066 {
0067   int i=0;
0068   int type,state;
0069   int sc;
0070 
0071   sc = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &type);
0072   fatal_posix_service_status( sc, 0, "cancel state deferred" );
0073   rtems_test_assert( type == PTHREAD_CANCEL_ENABLE );
0074   sc = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &state);
0075   fatal_posix_service_status( sc, 0, "cancel type deferred" );
0076   rtems_test_assert( state == PTHREAD_CANCEL_DEFERRED );
0077   while (1) {
0078     printf("countTaskDeferred: elapsed time (second): %2d\n", i++ );
0079     sleep(1);
0080     pthread_testcancel();
0081   }
0082 }
0083 
0084 static void *countTaskAsync(void *ignored)
0085 {
0086   int i=0;
0087   int type,state;
0088   int sc;
0089 
0090   sc = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &type);
0091   fatal_posix_service_status( sc, 0, "cancel state async" );
0092   rtems_test_assert( type == PTHREAD_CANCEL_ENABLE );
0093   sc = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &state);
0094   fatal_posix_service_status( sc, 0, "cancel type async" );
0095   rtems_test_assert( state == PTHREAD_CANCEL_DEFERRED );
0096   pthread_cleanup_push(countTask_cancel_handler, NULL);
0097   while (1) {
0098     printf("countTaskAsync: elapsed time (second): %2d\n", i++ );
0099     sleep(1);
0100   }
0101   countTask_handler = false;
0102   pthread_cleanup_pop(1);
0103   if ( countTask_handler == false ){
0104     puts("countTask_cancel_handler not executed");
0105     rtems_test_exit(0);
0106   }
0107 }
0108 
0109 static void *taskAsyncAndDetached(void *ignored)
0110 {
0111   int sc;
0112 
0113   sc = pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL );
0114   fatal_posix_service_status( sc, 0, "cancel type taskAsyncAndDetached" );
0115 
0116   sc = sem_post( &workerSem );
0117   rtems_test_assert( sc == 0 );
0118 
0119   sc = sem_wait( &masterSem );
0120   rtems_test_assert( sc == 0 );
0121 
0122   rtems_test_assert( 0 );
0123 }
0124 
0125 static void *taskSelfDetach(void *ignored)
0126 {
0127   int sc;
0128 
0129   sc = sem_post( &workerSem );
0130   rtems_test_assert( sc == 0 );
0131 
0132   sleep( 1 );
0133 
0134   sc = pthread_detach( pthread_self() );
0135   fatal_posix_service_status( sc, 0, "detach taskSelfDetach" );
0136 
0137   pthread_exit( (void *) 123 );
0138 }
0139 
0140 static void resourceSnapshotInit( void )
0141 {
0142 #if defined(__rtems__)
0143   rtems_resource_snapshot_take( &initialSnapshot );
0144 #endif
0145 }
0146 
0147 static void resourceSnapshotCheck( void )
0148 {
0149 #if defined(__rtems__)
0150   rtems_test_assert( rtems_resource_snapshot_check( &initialSnapshot ) );
0151 #endif
0152 }
0153 
0154 #if defined(__rtems__)
0155   void *POSIX_Init(void *ignored)
0156 #else
0157   int main(int argc, char **argv)
0158 #endif
0159 {
0160   pthread_t task;
0161   int       taskparameter = 0;
0162   int       sc;
0163   int       old;
0164   void     *exit_value;
0165 
0166   TEST_BEGIN();
0167 
0168   sc = sem_init( &masterSem, 0, 0 );
0169   rtems_test_assert( sc == 0 );
0170 
0171   sc = sem_init( &workerSem, 0, 0 );
0172   rtems_test_assert( sc == 0 );
0173 
0174   resourceSnapshotInit();
0175 
0176   /* generate some error conditions */
0177   puts( "Init - pthread_setcancelstate - NULL oldstate" );
0178   sc = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
0179   fatal_posix_service_status( sc, 0, "cancel state NULL" );
0180 
0181   puts( "Init - pthread_setcancelstate - bad state - EINVAL" );
0182   sc = pthread_setcancelstate(12, &old);
0183   fatal_posix_service_status( sc, EINVAL, "cancel state EINVAL" );
0184 
0185   puts( "Init - pthread_setcanceltype - NULL oldtype" );
0186   sc = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
0187   fatal_posix_service_status( sc, 0, "cancel type NULL" );
0188 
0189   puts( "Init - pthread_setcanceltype - bad type - EINVAL" );
0190   sc = pthread_setcanceltype(12, &old);
0191   fatal_posix_service_status( sc, EINVAL, "cancel type EINVAL" );
0192 
0193   puts( "Init - pthread_cancel - bad ID - ESRCH" );
0194   sc = pthread_cancel(0x100);
0195   fatal_posix_service_status( sc, ESRCH, "cancel bad Id" );
0196 
0197   resourceSnapshotCheck();
0198 
0199   /* Test resource reclamation due to pthread_detach() */
0200 
0201   sc = pthread_create( &task, NULL, taskAsyncAndDetached, NULL );
0202   fatal_posix_service_status( sc, 0, "create taskAsyncAndDetached" );
0203 
0204   sc = sem_wait( &workerSem );
0205   rtems_test_assert( sc == 0 );
0206 
0207   sc = pthread_cancel( task );
0208   fatal_posix_service_status( sc, 0, "cancel taskAsyncAndDetached" );
0209 
0210   sc = pthread_detach( task );
0211   fatal_posix_service_status( sc, 0, "detach taskAsyncAndDetached" );
0212 
0213   sched_yield();
0214 
0215   sc = pthread_join( task, &exit_value );
0216   fatal_posix_service_status( sc, ESRCH, "join taskAsyncAndDetached" );
0217 
0218   resourceSnapshotCheck();
0219 
0220   /* Test pthread_detach() after pthread_join() */
0221 
0222   sc = pthread_create( &task, NULL, taskSelfDetach, NULL );
0223   fatal_posix_service_status( sc, 0, "create taskSelfDetach" );
0224 
0225   sc = sem_wait( &workerSem );
0226   rtems_test_assert( sc == 0 );
0227 
0228   sc = pthread_join( task, &exit_value );
0229   fatal_posix_service_status( sc, 0, "join taskSelfDetach" );
0230   rtems_test_assert( exit_value == (void *) 123 );
0231 
0232   resourceSnapshotCheck();
0233 
0234   /* Start countTask deferred */
0235   {
0236     sc = pthread_create(&task, NULL, countTaskDeferred, &taskparameter);
0237     if (sc) {
0238       perror("pthread_create: countTask");
0239       rtems_test_exit(EXIT_FAILURE);
0240     }
0241     /* sleep for 5 seconds, then cancel it */
0242     sleep(5);
0243     sc = pthread_cancel(task);
0244     fatal_posix_service_status( sc, 0, "cancel deferred" );
0245     sc = pthread_join(task, NULL);
0246     fatal_posix_service_status( sc, 0, "join deferred" );
0247   }
0248 
0249   /* Start countTask asynchronous */
0250   {
0251     sc = pthread_create(&task, NULL, countTaskAsync, &taskparameter);
0252     if (sc) {
0253       perror("pthread_create: countTask");
0254       rtems_test_exit(EXIT_FAILURE);
0255     }
0256     /* sleep for 5 seconds, then cancel it */
0257     sleep(5);
0258     sc = pthread_cancel(task);
0259     fatal_posix_service_status( sc, 0, "cancel async" );
0260     sc = pthread_join(task, NULL);
0261     fatal_posix_service_status( sc, 0, "join async" );
0262   }
0263 
0264   resourceSnapshotCheck();
0265 
0266   TEST_END();
0267 
0268   #if defined(__rtems__)
0269     rtems_test_exit(EXIT_SUCCESS);
0270     return NULL;
0271   #else
0272     return 0;
0273   #endif
0274 }
0275 
0276 /* configuration information */
0277 #if defined(__rtems__)
0278 
0279 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0280 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0281 
0282 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0283 
0284 #define CONFIGURE_MAXIMUM_POSIX_THREADS 2
0285 
0286 #define CONFIGURE_POSIX_INIT_THREAD_TABLE
0287 
0288 #define CONFIGURE_INIT
0289 #include <rtems/confdefs.h>
0290 
0291 #endif /* __rtems__ */
0292