nsprpub/pr/tests/rwlocktest.c

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

mercurial