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 * If a signal is delivered to a thread waiting for a mutex, 21 * upon return from the signal handler the thread resumes 22 * waiting for the mutex as if it had not been interrupted. 23 24 25 * The steps are: 26 * -> Create a child thread 27 * -> Child registers a signal handler 28 * -> Child tries to lock a mutex owned by another thread 29 * -> A signal is sent to the child 30 * -> Check that the signal handler executes and then that the thread still 31 waits for the mutex. 32 * -> Release the mutex and check that the child takes it. 33 * -> Do all of this several times with different mutex attributes 34 * 35 * The test shall be considered to FAIL if it hangs! 36 * a call to alarm() might eventually be added but this is a problem under high 37 * system stress. 38 */ 39 40 /* 41 * - adam.li@intel.com 2004-05-13 42 * Add to PTS. Please refer to http://nptl.bullopensource.org/phpBB/ 43 * for general information 44 */ 45 46 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 47 #define _POSIX_C_SOURCE 200112L 48 49 /* We enable the following line to have mutex attributes defined */ 50#ifndef WITHOUT_XOPEN 51 #define _XOPEN_SOURCE 600 52#endif 53 54/********************************************************************************************/ 55/****************************** standard includes *****************************************/ 56/********************************************************************************************/ 57 #include <pthread.h> 58 #include <semaphore.h> 59 #include <errno.h> 60 #include <signal.h> 61 #include <unistd.h> 62 #include <stdio.h> 63 #include <stdlib.h> 64 #include <stdarg.h> 65 66/********************************************************************************************/ 67/****************************** Test framework *****************************************/ 68/********************************************************************************************/ 69 #include "testfrmw.h" 70 #include "testfrmw.c" 71 /* This header is responsible for defining the following macros: 72 * UNRESOLVED(ret, descr); 73 * where descr is a description of the error and ret is an int (error code for example) 74 * FAILED(descr); 75 * where descr is a short text saying why the test has failed. 76 * PASSED(); 77 * No parameter. 78 * 79 * Both three macros shall terminate the calling process. 80 * The testcase shall not terminate in any other maneer. 81 * 82 * The other file defines the functions 83 * void output_init() 84 * void output(char * string, ...) 85 * 86 * Those may be used to output information. 87 */ 88 89/********************************************************************************************/ 90/********************************** Configuration ******************************************/ 91/********************************************************************************************/ 92#ifndef VERBOSE 93#define VERBOSE 1 94#endif 95 96/********************************************************************************************/ 97/*********************************** Test case *****************************************/ 98/********************************************************************************************/ 99pthread_mutex_t mtx[5]; 100sem_t semsig, semstart; 101int ctrl=0; 102 103/********* signal handler **********/ 104void sighdl(int sig) 105{ 106 if (sem_post(&semsig)) 107 { UNRESOLVED(errno, "Sem_post in signal handler"); } 108} 109 110/********** thread *********/ 111void * threaded(void * arg) 112{ 113 int ret, i; 114 115 /* We register the signal handler */ 116 struct sigaction sa; 117 sigemptyset (&sa.sa_mask); 118 sa.sa_flags = 0; 119 sa.sa_handler = sighdl; 120 if ((ret = sigaction (SIGUSR1, &sa, NULL))) 121 { UNRESOLVED(ret, "Unable to register signal handler"); } 122 123 /* Start the real work */ 124 for (i=0; i<5; i++) /* We'll do this with the 5 kinds of mutex */ 125 { 126 if (sem_post(&semstart)) /* Tell the father we are ready */ 127 { UNRESOLVED(errno, "Sem post in thread"); } 128 129 if ((ret = pthread_mutex_lock(&mtx[i]))) /* Attempt to lock the mutex */ 130 { UNRESOLVED(ret, "Mutex lock failed in thread"); } 131 132 ctrl++; /* Notify the main we have passed the lock */ 133 134 if ((ret = pthread_mutex_unlock(&mtx[i]))) /* We don't need the mutex anymore */ 135 { UNRESOLVED(ret, "Mutex unlock failed in thread"); } 136 } 137 return NULL; 138} 139 140 141/********* main ********/ 142int main (int argc, char * argv[]) 143{ 144 int ret, i, j; 145 pthread_t th; 146 pthread_mutexattr_t ma[4], *pma[5]; 147 pma[4]=NULL; 148 149 output_init(); 150 151 /* Initialize the mutex attributes */ 152 for (i=0; i<4; i++) 153 { 154 pma[i]=&ma[i]; 155 if ((ret = pthread_mutexattr_init(pma[i]))) 156 { UNRESOLVED(ret, "pthread_mutexattr_init"); } 157 } 158 #ifndef WITHOUT_XOPEN 159 if ((ret = pthread_mutexattr_settype(pma[0], PTHREAD_MUTEX_NORMAL))) 160 { UNRESOLVED(ret, "pthread_mutexattr_settype (normal)"); } 161 if ((ret = pthread_mutexattr_settype(pma[1], PTHREAD_MUTEX_ERRORCHECK))) 162 { UNRESOLVED(ret, "pthread_mutexattr_settype (errorcheck)"); } 163 if ((ret = pthread_mutexattr_settype(pma[2], PTHREAD_MUTEX_RECURSIVE))) 164 { UNRESOLVED(ret, "pthread_mutexattr_settype (recursive)"); } 165 if ((ret = pthread_mutexattr_settype(pma[3], PTHREAD_MUTEX_DEFAULT))) 166 { UNRESOLVED(ret, "pthread_mutexattr_settype (default)"); } 167 #if VERBOSE >1 168 output("Mutex attributes NORMAL,ERRORCHECK,RECURSIVE,DEFAULT initialized\n"); 169 #endif 170 #else 171 #if VERBOSE > 0 172 output("Mutex attributes NORMAL,ERRORCHECK,RECURSIVE,DEFAULT unavailable\n"); 173 #endif 174 #endif 175 176 /* Initialize the 5 mutex */ 177 for (i=0; i<5; i++) 178 { 179 if ((ret = pthread_mutex_init(&mtx[i], pma[i]))) 180 { UNRESOLVED(ret, "pthread_mutex_init failed")} 181 if ((ret = pthread_mutex_lock(&mtx[i]))) 182 { UNRESOLVED(ret, "Initial pthread_mutex_lock failed")} 183 } 184 185 #if VERBOSE >1 186 output("Mutex objects are initialized\n"); 187 #endif 188 189 /* We don't need the mutex attribute objects anymore */ 190 for (i=0; i<4; i++) 191 { 192 if ((ret = pthread_mutexattr_destroy(pma[i]))) 193 { UNRESOLVED(ret, "pthread_mutexattr_destroy"); } 194 } 195 196 /* Initialize the semaphores */ 197 if (sem_init(&semsig, 0, 1)) 198 { UNRESOLVED(errno, "Sem init (1) failed"); } 199 if (sem_init(&semstart, 0, 0)) 200 { UNRESOLVED(errno, "Sem init (0) failed"); } 201 202 203 #if VERBOSE >1 204 output("Going to create the child thread\n"); 205 #endif 206 /* Start the child */ 207 if ((ret = pthread_create(&th, NULL, threaded, NULL))) 208 { UNRESOLVED(ret, "Unable to create the thread"); } 209 #if VERBOSE >1 210 output("Child created\n"); 211 #endif 212 213 214 /* Monitor the child */ 215 for (i=0; i<5; i++) /* We will do this for the 5 kinds of mutex */ 216 { 217 if (sem_wait(&semstart)) /* Wait for the thread to be ready */ 218 { UNRESOLVED(errno, "Unable to wait for the child"); } 219 220 #if VERBOSE >1 221 output("Child is ready for iteration %i\n", i+1); 222 #endif 223 224 225 ctrl=0; /* init the ctrl var */ 226 227 /* Send some signals to the thread */ 228 for (j=0; j<10; j++) 229 { 230 if ((ret = sem_wait(&semsig))) 231 { UNRESOLVED(errno, "Sem_wait failed from the signal handler"); } 232 233 sched_yield(); /* Let the child do its stuff - might be a nanosleep here*/ 234 235 if ((ret = pthread_kill (th, SIGUSR1))) 236 { UNRESOLVED(ret, "Pthread_kill failed"); } 237 } 238 #if VERBOSE >1 239 output("Child was killed 10 times\n"); 240 #endif 241 242 /* Now check the thread is still waiting for the mutex */ 243 if (ctrl != 0) 244 { 245 FAILED("Killed child passed the pthread_mutex_lock without owning it"); 246 } 247 248 #if VERBOSE >1 249 output("Control was OK\n"); 250 #endif 251 252 /* Unlock the mutex so the thread can proceed to the next one */ 253 if ((ret = pthread_mutex_unlock(&mtx[i]))) 254 { UNRESOLVED(ret, "Mutex unlock in main failed"); } 255 } 256 257 #if VERBOSE >1 258 output("The test has passed, we are now going to clean up everything.\n"); 259 #endif 260 261 /* Clean everything: the test has passed */ 262 if ((ret = pthread_join(th, NULL))) 263 { UNRESOLVED(ret, "Unable to join the child"); } 264 265 for (i=0; i<5; i++) 266 { 267 if ((ret = pthread_mutex_destroy(&mtx[i]))) 268 { UNRESOLVED(ret, "Unable to finally destroy a mutex"); } 269 } 270 271 if (sem_destroy(&semstart)) 272 { UNRESOLVED(errno, "Unable to destroy semstart semaphore"); } 273 274 if (sem_destroy(&semsig)) 275 { UNRESOLVED(errno, "Unable to destroy semsig semaphore"); } 276 277 PASSED; 278} 279