Back to index

lightning-sunbird  0.9+nobinonly
rwlocktest.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape Portable Runtime (NSPR).
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 
00038 /*
00039  *
00040  * RWLock tests
00041  *
00042  *     Several threads are created to access and modify data arrays using
00043  *     PRRWLocks for synchronization. Two data arrays, array_A and array_B, are
00044  *     initialized with random data and a third array, array_C, is initialized
00045  *     with the sum of the first 2 arrays.
00046  *
00047  *     Each one of the threads acquires a read lock to verify that the sum of
00048  *     the arrays A and B is equal to array C, and acquires a write lock to
00049  *     consistently update arrays A and B so that their is equal to array C.
00050  *            
00051  */
00052  
00053 #include "nspr.h"
00054 #include "plgetopt.h"
00055 #include "prrwlock.h"
00056 
00057 static int _debug_on;
00058 static void rwtest(void *args);
00059 static PRInt32 *array_A,*array_B,*array_C;
00060 static void update_array(void);
00061 static void check_array(void);
00062 
00063 typedef struct thread_args {
00064        PRRWLock      *rwlock;
00065        PRInt32              loop_cnt;
00066 } thread_args;
00067 
00068 PRFileDesc  *output;
00069 PRFileDesc  *errhandle;
00070 
00071 #define       DEFAULT_THREAD_CNT   4
00072 #define       DEFAULT_LOOP_CNT     100
00073 #define       TEST_ARRAY_SIZE             100
00074 
00075 PRIntn main(PRIntn argc, char **argv)
00076 {
00077     PRInt32 cnt;
00078        PRStatus rc;
00079        PRInt32 i;
00080 
00081        PRInt32 thread_cnt = DEFAULT_THREAD_CNT;
00082        PRInt32 loop_cnt = DEFAULT_LOOP_CNT;
00083        PRThread **threads;
00084        thread_args *params;
00085        PRRWLock      *rwlock1;
00086 
00087        PLOptStatus os;
00088        PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:");
00089 
00090        while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
00091     {
00092               if (PL_OPT_BAD == os) continue;
00093         switch (opt->option)
00094         {
00095         case 'd':  /* debug mode */
00096                      _debug_on = 1;
00097             break;
00098         case 't':  /* thread count */
00099             thread_cnt = atoi(opt->value);
00100             break;
00101         case 'c':  /* loop count */
00102             loop_cnt = atoi(opt->value);
00103             break;
00104          default:
00105             break;
00106         }
00107     }
00108        PL_DestroyOptState(opt);
00109 
00110        PR_SetConcurrency(4);
00111 
00112     output = PR_GetSpecialFD(PR_StandardOutput);
00113     errhandle = PR_GetSpecialFD(PR_StandardError);
00114 
00115        rwlock1 = PR_NewRWLock(0,"Lock 1");
00116        if (rwlock1 == NULL) {
00117               PR_fprintf(errhandle, "PR_NewRWLock failed - error %d\n",
00118                                                         PR_GetError());
00119               return 1;
00120        }
00121 
00122        threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * thread_cnt);
00123        params = (thread_args *) PR_CALLOC(sizeof(thread_args) * thread_cnt);
00124 
00125        /*
00126         * allocate and initialize data arrays
00127         */
00128        array_A =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
00129        array_B =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
00130        array_C =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
00131        cnt = 0;
00132        for (i=0; i < TEST_ARRAY_SIZE;i++) {
00133               array_A[i] = cnt++;
00134               array_B[i] = cnt++;
00135               array_C[i] = array_A[i] + array_B[i];
00136        }
00137 
00138        if (_debug_on)
00139               PR_fprintf(output,"%s: thread_cnt = %d loop_cnt = %d\n", argv[0],
00140                                                  thread_cnt, loop_cnt);
00141        for(cnt = 0; cnt < thread_cnt; cnt++) {
00142               PRThreadScope scope;
00143 
00144               params[cnt].rwlock = rwlock1;
00145               params[cnt].loop_cnt = loop_cnt;
00146 
00147               /*
00148                * create LOCAL and GLOBAL threads alternately
00149                */
00150               if (cnt & 1)
00151                      scope = PR_LOCAL_THREAD;
00152               else
00153                      scope = PR_GLOBAL_THREAD;
00154 
00155               threads[cnt] = PR_CreateThread(PR_USER_THREAD,
00156                                             rwtest, &params[cnt],
00157                                             PR_PRIORITY_NORMAL,
00158                                             scope,
00159                                             PR_JOINABLE_THREAD,
00160                                             0);
00161               if (threads[cnt] == NULL) {
00162                      PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n",
00163                                                         PR_GetError());
00164                      PR_ProcessExit(2);
00165               }
00166               if (_debug_on)
00167                      PR_fprintf(output,"%s: created thread = 0x%x\n", argv[0],
00168                                                                       threads[cnt]);
00169        }
00170 
00171        for(cnt = 0; cnt < thread_cnt; cnt++) {
00172        rc = PR_JoinThread(threads[cnt]);
00173               PR_ASSERT(rc == PR_SUCCESS);
00174 
00175        }
00176 
00177        PR_DELETE(threads);
00178        PR_DELETE(params);
00179 
00180        PR_DELETE(array_A);  
00181        PR_DELETE(array_B);  
00182        PR_DELETE(array_C);  
00183 
00184        PR_DestroyRWLock(rwlock1);
00185 
00186        
00187        printf("PASS\n");
00188        return 0;
00189 }
00190 
00191 static void rwtest(void *args)
00192 {
00193     PRInt32 index;
00194        thread_args *arg = (thread_args *) args;
00195 
00196 
00197        for (index = 0; index < arg->loop_cnt; index++) {
00198 
00199               /*
00200                * verify sum, update arrays and verify sum again
00201                */
00202 
00203               PR_RWLock_Rlock(arg->rwlock);
00204               check_array();
00205               PR_RWLock_Unlock(arg->rwlock);
00206 
00207               PR_RWLock_Wlock(arg->rwlock);
00208               update_array();
00209               PR_RWLock_Unlock(arg->rwlock);
00210 
00211               PR_RWLock_Rlock(arg->rwlock);
00212               check_array();
00213               PR_RWLock_Unlock(arg->rwlock);
00214        }
00215        if (_debug_on)
00216               PR_fprintf(output,
00217               "Thread[0x%x] lock = 0x%x exiting\n",
00218                             PR_GetCurrentThread(), arg->rwlock);
00219 
00220 }
00221 
00222 static void check_array(void)
00223 {
00224 PRInt32 i;
00225 
00226        for (i=0; i < TEST_ARRAY_SIZE;i++)
00227               if (array_C[i] != (array_A[i] + array_B[i])) {
00228                      PR_fprintf(output, "Error - data check failed\n");
00229                      PR_ProcessExit(1);
00230               }
00231 }
00232 
00233 static void update_array(void)
00234 {
00235 PRInt32 i;
00236 
00237        for (i=0; i < TEST_ARRAY_SIZE;i++) {
00238               array_A[i] += i;
00239               array_B[i] -= i;
00240        }
00241 }