Wed, 31 Dec 2014 06:55:46 +0100
Added tag TORBROWSER_REPLICA for changeset 6474c204b198
michael@0 | 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /*********************************************************************** |
michael@0 | 7 | ** 1996 - Netscape Communications Corporation |
michael@0 | 8 | ** |
michael@0 | 9 | ** Name: attach.c |
michael@0 | 10 | ** |
michael@0 | 11 | ** Description: Platform-specific code to create a native thread. The native thread will |
michael@0 | 12 | ** repeatedly call PR_AttachThread and PR_DetachThread. The |
michael@0 | 13 | ** primordial thread waits for this new thread to finish. |
michael@0 | 14 | ** |
michael@0 | 15 | ** Modification History: |
michael@0 | 16 | ** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. |
michael@0 | 17 | ** The debug mode will print all of the printfs associated with this test. |
michael@0 | 18 | ** The regress mode will be the default mode. Since the regress tool limits |
michael@0 | 19 | ** the output to a one line status:PASS or FAIL,all of the printf statements |
michael@0 | 20 | ** have been handled with an if (debug_mode) statement. |
michael@0 | 21 | ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to |
michael@0 | 22 | ** recognize the return code from tha main program. |
michael@0 | 23 | ** 12-June-97 Revert to return code 0 and 1. |
michael@0 | 24 | ***********************************************************************/ |
michael@0 | 25 | |
michael@0 | 26 | /*********************************************************************** |
michael@0 | 27 | ** Includes |
michael@0 | 28 | ***********************************************************************/ |
michael@0 | 29 | |
michael@0 | 30 | /* Used to get the command line option */ |
michael@0 | 31 | #include "nspr.h" |
michael@0 | 32 | #include "pprthred.h" |
michael@0 | 33 | #include "plgetopt.h" |
michael@0 | 34 | |
michael@0 | 35 | #include <stdio.h> |
michael@0 | 36 | |
michael@0 | 37 | #ifdef WIN32 |
michael@0 | 38 | #include <windows.h> |
michael@0 | 39 | #include <process.h> |
michael@0 | 40 | #elif defined(_PR_PTHREADS) |
michael@0 | 41 | #include <pthread.h> |
michael@0 | 42 | #include "md/_pth.h" |
michael@0 | 43 | #elif defined(IRIX) |
michael@0 | 44 | #include <sys/types.h> |
michael@0 | 45 | #include <sys/prctl.h> |
michael@0 | 46 | #include <sys/wait.h> |
michael@0 | 47 | #include <errno.h> |
michael@0 | 48 | #elif defined(SOLARIS) |
michael@0 | 49 | #include <thread.h> |
michael@0 | 50 | #elif defined(OS2) |
michael@0 | 51 | #define INCL_DOS |
michael@0 | 52 | #define INCL_ERRORS |
michael@0 | 53 | #include <os2.h> |
michael@0 | 54 | #include <process.h> |
michael@0 | 55 | #elif defined(XP_BEOS) |
michael@0 | 56 | #include <kernel/OS.h> |
michael@0 | 57 | #endif |
michael@0 | 58 | |
michael@0 | 59 | #define DEFAULT_COUNT 1000 |
michael@0 | 60 | PRIntn failed_already=0; |
michael@0 | 61 | PRIntn debug_mode; |
michael@0 | 62 | |
michael@0 | 63 | |
michael@0 | 64 | int count; |
michael@0 | 65 | |
michael@0 | 66 | |
michael@0 | 67 | static void |
michael@0 | 68 | AttachDetach(void) |
michael@0 | 69 | { |
michael@0 | 70 | PRThread *me; |
michael@0 | 71 | PRInt32 index; |
michael@0 | 72 | |
michael@0 | 73 | for (index=0;index<count; index++) { |
michael@0 | 74 | me = PR_AttachThread(PR_USER_THREAD, |
michael@0 | 75 | PR_PRIORITY_NORMAL, |
michael@0 | 76 | NULL); |
michael@0 | 77 | |
michael@0 | 78 | if (!me) { |
michael@0 | 79 | fprintf(stderr, "Error attaching thread %d: PR_AttachThread failed\n", |
michael@0 | 80 | count); |
michael@0 | 81 | failed_already = 1; |
michael@0 | 82 | return; |
michael@0 | 83 | } |
michael@0 | 84 | PR_DetachThread(); |
michael@0 | 85 | } |
michael@0 | 86 | } |
michael@0 | 87 | |
michael@0 | 88 | /************************************************************************/ |
michael@0 | 89 | |
michael@0 | 90 | static void Measure(void (*func)(void), const char *msg) |
michael@0 | 91 | { |
michael@0 | 92 | PRIntervalTime start, stop; |
michael@0 | 93 | double d; |
michael@0 | 94 | |
michael@0 | 95 | start = PR_IntervalNow(); |
michael@0 | 96 | (*func)(); |
michael@0 | 97 | stop = PR_IntervalNow(); |
michael@0 | 98 | |
michael@0 | 99 | d = (double)PR_IntervalToMicroseconds(stop - start); |
michael@0 | 100 | if (debug_mode) |
michael@0 | 101 | printf("%40s: %6.2f usec\n", msg, d / count); |
michael@0 | 102 | } |
michael@0 | 103 | |
michael@0 | 104 | #ifdef WIN32 |
michael@0 | 105 | static unsigned __stdcall threadStartFunc(void *arg) |
michael@0 | 106 | #elif defined(IRIX) && !defined(_PR_PTHREADS) |
michael@0 | 107 | static void threadStartFunc(void *arg) |
michael@0 | 108 | #elif defined(XP_BEOS) |
michael@0 | 109 | static int32 threadStartFunc(void *arg) |
michael@0 | 110 | #else |
michael@0 | 111 | static void * threadStartFunc(void *arg) |
michael@0 | 112 | #endif |
michael@0 | 113 | { |
michael@0 | 114 | #ifdef _PR_DCETHREADS |
michael@0 | 115 | { |
michael@0 | 116 | int rv; |
michael@0 | 117 | pthread_t self = pthread_self(); |
michael@0 | 118 | rv = pthread_detach(&self); |
michael@0 | 119 | if (debug_mode) PR_ASSERT(0 == rv); |
michael@0 | 120 | else if (0 != rv) failed_already=1; |
michael@0 | 121 | } |
michael@0 | 122 | #endif |
michael@0 | 123 | |
michael@0 | 124 | Measure(AttachDetach, "Attach/Detach"); |
michael@0 | 125 | |
michael@0 | 126 | #ifndef IRIX |
michael@0 | 127 | return 0; |
michael@0 | 128 | #endif |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | int main(int argc, char **argv) |
michael@0 | 132 | { |
michael@0 | 133 | #ifdef _PR_PTHREADS |
michael@0 | 134 | int rv; |
michael@0 | 135 | pthread_t threadID; |
michael@0 | 136 | pthread_attr_t attr; |
michael@0 | 137 | #elif defined(SOLARIS) |
michael@0 | 138 | int rv; |
michael@0 | 139 | thread_t threadID; |
michael@0 | 140 | #elif defined(WIN32) |
michael@0 | 141 | DWORD rv; |
michael@0 | 142 | unsigned threadID; |
michael@0 | 143 | HANDLE hThread; |
michael@0 | 144 | #elif defined(IRIX) |
michael@0 | 145 | int rv; |
michael@0 | 146 | int threadID; |
michael@0 | 147 | #elif defined(OS2) |
michael@0 | 148 | int rv; |
michael@0 | 149 | TID threadID; |
michael@0 | 150 | #elif defined(XP_BEOS) |
michael@0 | 151 | thread_id threadID; |
michael@0 | 152 | int32 threadRV; |
michael@0 | 153 | status_t waitRV; |
michael@0 | 154 | #endif |
michael@0 | 155 | |
michael@0 | 156 | /* The command line argument: -d is used to determine if the test is being run |
michael@0 | 157 | in debug mode. The regress tool requires only one line output:PASS or FAIL. |
michael@0 | 158 | All of the printfs associated with this test has been handled with a if (debug_mode) |
michael@0 | 159 | test. |
michael@0 | 160 | Usage: test_name [-d] [-c n] |
michael@0 | 161 | */ |
michael@0 | 162 | PLOptStatus os; |
michael@0 | 163 | PLOptState *opt = PL_CreateOptState(argc, argv, "dc:"); |
michael@0 | 164 | while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) |
michael@0 | 165 | { |
michael@0 | 166 | if (PL_OPT_BAD == os) continue; |
michael@0 | 167 | switch (opt->option) |
michael@0 | 168 | { |
michael@0 | 169 | case 'd': /* debug mode */ |
michael@0 | 170 | debug_mode = 1; |
michael@0 | 171 | break; |
michael@0 | 172 | case 'c': /* loop count */ |
michael@0 | 173 | count = atoi(opt->value); |
michael@0 | 174 | break; |
michael@0 | 175 | default: |
michael@0 | 176 | break; |
michael@0 | 177 | } |
michael@0 | 178 | } |
michael@0 | 179 | PL_DestroyOptState(opt); |
michael@0 | 180 | |
michael@0 | 181 | #if defined(WIN16) |
michael@0 | 182 | printf("attach: This test is not valid for Win16\n"); |
michael@0 | 183 | goto exit_now; |
michael@0 | 184 | #endif |
michael@0 | 185 | |
michael@0 | 186 | if(0 == count) count = DEFAULT_COUNT; |
michael@0 | 187 | |
michael@0 | 188 | /* |
michael@0 | 189 | * To force the implicit initialization of nspr20 |
michael@0 | 190 | */ |
michael@0 | 191 | PR_SetError(0, 0); |
michael@0 | 192 | PR_STDIO_INIT(); |
michael@0 | 193 | |
michael@0 | 194 | /* |
michael@0 | 195 | * Platform-specific code to create a native thread. The native |
michael@0 | 196 | * thread will repeatedly call PR_AttachThread and PR_DetachThread. |
michael@0 | 197 | * The primordial thread waits for this new thread to finish. |
michael@0 | 198 | */ |
michael@0 | 199 | |
michael@0 | 200 | #ifdef _PR_PTHREADS |
michael@0 | 201 | |
michael@0 | 202 | rv = _PT_PTHREAD_ATTR_INIT(&attr); |
michael@0 | 203 | if (debug_mode) PR_ASSERT(0 == rv); |
michael@0 | 204 | else if (0 != rv) { |
michael@0 | 205 | failed_already=1; |
michael@0 | 206 | goto exit_now; |
michael@0 | 207 | } |
michael@0 | 208 | |
michael@0 | 209 | #ifndef _PR_DCETHREADS |
michael@0 | 210 | rv = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); |
michael@0 | 211 | if (debug_mode) PR_ASSERT(0 == rv); |
michael@0 | 212 | else if (0 != rv) { |
michael@0 | 213 | failed_already=1; |
michael@0 | 214 | goto exit_now; |
michael@0 | 215 | } |
michael@0 | 216 | #endif /* !_PR_DCETHREADS */ |
michael@0 | 217 | rv = _PT_PTHREAD_CREATE(&threadID, attr, threadStartFunc, NULL); |
michael@0 | 218 | if (rv != 0) { |
michael@0 | 219 | fprintf(stderr, "thread creation failed: error code %d\n", rv); |
michael@0 | 220 | failed_already=1; |
michael@0 | 221 | goto exit_now; |
michael@0 | 222 | } |
michael@0 | 223 | else { |
michael@0 | 224 | if (debug_mode) |
michael@0 | 225 | printf ("thread creation succeeded \n"); |
michael@0 | 226 | |
michael@0 | 227 | } |
michael@0 | 228 | rv = _PT_PTHREAD_ATTR_DESTROY(&attr); |
michael@0 | 229 | if (debug_mode) PR_ASSERT(0 == rv); |
michael@0 | 230 | else if (0 != rv) { |
michael@0 | 231 | failed_already=1; |
michael@0 | 232 | goto exit_now; |
michael@0 | 233 | } |
michael@0 | 234 | rv = pthread_join(threadID, NULL); |
michael@0 | 235 | if (debug_mode) PR_ASSERT(0 == rv); |
michael@0 | 236 | else if (0 != rv) { |
michael@0 | 237 | failed_already=1; |
michael@0 | 238 | goto exit_now; |
michael@0 | 239 | } |
michael@0 | 240 | |
michael@0 | 241 | #elif defined(SOLARIS) |
michael@0 | 242 | |
michael@0 | 243 | rv = thr_create(NULL, 0, threadStartFunc, NULL, 0, &threadID); |
michael@0 | 244 | if (rv != 0) { |
michael@0 | 245 | if(!debug_mode) { |
michael@0 | 246 | failed_already=1; |
michael@0 | 247 | goto exit_now; |
michael@0 | 248 | } else |
michael@0 | 249 | fprintf(stderr, "thread creation failed: error code %d\n", rv); |
michael@0 | 250 | } |
michael@0 | 251 | rv = thr_join(threadID, NULL, NULL); |
michael@0 | 252 | if (debug_mode) PR_ASSERT(0 == rv); |
michael@0 | 253 | else if (0 != rv) |
michael@0 | 254 | { |
michael@0 | 255 | failed_already=1; |
michael@0 | 256 | goto exit_now; |
michael@0 | 257 | } |
michael@0 | 258 | |
michael@0 | 259 | |
michael@0 | 260 | #elif defined(WIN32) |
michael@0 | 261 | |
michael@0 | 262 | hThread = (HANDLE) _beginthreadex(NULL, 0, threadStartFunc, NULL, |
michael@0 | 263 | STACK_SIZE_PARAM_IS_A_RESERVATION, &threadID); |
michael@0 | 264 | if (hThread == 0) { |
michael@0 | 265 | fprintf(stderr, "thread creation failed: error code %d\n", |
michael@0 | 266 | GetLastError()); |
michael@0 | 267 | failed_already=1; |
michael@0 | 268 | goto exit_now; |
michael@0 | 269 | } |
michael@0 | 270 | rv = WaitForSingleObject(hThread, INFINITE); |
michael@0 | 271 | if (debug_mode)PR_ASSERT(rv != WAIT_FAILED); |
michael@0 | 272 | else if (rv == WAIT_FAILED) { |
michael@0 | 273 | failed_already=1; |
michael@0 | 274 | goto exit_now; |
michael@0 | 275 | } |
michael@0 | 276 | |
michael@0 | 277 | #elif defined(IRIX) |
michael@0 | 278 | |
michael@0 | 279 | threadID = sproc(threadStartFunc, PR_SALL, NULL); |
michael@0 | 280 | if (threadID == -1) { |
michael@0 | 281 | |
michael@0 | 282 | fprintf(stderr, "thread creation failed: error code %d\n", |
michael@0 | 283 | errno); |
michael@0 | 284 | failed_already=1; |
michael@0 | 285 | goto exit_now; |
michael@0 | 286 | |
michael@0 | 287 | } |
michael@0 | 288 | else { |
michael@0 | 289 | if (debug_mode) |
michael@0 | 290 | printf ("thread creation succeeded \n"); |
michael@0 | 291 | sleep(3); |
michael@0 | 292 | goto exit_now; |
michael@0 | 293 | } |
michael@0 | 294 | rv = waitpid(threadID, NULL, 0); |
michael@0 | 295 | if (debug_mode) PR_ASSERT(rv != -1); |
michael@0 | 296 | else if (rv != -1) { |
michael@0 | 297 | failed_already=1; |
michael@0 | 298 | goto exit_now; |
michael@0 | 299 | } |
michael@0 | 300 | |
michael@0 | 301 | #elif defined(OS2) |
michael@0 | 302 | |
michael@0 | 303 | threadID = (TID) _beginthread((void *)threadStartFunc, NULL, |
michael@0 | 304 | 32768, NULL); |
michael@0 | 305 | if (threadID == -1) { |
michael@0 | 306 | fprintf(stderr, "thread creation failed: error code %d\n", errno); |
michael@0 | 307 | failed_already=1; |
michael@0 | 308 | goto exit_now; |
michael@0 | 309 | } |
michael@0 | 310 | rv = DosWaitThread(&threadID, DCWW_WAIT); |
michael@0 | 311 | if (debug_mode) { |
michael@0 | 312 | PR_ASSERT(rv == NO_ERROR); |
michael@0 | 313 | } else if (rv != NO_ERROR) { |
michael@0 | 314 | failed_already=1; |
michael@0 | 315 | goto exit_now; |
michael@0 | 316 | } |
michael@0 | 317 | |
michael@0 | 318 | #elif defined(XP_BEOS) |
michael@0 | 319 | |
michael@0 | 320 | threadID = spawn_thread(threadStartFunc, NULL, B_NORMAL_PRIORITY, NULL); |
michael@0 | 321 | if (threadID <= B_ERROR) { |
michael@0 | 322 | fprintf(stderr, "thread creation failed: error code %08lx\n", threadID); |
michael@0 | 323 | failed_already = 1; |
michael@0 | 324 | goto exit_now; |
michael@0 | 325 | } |
michael@0 | 326 | if (resume_thread(threadID) != B_OK) { |
michael@0 | 327 | fprintf(stderr, "failed starting thread: error code %08lx\n", threadID); |
michael@0 | 328 | failed_already = 1; |
michael@0 | 329 | goto exit_now; |
michael@0 | 330 | } |
michael@0 | 331 | |
michael@0 | 332 | waitRV = wait_for_thread(threadID, &threadRV); |
michael@0 | 333 | if (debug_mode) |
michael@0 | 334 | PR_ASSERT(waitRV == B_OK); |
michael@0 | 335 | else if (waitRV != B_OK) { |
michael@0 | 336 | failed_already = 1; |
michael@0 | 337 | goto exit_now; |
michael@0 | 338 | } |
michael@0 | 339 | |
michael@0 | 340 | #else |
michael@0 | 341 | if (!debug_mode) |
michael@0 | 342 | failed_already=1; |
michael@0 | 343 | else |
michael@0 | 344 | printf("The attach test does not apply to this platform because\n" |
michael@0 | 345 | "either this platform does not have native threads or the\n" |
michael@0 | 346 | "test needs to be written for this platform.\n"); |
michael@0 | 347 | goto exit_now; |
michael@0 | 348 | #endif |
michael@0 | 349 | |
michael@0 | 350 | exit_now: |
michael@0 | 351 | if(failed_already) |
michael@0 | 352 | return 1; |
michael@0 | 353 | else |
michael@0 | 354 | return 0; |
michael@0 | 355 | } |