blob: 5276a349d45ce92122fadaee476ba23f283f694b [file] [log] [blame]
bart31b983d2010-02-21 14:52:59 +00001/** Broadcast a (POSIX threads) signal to all running threads, where the
bart7d12b0c2008-03-03 17:37:24 +00002 * number of threads can be specified on the command line. This test program
3 * is intended not only to test the correctness of drd but also to test
4 * whether performance does not degrade too much when the number of threads
5 * increases.
6 */
sewardjc68cbe32007-11-27 01:59:38 +00007
8
9#include <assert.h>
10#include <pthread.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <unistd.h>
15
16
17// Counting semaphore.
18
19struct csema
20{
21 pthread_mutex_t m_mutex;
22 pthread_cond_t m_cond;
23 int m_count;
24};
25
26void csema_ctr(struct csema* p)
27{
28 memset(p, 0, sizeof(*p));
29 pthread_mutex_init(&p->m_mutex, 0);
30 pthread_cond_init(&p->m_cond, 0);
31}
32
33void csema_dtr(struct csema* p)
34{
35 pthread_cond_destroy(&p->m_cond);
36 pthread_mutex_destroy(&p->m_mutex);
37}
38
39void csema_p(struct csema* p, const int n)
40{
41 pthread_mutex_lock(&p->m_mutex);
42 while (p->m_count < n)
43 pthread_cond_wait(&p->m_cond, &p->m_mutex);
44 p->m_count -= n;
45 pthread_cond_signal(&p->m_cond);
46 pthread_mutex_unlock(&p->m_mutex);
47}
48
49void csema_v(struct csema* p)
50{
51 pthread_mutex_lock(&p->m_mutex);
52 p->m_count++;
53 pthread_cond_signal(&p->m_cond);
54 pthread_mutex_unlock(&p->m_mutex);
55}
56
57
58struct cthread
59{
60 pthread_t m_thread;
61 int m_threadnum;
62 struct csema* m_sema;
63};
64
65void cthread_ctr(struct cthread* p)
66{
67 p->m_thread = 0;
68 p->m_sema = 0;
69}
70
71void cthread_dtr(struct cthread* p)
72{ }
73
74
75// Local variables.
76
77static int s_debug = 0;
78static int s_trace = 0;
79static int s_signal_count;
80static pthread_mutex_t s_mutex;
81static pthread_cond_t s_cond;
82
83
84// Function definitions.
85
86static void thread_func(struct cthread* thread_info)
87{
88 int i;
89
90 pthread_mutex_lock(&s_mutex);
91
92 for (i = 0; i < s_signal_count; i++)
93 {
94 if (s_trace)
95 {
96 printf("thread %d [%d] (1)\n", thread_info->m_threadnum, i);
97 }
98 csema_v(thread_info->m_sema);
bart31b983d2010-02-21 14:52:59 +000099
sewardjc68cbe32007-11-27 01:59:38 +0000100 // Wait until the main thread signals us via pthread_cond_broadcast().
101 pthread_cond_wait(&s_cond, &s_mutex);
102 if (s_trace)
103 {
104 printf("thread %d [%d] (2)\n", thread_info->m_threadnum, i);
105 }
106 }
107
108 pthread_mutex_unlock(&s_mutex);
109}
110
111int main(int argc, char** argv)
112{
113 int optchar;
114 int thread_count;
115
116 while ((optchar = getopt(argc, argv, "d")) != EOF)
117 {
118 switch (optchar)
119 {
120 case 'd':
121 s_debug = 1;
122 break;
123 default:
124 assert(0);
125 break;
126 }
127 }
bart064d1fa2008-03-03 11:16:33 +0000128
129 /* This test should complete in 15s or less. If the test does not complete */
130 /* within that time, abort the test via the signal SIGALRM. */
131 alarm(100);
132
sewardjc68cbe32007-11-27 01:59:38 +0000133 s_signal_count = argc > optind ? atoi(argv[optind]) : 10;
134 thread_count = argc > optind + 1 ? atoi(argv[optind + 1]) : 10;
135
136 if (s_debug)
137 printf("&s_cond = %p\n", &s_cond);
138
139 pthread_mutex_init(&s_mutex, 0);
140 pthread_cond_init(&s_cond, 0);
141 {
142 int i;
143 struct csema sema;
144 struct cthread* p;
145 struct cthread* thread_vec;
146
147 csema_ctr(&sema);
148 thread_vec = malloc(sizeof(struct cthread) * thread_count);
149 for (p = thread_vec; p != thread_vec + thread_count; p++)
150 {
151 cthread_ctr(p);
152 p->m_threadnum = p - thread_vec;
153 p->m_sema = &sema;
154 pthread_create(&p->m_thread, 0,
155 (void*(*)(void*))thread_func, &*p);
156 }
157 for (i = 0; i < s_signal_count; i++)
158 {
159 if (s_trace)
160 printf("main [%d] (1)\n", i);
161 csema_p(&sema, thread_count);
162 if (s_trace)
163 printf("main [%d] (2)\n", i);
164 pthread_mutex_lock(&s_mutex);
165 pthread_cond_broadcast(&s_cond);
166 pthread_mutex_unlock(&s_mutex);
167 if (s_trace)
168 printf("main [%d] (3)\n", i);
169 }
170 for (i = 0; i < thread_count; i++)
171 {
172 pthread_join(thread_vec[i].m_thread, 0);
173 cthread_dtr(&thread_vec[i]);
174 }
175 free(thread_vec);
176 csema_dtr(&sema);
177 }
178 pthread_cond_destroy(&s_cond);
179 pthread_mutex_destroy(&s_mutex);
bart7d12b0c2008-03-03 17:37:24 +0000180
181 fprintf(stderr, "Done.\n");
182
sewardjc68cbe32007-11-27 01:59:38 +0000183 return 0;
184}