1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/tests/lockfile.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,229 @@ 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 +/* 1.10 +** File: lockfile.c 1.11 +** Purpose: test basic locking functions 1.12 +** Just because this times stuff, don't think its a perforamnce 1.13 +** test!!! 1.14 +** 1.15 +** Modification History: 1.16 +** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. 1.17 +** The debug mode will print all of the printfs associated with this test. 1.18 +** The regress mode will be the default mode. Since the regress tool limits 1.19 +** the output to a one line status:PASS or FAIL,all of the printf statements 1.20 +** have been handled with an if (debug_mode) statement. 1.21 +** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to 1.22 +** recognize the return code from tha main program. 1.23 +***********************************************************************/ 1.24 +/*********************************************************************** 1.25 +** Includes 1.26 +***********************************************************************/ 1.27 +/* Used to get the command line option */ 1.28 +#include "plgetopt.h" 1.29 + 1.30 +#include "prcmon.h" 1.31 +#include "prerror.h" 1.32 +#include "prinit.h" 1.33 +#include "prinrval.h" 1.34 +#include "prlock.h" 1.35 +#include "prlog.h" 1.36 +#include "prmon.h" 1.37 +#include "prthread.h" 1.38 +#include "prtypes.h" 1.39 + 1.40 +#include "private/pprio.h" 1.41 + 1.42 +#include <stdio.h> 1.43 +#include <stdlib.h> 1.44 +#include <string.h> 1.45 + 1.46 +PRIntn failed_already=0; 1.47 +PRIntn debug_mode; 1.48 + 1.49 +const static PRIntervalTime contention_interval = 50; 1.50 + 1.51 +typedef struct LockContentious_s { 1.52 + PRLock *ml; 1.53 + PRInt32 loops; 1.54 + PRIntervalTime overhead; 1.55 + PRIntervalTime interval; 1.56 +} LockContentious_t; 1.57 + 1.58 +#define LOCKFILE "prlock.fil" 1.59 + 1.60 + 1.61 + 1.62 +static PRIntervalTime NonContentiousLock(PRInt32 loops) 1.63 +{ 1.64 + PRFileDesc *_lockfile; 1.65 + while (loops-- > 0) 1.66 + { 1.67 + _lockfile = PR_Open(LOCKFILE, PR_CREATE_FILE|PR_RDWR, 0666); 1.68 + if (!_lockfile) { 1.69 + if (debug_mode) printf( 1.70 + "could not create lockfile: %d [%d]\n", 1.71 + PR_GetError(), PR_GetOSError()); 1.72 + return PR_INTERVAL_NO_TIMEOUT; 1.73 + } 1.74 + PR_LockFile(_lockfile); 1.75 + PR_UnlockFile(_lockfile); 1.76 + PR_Close(_lockfile); 1.77 + } 1.78 + return 0; 1.79 +} /* NonContentiousLock */ 1.80 + 1.81 +static void PR_CALLBACK LockContender(void *arg) 1.82 +{ 1.83 + LockContentious_t *contention = (LockContentious_t*)arg; 1.84 + PRFileDesc *_lockfile; 1.85 + while (contention->loops-- > 0) 1.86 + { 1.87 + _lockfile = PR_Open(LOCKFILE, PR_CREATE_FILE|PR_RDWR, 0666); 1.88 + if (!_lockfile) { 1.89 + if (debug_mode) printf( 1.90 + "could not create lockfile: %d [%d]\n", 1.91 + PR_GetError(), PR_GetOSError()); 1.92 + break; 1.93 + } 1.94 + PR_LockFile(_lockfile); 1.95 + PR_Sleep(contention->interval); 1.96 + PR_UnlockFile(_lockfile); 1.97 + PR_Close(_lockfile); 1.98 + } 1.99 + 1.100 +} /* LockContender */ 1.101 + 1.102 +/* 1.103 +** Win16 requires things passed to Threads not be on the stack 1.104 +*/ 1.105 +static LockContentious_t contention; 1.106 + 1.107 +static PRIntervalTime ContentiousLock(PRInt32 loops) 1.108 +{ 1.109 + PRStatus status; 1.110 + PRThread *thread = NULL; 1.111 + PRIntervalTime overhead, timein = PR_IntervalNow(); 1.112 + 1.113 + contention.loops = loops; 1.114 + contention.overhead = 0; 1.115 + contention.ml = PR_NewLock(); 1.116 + contention.interval = contention_interval; 1.117 + thread = PR_CreateThread( 1.118 + PR_USER_THREAD, LockContender, &contention, 1.119 + PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); 1.120 + PR_ASSERT(thread != NULL); 1.121 + 1.122 + overhead = PR_IntervalNow() - timein; 1.123 + 1.124 + while (contention.loops > 0) 1.125 + { 1.126 + PR_Lock(contention.ml); 1.127 + contention.overhead += contention.interval; 1.128 + PR_Sleep(contention.interval); 1.129 + PR_Unlock(contention.ml); 1.130 + } 1.131 + 1.132 + timein = PR_IntervalNow(); 1.133 + status = PR_JoinThread(thread); 1.134 + PR_DestroyLock(contention.ml); 1.135 + overhead += (PR_IntervalNow() - timein); 1.136 + return overhead + contention.overhead; 1.137 +} /* ContentiousLock */ 1.138 + 1.139 +static PRIntervalTime Test( 1.140 + const char* msg, PRIntervalTime (*test)(PRInt32 loops), 1.141 + PRInt32 loops, PRIntervalTime overhead) 1.142 +{ 1.143 + /* 1.144 + * overhead - overhead not measured by the test. 1.145 + * duration - wall clock time it took to perform test. 1.146 + * predicted - extra time test says should not be counted 1.147 + * 1.148 + * Time accountable to the test is duration - overhead - predicted 1.149 + * All times are Intervals and accumulated for all iterations. 1.150 + */ 1.151 + PRFloat64 elapsed; 1.152 + PRIntervalTime accountable, duration; 1.153 + PRUintn spaces = strlen(msg); 1.154 + PRIntervalTime timeout, timein = PR_IntervalNow(); 1.155 + PRIntervalTime predicted = test(loops); 1.156 + timeout = PR_IntervalNow(); 1.157 + duration = timeout - timein; 1.158 + accountable = duration - predicted; 1.159 + accountable -= overhead; 1.160 + elapsed = (PRFloat64)PR_IntervalToMicroseconds(accountable); 1.161 + if (debug_mode) printf("%s:", msg); 1.162 + while (spaces++ < 50) if (debug_mode) printf(" "); 1.163 + if ((PRInt32)accountable < 0) { 1.164 + if (debug_mode) printf("*****.** usecs/iteration\n"); 1.165 + } else { 1.166 + if (debug_mode) printf("%8.2f usecs/iteration\n", elapsed/loops); 1.167 + } 1.168 + return duration; 1.169 +} /* Test */ 1.170 + 1.171 +int main(int argc, char **argv) 1.172 +{ 1.173 + PRIntervalTime duration; 1.174 + PRUint32 cpu, cpus = 2; 1.175 + PRInt32 loops = 100; 1.176 + 1.177 + 1.178 + /* The command line argument: -d is used to determine if the test is being run 1.179 + in debug mode. The regress tool requires only one line output:PASS or FAIL. 1.180 + All of the printfs associated with this test has been handled with a if (debug_mode) 1.181 + test. 1.182 + Usage: test_name -d 1.183 + */ 1.184 + PLOptStatus os; 1.185 + PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); 1.186 + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) 1.187 + { 1.188 + if (PL_OPT_BAD == os) continue; 1.189 + switch (opt->option) 1.190 + { 1.191 + case 'd': /* debug mode */ 1.192 + debug_mode = 1; 1.193 + break; 1.194 + default: 1.195 + break; 1.196 + } 1.197 + } 1.198 + PL_DestroyOptState(opt); 1.199 + 1.200 + /* main test */ 1.201 + 1.202 + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); 1.203 + PR_STDIO_INIT(); 1.204 + 1.205 + if (argc > 1) loops = atoi(argv[1]); 1.206 + if (loops == 0) loops = 100; 1.207 + if (debug_mode) printf("Lock: Using %d loops\n", loops); 1.208 + 1.209 + cpus = (argc < 3) ? 2 : atoi(argv[2]); 1.210 + if (cpus == 0) cpus = 2; 1.211 + if (debug_mode) printf("Lock: Using %d cpu(s)\n", cpus); 1.212 + 1.213 + 1.214 + for (cpu = 1; cpu <= cpus; ++cpu) 1.215 + { 1.216 + if (debug_mode) printf("\nLockFile: Using %d CPU(s)\n", cpu); 1.217 + PR_SetConcurrency(cpu); 1.218 + 1.219 + duration = Test("LockFile non-contentious locking/unlocking", NonContentiousLock, loops, 0); 1.220 + (void)Test("LockFile contentious locking/unlocking", ContentiousLock, loops, duration); 1.221 + } 1.222 + 1.223 + PR_Delete(LOCKFILE); /* try to get rid of evidence */ 1.224 + 1.225 + if (debug_mode) printf("%s: test %s\n", "Lock(mutex) test", ((failed_already) ? "failed" : "passed")); 1.226 + if(failed_already) 1.227 + return 1; 1.228 + else 1.229 + return 0; 1.230 +} /* main */ 1.231 + 1.232 +/* testlock.c */