test_mutex2.c (4897B)
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/. */ 4 /* 5 * test_mutex2.c 6 * 7 * Tests multi-threaded functionality of Mutex 8 * 9 */ 10 11 #include "testutil.h" 12 #include "testutil_nss.h" 13 14 static int box1 = 0, box2 = 0, box3 = 0; 15 static PKIX_PL_Mutex *mutex; 16 static PRCondVar *cv; 17 static void *plContext = NULL; 18 19 static void 20 consumer(/* ARGSUSED */ void *arg) 21 { 22 PRStatus status = PR_SUCCESS; 23 PKIX_Error *errorResult; 24 int i = 0; 25 for (i = 0; i < 5; i++) { 26 (void)PKIX_PL_Mutex_Lock(mutex, plContext); 27 while (((box1 == 0) || 28 (box2 == 0) || 29 (box3 == 0)) && 30 (status == PR_SUCCESS)) 31 status = PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT); 32 33 (void)printf("\tConsumer got Box1 = %d ", box1); 34 box1 = 0; 35 (void)printf("Box2 = %d ", box2); 36 box2 = 0; 37 (void)printf("Box3 = %d\n", box3); 38 box3 = 0; 39 40 status = PR_NotifyAllCondVar(cv); 41 if (status == PR_FAILURE) 42 (void)printf("Consumer error while notifying condvar\n"); 43 errorResult = PKIX_PL_Mutex_Unlock(mutex, plContext); 44 if (errorResult) 45 testError("PKIX_PL_Mutex_Unlock failed"); 46 } 47 (void)printf("Consumer exiting...\n"); 48 } 49 50 static void 51 producer(void *arg) 52 { 53 PRStatus status = PR_SUCCESS; 54 int value = *(int *)arg; 55 int i = 0; 56 int *box; 57 PKIX_Error *errorResult; 58 if (value == 10) 59 box = &box1; 60 else if (value == 20) 61 box = &box2; 62 else if (value == 30) 63 box = &box3; 64 65 for (i = 0; i < 5; i++) { 66 (void)PKIX_PL_Mutex_Lock(mutex, plContext); 67 while ((*box != 0) && (status == PR_SUCCESS)) 68 status = PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT); 69 70 *box = i + 1; 71 (void)printf("\tProducer %d put value: %d\n", value, *box); 72 73 status = PR_NotifyAllCondVar(cv); 74 if (status == PR_FAILURE) 75 (void)printf("Producer %d error while notifying condvar\n", 76 value); 77 errorResult = PKIX_PL_Mutex_Unlock(mutex, plContext); 78 if (errorResult) 79 testError("PKIX_PL_Mutex_Unlock failed"); 80 } 81 } 82 83 int 84 test_mutex2(int argc, char *argv[]) 85 { 86 87 PRThread *consThread, *prodThread, *prodThread2, *prodThread3; 88 int x = 10, y = 20, z = 30; 89 PKIX_UInt32 actualMinorVersion; 90 PKIX_UInt32 j = 0; 91 92 PKIX_TEST_STD_VARS(); 93 94 startTests("Mutex and Threads"); 95 96 PKIX_TEST_EXPECT_NO_ERROR( 97 PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext)); 98 99 (void)printf("Attempting to create new mutex...\n"); 100 subTest("Mutex Creation"); 101 PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Create(&mutex, plContext)); 102 103 cv = PR_NewCondVar(*(PRLock **)mutex); 104 105 subTest("Starting consumer thread"); 106 consThread = PR_CreateThread(PR_USER_THREAD, 107 consumer, 108 NULL, 109 PR_PRIORITY_NORMAL, 110 PR_LOCAL_THREAD, 111 PR_JOINABLE_THREAD, 112 0); 113 114 subTest("Starting producer thread 1"); 115 prodThread = PR_CreateThread(PR_USER_THREAD, 116 producer, 117 &x, 118 PR_PRIORITY_NORMAL, 119 PR_LOCAL_THREAD, 120 PR_JOINABLE_THREAD, 121 0); 122 123 subTest("Starting producer thread 2"); 124 prodThread2 = PR_CreateThread(PR_USER_THREAD, 125 producer, 126 &y, 127 PR_PRIORITY_NORMAL, 128 PR_LOCAL_THREAD, 129 PR_JOINABLE_THREAD, 130 0); 131 132 subTest("Starting producer thread 3"); 133 prodThread3 = PR_CreateThread(PR_USER_THREAD, 134 producer, 135 &z, 136 PR_PRIORITY_NORMAL, 137 PR_LOCAL_THREAD, 138 PR_JOINABLE_THREAD, 139 0); 140 141 PR_JoinThread(consThread); 142 143 (void)PR_DestroyCondVar(cv); 144 PKIX_TEST_DECREF_BC(mutex); 145 146 /* 147 * Note: we should also be freeing each thread's stack, but we 148 * don't have access to the prodThread->stack variable (since 149 * it is not exported). As a result, we have 120 bytes of memory 150 * leakage. 151 */ 152 153 PR_Free(prodThread); 154 PR_Free(prodThread2); 155 PR_Free(prodThread3); 156 157 cleanup: 158 159 PKIX_Shutdown(plContext); 160 161 PKIX_TEST_RETURN(); 162 163 endTests("Mutex and Threads"); 164 165 return (0); 166 }