Home | History | Annotate | Download | only in pthread_exit
      1 /*
      2  * Copyright (c) 2004, Bull S.A..  All rights reserved.
      3  * Created by: Sebastien Decugis
      4 
      5  * This program is free software; you can redistribute it and/or modify it
      6  * under the terms of version 2 of the GNU General Public License as
      7  * published by the Free Software Foundation.
      8  *
      9  * This program is distributed in the hope that it would be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12  *
     13  * You should have received a copy of the GNU General Public License along
     14  * with this program; if not, write the Free Software Foundation, Inc.,
     15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     16 
     17  * This sample test aims to check the following assertion:
     18  *
     19  * When a thread other than the first thread of a process returns,
     20  * an implicit call to pthread_exit() is made with the returned value
     21  * as a parameter.
     22 
     23  * The steps are:
     24  *
     25  * Same test as 1-2, 3-2, 4-1, but with return in place of pthread_exit.
     26  * The results shall be the same.
     27 
     28   */
     29 
     30  /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
     31 #define _POSIX_C_SOURCE 200112L
     32 
     33  /* Some routines are part of the XSI Extensions */
     34 #ifndef WITHOUT_XOPEN
     35 #define _XOPEN_SOURCE	600
     36 #endif
     37 
     38 /********************************************************************************************/
     39 /****************************** standard includes *****************************************/
     40 /********************************************************************************************/
     41 #include <pthread.h>
     42 #include <stdarg.h>
     43 #include <stdio.h>
     44 #include <stdlib.h>
     45 #include <string.h>
     46 #include <unistd.h>
     47 
     48 #include <sched.h>
     49 #include <semaphore.h>
     50 #include <errno.h>
     51 #include <assert.h>
     52 /********************************************************************************************/
     53 /******************************   Test framework   *****************************************/
     54 /********************************************************************************************/
     55 #include "../testfrmw/testfrmw.h"
     56 #include "../testfrmw/testfrmw.c"
     57  /* This header is responsible for defining the following macros:
     58   * UNRESOLVED(ret, descr);
     59   *    where descr is a description of the error and ret is an int (error code for example)
     60   * FAILED(descr);
     61   *    where descr is a short text saying why the test has failed.
     62   * PASSED();
     63   *    No parameter.
     64   *
     65   * Both three macros shall terminate the calling process.
     66   * The testcase shall not terminate in any other maneer.
     67   *
     68   * The other file defines the functions
     69   * void output_init()
     70   * void output(char * string, ...)
     71   *
     72   * Those may be used to output information.
     73   */
     74 
     75 /********************************************************************************************/
     76 /********************************** Configuration ******************************************/
     77 /********************************************************************************************/
     78 #ifndef VERBOSE
     79 #define VERBOSE 1
     80 #endif
     81 
     82 /********************************************************************************************/
     83 /***********************************    Test cases  *****************************************/
     84 /********************************************************************************************/
     85 
     86 #include "../testfrmw/threads_scenarii.c"
     87 
     88 /* This file will define the following objects:
     89  * scenarii: array of struct __scenario type.
     90  * NSCENAR : macro giving the total # of scenarii
     91  * scenar_init(): function to call before use the scenarii array.
     92  * scenar_fini(): function to call after end of use of the scenarii array.
     93  */
     94 
     95 /********************************************************************************************/
     96 /***********************************    Real Test   *****************************************/
     97 /********************************************************************************************/
     98 
     99 int atctl = 0;
    100 pthread_key_t tld[3];
    101 
    102 /* atexit() routines */
    103 void at1(void)
    104 {
    105 	atctl += 1;
    106 }
    107 
    108 void at2(void)
    109 {
    110 	atctl += 2;
    111 }
    112 
    113 /* TLD destructor */
    114 void destructor(void *arg)
    115 {
    116 	*(int *)arg += 1;
    117 }
    118 
    119 /* Thread routine */
    120 void *threaded(void *arg)
    121 {
    122 	int ret = 0;
    123 
    124 	ret = atexit(at2);
    125 	if (ret != 0) {
    126 		UNRESOLVED(ret, "Failed to register an atexit() routine");
    127 	}
    128 
    129 	ret = pthread_setspecific(tld[0], arg);
    130 	if (ret != 0) {
    131 		UNRESOLVED(ret, "Failed to set TLD data");
    132 	}
    133 
    134 	ret = pthread_setspecific(tld[1], arg);
    135 	if (ret != 0) {
    136 		UNRESOLVED(ret, "Failed to set TLD data");
    137 	}
    138 
    139 	ret = pthread_setspecific(tld[2], arg);
    140 	if (ret != 0) {
    141 		UNRESOLVED(ret, "Failed to set TLD data");
    142 	}
    143 
    144 	return NULL + 1;
    145 
    146 	FAILED("return did not terminate the thread (oO)");
    147 	return NULL;
    148 }
    149 
    150 /* Main routine */
    151 int main(void)
    152 {
    153 	int ret = 0;
    154 	int ctl = 0;
    155 	void *rval;
    156 	pthread_t child;
    157 	int i, j;
    158 
    159 	output_init();
    160 
    161 	scenar_init();
    162 
    163 	for (j = 0; j < 3; j++) {
    164 		ret = pthread_key_create(&tld[j], destructor);
    165 		if (ret != 0) {
    166 			UNRESOLVED(ret, "Failed to create a TLD key");
    167 		}
    168 	}
    169 
    170 	for (i = 0; i < NSCENAR; i++) {
    171 		if (scenarii[i].detached == 0) {
    172 #if VERBOSE > 0
    173 			output("-----\n");
    174 			output("Starting test with scenario (%i): %s\n", i,
    175 			       scenarii[i].descr);
    176 #endif
    177 
    178 			ctl = 0;
    179 
    180 			ret =
    181 			    pthread_create(&child, &scenarii[i].ta, threaded,
    182 					   &ctl);
    183 			switch (scenarii[i].result) {
    184 			case 0:	/* Operation was expected to succeed */
    185 				if (ret != 0) {
    186 					UNRESOLVED(ret,
    187 						   "Failed to create this thread");
    188 				}
    189 				break;
    190 
    191 			case 1:	/* Operation was expected to fail */
    192 				if (ret == 0) {
    193 					UNRESOLVED(-1,
    194 						   "An error was expected but the thread creation succeeded");
    195 				}
    196 				break;
    197 
    198 			case 2:	/* We did not know the expected result */
    199 			default:
    200 #if VERBOSE > 0
    201 				if (ret == 0) {
    202 					output
    203 					    ("Thread has been created successfully for this scenario\n");
    204 				} else {
    205 					output
    206 					    ("Thread creation failed with the error: %s\n",
    207 					     strerror(ret));
    208 				}
    209 #endif
    210 			}
    211 			if (ret == 0) {	/* The new thread is running */
    212 				ret = pthread_join(child, &rval);
    213 				if (ret != 0) {
    214 					UNRESOLVED(ret,
    215 						   "Unable to join a thread");
    216 				}
    217 
    218 				if (rval != (NULL + 1)) {
    219 					FAILED
    220 					    ("pthread_join() did not retrieve the pthread_exit() param");
    221 				}
    222 
    223 				if (atctl != 0) {
    224 					FAILED
    225 					    ("The function registered with atexit() executed");
    226 				}
    227 
    228 				if (ctl != 3) {
    229 					FAILED
    230 					    ("The TLD destructors were not called");
    231 				}
    232 			}
    233 		}
    234 	}
    235 
    236 	for (j = 0; j < 3; j++) {
    237 		ret = pthread_key_delete(tld[j]);
    238 		if (ret != 0) {
    239 			UNRESOLVED(ret, "Failed to delete a TLD key");
    240 		}
    241 	}
    242 
    243 	scenar_fini();
    244 #if VERBOSE > 0
    245 	output("-----\n");
    246 	output("All test data destroyed\n");
    247 	output("Test PASSED\n");
    248 #endif
    249 
    250 	PASSED;
    251 }
    252