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/. */
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.
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.
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);
31 typedef struct thread_args
{
37 PRFileDesc
*errhandle
;
39 #define DEFAULT_THREAD_CNT 4
40 #define DEFAULT_LOOP_CNT 100
41 #define TEST_ARRAY_SIZE 100
43 int main(int argc
, char **argv
)
49 PRInt32 thread_cnt
= DEFAULT_THREAD_CNT
;
50 PRInt32 loop_cnt
= DEFAULT_LOOP_CNT
;
56 PLOptState
*opt
= PL_CreateOptState(argc
, argv
, "dt:c:");
58 while (PL_OPT_EOL
!= (os
= PL_GetNextOpt(opt
)))
60 if (PL_OPT_BAD
== os
) {
65 case 'd': /* debug mode */
68 case 't': /* thread count */
69 thread_cnt
= atoi(opt
->value
);
71 case 'c': /* loop count */
72 loop_cnt
= atoi(opt
->value
);
78 PL_DestroyOptState(opt
);
82 output
= PR_GetSpecialFD(PR_StandardOutput
);
83 errhandle
= PR_GetSpecialFD(PR_StandardError
);
85 rwlock1
= PR_NewRWLock(0,"Lock 1");
86 if (rwlock1
== NULL
) {
87 PR_fprintf(errhandle
, "PR_NewRWLock failed - error %d\n",
92 threads
= (PRThread
**) PR_CALLOC(sizeof(PRThread
*) * thread_cnt
);
93 params
= (thread_args
*) PR_CALLOC(sizeof(thread_args
) * thread_cnt
);
96 * allocate and initialize data arrays
98 array_A
=(PRInt32
*) PR_MALLOC(sizeof(PRInt32
) * TEST_ARRAY_SIZE
);
99 array_B
=(PRInt32
*) PR_MALLOC(sizeof(PRInt32
) * TEST_ARRAY_SIZE
);
100 array_C
=(PRInt32
*) PR_MALLOC(sizeof(PRInt32
) * TEST_ARRAY_SIZE
);
102 for (i
=0; i
< TEST_ARRAY_SIZE
; i
++) {
105 array_C
[i
] = array_A
[i
] + array_B
[i
];
109 PR_fprintf(output
,"%s: thread_cnt = %d loop_cnt = %d\n", argv
[0],
110 thread_cnt
, loop_cnt
);
111 for(cnt
= 0; cnt
< thread_cnt
; cnt
++) {
114 params
[cnt
].rwlock
= rwlock1
;
115 params
[cnt
].loop_cnt
= loop_cnt
;
118 * create LOCAL and GLOBAL threads alternately
121 scope
= PR_LOCAL_THREAD
;
124 scope
= PR_GLOBAL_THREAD
;
127 threads
[cnt
] = PR_CreateThread(PR_USER_THREAD
,
128 rwtest
, ¶ms
[cnt
],
133 if (threads
[cnt
] == NULL
) {
134 PR_fprintf(errhandle
, "PR_CreateThread failed - error %d\n",
139 PR_fprintf(output
,"%s: created thread = %p\n", argv
[0],
143 for(cnt
= 0; cnt
< thread_cnt
; cnt
++) {
144 rc
= PR_JoinThread(threads
[cnt
]);
145 PR_ASSERT(rc
== PR_SUCCESS
);
156 PR_DestroyRWLock(rwlock1
);
163 static void rwtest(void *args
)
166 thread_args
*arg
= (thread_args
*) args
;
169 for (index
= 0; index
< arg
->loop_cnt
; index
++) {
172 * verify sum, update arrays and verify sum again
175 PR_RWLock_Rlock(arg
->rwlock
);
177 PR_RWLock_Unlock(arg
->rwlock
);
179 PR_RWLock_Wlock(arg
->rwlock
);
181 PR_RWLock_Unlock(arg
->rwlock
);
183 PR_RWLock_Rlock(arg
->rwlock
);
185 PR_RWLock_Unlock(arg
->rwlock
);
189 "Thread[0x%x] lock = 0x%x exiting\n",
190 PR_GetCurrentThread(), arg
->rwlock
);
194 static void check_array(void)
198 for (i
=0; i
< TEST_ARRAY_SIZE
; i
++)
199 if (array_C
[i
] != (array_A
[i
] + array_B
[i
])) {
200 PR_fprintf(output
, "Error - data check failed\n");
205 static void update_array(void)
209 for (i
=0; i
< TEST_ARRAY_SIZE
; i
++) {