pth_broadcast.c revision e739ac0589b4fb43561f801c4faba8c1b89f8680
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 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); 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 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 } 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