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 PRIntn
main(PRIntn 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
++) {