tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }