attach.c (6434B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 /*********************************************************************** 7 ** 1996 - Netscape Communications Corporation 8 ** 9 ** Name: attach.c 10 ** 11 ** Description: Platform-specific code to create a native thread. The native 12 *thread will 13 ** repeatedly call PR_AttachThread and 14 *PR_DetachThread. The 15 ** primordial thread waits for this new thread to 16 *finish. 17 ** 18 ** Modification History: 19 ** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. 20 ** The debug mode will print all of the printfs associated with this 21 *test. 22 ** The regress mode will be the default mode. Since the regress tool 23 *limits 24 ** the output to a one line status:PASS or FAIL,all of the printf 25 *statements 26 ** have been handled with an if (debug_mode) statement. 27 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been 28 *updated to 29 ** recognize the return code from tha main program. 30 ** 12-June-97 Revert to return code 0 and 1. 31 ***********************************************************************/ 32 33 /*********************************************************************** 34 ** Includes 35 ***********************************************************************/ 36 37 /* Used to get the command line option */ 38 #include "nspr.h" 39 #include "pprthred.h" 40 #include "plgetopt.h" 41 42 #include <stdio.h> 43 44 #ifdef WIN32 45 # include <windows.h> 46 # include <process.h> 47 #elif defined(_PR_PTHREADS) 48 # include <pthread.h> 49 # include "md/_pth.h" 50 #elif defined(SOLARIS) 51 # include <thread.h> 52 #endif 53 54 #define DEFAULT_COUNT 1000 55 PRIntn failed_already = 0; 56 PRIntn debug_mode; 57 58 int count; 59 60 static void AttachDetach(void) { 61 PRThread* me; 62 PRInt32 index; 63 64 for (index = 0; index < count; index++) { 65 me = PR_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL); 66 67 if (!me) { 68 fprintf(stderr, "Error attaching thread %d: PR_AttachThread failed\n", 69 count); 70 failed_already = 1; 71 return; 72 } 73 PR_DetachThread(); 74 } 75 } 76 77 /************************************************************************/ 78 79 static void Measure(void (*func)(void), const char* msg) { 80 PRIntervalTime start, stop; 81 double d; 82 83 start = PR_IntervalNow(); 84 (*func)(); 85 stop = PR_IntervalNow(); 86 87 d = (double)PR_IntervalToMicroseconds(stop - start); 88 if (debug_mode) { 89 printf("%40s: %6.2f usec\n", msg, d / count); 90 } 91 } 92 93 #ifdef WIN32 94 static unsigned __stdcall threadStartFunc(void* arg) 95 #else 96 static void* threadStartFunc(void* arg) 97 #endif 98 { 99 Measure(AttachDetach, "Attach/Detach"); 100 101 return 0; 102 } 103 104 int main(int argc, char** argv) { 105 #ifdef _PR_PTHREADS 106 int rv; 107 pthread_t threadID; 108 pthread_attr_t attr; 109 #elif defined(SOLARIS) 110 int rv; 111 thread_t threadID; 112 #elif defined(WIN32) 113 DWORD rv; 114 unsigned threadID; 115 HANDLE hThread; 116 #endif 117 118 /* The command line argument: -d is used to determine if the test is being run 119 in debug mode. The regress tool requires only one line output:PASS or FAIL. 120 All of the printfs associated with this test has been handled with a if 121 (debug_mode) test. Usage: test_name [-d] [-c n] 122 */ 123 PLOptStatus os; 124 PLOptState* opt = PL_CreateOptState(argc, argv, "dc:"); 125 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { 126 if (PL_OPT_BAD == os) { 127 continue; 128 } 129 switch (opt->option) { 130 case 'd': /* debug mode */ 131 debug_mode = 1; 132 break; 133 case 'c': /* loop count */ 134 count = atoi(opt->value); 135 break; 136 default: 137 break; 138 } 139 } 140 PL_DestroyOptState(opt); 141 142 if (0 == count) { 143 count = DEFAULT_COUNT; 144 } 145 146 /* 147 * To force the implicit initialization of nspr20 148 */ 149 PR_SetError(0, 0); 150 151 /* 152 * Platform-specific code to create a native thread. The native 153 * thread will repeatedly call PR_AttachThread and PR_DetachThread. 154 * The primordial thread waits for this new thread to finish. 155 */ 156 157 #ifdef _PR_PTHREADS 158 159 rv = _PT_PTHREAD_ATTR_INIT(&attr); 160 if (debug_mode) { 161 PR_ASSERT(0 == rv); 162 } else if (0 != rv) { 163 failed_already = 1; 164 goto exit_now; 165 } 166 167 rv = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 168 if (debug_mode) { 169 PR_ASSERT(0 == rv); 170 } else if (0 != rv) { 171 failed_already = 1; 172 goto exit_now; 173 } 174 rv = _PT_PTHREAD_CREATE(&threadID, attr, threadStartFunc, NULL); 175 if (rv != 0) { 176 fprintf(stderr, "thread creation failed: error code %d\n", rv); 177 failed_already = 1; 178 goto exit_now; 179 } else { 180 if (debug_mode) { 181 printf("thread creation succeeded \n"); 182 } 183 } 184 rv = _PT_PTHREAD_ATTR_DESTROY(&attr); 185 if (debug_mode) { 186 PR_ASSERT(0 == rv); 187 } else if (0 != rv) { 188 failed_already = 1; 189 goto exit_now; 190 } 191 rv = pthread_join(threadID, NULL); 192 if (debug_mode) { 193 PR_ASSERT(0 == rv); 194 } else if (0 != rv) { 195 failed_already = 1; 196 goto exit_now; 197 } 198 199 #elif defined(SOLARIS) 200 201 rv = thr_create(NULL, 0, threadStartFunc, NULL, 0, &threadID); 202 if (rv != 0) { 203 if (!debug_mode) { 204 failed_already = 1; 205 goto exit_now; 206 } else { 207 fprintf(stderr, "thread creation failed: error code %d\n", rv); 208 } 209 } 210 rv = thr_join(threadID, NULL, NULL); 211 if (debug_mode) { 212 PR_ASSERT(0 == rv); 213 } else if (0 != rv) { 214 failed_already = 1; 215 goto exit_now; 216 } 217 218 #elif defined(WIN32) 219 220 hThread = 221 (HANDLE)_beginthreadex(NULL, 0, threadStartFunc, NULL, 222 STACK_SIZE_PARAM_IS_A_RESERVATION, &threadID); 223 if (hThread == 0) { 224 fprintf(stderr, "thread creation failed: error code %d\n", GetLastError()); 225 failed_already = 1; 226 goto exit_now; 227 } 228 rv = WaitForSingleObject(hThread, INFINITE); 229 if (debug_mode) { 230 PR_ASSERT(rv != WAIT_FAILED); 231 } else if (rv == WAIT_FAILED) { 232 failed_already = 1; 233 goto exit_now; 234 } 235 236 #else 237 if (!debug_mode) { 238 failed_already = 1; 239 } else 240 printf( 241 "The attach test does not apply to this platform because\n" 242 "either this platform does not have native threads or the\n" 243 "test needs to be written for this platform.\n"); 244 goto exit_now; 245 #endif 246 247 exit_now: 248 if (failed_already) { 249 return 1; 250 } else { 251 return 0; 252 } 253 }