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 stress test aims to test the following assertion: 18 19 * The init_routine from pthread_once never execute 20 * more or less than once. 21 22 * The steps are: 23 * -> Create several threads 24 * -> All threads call pthread_once at the same time 25 * -> Check the init_routine executed once. 26 27 */ 28 29 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 30 #define _POSIX_C_SOURCE 200112L 31 32 /********************************************************************************************/ 33 /****************************** standard includes *****************************************/ 34 /********************************************************************************************/ 35 #include <pthread.h> 36 #include <stdarg.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 42 #include <errno.h> 43 #include <signal.h> 44 45 /********************************************************************************************/ 46 /****************************** Test framework *****************************************/ 47 /********************************************************************************************/ 48 #include "testfrmw.h" 49 #include "testfrmw.c" 50 /* This header is responsible for defining the following macros: 51 * UNRESOLVED(ret, descr); 52 * where descr is a description of the error and ret is an int (error code for example) 53 * FAILED(descr); 54 * where descr is a short text saying why the test has failed. 55 * PASSED(); 56 * No parameter. 57 * 58 * Both three macros shall terminate the calling process. 59 * The testcase shall not terminate in any other maneer. 60 * 61 * The other file defines the functions 62 * void output_init() 63 * void output(char * string, ...) 64 * 65 * Those may be used to output information. 66 */ 67 68 /********************************************************************************************/ 69 /********************************** Configuration ******************************************/ 70 /********************************************************************************************/ 71 #ifndef VERBOSE 72 #define VERBOSE 1 73 #endif 74 75 #define NTHREADS 30 76 77 /********************************************************************************************/ 78 /*********************************** Test cases *****************************************/ 79 /********************************************************************************************/ 80 81 char do_it = 1; 82 long long iterations = 0; 83 84 /* Handler for user request to terminate */ 85 void sighdl(int sig) 86 { 87 do { 88 do_it = 0; 89 } 90 while (do_it); 91 } 92 93 pthread_once_t once_ctl; 94 int once_chk; 95 pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; 96 97 void init_routine(void) 98 { 99 int ret = 0; 100 ret = pthread_mutex_lock(&mtx); 101 102 if (ret != 0) { 103 UNRESOLVED(ret, "Failed to lock mutex in initializer"); 104 } 105 106 once_chk++; 107 108 ret = pthread_mutex_unlock(&mtx); 109 110 if (ret != 0) { 111 UNRESOLVED(ret, "Failed to unlock mutex in initializer"); 112 } 113 114 return; 115 } 116 117 /* Thread function */ 118 void *threaded(void *arg) 119 { 120 int ret = 0; 121 122 /* Wait for all threads being created */ 123 ret = pthread_barrier_wait(arg); 124 125 if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { 126 UNRESOLVED(ret, "Barrier wait failed"); 127 } 128 129 /* Call init routine */ 130 ret = pthread_once(&once_ctl, init_routine); 131 132 if (ret != 0) { 133 UNRESOLVED(ret, "pthread_once failed"); 134 } 135 136 return NULL; 137 } 138 139 /* Main function */ 140 int main(int argc, char *argv[]) 141 { 142 int ret = 0, i; 143 144 struct sigaction sa; 145 146 pthread_barrier_t bar; 147 148 pthread_t th[NTHREADS]; 149 150 /* Initialize output routine */ 151 output_init(); 152 153 /* Initialize barrier */ 154 ret = pthread_barrier_init(&bar, NULL, NTHREADS); 155 156 if (ret != 0) { 157 UNRESOLVED(ret, "Failed to init barrier"); 158 } 159 160 /* Register the signal handler for SIGUSR1 */ 161 sigemptyset(&sa.sa_mask); 162 163 sa.sa_flags = 0; 164 165 sa.sa_handler = sighdl; 166 167 if ((ret = sigaction(SIGUSR1, &sa, NULL))) { 168 UNRESOLVED(ret, "Unable to register signal handler"); 169 } 170 171 if ((ret = sigaction(SIGALRM, &sa, NULL))) { 172 UNRESOLVED(ret, "Unable to register signal handler"); 173 } 174 #if VERBOSE > 1 175 output("[parent] Signal handler registered\n"); 176 177 #endif 178 179 while (do_it) { 180 /* Reinitialize once handler & check value */ 181 once_ctl = PTHREAD_ONCE_INIT; 182 once_chk = 0; 183 184 /* create the threads */ 185 186 for (i = 0; i < NTHREADS; i++) { 187 ret = pthread_create(&th[i], NULL, threaded, &bar); 188 189 if (ret != 0) { 190 UNRESOLVED(ret, "Failed to create a thread"); 191 } 192 } 193 194 /* Then join */ 195 for (i = 0; i < NTHREADS; i++) { 196 ret = pthread_join(th[i], NULL); 197 198 if (ret != 0) { 199 UNRESOLVED(ret, "Failed to join a thread"); 200 } 201 } 202 203 /* check the value */ 204 ret = pthread_mutex_lock(&mtx); 205 206 if (ret != 0) { 207 UNRESOLVED(ret, "Failed to lock mutex in initializer"); 208 } 209 210 if (once_chk != 1) { 211 output("Control: %d\n", once_chk); 212 FAILED("The initializer function did not execute once"); 213 } 214 215 ret = pthread_mutex_unlock(&mtx); 216 217 if (ret != 0) { 218 UNRESOLVED(ret, 219 "Failed to unlock mutex in initializer"); 220 } 221 222 iterations++; 223 } 224 225 /* We've been asked to stop */ 226 227 output("pthread_once stress test PASSED -- %llu iterations\n", 228 iterations); 229 230 ret = pthread_barrier_destroy(&bar); 231 232 if (ret != 0) { 233 UNRESOLVED(ret, "Failed to destroy the barrier"); 234 } 235 236 PASSED; 237 } 238