1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/tests/threads.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,203 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nspr.h" 1.10 +#include "prinrval.h" 1.11 +#include "plgetopt.h" 1.12 +#include "pprthred.h" 1.13 +#include <stdio.h> 1.14 +#include <stdlib.h> 1.15 +#include <string.h> 1.16 + 1.17 +PRMonitor *mon; 1.18 +PRInt32 count, iterations, alive; 1.19 + 1.20 +PRBool debug_mode = PR_FALSE, passed = PR_TRUE; 1.21 + 1.22 +void 1.23 +PR_CALLBACK 1.24 +ReallyDumbThread(void *arg) 1.25 +{ 1.26 + return; 1.27 +} 1.28 + 1.29 +void 1.30 +PR_CALLBACK 1.31 +DumbThread(void *arg) 1.32 +{ 1.33 + PRInt32 tmp = (PRInt32)arg; 1.34 + PRThreadScope scope = (PRThreadScope)tmp; 1.35 + PRThread *thr; 1.36 + 1.37 + thr = PR_CreateThread(PR_USER_THREAD, 1.38 + ReallyDumbThread, 1.39 + NULL, 1.40 + PR_PRIORITY_NORMAL, 1.41 + scope, 1.42 + PR_JOINABLE_THREAD, 1.43 + 0); 1.44 + 1.45 + if (!thr) { 1.46 + if (debug_mode) { 1.47 + printf("Could not create really dumb thread (%d, %d)!\n", 1.48 + PR_GetError(), PR_GetOSError()); 1.49 + } 1.50 + passed = PR_FALSE; 1.51 + } else { 1.52 + PR_JoinThread(thr); 1.53 + } 1.54 + PR_EnterMonitor(mon); 1.55 + alive--; 1.56 + PR_Notify(mon); 1.57 + PR_ExitMonitor(mon); 1.58 +} 1.59 + 1.60 +static void CreateThreads(PRThreadScope scope1, PRThreadScope scope2) 1.61 +{ 1.62 + PRThread *thr; 1.63 + int n; 1.64 + 1.65 + alive = 0; 1.66 + mon = PR_NewMonitor(); 1.67 + 1.68 + alive = count; 1.69 + for (n=0; n<count; n++) { 1.70 + thr = PR_CreateThread(PR_USER_THREAD, 1.71 + DumbThread, 1.72 + (void *)scope2, 1.73 + PR_PRIORITY_NORMAL, 1.74 + scope1, 1.75 + PR_UNJOINABLE_THREAD, 1.76 + 0); 1.77 + if (!thr) { 1.78 + if (debug_mode) { 1.79 + printf("Could not create dumb thread (%d, %d)!\n", 1.80 + PR_GetError(), PR_GetOSError()); 1.81 + } 1.82 + passed = PR_FALSE; 1.83 + alive--; 1.84 + } 1.85 + 1.86 + PR_Sleep(0); 1.87 + } 1.88 + 1.89 + /* Wait for all threads to exit */ 1.90 + PR_EnterMonitor(mon); 1.91 + while (alive) { 1.92 + PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); 1.93 + } 1.94 + 1.95 + PR_ExitMonitor(mon); 1.96 + PR_DestroyMonitor(mon); 1.97 +} 1.98 + 1.99 +static void CreateThreadsUU(void) 1.100 +{ 1.101 + CreateThreads(PR_LOCAL_THREAD, PR_LOCAL_THREAD); 1.102 +} 1.103 + 1.104 +static void CreateThreadsUK(void) 1.105 +{ 1.106 + CreateThreads(PR_LOCAL_THREAD, PR_GLOBAL_THREAD); 1.107 +} 1.108 + 1.109 +static void CreateThreadsKU(void) 1.110 +{ 1.111 + CreateThreads(PR_GLOBAL_THREAD, PR_LOCAL_THREAD); 1.112 +} 1.113 + 1.114 +static void CreateThreadsKK(void) 1.115 +{ 1.116 + CreateThreads(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD); 1.117 +} 1.118 + 1.119 +/************************************************************************/ 1.120 + 1.121 +static void Measure(void (*func)(void), const char *msg) 1.122 +{ 1.123 + PRIntervalTime start, stop; 1.124 + double d; 1.125 + 1.126 + start = PR_IntervalNow(); 1.127 + (*func)(); 1.128 + stop = PR_IntervalNow(); 1.129 + 1.130 + if (debug_mode) 1.131 + { 1.132 + d = (double)PR_IntervalToMicroseconds(stop - start); 1.133 + printf("%40s: %6.2f usec\n", msg, d / count); 1.134 + } 1.135 +} 1.136 + 1.137 +int main(int argc, char **argv) 1.138 +{ 1.139 + int index; 1.140 + 1.141 + PR_STDIO_INIT(); 1.142 + PR_Init(PR_USER_THREAD, PR_PRIORITY_HIGH, 0); 1.143 + 1.144 + { 1.145 + PLOptStatus os; 1.146 + PLOptState *opt = PL_CreateOptState(argc, argv, "dc:i:"); 1.147 + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) 1.148 + { 1.149 + if (PL_OPT_BAD == os) continue; 1.150 + switch (opt->option) 1.151 + { 1.152 + case 'd': /* debug mode */ 1.153 + debug_mode = PR_TRUE; 1.154 + break; 1.155 + case 'c': /* loop counter */ 1.156 + count = atoi(opt->value); 1.157 + break; 1.158 + case 'i': /* loop counter */ 1.159 + iterations = atoi(opt->value); 1.160 + break; 1.161 + default: 1.162 + break; 1.163 + } 1.164 + } 1.165 + PL_DestroyOptState(opt); 1.166 + } 1.167 + 1.168 + if (0 == count) count = 50; 1.169 + if (0 == iterations) iterations = 10; 1.170 + 1.171 + if (debug_mode) 1.172 + { 1.173 + printf("\ 1.174 +** Tests lots of thread creations. \n\ 1.175 +** Create %ld native threads %ld times. \n\ 1.176 +** Create %ld user threads %ld times \n", iterations,count,iterations,count); 1.177 + } 1.178 + 1.179 + for (index=0; index<iterations; index++) { 1.180 + Measure(CreateThreadsUU, "Create user/user threads"); 1.181 + Measure(CreateThreadsUK, "Create user/native threads"); 1.182 + Measure(CreateThreadsKU, "Create native/user threads"); 1.183 + Measure(CreateThreadsKK, "Create native/native threads"); 1.184 + } 1.185 + 1.186 + if (debug_mode) printf("\nNow switch to recycling threads \n\n"); 1.187 + PR_SetThreadRecycleMode(1); 1.188 + 1.189 + for (index=0; index<iterations; index++) { 1.190 + Measure(CreateThreadsUU, "Create user/user threads"); 1.191 + Measure(CreateThreadsUK, "Create user/native threads"); 1.192 + Measure(CreateThreadsKU, "Create native/user threads"); 1.193 + Measure(CreateThreadsKK, "Create native/native threads"); 1.194 + } 1.195 + 1.196 + 1.197 + printf("%s\n", ((passed) ? "PASS" : "FAIL")); 1.198 + 1.199 + PR_Cleanup(); 1.200 + 1.201 + if (passed) { 1.202 + return 0; 1.203 + } else { 1.204 + return 1; 1.205 + } 1.206 +}