4 * @brief Multithreaded test program that triggers various access patterns
5 * without triggering any race conditions.
12 #include <limits.h> /* PTHREAD_STACK_MIN */
15 #include <stdlib.h> /* malloc() */
16 #include <string.h> /* strerror() */
17 #include <unistd.h> /* getopt() */
19 static int s_num_threads
= 10;
20 static int s_num_iterations
= 1000;
21 static pthread_mutex_t s_mutex
;
22 static long long s_grand_sum
; /* protected by s_mutex. */
23 static pthread_rwlock_t s_rwlock
;
24 static int s_counter
; /* protected by s_rwlock. */
26 static void* thread_func(void* arg
)
29 int sum1
= 0, sum2
= 0;
31 for (i
= s_num_iterations
; i
> 0; i
--)
33 r
= pthread_rwlock_rdlock(&s_rwlock
);
36 r
= pthread_rwlock_unlock(&s_rwlock
);
38 r
= pthread_rwlock_wrlock(&s_rwlock
);
41 r
= pthread_rwlock_unlock(&s_rwlock
);
45 pthread_mutex_lock(&s_mutex
);
47 pthread_mutex_unlock(&s_mutex
);
52 int main(int argc
, char** argv
)
61 long long expected_grand_sum
;
63 while ((optchar
= getopt(argc
, argv
, "i:t:")) != EOF
)
68 s_num_iterations
= atoi(optarg
);
71 s_num_threads
= atoi(optarg
);
74 fprintf(stderr
, "Error: unknown option '%c'.\n", optchar
);
79 pthread_mutex_init(&s_mutex
, NULL
);
80 pthread_rwlock_init(&s_rwlock
, NULL
);
82 pthread_attr_init(&attr
);
83 err
= pthread_attr_setstacksize(&attr
, PTHREAD_STACK_MIN
+ 4096);
86 tid
= calloc(s_num_threads
, sizeof(*tid
));
88 for (i
= 0; i
< s_num_threads
; i
++)
90 err
= pthread_create(&tid
[i
], &attr
, thread_func
, 0);
92 printf("failed to create thread %d: %s\n", i
, strerror(err
));
97 pthread_attr_destroy(&attr
);
99 for (i
= 0; i
< s_num_threads
; i
++)
102 pthread_join(tid
[i
], 0);
106 expected_counter
= threads_created
* s_num_iterations
;
107 fprintf(stderr
, "s_counter - expected_counter = %d\n",
108 s_counter
- expected_counter
);
109 expected_grand_sum
= 1ULL * expected_counter
* (expected_counter
- 1) / 2;
110 fprintf(stderr
, "s_grand_sum - expected_grand_sum = %lld\n",
111 s_grand_sum
- expected_grand_sum
);
112 fprintf(stderr
, "Finished.\n");