Upload Tizen:Base source
[toolchains/nspr.git] / mozilla / nsprpub / pr / tests / rwlocktest.c
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
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/
8  *
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
12  * License.
13  *
14  * The Original Code is the Netscape Portable Runtime (NSPR).
15  *
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.
20  *
21  * Contributor(s):
22  *
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.
34  *
35  * ***** END LICENSE BLOCK ***** */
36
37
38 /*
39  *
40  * RWLock tests
41  *
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.
46  *
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.
50  *              
51  */
52  
53 #include "nspr.h"
54 #include "plgetopt.h"
55 #include "prrwlock.h"
56
57 static int _debug_on;
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);
62
63 typedef struct thread_args {
64         PRRWLock        *rwlock;
65         PRInt32         loop_cnt;
66 } thread_args;
67
68 PRFileDesc  *output;
69 PRFileDesc  *errhandle;
70
71 #define DEFAULT_THREAD_CNT      4
72 #define DEFAULT_LOOP_CNT        100
73 #define TEST_ARRAY_SIZE         100
74
75 int main(int argc, char **argv)
76 {
77     PRInt32 cnt;
78         PRStatus rc;
79         PRInt32 i;
80
81         PRInt32 thread_cnt = DEFAULT_THREAD_CNT;
82         PRInt32 loop_cnt = DEFAULT_LOOP_CNT;
83         PRThread **threads;
84         thread_args *params;
85         PRRWLock        *rwlock1;
86
87         PLOptStatus os;
88         PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:");
89
90         while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
91     {
92                 if (PL_OPT_BAD == os) continue;
93         switch (opt->option)
94         {
95         case 'd':  /* debug mode */
96                         _debug_on = 1;
97             break;
98         case 't':  /* thread count */
99             thread_cnt = atoi(opt->value);
100             break;
101         case 'c':  /* loop count */
102             loop_cnt = atoi(opt->value);
103             break;
104          default:
105             break;
106         }
107     }
108         PL_DestroyOptState(opt);
109
110         PR_SetConcurrency(4);
111
112     output = PR_GetSpecialFD(PR_StandardOutput);
113     errhandle = PR_GetSpecialFD(PR_StandardError);
114
115         rwlock1 = PR_NewRWLock(0,"Lock 1");
116         if (rwlock1 == NULL) {
117                 PR_fprintf(errhandle, "PR_NewRWLock failed - error %d\n",
118                                                                 PR_GetError());
119                 return 1;
120         }
121
122         threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * thread_cnt);
123         params = (thread_args *) PR_CALLOC(sizeof(thread_args) * thread_cnt);
124
125         /*
126          * allocate and initialize data arrays
127          */
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);
131         cnt = 0;
132         for (i=0; i < TEST_ARRAY_SIZE;i++) {
133                 array_A[i] = cnt++;
134                 array_B[i] = cnt++;
135                 array_C[i] = array_A[i] + array_B[i];
136         }
137
138         if (_debug_on)
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++) {
142                 PRThreadScope scope;
143
144                 params[cnt].rwlock = rwlock1;
145                 params[cnt].loop_cnt = loop_cnt;
146
147                 /*
148                  * create LOCAL and GLOBAL threads alternately
149                  */
150                 if (cnt & 1)
151                         scope = PR_LOCAL_THREAD;
152                 else
153                         scope = PR_GLOBAL_THREAD;
154
155                 threads[cnt] = PR_CreateThread(PR_USER_THREAD,
156                                                   rwtest, &params[cnt],
157                                                   PR_PRIORITY_NORMAL,
158                                                   scope,
159                                                   PR_JOINABLE_THREAD,
160                                                   0);
161                 if (threads[cnt] == NULL) {
162                         PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n",
163                                                                 PR_GetError());
164                         PR_ProcessExit(2);
165                 }
166                 if (_debug_on)
167                         PR_fprintf(output,"%s: created thread = 0x%x\n", argv[0],
168                                                                                 threads[cnt]);
169         }
170
171         for(cnt = 0; cnt < thread_cnt; cnt++) {
172         rc = PR_JoinThread(threads[cnt]);
173                 PR_ASSERT(rc == PR_SUCCESS);
174
175         }
176
177         PR_DELETE(threads);
178         PR_DELETE(params);
179
180         PR_DELETE(array_A);     
181         PR_DELETE(array_B);     
182         PR_DELETE(array_C);     
183
184         PR_DestroyRWLock(rwlock1);
185
186         
187         printf("PASS\n");
188         return 0;
189 }
190
191 static void rwtest(void *args)
192 {
193     PRInt32 index;
194         thread_args *arg = (thread_args *) args;
195
196
197         for (index = 0; index < arg->loop_cnt; index++) {
198
199                 /*
200                  * verify sum, update arrays and verify sum again
201                  */
202
203                 PR_RWLock_Rlock(arg->rwlock);
204                 check_array();
205                 PR_RWLock_Unlock(arg->rwlock);
206
207                 PR_RWLock_Wlock(arg->rwlock);
208                 update_array();
209                 PR_RWLock_Unlock(arg->rwlock);
210
211                 PR_RWLock_Rlock(arg->rwlock);
212                 check_array();
213                 PR_RWLock_Unlock(arg->rwlock);
214         }
215         if (_debug_on)
216                 PR_fprintf(output,
217                 "Thread[0x%x] lock = 0x%x exiting\n",
218                                 PR_GetCurrentThread(), arg->rwlock);
219
220 }
221
222 static void check_array(void)
223 {
224 PRInt32 i;
225
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");
229                         PR_ProcessExit(1);
230                 }
231 }
232
233 static void update_array(void)
234 {
235 PRInt32 i;
236
237         for (i=0; i < TEST_ARRAY_SIZE;i++) {
238                 array_A[i] += i;
239                 array_B[i] -= i;
240         }
241 }