rwlocktest.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. *
  6. * RWLock tests
  7. *
  8. * Several threads are created to access and modify data arrays using
  9. * PRRWLocks for synchronization. Two data arrays, array_A and array_B, are
  10. * initialized with random data and a third array, array_C, is initialized
  11. * with the sum of the first 2 arrays.
  12. *
  13. * Each one of the threads acquires a read lock to verify that the sum of
  14. * the arrays A and B is equal to array C, and acquires a write lock to
  15. * consistently update arrays A and B so that their is equal to array C.
  16. *
  17. */
  18. #include "nspr.h"
  19. #include "plgetopt.h"
  20. #include "prrwlock.h"
  21. static int _debug_on;
  22. static void rwtest(void *args);
  23. static PRInt32 *array_A,*array_B,*array_C;
  24. static void update_array(void);
  25. static void check_array(void);
  26. typedef struct thread_args {
  27. PRRWLock *rwlock;
  28. PRInt32 loop_cnt;
  29. } thread_args;
  30. PRFileDesc *output;
  31. PRFileDesc *errhandle;
  32. #define DEFAULT_THREAD_CNT 4
  33. #define DEFAULT_LOOP_CNT 100
  34. #define TEST_ARRAY_SIZE 100
  35. int main(int argc, char **argv)
  36. {
  37. PRInt32 cnt;
  38. PRStatus rc;
  39. PRInt32 i;
  40. PRInt32 thread_cnt = DEFAULT_THREAD_CNT;
  41. PRInt32 loop_cnt = DEFAULT_LOOP_CNT;
  42. PRThread **threads;
  43. thread_args *params;
  44. PRRWLock *rwlock1;
  45. PLOptStatus os;
  46. PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:");
  47. while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
  48. {
  49. if (PL_OPT_BAD == os) {
  50. continue;
  51. }
  52. switch (opt->option)
  53. {
  54. case 'd': /* debug mode */
  55. _debug_on = 1;
  56. break;
  57. case 't': /* thread count */
  58. thread_cnt = atoi(opt->value);
  59. break;
  60. case 'c': /* loop count */
  61. loop_cnt = atoi(opt->value);
  62. break;
  63. default:
  64. break;
  65. }
  66. }
  67. PL_DestroyOptState(opt);
  68. PR_SetConcurrency(4);
  69. output = PR_GetSpecialFD(PR_StandardOutput);
  70. errhandle = PR_GetSpecialFD(PR_StandardError);
  71. rwlock1 = PR_NewRWLock(0,"Lock 1");
  72. if (rwlock1 == NULL) {
  73. PR_fprintf(errhandle, "PR_NewRWLock failed - error %d\n",
  74. PR_GetError());
  75. return 1;
  76. }
  77. threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * thread_cnt);
  78. params = (thread_args *) PR_CALLOC(sizeof(thread_args) * thread_cnt);
  79. /*
  80. * allocate and initialize data arrays
  81. */
  82. array_A =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
  83. array_B =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
  84. array_C =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
  85. cnt = 0;
  86. for (i=0; i < TEST_ARRAY_SIZE; i++) {
  87. array_A[i] = cnt++;
  88. array_B[i] = cnt++;
  89. array_C[i] = array_A[i] + array_B[i];
  90. }
  91. if (_debug_on)
  92. PR_fprintf(output,"%s: thread_cnt = %d loop_cnt = %d\n", argv[0],
  93. thread_cnt, loop_cnt);
  94. for(cnt = 0; cnt < thread_cnt; cnt++) {
  95. PRThreadScope scope;
  96. params[cnt].rwlock = rwlock1;
  97. params[cnt].loop_cnt = loop_cnt;
  98. /*
  99. * create LOCAL and GLOBAL threads alternately
  100. */
  101. if (cnt & 1) {
  102. scope = PR_LOCAL_THREAD;
  103. }
  104. else {
  105. scope = PR_GLOBAL_THREAD;
  106. }
  107. threads[cnt] = PR_CreateThread(PR_USER_THREAD,
  108. rwtest, &params[cnt],
  109. PR_PRIORITY_NORMAL,
  110. scope,
  111. PR_JOINABLE_THREAD,
  112. 0);
  113. if (threads[cnt] == NULL) {
  114. PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n",
  115. PR_GetError());
  116. PR_ProcessExit(2);
  117. }
  118. if (_debug_on)
  119. PR_fprintf(output,"%s: created thread = %p\n", argv[0],
  120. threads[cnt]);
  121. }
  122. for(cnt = 0; cnt < thread_cnt; cnt++) {
  123. rc = PR_JoinThread(threads[cnt]);
  124. PR_ASSERT(rc == PR_SUCCESS);
  125. }
  126. PR_DELETE(threads);
  127. PR_DELETE(params);
  128. PR_DELETE(array_A);
  129. PR_DELETE(array_B);
  130. PR_DELETE(array_C);
  131. PR_DestroyRWLock(rwlock1);
  132. printf("PASS\n");
  133. return 0;
  134. }
  135. static void rwtest(void *args)
  136. {
  137. PRInt32 index;
  138. thread_args *arg = (thread_args *) args;
  139. for (index = 0; index < arg->loop_cnt; index++) {
  140. /*
  141. * verify sum, update arrays and verify sum again
  142. */
  143. PR_RWLock_Rlock(arg->rwlock);
  144. check_array();
  145. PR_RWLock_Unlock(arg->rwlock);
  146. PR_RWLock_Wlock(arg->rwlock);
  147. update_array();
  148. PR_RWLock_Unlock(arg->rwlock);
  149. PR_RWLock_Rlock(arg->rwlock);
  150. check_array();
  151. PR_RWLock_Unlock(arg->rwlock);
  152. }
  153. if (_debug_on)
  154. PR_fprintf(output,
  155. "Thread[0x%x] lock = 0x%x exiting\n",
  156. PR_GetCurrentThread(), arg->rwlock);
  157. }
  158. static void check_array(void)
  159. {
  160. PRInt32 i;
  161. for (i=0; i < TEST_ARRAY_SIZE; i++)
  162. if (array_C[i] != (array_A[i] + array_B[i])) {
  163. PR_fprintf(output, "Error - data check failed\n");
  164. PR_ProcessExit(1);
  165. }
  166. }
  167. static void update_array(void)
  168. {
  169. PRInt32 i;
  170. for (i=0; i < TEST_ARRAY_SIZE; i++) {
  171. array_A[i] += i;
  172. array_B[i] -= i;
  173. }
  174. }