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_cond_init and pthread_cond_destroy 26 * operations. 27 * -> Create another thread which loops on sending a signal to the first thread. 28 * 29 * 30 */ 31 32 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 33 #define _POSIX_C_SOURCE 200112L 34 35 36/********************************************************************************************/ 37/****************************** standard includes *****************************************/ 38/********************************************************************************************/ 39 #include <pthread.h> 40 #include <semaphore.h> 41 #include <errno.h> 42 #include <signal.h> 43 #include <unistd.h> 44 #include <stdio.h> 45 #include <stdarg.h> 46 #include <stdlib.h> 47 48/********************************************************************************************/ 49/****************************** Test framework *****************************************/ 50/********************************************************************************************/ 51 #include "testfrmw.h" 52 #include "testfrmw.c" 53 /* This header is responsible for defining the following macros: 54 * UNRESOLVED(ret, descr); 55 * where descr is a description of the error and ret is an int (error code for example) 56 * FAILED(descr); 57 * where descr is a short text saying why the test has failed. 58 * PASSED(); 59 * No parameter. 60 * 61 * Both three macros shall terminate the calling process. 62 * The testcase shall not terminate in any other maneer. 63 * 64 * The other file defines the functions 65 * void output_init() 66 * void output(char * string, ...) 67 * 68 * Those may be used to output information. 69 */ 70 71/********************************************************************************************/ 72/********************************** Configuration ******************************************/ 73/********************************************************************************************/ 74#define WITH_SYNCHRO 75#ifndef VERBOSE 76#define VERBOSE 2 77#endif 78 79/********************************************************************************************/ 80/*********************************** Test case *****************************************/ 81/********************************************************************************************/ 82char do_it=1; 83unsigned long count_ope=0; 84pthread_mutex_t count_protect = PTHREAD_MUTEX_INITIALIZER; 85#ifdef WITH_SYNCHRO 86sem_t semsig1; 87sem_t semsig2; 88unsigned long count_sig=0; 89#endif 90sem_t semsync; 91 92typedef struct 93{ 94 pthread_t *thr; 95 int sig; 96#ifdef WITH_SYNCHRO 97 sem_t *sem; 98#endif 99} thestruct; 100 101/* the following function keeps on sending the signal to the thread pointed by arg 102 * If WITH_SYNCHRO is defined, the target thread has a handler for the signal */ 103void * sendsig (void * arg) 104{ 105 thestruct *thearg = (thestruct *) arg; 106 int ret; 107 while (do_it) 108 { 109 #ifdef WITH_SYNCHRO 110 if ((ret = sem_wait(thearg->sem))) 111 { UNRESOLVED(errno, "Sem_wait in sendsig"); } 112 count_sig++; 113 #endif 114 115 if ((ret = pthread_kill (*(thearg->thr), thearg->sig))) 116 { UNRESOLVED(ret, "Pthread_kill in sendsig"); } 117 118 } 119 120 return NULL; 121} 122 123/* Next are the signal handlers. */ 124void sighdl1(int sig) 125{ 126#ifdef WITH_SYNCHRO 127 if (sem_post(&semsig1)) 128 { UNRESOLVED(errno, "Sem_post in signal handler 1"); } 129#endif 130} 131void sighdl2(int sig) 132{ 133#ifdef WITH_SYNCHRO 134 if (sem_post(&semsig2)) 135 { UNRESOLVED(errno, "Sem_post in signal handler 2"); } 136#endif 137} 138 139/* The following function loops on init/destroy some condvars (with different attributes) 140 * it does check that no error code of EINTR is returned */ 141 142void * threaded(void * arg) 143{ 144 pthread_condattr_t ca[4], *pca[5]; 145 pthread_cond_t c[5]; 146 int i; 147 int ret; 148 149 /* We need to register the signal handlers */ 150 struct sigaction sa; 151 sigemptyset (&sa.sa_mask); 152 sa.sa_flags = 0; 153 sa.sa_handler = sighdl1; 154 if ((ret = sigaction (SIGUSR1, &sa, NULL))) 155 { UNRESOLVED(ret, "Unable to register signal handler1"); } 156 sa.sa_handler = sighdl2; 157 if ((ret = sigaction (SIGUSR2, &sa, NULL))) 158 { UNRESOLVED(ret, "Unable to register signal handler2"); } 159 160 /* Initialize the different cond attributes */ 161 pca[4]=NULL; 162 163 for (i=0; i<4; i++) 164 { 165 pca[i]=&ca[i]; 166 if ((ret = pthread_condattr_init(pca[i]))) 167 { UNRESOLVED(ret, "pthread_condattr_init"); } 168 } 169 170 ret = pthread_condattr_setpshared(pca[0], PTHREAD_PROCESS_SHARED); 171 if (ret != 0) { UNRESOLVED(ret, "Cond attribute PSHARED failed"); } 172 ret = pthread_condattr_setpshared(pca[1], PTHREAD_PROCESS_SHARED); 173 if (ret != 0) { UNRESOLVED(ret, "Cond attribute PSHARED failed"); } 174 175 #if VERBOSE >1 176 output("PShared condvar attributes initialized\n"); 177 #endif 178 if (sysconf(_SC_MONOTONIC_CLOCK) > 0) 179 { 180 ret = pthread_condattr_setclock(pca[1], CLOCK_MONOTONIC); 181 if (ret != 0) { UNRESOLVED(ret, "Cond set monotonic clock failed"); } 182 ret = pthread_condattr_setclock(pca[2], CLOCK_MONOTONIC); 183 if (ret != 0) { UNRESOLVED(ret, "Cond set monotonic clock failed"); } 184 #if VERBOSE >1 185 output("Alternative clock condvar attributes initialized\n"); 186 #endif 187 } 188 189 /* We are ready to proceed */ 190 while (do_it) 191 { 192 for (i=0; i<5; i++) 193 { 194 ret = pthread_cond_init(&c[i], pca[i]); 195 if (ret == EINTR) 196 { 197 FAILED("pthread_cond_init returned EINTR"); 198 } 199 if (ret != 0) 200 { 201 UNRESOLVED(ret, "pthread_cond_init failed"); 202 } 203 ret = pthread_cond_destroy(&c[i]); 204 if (ret == EINTR) 205 { 206 FAILED("pthread_cond_destroy returned EINTR"); 207 } 208 if (ret != 0) 209 { 210 UNRESOLVED(ret, "pthread_cond_destroy failed"); 211 } 212 pthread_mutex_lock(&count_protect); 213 count_ope++; 214 pthread_mutex_unlock(&count_protect); 215 } 216 } 217 218 /* Now we can destroy the mutex attributes objects */ 219 for (i=0; i<4; i++) 220 { 221 if ((ret = pthread_condattr_destroy(pca[i]))) 222 { UNRESOLVED(ret, "pthread_condattr_init"); } 223 } 224 225 do { 226 ret = sem_wait(&semsync); 227 } while (ret && (errno == EINTR)); 228 if (ret) 229 { UNRESOLVED(errno, "Could not wait for sig senders termination"); } 230 231 return NULL; 232} 233 234/* Main function */ 235int main (int argc, char * argv[]) 236{ 237 int ret; 238 pthread_t th_work, th_sig1, th_sig2; 239 thestruct arg1, arg2; 240 241 output_init(); 242 243 #ifdef WITH_SYNCHRO 244 if (sem_init(&semsig1, 0, 1)) 245 { UNRESOLVED(errno, "Semsig1 init"); } 246 if (sem_init(&semsig2, 0, 1)) 247 { UNRESOLVED(errno, "Semsig2 init"); } 248 #endif 249 250 if (sem_init(&semsync, 0, 0)) 251 { UNRESOLVED(errno, "semsync init"); } 252 253 if ((ret = pthread_create(&th_work, NULL, threaded, NULL))) 254 { UNRESOLVED(ret, "Worker thread creation failed"); } 255 256 arg1.thr = &th_work; 257 arg2.thr = &th_work; 258 arg1.sig = SIGUSR1; 259 arg2.sig = SIGUSR2; 260#ifdef WITH_SYNCHRO 261 arg1.sem = &semsig1; 262 arg2.sem = &semsig2; 263#endif 264 265 if ((ret = pthread_create(&th_sig1, NULL, sendsig, (void *)&arg1))) 266 { UNRESOLVED(ret, "Signal 1 sender thread creation failed"); } 267 if ((ret = pthread_create(&th_sig2, NULL, sendsig, (void *)&arg2))) 268 { UNRESOLVED(ret, "Signal 2 sender thread creation failed"); } 269 270 /* Let's wait for a while now */ 271 sleep(1); 272 273 /* Now stop the threads and join them */ 274 do { do_it=0; } 275 while (do_it); 276 277 if ((ret = pthread_join(th_sig1, NULL))) 278 { UNRESOLVED(ret, "Signal 1 sender thread join failed"); } 279 if ((ret = pthread_join(th_sig2, NULL))) 280 { UNRESOLVED(ret, "Signal 2 sender thread join failed"); } 281 282 if (sem_post(&semsync)) 283 { UNRESOLVED(errno, "could not post semsync"); } 284 285 if ((ret = pthread_join(th_work, NULL))) 286 { UNRESOLVED(ret, "Worker thread join failed"); } 287 288 #if VERBOSE > 0 289 output("Test executed successfully.\n"); 290 output(" %d condvars initialization and destruction were done.\n", count_ope); 291 #ifdef WITH_SYNCHRO 292 output(" %d signals were sent meanwhile.\n", count_sig); 293 #endif 294 #endif 295 PASSED; 296} 297