nsprpub/pr/tests/lockfile.c

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rw-r--r--

Correct small whitespace inconsistency, lost while renaming variables.

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 ** File: lockfile.c
michael@0 8 ** Purpose: test basic locking functions
michael@0 9 ** Just because this times stuff, don't think its a perforamnce
michael@0 10 ** test!!!
michael@0 11 **
michael@0 12 ** Modification History:
michael@0 13 ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
michael@0 14 ** The debug mode will print all of the printfs associated with this test.
michael@0 15 ** The regress mode will be the default mode. Since the regress tool limits
michael@0 16 ** the output to a one line status:PASS or FAIL,all of the printf statements
michael@0 17 ** have been handled with an if (debug_mode) statement.
michael@0 18 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
michael@0 19 ** recognize the return code from tha main program.
michael@0 20 ***********************************************************************/
michael@0 21 /***********************************************************************
michael@0 22 ** Includes
michael@0 23 ***********************************************************************/
michael@0 24 /* Used to get the command line option */
michael@0 25 #include "plgetopt.h"
michael@0 26
michael@0 27 #include "prcmon.h"
michael@0 28 #include "prerror.h"
michael@0 29 #include "prinit.h"
michael@0 30 #include "prinrval.h"
michael@0 31 #include "prlock.h"
michael@0 32 #include "prlog.h"
michael@0 33 #include "prmon.h"
michael@0 34 #include "prthread.h"
michael@0 35 #include "prtypes.h"
michael@0 36
michael@0 37 #include "private/pprio.h"
michael@0 38
michael@0 39 #include <stdio.h>
michael@0 40 #include <stdlib.h>
michael@0 41 #include <string.h>
michael@0 42
michael@0 43 PRIntn failed_already=0;
michael@0 44 PRIntn debug_mode;
michael@0 45
michael@0 46 const static PRIntervalTime contention_interval = 50;
michael@0 47
michael@0 48 typedef struct LockContentious_s {
michael@0 49 PRLock *ml;
michael@0 50 PRInt32 loops;
michael@0 51 PRIntervalTime overhead;
michael@0 52 PRIntervalTime interval;
michael@0 53 } LockContentious_t;
michael@0 54
michael@0 55 #define LOCKFILE "prlock.fil"
michael@0 56
michael@0 57
michael@0 58
michael@0 59 static PRIntervalTime NonContentiousLock(PRInt32 loops)
michael@0 60 {
michael@0 61 PRFileDesc *_lockfile;
michael@0 62 while (loops-- > 0)
michael@0 63 {
michael@0 64 _lockfile = PR_Open(LOCKFILE, PR_CREATE_FILE|PR_RDWR, 0666);
michael@0 65 if (!_lockfile) {
michael@0 66 if (debug_mode) printf(
michael@0 67 "could not create lockfile: %d [%d]\n",
michael@0 68 PR_GetError(), PR_GetOSError());
michael@0 69 return PR_INTERVAL_NO_TIMEOUT;
michael@0 70 }
michael@0 71 PR_LockFile(_lockfile);
michael@0 72 PR_UnlockFile(_lockfile);
michael@0 73 PR_Close(_lockfile);
michael@0 74 }
michael@0 75 return 0;
michael@0 76 } /* NonContentiousLock */
michael@0 77
michael@0 78 static void PR_CALLBACK LockContender(void *arg)
michael@0 79 {
michael@0 80 LockContentious_t *contention = (LockContentious_t*)arg;
michael@0 81 PRFileDesc *_lockfile;
michael@0 82 while (contention->loops-- > 0)
michael@0 83 {
michael@0 84 _lockfile = PR_Open(LOCKFILE, PR_CREATE_FILE|PR_RDWR, 0666);
michael@0 85 if (!_lockfile) {
michael@0 86 if (debug_mode) printf(
michael@0 87 "could not create lockfile: %d [%d]\n",
michael@0 88 PR_GetError(), PR_GetOSError());
michael@0 89 break;
michael@0 90 }
michael@0 91 PR_LockFile(_lockfile);
michael@0 92 PR_Sleep(contention->interval);
michael@0 93 PR_UnlockFile(_lockfile);
michael@0 94 PR_Close(_lockfile);
michael@0 95 }
michael@0 96
michael@0 97 } /* LockContender */
michael@0 98
michael@0 99 /*
michael@0 100 ** Win16 requires things passed to Threads not be on the stack
michael@0 101 */
michael@0 102 static LockContentious_t contention;
michael@0 103
michael@0 104 static PRIntervalTime ContentiousLock(PRInt32 loops)
michael@0 105 {
michael@0 106 PRStatus status;
michael@0 107 PRThread *thread = NULL;
michael@0 108 PRIntervalTime overhead, timein = PR_IntervalNow();
michael@0 109
michael@0 110 contention.loops = loops;
michael@0 111 contention.overhead = 0;
michael@0 112 contention.ml = PR_NewLock();
michael@0 113 contention.interval = contention_interval;
michael@0 114 thread = PR_CreateThread(
michael@0 115 PR_USER_THREAD, LockContender, &contention,
michael@0 116 PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
michael@0 117 PR_ASSERT(thread != NULL);
michael@0 118
michael@0 119 overhead = PR_IntervalNow() - timein;
michael@0 120
michael@0 121 while (contention.loops > 0)
michael@0 122 {
michael@0 123 PR_Lock(contention.ml);
michael@0 124 contention.overhead += contention.interval;
michael@0 125 PR_Sleep(contention.interval);
michael@0 126 PR_Unlock(contention.ml);
michael@0 127 }
michael@0 128
michael@0 129 timein = PR_IntervalNow();
michael@0 130 status = PR_JoinThread(thread);
michael@0 131 PR_DestroyLock(contention.ml);
michael@0 132 overhead += (PR_IntervalNow() - timein);
michael@0 133 return overhead + contention.overhead;
michael@0 134 } /* ContentiousLock */
michael@0 135
michael@0 136 static PRIntervalTime Test(
michael@0 137 const char* msg, PRIntervalTime (*test)(PRInt32 loops),
michael@0 138 PRInt32 loops, PRIntervalTime overhead)
michael@0 139 {
michael@0 140 /*
michael@0 141 * overhead - overhead not measured by the test.
michael@0 142 * duration - wall clock time it took to perform test.
michael@0 143 * predicted - extra time test says should not be counted
michael@0 144 *
michael@0 145 * Time accountable to the test is duration - overhead - predicted
michael@0 146 * All times are Intervals and accumulated for all iterations.
michael@0 147 */
michael@0 148 PRFloat64 elapsed;
michael@0 149 PRIntervalTime accountable, duration;
michael@0 150 PRUintn spaces = strlen(msg);
michael@0 151 PRIntervalTime timeout, timein = PR_IntervalNow();
michael@0 152 PRIntervalTime predicted = test(loops);
michael@0 153 timeout = PR_IntervalNow();
michael@0 154 duration = timeout - timein;
michael@0 155 accountable = duration - predicted;
michael@0 156 accountable -= overhead;
michael@0 157 elapsed = (PRFloat64)PR_IntervalToMicroseconds(accountable);
michael@0 158 if (debug_mode) printf("%s:", msg);
michael@0 159 while (spaces++ < 50) if (debug_mode) printf(" ");
michael@0 160 if ((PRInt32)accountable < 0) {
michael@0 161 if (debug_mode) printf("*****.** usecs/iteration\n");
michael@0 162 } else {
michael@0 163 if (debug_mode) printf("%8.2f usecs/iteration\n", elapsed/loops);
michael@0 164 }
michael@0 165 return duration;
michael@0 166 } /* Test */
michael@0 167
michael@0 168 int main(int argc, char **argv)
michael@0 169 {
michael@0 170 PRIntervalTime duration;
michael@0 171 PRUint32 cpu, cpus = 2;
michael@0 172 PRInt32 loops = 100;
michael@0 173
michael@0 174
michael@0 175 /* The command line argument: -d is used to determine if the test is being run
michael@0 176 in debug mode. The regress tool requires only one line output:PASS or FAIL.
michael@0 177 All of the printfs associated with this test has been handled with a if (debug_mode)
michael@0 178 test.
michael@0 179 Usage: test_name -d
michael@0 180 */
michael@0 181 PLOptStatus os;
michael@0 182 PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
michael@0 183 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
michael@0 184 {
michael@0 185 if (PL_OPT_BAD == os) continue;
michael@0 186 switch (opt->option)
michael@0 187 {
michael@0 188 case 'd': /* debug mode */
michael@0 189 debug_mode = 1;
michael@0 190 break;
michael@0 191 default:
michael@0 192 break;
michael@0 193 }
michael@0 194 }
michael@0 195 PL_DestroyOptState(opt);
michael@0 196
michael@0 197 /* main test */
michael@0 198
michael@0 199 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
michael@0 200 PR_STDIO_INIT();
michael@0 201
michael@0 202 if (argc > 1) loops = atoi(argv[1]);
michael@0 203 if (loops == 0) loops = 100;
michael@0 204 if (debug_mode) printf("Lock: Using %d loops\n", loops);
michael@0 205
michael@0 206 cpus = (argc < 3) ? 2 : atoi(argv[2]);
michael@0 207 if (cpus == 0) cpus = 2;
michael@0 208 if (debug_mode) printf("Lock: Using %d cpu(s)\n", cpus);
michael@0 209
michael@0 210
michael@0 211 for (cpu = 1; cpu <= cpus; ++cpu)
michael@0 212 {
michael@0 213 if (debug_mode) printf("\nLockFile: Using %d CPU(s)\n", cpu);
michael@0 214 PR_SetConcurrency(cpu);
michael@0 215
michael@0 216 duration = Test("LockFile non-contentious locking/unlocking", NonContentiousLock, loops, 0);
michael@0 217 (void)Test("LockFile contentious locking/unlocking", ContentiousLock, loops, duration);
michael@0 218 }
michael@0 219
michael@0 220 PR_Delete(LOCKFILE); /* try to get rid of evidence */
michael@0 221
michael@0 222 if (debug_mode) printf("%s: test %s\n", "Lock(mutex) test", ((failed_already) ? "failed" : "passed"));
michael@0 223 if(failed_already)
michael@0 224 return 1;
michael@0 225 else
michael@0 226 return 0;
michael@0 227 } /* main */
michael@0 228
michael@0 229 /* testlock.c */

mercurial