rwlock7.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * rwlock7.c
  3. *
  4. * Hammer on a bunch of rwlocks to test robustness and fairness.
  5. * Printed stats should be roughly even for each thread.
  6. */
  7. #include "test.h"
  8. #ifdef __GNUC__
  9. #include <stdlib.h>
  10. #endif
  11. #define THREADS 5
  12. #define DATASIZE 7
  13. #define ITERATIONS 100000
  14. /*
  15. * Keep statistics for each thread.
  16. */
  17. typedef struct thread_tag
  18. {
  19. int thread_num;
  20. pthread_t thread_id;
  21. int updates;
  22. int reads;
  23. int changed;
  24. unsigned int seed;
  25. } thread_t;
  26. /*
  27. * Read-write lock and shared data
  28. */
  29. typedef struct data_tag
  30. {
  31. pthread_rwlock_t lock;
  32. int data;
  33. int updates;
  34. } data_t;
  35. static thread_t threads[THREADS];
  36. static data_t data[DATASIZE];
  37. /*
  38. * Thread start routine that uses read-write locks
  39. */
  40. static void *thread_routine (void *arg)
  41. {
  42. thread_t *self = (thread_t*)arg;
  43. int iteration;
  44. int element = 0;
  45. int interval = 1 + rand() % 71;
  46. self->changed = 0;
  47. for (iteration = 0; iteration < ITERATIONS; iteration++)
  48. {
  49. /*
  50. if (iteration % (ITERATIONS / 10) == 0)
  51. {
  52. putchar('.');
  53. fflush(stdout);
  54. }
  55. */
  56. /*
  57. * Each "self->interval" iterations, perform an
  58. * update operation (write lock instead of read
  59. * lock).
  60. */
  61. if ((iteration % interval) == 0)
  62. {
  63. assert(pthread_rwlock_wrlock (&data[element].lock) == 0);
  64. data[element].data = self->thread_num;
  65. data[element].updates++;
  66. self->updates++;
  67. interval = 1 + rand () % 71;
  68. assert(pthread_rwlock_unlock (&data[element].lock) == 0);
  69. }
  70. else
  71. {
  72. /*
  73. * Look at the current data element to see whether
  74. * the current thread last updated it. Count the
  75. * times, to report later.
  76. */
  77. assert(pthread_rwlock_rdlock (&data[element].lock) == 0);
  78. self->reads++;
  79. if (data[element].data != self->thread_num)
  80. {
  81. self->changed++;
  82. interval = 1 + self->changed % 71;
  83. }
  84. assert(pthread_rwlock_unlock (&data[element].lock) == 0);
  85. }
  86. element = (element + 1) % DATASIZE;
  87. }
  88. return NULL;
  89. }
  90. int pthread_test_rwlock7()
  91. {
  92. int count;
  93. int data_count;
  94. int thread_updates = 0;
  95. int data_updates = 0;
  96. struct _timeb currSysTime1;
  97. struct _timeb currSysTime2;
  98. /*
  99. * Initialize the shared data.
  100. */
  101. for (data_count = 0; data_count < DATASIZE; data_count++)
  102. {
  103. data[data_count].data = 0;
  104. data[data_count].updates = 0;
  105. assert(pthread_rwlock_init (&data[data_count].lock, NULL) == 0);
  106. }
  107. _ftime(&currSysTime1);
  108. /*
  109. * Create THREADS threads to access shared data.
  110. */
  111. for (count = 0; count < THREADS; count++)
  112. {
  113. threads[count].thread_num = count;
  114. threads[count].updates = 0;
  115. threads[count].reads = 0;
  116. threads[count].seed = 1 + rand() % 71;
  117. assert(pthread_create (&threads[count].thread_id,
  118. NULL, thread_routine, (void*)&threads[count]) == 0);
  119. }
  120. /*
  121. * Wait for all threads to complete, and collect
  122. * statistics.
  123. */
  124. for (count = 0; count < THREADS; count++)
  125. {
  126. assert(pthread_join (threads[count].thread_id, NULL) == 0);
  127. }
  128. /*
  129. putchar('\n');
  130. fflush(stdout);
  131. */
  132. for (count = 0; count < THREADS; count++)
  133. {
  134. }
  135. /*
  136. putchar('\n');
  137. fflush(stdout);
  138. */
  139. for (count = 0; count < THREADS; count++)
  140. {
  141. thread_updates += threads[count].updates;
  142. }
  143. /*
  144. putchar('\n');
  145. fflush(stdout);
  146. */
  147. /*
  148. * Collect statistics for the data.
  149. */
  150. for (data_count = 0; data_count < DATASIZE; data_count++)
  151. {
  152. data_updates += data[data_count].updates;
  153. assert(pthread_rwlock_destroy (&data[data_count].lock) == 0);
  154. }
  155. _ftime(&currSysTime2);
  156. return 0;
  157. }