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., 59 15 * Temple Place - Suite 330, Boston MA 02111-1307, USA. 16 * 17 18 19 * This sample test aims to check the following assertion: 20 * The function does not return an error code of EINTR 21 22 23 * The steps are: 24 * 25 * -> Create a thread which loops on pthread_mutex_lock and pthread_mutex_unlock 26 * operations. 27 * -> Create another thread which loops on sending a signal to the first thread. 28 * 29 * 30 */ 31 32 /* 33 * - adam.li@intel.com 2004-05-13 34 * Add to PTS. Please refer to http://nptl.bullopensource.org/phpBB/ 35 * for general information 36 */ 37 38 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 39 #define _POSIX_C_SOURCE 200112L 40 41 /* We enable the following line to have mutex attributes defined */ 42#ifndef WITHOUT_XOPEN 43 #define _XOPEN_SOURCE 600 44#endif 45 46/********************************************************************************************/ 47/****************************** standard includes *****************************************/ 48/********************************************************************************************/ 49 #include <pthread.h> 50 #include <semaphore.h> 51 #include <errno.h> 52 #include <signal.h> 53 #include <unistd.h> 54 #include <stdlib.h> 55 #include <stdio.h> 56 #include <stdarg.h> 57 58/********************************************************************************************/ 59/****************************** Test framework *****************************************/ 60/********************************************************************************************/ 61 #include "testfrmw.h" 62 #include "testfrmw.c" 63 /* This header is responsible for defining the following macros: 64 * UNRESOLVED(ret, descr); 65 * where descr is a description of the error and ret is an int (error code for example) 66 * FAILED(descr); 67 * where descr is a short text saying why the test has failed. 68 * PASSED(); 69 * No parameter. 70 * 71 * Both three macros shall terminate the calling process. 72 * The testcase shall not terminate in any other maneer. 73 * 74 * The other file defines the functions 75 * void output_init() 76 * void output(char * string, ...) 77 * 78 * Those may be used to output information. 79 */ 80 81/********************************************************************************************/ 82/********************************** Configuration ******************************************/ 83/********************************************************************************************/ 84#define WITH_SYNCHRO 85#ifndef VERBOSE 86#define VERBOSE 1 87#endif 88 89/********************************************************************************************/ 90/*********************************** Test case *****************************************/ 91/********************************************************************************************/ 92char do_it=1; 93unsigned long count_ope=0; 94pthread_mutex_t count_protect = PTHREAD_MUTEX_INITIALIZER; 95#ifdef WITH_SYNCHRO 96sem_t semsig1; 97sem_t semsig2; 98unsigned long count_sig=0; 99#endif 100sem_t semsync; 101 102typedef struct 103{ 104 pthread_t *thr; 105 int sig; 106#ifdef WITH_SYNCHRO 107 sem_t *sem; 108#endif 109} thestruct; 110 111/* the following function keeps on sending the signal to the thread pointed by arg 112 * If WITH_SYNCHRO is defined, the target thread has a handler for the signal */ 113void * sendsig (void * arg) 114{ 115 thestruct *thearg = (thestruct *) arg; 116 int ret; 117 while (do_it) 118 { 119 #ifdef WITH_SYNCHRO 120 if ((ret = sem_wait(thearg->sem))) 121 { UNRESOLVED(errno, "Sem_wait in sendsig"); } 122 count_sig++; 123 #endif 124 125 if ((ret = pthread_kill (*(thearg->thr), thearg->sig))) 126 { UNRESOLVED(ret, "Pthread_kill in sendsig"); } 127 128 } 129 130 return NULL; 131} 132 133/* Next are the signal handlers. */ 134void sighdl1(int sig) 135{ 136#ifdef WITH_SYNCHRO 137 if ((sem_post(&semsig1))) 138 { UNRESOLVED(errno, "Sem_post in signal handler 1"); } 139#endif 140} 141void sighdl2(int sig) 142{ 143#ifdef WITH_SYNCHRO 144 if ((sem_post(&semsig2))) 145 { UNRESOLVED(errno, "Sem_post in signal handler 2"); } 146#endif 147} 148 149/* The following function loops on init/destroy some mutex (with different attributes) 150 * it does check that no error code of EINTR is returned */ 151 152void * threaded(void * arg) 153{ 154 pthread_mutexattr_t ma[4], *pma[5]; 155 pthread_mutex_t m[5]; 156 int i; 157 int ret; 158 159 /* We need to register the signal handlers */ 160 struct sigaction sa; 161 sigemptyset (&sa.sa_mask); 162 sa.sa_flags = 0; 163 sa.sa_handler = sighdl1; 164 if ((ret = sigaction (SIGUSR1, &sa, NULL))) 165 { UNRESOLVED(ret, "Unable to register signal handler1"); } 166 sa.sa_handler = sighdl2; 167 if ((ret = sigaction (SIGUSR2, &sa, NULL))) 168 { UNRESOLVED(ret, "Unable to register signal handler2"); } 169 170 /* Initialize the different mutex */ 171 pma[4]=NULL; 172 173 for (i=0; i<4; i++) 174 { 175 pma[i]=&ma[i]; 176 if ((ret = pthread_mutexattr_init(pma[i]))) 177 { UNRESOLVED(ret, "pthread_mutexattr_init"); } 178 } 179 180 #ifndef WITHOUT_XOPEN 181 if ((ret = pthread_mutexattr_settype(pma[0], PTHREAD_MUTEX_NORMAL))) 182 { UNRESOLVED(ret, "pthread_mutexattr_settype (normal)"); } 183 if ((ret = pthread_mutexattr_settype(pma[1], PTHREAD_MUTEX_ERRORCHECK))) 184 { UNRESOLVED(ret, "pthread_mutexattr_settype (errorcheck)"); } 185 if ((ret = pthread_mutexattr_settype(pma[2], PTHREAD_MUTEX_RECURSIVE))) 186 { UNRESOLVED(ret, "pthread_mutexattr_settype (recursive)"); } 187 if ((ret = pthread_mutexattr_settype(pma[3], PTHREAD_MUTEX_DEFAULT))) 188 { UNRESOLVED(ret, "pthread_mutexattr_settype (default)"); } 189 #if VERBOSE >1 190 output("Mutex attributes NORMAL,ERRORCHECK,RECURSIVE,DEFAULT initialized\n"); 191 #endif 192 #else 193 #if VERBOSE > 0 194 output("Mutex attributes NORMAL,ERRORCHECK,RECURSIVE,DEFAULT unavailable\n"); 195 #endif 196 #endif 197 198 for (i=0; i<5; i++) 199 { 200 ret = pthread_mutex_init(&m[i], pma[i]); 201 if (ret == EINTR) 202 { 203 FAILED("pthread_mutex_init returned EINTR"); 204 } 205 if (ret != 0) 206 { 207 UNRESOLVED(ret, "pthread_mutex_init failed"); 208 } 209 } 210 /* The mutex are ready, we will loop on lock/unlock now */ 211 212 while (do_it) 213 { 214 for (i=0; i<5; i++) 215 { 216 ret = pthread_mutex_lock(&m[i]); 217 if (ret == EINTR) 218 { 219 FAILED("pthread_mutex_lock returned EINTR"); 220 } 221 if (ret != 0) 222 { 223 UNRESOLVED(ret, "pthread_mutex_lock failed"); 224 } 225 ret = pthread_mutex_unlock(&m[i]); 226 if (ret == EINTR) 227 { 228 FAILED("pthread_mutex_unlock returned EINTR"); 229 } 230 if (ret != 0) 231 { 232 UNRESOLVED(ret, "pthread_mutex_unlock failed"); 233 } 234 } 235 ret = pthread_mutex_lock(&count_protect); 236 if (ret == EINTR) 237 { 238 FAILED("pthread_mutex_lock returned EINTR"); 239 } 240 if (ret != 0) 241 { 242 UNRESOLVED(ret, "pthread_mutex_lock failed"); 243 } 244 count_ope++; 245 pthread_mutex_unlock(&count_protect); 246 if (ret == EINTR) 247 { 248 FAILED("pthread_mutex_unlock returned EINTR"); 249 } 250 if (ret != 0) 251 { 252 UNRESOLVED(ret, "pthread_mutex_unlock failed"); 253 } 254 } 255 256 /* Now we can destroy the mutex objects */ 257 for (i=0; i<4; i++) 258 { 259 if ((ret = pthread_mutexattr_destroy(pma[i]))) 260 { UNRESOLVED(ret, "pthread_mutexattr_init"); } 261 } 262 for (i=0; i<5; i++) 263 { 264 ret = pthread_mutex_destroy(&m[i]); 265 if (ret == EINTR) 266 { 267 FAILED("pthread_mutex_destroy returned EINTR"); 268 } 269 if (ret != 0) 270 { 271 UNRESOLVED(ret, "pthread_mutex_destroy failed"); 272 } 273 } 274 275 do { 276 ret = sem_wait(&semsync); 277 } while (ret && (errno == EINTR)); 278 if (ret) 279 { UNRESOLVED(errno, "Could not wait for sig senders termination"); } 280 281 return NULL; 282} 283 284/* At last (but not least) we need a main */ 285int main (int argc, char * argv[]) 286{ 287 int ret; 288 pthread_t th_work, th_sig1, th_sig2; 289 thestruct arg1, arg2; 290 291 output_init(); 292 293 #ifdef WITH_SYNCHRO 294 #if VERBOSE >1 295 output("Running in synchronized mode\n"); 296 #endif 297 if ((sem_init(&semsig1, 0, 1))) 298 { UNRESOLVED(errno, "Semsig1 init"); } 299 if ((sem_init(&semsig2, 0, 1))) 300 { UNRESOLVED(errno, "Semsig2 init"); } 301 #endif 302 303 if ((sem_init(&semsync, 0, 0))) 304 { UNRESOLVED(errno, "semsync init"); } 305 306 #if VERBOSE >1 307 output("Starting the worker thread\n"); 308 #endif 309 if ((ret = pthread_create(&th_work, NULL, threaded, NULL))) 310 { UNRESOLVED(ret, "Worker thread creation failed"); } 311 312 arg1.thr = &th_work; 313 arg2.thr = &th_work; 314 arg1.sig = SIGUSR1; 315 arg2.sig = SIGUSR2; 316#ifdef WITH_SYNCHRO 317 arg1.sem = &semsig1; 318 arg2.sem = &semsig2; 319#endif 320 321 #if VERBOSE >1 322 output("Starting the signal sources\n"); 323 #endif 324 if ((ret = pthread_create(&th_sig1, NULL, sendsig, (void *)&arg1))) 325 { UNRESOLVED(ret, "Signal 1 sender thread creation failed"); } 326 if ((ret = pthread_create(&th_sig2, NULL, sendsig, (void *)&arg2))) 327 { UNRESOLVED(ret, "Signal 2 sender thread creation failed"); } 328 329 /* Let's wait for a while now */ 330 #if VERBOSE >1 331 output("Let the worker be killed for a second\n"); 332 #endif 333 sleep(1); 334 335 /* Now stop the threads and join them */ 336 #if VERBOSE >1 337 output("Stop everybody\n"); 338 #endif 339 do { do_it=0; } 340 while (do_it); 341 342 if ((ret = pthread_join(th_sig1, NULL))) 343 { UNRESOLVED(ret, "Signal 1 sender thread join failed"); } 344 if ((ret = pthread_join(th_sig2, NULL))) 345 { UNRESOLVED(ret, "Signal 2 sender thread join failed"); } 346 347 #if VERBOSE >1 348 output("Signal sources are stopped, we can stop the worker\n"); 349 #endif 350 if ((sem_post(&semsync))) 351 { UNRESOLVED(errno, "could not post semsync"); } 352 353 if ((ret = pthread_join(th_work, NULL))) 354 { UNRESOLVED(ret, "Worker thread join failed"); } 355 356 #if VERBOSE > 0 357 output("Test executed successfully.\n"); 358 output(" %d mutex lock and unlock were done.\n", count_ope); 359 #ifdef WITH_SYNCHRO 360 output(" %d signals were sent meanwhile.\n", count_sig); 361 #endif 362 #endif 363 PASSED; 364} 365