nsprpub/pr/tests/rwlocktest.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5
michael@0 6 /*
michael@0 7 *
michael@0 8 * RWLock tests
michael@0 9 *
michael@0 10 * Several threads are created to access and modify data arrays using
michael@0 11 * PRRWLocks for synchronization. Two data arrays, array_A and array_B, are
michael@0 12 * initialized with random data and a third array, array_C, is initialized
michael@0 13 * with the sum of the first 2 arrays.
michael@0 14 *
michael@0 15 * Each one of the threads acquires a read lock to verify that the sum of
michael@0 16 * the arrays A and B is equal to array C, and acquires a write lock to
michael@0 17 * consistently update arrays A and B so that their is equal to array C.
michael@0 18 *
michael@0 19 */
michael@0 20
michael@0 21 #include "nspr.h"
michael@0 22 #include "plgetopt.h"
michael@0 23 #include "prrwlock.h"
michael@0 24
michael@0 25 static int _debug_on;
michael@0 26 static void rwtest(void *args);
michael@0 27 static PRInt32 *array_A,*array_B,*array_C;
michael@0 28 static void update_array(void);
michael@0 29 static void check_array(void);
michael@0 30
michael@0 31 typedef struct thread_args {
michael@0 32 PRRWLock *rwlock;
michael@0 33 PRInt32 loop_cnt;
michael@0 34 } thread_args;
michael@0 35
michael@0 36 PRFileDesc *output;
michael@0 37 PRFileDesc *errhandle;
michael@0 38
michael@0 39 #define DEFAULT_THREAD_CNT 4
michael@0 40 #define DEFAULT_LOOP_CNT 100
michael@0 41 #define TEST_ARRAY_SIZE 100
michael@0 42
michael@0 43 int main(int argc, char **argv)
michael@0 44 {
michael@0 45 PRInt32 cnt;
michael@0 46 PRStatus rc;
michael@0 47 PRInt32 i;
michael@0 48
michael@0 49 PRInt32 thread_cnt = DEFAULT_THREAD_CNT;
michael@0 50 PRInt32 loop_cnt = DEFAULT_LOOP_CNT;
michael@0 51 PRThread **threads;
michael@0 52 thread_args *params;
michael@0 53 PRRWLock *rwlock1;
michael@0 54
michael@0 55 PLOptStatus os;
michael@0 56 PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:");
michael@0 57
michael@0 58 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
michael@0 59 {
michael@0 60 if (PL_OPT_BAD == os) continue;
michael@0 61 switch (opt->option)
michael@0 62 {
michael@0 63 case 'd': /* debug mode */
michael@0 64 _debug_on = 1;
michael@0 65 break;
michael@0 66 case 't': /* thread count */
michael@0 67 thread_cnt = atoi(opt->value);
michael@0 68 break;
michael@0 69 case 'c': /* loop count */
michael@0 70 loop_cnt = atoi(opt->value);
michael@0 71 break;
michael@0 72 default:
michael@0 73 break;
michael@0 74 }
michael@0 75 }
michael@0 76 PL_DestroyOptState(opt);
michael@0 77
michael@0 78 PR_SetConcurrency(4);
michael@0 79
michael@0 80 output = PR_GetSpecialFD(PR_StandardOutput);
michael@0 81 errhandle = PR_GetSpecialFD(PR_StandardError);
michael@0 82
michael@0 83 rwlock1 = PR_NewRWLock(0,"Lock 1");
michael@0 84 if (rwlock1 == NULL) {
michael@0 85 PR_fprintf(errhandle, "PR_NewRWLock failed - error %d\n",
michael@0 86 PR_GetError());
michael@0 87 return 1;
michael@0 88 }
michael@0 89
michael@0 90 threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * thread_cnt);
michael@0 91 params = (thread_args *) PR_CALLOC(sizeof(thread_args) * thread_cnt);
michael@0 92
michael@0 93 /*
michael@0 94 * allocate and initialize data arrays
michael@0 95 */
michael@0 96 array_A =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
michael@0 97 array_B =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
michael@0 98 array_C =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
michael@0 99 cnt = 0;
michael@0 100 for (i=0; i < TEST_ARRAY_SIZE;i++) {
michael@0 101 array_A[i] = cnt++;
michael@0 102 array_B[i] = cnt++;
michael@0 103 array_C[i] = array_A[i] + array_B[i];
michael@0 104 }
michael@0 105
michael@0 106 if (_debug_on)
michael@0 107 PR_fprintf(output,"%s: thread_cnt = %d loop_cnt = %d\n", argv[0],
michael@0 108 thread_cnt, loop_cnt);
michael@0 109 for(cnt = 0; cnt < thread_cnt; cnt++) {
michael@0 110 PRThreadScope scope;
michael@0 111
michael@0 112 params[cnt].rwlock = rwlock1;
michael@0 113 params[cnt].loop_cnt = loop_cnt;
michael@0 114
michael@0 115 /*
michael@0 116 * create LOCAL and GLOBAL threads alternately
michael@0 117 */
michael@0 118 if (cnt & 1)
michael@0 119 scope = PR_LOCAL_THREAD;
michael@0 120 else
michael@0 121 scope = PR_GLOBAL_THREAD;
michael@0 122
michael@0 123 threads[cnt] = PR_CreateThread(PR_USER_THREAD,
michael@0 124 rwtest, &params[cnt],
michael@0 125 PR_PRIORITY_NORMAL,
michael@0 126 scope,
michael@0 127 PR_JOINABLE_THREAD,
michael@0 128 0);
michael@0 129 if (threads[cnt] == NULL) {
michael@0 130 PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n",
michael@0 131 PR_GetError());
michael@0 132 PR_ProcessExit(2);
michael@0 133 }
michael@0 134 if (_debug_on)
michael@0 135 PR_fprintf(output,"%s: created thread = %p\n", argv[0],
michael@0 136 threads[cnt]);
michael@0 137 }
michael@0 138
michael@0 139 for(cnt = 0; cnt < thread_cnt; cnt++) {
michael@0 140 rc = PR_JoinThread(threads[cnt]);
michael@0 141 PR_ASSERT(rc == PR_SUCCESS);
michael@0 142
michael@0 143 }
michael@0 144
michael@0 145 PR_DELETE(threads);
michael@0 146 PR_DELETE(params);
michael@0 147
michael@0 148 PR_DELETE(array_A);
michael@0 149 PR_DELETE(array_B);
michael@0 150 PR_DELETE(array_C);
michael@0 151
michael@0 152 PR_DestroyRWLock(rwlock1);
michael@0 153
michael@0 154
michael@0 155 printf("PASS\n");
michael@0 156 return 0;
michael@0 157 }
michael@0 158
michael@0 159 static void rwtest(void *args)
michael@0 160 {
michael@0 161 PRInt32 index;
michael@0 162 thread_args *arg = (thread_args *) args;
michael@0 163
michael@0 164
michael@0 165 for (index = 0; index < arg->loop_cnt; index++) {
michael@0 166
michael@0 167 /*
michael@0 168 * verify sum, update arrays and verify sum again
michael@0 169 */
michael@0 170
michael@0 171 PR_RWLock_Rlock(arg->rwlock);
michael@0 172 check_array();
michael@0 173 PR_RWLock_Unlock(arg->rwlock);
michael@0 174
michael@0 175 PR_RWLock_Wlock(arg->rwlock);
michael@0 176 update_array();
michael@0 177 PR_RWLock_Unlock(arg->rwlock);
michael@0 178
michael@0 179 PR_RWLock_Rlock(arg->rwlock);
michael@0 180 check_array();
michael@0 181 PR_RWLock_Unlock(arg->rwlock);
michael@0 182 }
michael@0 183 if (_debug_on)
michael@0 184 PR_fprintf(output,
michael@0 185 "Thread[0x%x] lock = 0x%x exiting\n",
michael@0 186 PR_GetCurrentThread(), arg->rwlock);
michael@0 187
michael@0 188 }
michael@0 189
michael@0 190 static void check_array(void)
michael@0 191 {
michael@0 192 PRInt32 i;
michael@0 193
michael@0 194 for (i=0; i < TEST_ARRAY_SIZE;i++)
michael@0 195 if (array_C[i] != (array_A[i] + array_B[i])) {
michael@0 196 PR_fprintf(output, "Error - data check failed\n");
michael@0 197 PR_ProcessExit(1);
michael@0 198 }
michael@0 199 }
michael@0 200
michael@0 201 static void update_array(void)
michael@0 202 {
michael@0 203 PRInt32 i;
michael@0 204
michael@0 205 for (i=0; i < TEST_ARRAY_SIZE;i++) {
michael@0 206 array_A[i] += i;
michael@0 207 array_B[i] -= i;
michael@0 208 }
michael@0 209 }

mercurial