1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape Portable Runtime (NSPR).
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1998-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
42 * Several threads are created to access and modify data arrays using
43 * PRRWLocks for synchronization. Two data arrays, array_A and array_B, are
44 * initialized with random data and a third array, array_C, is initialized
45 * with the sum of the first 2 arrays.
47 * Each one of the threads acquires a read lock to verify that the sum of
48 * the arrays A and B is equal to array C, and acquires a write lock to
49 * consistently update arrays A and B so that their is equal to array C.
58 static void rwtest(void *args);
59 static PRInt32 *array_A,*array_B,*array_C;
60 static void update_array(void);
61 static void check_array(void);
63 typedef struct thread_args {
69 PRFileDesc *errhandle;
71 #define DEFAULT_THREAD_CNT 4
72 #define DEFAULT_LOOP_CNT 100
73 #define TEST_ARRAY_SIZE 100
75 int main(int argc, char **argv)
81 PRInt32 thread_cnt = DEFAULT_THREAD_CNT;
82 PRInt32 loop_cnt = DEFAULT_LOOP_CNT;
88 PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:");
90 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
92 if (PL_OPT_BAD == os) continue;
95 case 'd': /* debug mode */
98 case 't': /* thread count */
99 thread_cnt = atoi(opt->value);
101 case 'c': /* loop count */
102 loop_cnt = atoi(opt->value);
108 PL_DestroyOptState(opt);
110 PR_SetConcurrency(4);
112 output = PR_GetSpecialFD(PR_StandardOutput);
113 errhandle = PR_GetSpecialFD(PR_StandardError);
115 rwlock1 = PR_NewRWLock(0,"Lock 1");
116 if (rwlock1 == NULL) {
117 PR_fprintf(errhandle, "PR_NewRWLock failed - error %d\n",
122 threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * thread_cnt);
123 params = (thread_args *) PR_CALLOC(sizeof(thread_args) * thread_cnt);
126 * allocate and initialize data arrays
128 array_A =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
129 array_B =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
130 array_C =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
132 for (i=0; i < TEST_ARRAY_SIZE;i++) {
135 array_C[i] = array_A[i] + array_B[i];
139 PR_fprintf(output,"%s: thread_cnt = %d loop_cnt = %d\n", argv[0],
140 thread_cnt, loop_cnt);
141 for(cnt = 0; cnt < thread_cnt; cnt++) {
144 params[cnt].rwlock = rwlock1;
145 params[cnt].loop_cnt = loop_cnt;
148 * create LOCAL and GLOBAL threads alternately
151 scope = PR_LOCAL_THREAD;
153 scope = PR_GLOBAL_THREAD;
155 threads[cnt] = PR_CreateThread(PR_USER_THREAD,
156 rwtest, ¶ms[cnt],
161 if (threads[cnt] == NULL) {
162 PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n",
167 PR_fprintf(output,"%s: created thread = 0x%x\n", argv[0],
171 for(cnt = 0; cnt < thread_cnt; cnt++) {
172 rc = PR_JoinThread(threads[cnt]);
173 PR_ASSERT(rc == PR_SUCCESS);
184 PR_DestroyRWLock(rwlock1);
191 static void rwtest(void *args)
194 thread_args *arg = (thread_args *) args;
197 for (index = 0; index < arg->loop_cnt; index++) {
200 * verify sum, update arrays and verify sum again
203 PR_RWLock_Rlock(arg->rwlock);
205 PR_RWLock_Unlock(arg->rwlock);
207 PR_RWLock_Wlock(arg->rwlock);
209 PR_RWLock_Unlock(arg->rwlock);
211 PR_RWLock_Rlock(arg->rwlock);
213 PR_RWLock_Unlock(arg->rwlock);
217 "Thread[0x%x] lock = 0x%x exiting\n",
218 PR_GetCurrentThread(), arg->rwlock);
222 static void check_array(void)
226 for (i=0; i < TEST_ARRAY_SIZE;i++)
227 if (array_C[i] != (array_A[i] + array_B[i])) {
228 PR_fprintf(output, "Error - data check failed\n");
233 static void update_array(void)
237 for (i=0; i < TEST_ARRAY_SIZE;i++) {