1 /* 2 * Disktest 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 * 20 * Please send e-mail to yardleyb (at) us.ibm.com if you have 21 * questions or comments. 22 * 23 * Project Website: TBD 24 * 25 * $Id: threading.c,v 1.7 2009/02/26 12:14:53 subrata_modak Exp $ 26 * $Log: threading.c,v $ 27 * Revision 1.7 2009/02/26 12:14:53 subrata_modak 28 * Clean Trailing Tab: Signed-off-by: Michal Simek <monstr (at) monstr.eu>. 29 * 30 * Revision 1.6 2009/02/26 12:02:23 subrata_modak 31 * Clear Trailing Whitespace. Signed-off-by: Michal Simek <monstr (at) monstr.eu>. 32 * 33 * Revision 1.5 2008/02/14 08:22:24 subrata_modak 34 * Disktest application update to version 1.4.2, by, Brent Yardley <yardleyb (at) us.ibm.com> 35 * 36 * Revision 1.11 2006/04/21 23:10:43 yardleyb 37 * Major updates for v1_3_3 of disktest. View README for details. 38 * 39 * Revision 1.10 2004/11/20 04:43:42 yardleyb 40 * Minor code fixes. Checking for alloc errors. 41 * 42 * Revision 1.9 2004/11/19 21:45:12 yardleyb 43 * Fixed issue with code added for -F option. Cased disktest 44 * to SEG FAULT when cleaning up threads. 45 * 46 * Revision 1.8 2004/11/02 20:47:13 yardleyb 47 * Added -F functions. 48 * lots of minor fixes. see README 49 * 50 * Revision 1.7 2002/04/24 01:45:31 yardleyb 51 * Minor Fixes: 52 * Read/write time could exceeds overall time 53 * Heartbeat options sometimes only displayed once 54 * Cleanup time for large number of threads was very long (windows) 55 * If heartbeat specified, now checks for performance option also 56 * No IO was performed when -S0:0 and -pr specified 57 * 58 * Revision 1.6 2002/03/30 01:32:14 yardleyb 59 * Major Changes: 60 * 61 * Added Dumping routines for 62 * data miscompares, 63 * 64 * Updated performance output 65 * based on command line. Gave 66 * one decimal in MB/s output. 67 * 68 * Rewrote -pL IO routine to show 69 * correct stats. Now show pass count 70 * when using -C. 71 * 72 * Minor Changes: 73 * 74 * Code cleanup to remove the plethera 75 * if #ifdef for windows/unix functional 76 * differences. 77 * 78 * Revision 1.5 2002/03/07 03:30:11 yardleyb 79 * Return errno on thread 80 * create failure 81 * 82 * Revision 1.4 2002/02/28 04:25:45 yardleyb 83 * reworked threading code 84 * made locking code a macro. 85 * 86 * Revision 1.3 2002/02/19 02:46:37 yardleyb 87 * Added changes to compile for AIX. 88 * Update getvsiz so it returns a -1 89 * if the ioctl fails and we handle 90 * that fact correctly. Added check 91 * to force vsiz to always be greater 92 * then stop_lba. 93 * 94 * Revision 1.2 2002/02/04 20:35:38 yardleyb 95 * Changed max. number of threads to 64k. 96 * Check for max threads in parsing. 97 * Fixed windows getopt to return correctly 98 * when a bad option is given. 99 * Update time output to be in the format: 100 * YEAR/MONTH/DAY-HOUR:MIN:SEC 101 * instead of epoch time. 102 * 103 * Revision 1.1 2001/12/04 18:51:06 yardleyb 104 * Checkin of new source files and removal 105 * of outdated source 106 * 107 */ 108 109 #ifdef WINDOWS 110 #include <windows.h> 111 #else 112 #include <pthread.h> 113 #include <sys/types.h> 114 #include <unistd.h> 115 #include <string.h> 116 #endif 117 118 #include "defs.h" 119 #include "sfunc.h" 120 #include "main.h" 121 #include "childmain.h" 122 #include "threading.h" 123 124 /* 125 * This routine will sit waiting for all threads to exit. In 126 * unix, this is done through pthread_join. In Windows we 127 * use a sleeping loop. 128 */ 129 void cleanUpTestChildren(test_ll_t * test) 130 { 131 thread_struct_t *pTmpThread = NULL, *pTmpThreadLast = NULL; 132 133 while (test->env->pThreads) { 134 pTmpThread = test->env->pThreads->next; 135 pTmpThreadLast = test->env->pThreads; 136 137 closeThread(pTmpThreadLast->hThread); 138 139 test->env->pThreads = pTmpThread; 140 FREE(pTmpThreadLast); 141 test->env->kids--; 142 } 143 } 144 145 /* 146 * This function will create children for us based on the action specified 147 * during the call. if we cannot create a child, we fail and exit with 148 * errno as the exit status. 149 */ 150 void CreateTestChild(void *function, test_ll_t * test) 151 { 152 thread_struct_t *pNewThread; 153 hThread_t hTmpThread; 154 155 hTmpThread = spawnThread(function, test); 156 157 if (ISTHREADVALID(hTmpThread)) { 158 if ((pNewThread = 159 (thread_struct_t *) ALLOC(sizeof(thread_struct_t))) == 160 NULL) { 161 pMsg(ERR, test->args, 162 "%d : Could not allocate memory for child thread...\n", 163 GETLASTERROR()); 164 exit(GETLASTERROR()); 165 } 166 test->env->kids++; 167 memset(pNewThread, 0, sizeof(thread_struct_t)); 168 pNewThread->next = test->env->pThreads; 169 test->env->pThreads = pNewThread; 170 test->env->pThreads->hThread = hTmpThread; 171 } else { 172 pMsg(ERR, test->args, 173 "%d : Could not create all child threads.\n", 174 GETLASTERROR()); 175 pMsg(INFO, test->args, 176 "Total Number of Threads created was %u\n", 177 test->env->kids); 178 exit(GETLASTERROR()); 179 } 180 } 181 182 void createChild(void *function, test_ll_t * test) 183 { 184 hThread_t hTmpThread; 185 186 hTmpThread = spawnThread(function, test); 187 188 if (ISTHREADVALID(hTmpThread)) { 189 test->hThread = hTmpThread; 190 } else { 191 pMsg(ERR, test->args, "%d : Could not create child thread...\n", 192 GETLASTERROR()); 193 exit(GETLASTERROR()); 194 } 195 } 196 197 void cleanUp(test_ll_t * test) 198 { 199 test_ll_t *pTmpTest = test; 200 test_ll_t *pLastTest; 201 while (pTmpTest != NULL) { 202 pLastTest = pTmpTest; 203 pTmpTest = pTmpTest->next; 204 closeThread(pLastTest->hThread); 205 FREE(pLastTest->env->action_list); 206 FREE(pLastTest->args); 207 FREE(pLastTest->env); 208 FREE(pLastTest); 209 } 210 } 211 212 hThread_t spawnThread(void *function, void *param) 213 { 214 hThread_t hTmpThread; 215 216 #ifdef WINDOWS 217 hTmpThread = CreateThread(NULL, 0, function, param, 0, NULL); 218 #else 219 if (pthread_create(&hTmpThread, NULL, function, param) != 0) { 220 hTmpThread = 0; 221 } 222 #endif 223 224 return hTmpThread; 225 } 226 227 void closeThread(hThread_t hThread) 228 { 229 #ifdef WINDOWS 230 DWORD dwExitCode = 0; 231 232 do { 233 GetExitCodeThread(hThread, &dwExitCode); 234 /* 235 * Sleep(0) will force this thread to 236 * relinquish the remainder of its time slice 237 */ 238 if (dwExitCode == STILL_ACTIVE) 239 Sleep(0); 240 } while (dwExitCode == STILL_ACTIVE); 241 #else 242 pthread_join(hThread, NULL); 243 #endif 244 } 245