tor-browser

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

threads.c (4446B)


      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 #include "nspr.h"
      7 #include "prinrval.h"
      8 #include "plgetopt.h"
      9 #include "pprthred.h"
     10 #include <stdio.h>
     11 #include <stdlib.h>
     12 #include <string.h>
     13 
     14 PRMonitor* mon;
     15 PRInt32 count, iterations, alive;
     16 
     17 PRBool debug_mode = PR_FALSE, passed = PR_TRUE;
     18 
     19 void PR_CALLBACK ReallyDumbThread(void* arg) { return; }
     20 
     21 void PR_CALLBACK DumbThread(void* arg) {
     22  PRInt32 tmp = (PRInt32)arg;
     23  PRThreadScope scope = (PRThreadScope)tmp;
     24  PRThread* thr;
     25 
     26  thr = PR_CreateThread(PR_USER_THREAD, ReallyDumbThread, NULL,
     27                        PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
     28 
     29  if (!thr) {
     30    if (debug_mode) {
     31      printf("Could not create really dumb thread (%d, %d)!\n", PR_GetError(),
     32             PR_GetOSError());
     33    }
     34    passed = PR_FALSE;
     35  } else {
     36    PR_JoinThread(thr);
     37  }
     38  PR_EnterMonitor(mon);
     39  alive--;
     40  PR_Notify(mon);
     41  PR_ExitMonitor(mon);
     42 }
     43 
     44 static void CreateThreads(PRThreadScope scope1, PRThreadScope scope2) {
     45  PRThread* thr;
     46  int n;
     47 
     48  alive = 0;
     49  mon = PR_NewMonitor();
     50 
     51  alive = count;
     52  for (n = 0; n < count; n++) {
     53    thr = PR_CreateThread(PR_USER_THREAD, DumbThread, (void*)scope2,
     54                          PR_PRIORITY_NORMAL, scope1, PR_UNJOINABLE_THREAD, 0);
     55    if (!thr) {
     56      if (debug_mode) {
     57        printf("Could not create dumb thread (%d, %d)!\n", PR_GetError(),
     58               PR_GetOSError());
     59      }
     60      passed = PR_FALSE;
     61      alive--;
     62    }
     63 
     64    PR_Sleep(0);
     65  }
     66 
     67  /* Wait for all threads to exit */
     68  PR_EnterMonitor(mon);
     69  while (alive) {
     70    PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
     71  }
     72 
     73  PR_ExitMonitor(mon);
     74  PR_DestroyMonitor(mon);
     75 }
     76 
     77 static void CreateThreadsUU(void) {
     78  CreateThreads(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
     79 }
     80 
     81 static void CreateThreadsUK(void) {
     82  CreateThreads(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
     83 }
     84 
     85 static void CreateThreadsKU(void) {
     86  CreateThreads(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
     87 }
     88 
     89 static void CreateThreadsKK(void) {
     90  CreateThreads(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
     91 }
     92 
     93 /************************************************************************/
     94 
     95 static void Measure(void (*func)(void), const char* msg) {
     96  PRIntervalTime start, stop;
     97  double d;
     98 
     99  start = PR_IntervalNow();
    100  (*func)();
    101  stop = PR_IntervalNow();
    102 
    103  if (debug_mode) {
    104    d = (double)PR_IntervalToMicroseconds(stop - start);
    105    printf("%40s: %6.2f usec\n", msg, d / count);
    106  }
    107 }
    108 
    109 int main(int argc, char** argv) {
    110  int index;
    111 
    112  PR_Init(PR_USER_THREAD, PR_PRIORITY_HIGH, 0);
    113 
    114  {
    115    PLOptStatus os;
    116    PLOptState* opt = PL_CreateOptState(argc, argv, "dc:i:");
    117    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
    118      if (PL_OPT_BAD == os) {
    119        continue;
    120      }
    121      switch (opt->option) {
    122        case 'd': /* debug mode */
    123          debug_mode = PR_TRUE;
    124          break;
    125        case 'c': /* loop counter */
    126          count = atoi(opt->value);
    127          break;
    128        case 'i': /* loop counter */
    129          iterations = atoi(opt->value);
    130          break;
    131        default:
    132          break;
    133      }
    134    }
    135    PL_DestroyOptState(opt);
    136  }
    137 
    138  if (0 == count) {
    139    count = 50;
    140  }
    141  if (0 == iterations) {
    142    iterations = 10;
    143  }
    144 
    145  if (debug_mode) {
    146    printf(
    147        "\
    148 ** Tests lots of thread creations.  \n\
    149 ** Create %ld native threads %ld times. \n\
    150 ** Create %ld user threads %ld times \n",
    151        iterations, count, iterations, count);
    152  }
    153 
    154  for (index = 0; index < iterations; index++) {
    155    Measure(CreateThreadsUU, "Create user/user threads");
    156    Measure(CreateThreadsUK, "Create user/native threads");
    157    Measure(CreateThreadsKU, "Create native/user threads");
    158    Measure(CreateThreadsKK, "Create native/native threads");
    159  }
    160 
    161  if (debug_mode) {
    162    printf("\nNow switch to recycling threads \n\n");
    163  }
    164  PR_SetThreadRecycleMode(1);
    165 
    166  for (index = 0; index < iterations; index++) {
    167    Measure(CreateThreadsUU, "Create user/user threads");
    168    Measure(CreateThreadsUK, "Create user/native threads");
    169    Measure(CreateThreadsKU, "Create native/user threads");
    170    Measure(CreateThreadsKK, "Create native/native threads");
    171  }
    172 
    173  printf("%s\n", ((passed) ? "PASS" : "FAIL"));
    174 
    175  PR_Cleanup();
    176 
    177  if (passed) {
    178    return 0;
    179  } else {
    180    return 1;
    181  }
    182 }