Wed, 31 Dec 2014 06:09:35 +0100
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, ¶ms[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 | } |