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