nsprpub/pr/tests/lockfile.c

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

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

mercurial