• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** Broadcast a (POSIX threads) signal to all running threads, where the
2  *  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  */
7 
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 
19 struct csema
20 {
21   pthread_mutex_t  m_mutex;
22   pthread_cond_t   m_cond;
23   int              m_count;
24 };
25 
csema_ctr(struct csema * p)26 void 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 
csema_dtr(struct csema * p)33 void csema_dtr(struct csema* p)
34 {
35   pthread_cond_destroy(&p->m_cond);
36   pthread_mutex_destroy(&p->m_mutex);
37 }
38 
csema_p(struct csema * p,const int n)39 void 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 
csema_v(struct csema * p)49 void 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 
58 struct cthread
59 {
60   pthread_t     m_thread;
61   int           m_threadnum;
62   struct csema* m_sema;
63 };
64 
cthread_ctr(struct cthread * p)65 void cthread_ctr(struct cthread* p)
66 {
67   p->m_thread = 0;
68   p->m_sema   = 0;
69 }
70 
cthread_dtr(struct cthread * p)71 void cthread_dtr(struct cthread* p)
72 { }
73 
74 
75 // Local variables.
76 
77 static int s_debug = 0;
78 static int s_trace = 0;
79 static int s_signal_count;
80 static pthread_mutex_t s_mutex;
81 static pthread_cond_t  s_cond;
82 
83 
84 // Function definitions.
85 
thread_func(struct cthread * thread_info)86 static 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);
99 
100     // 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 
main(int argc,char ** argv)111 int 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   }
128 
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 
133   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);
180 
181   fprintf(stderr, "Done.\n");
182 
183   return 0;
184 }
185