mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-08 16:36:21 +00:00
185 lines
3.9 KiB
C
185 lines
3.9 KiB
C
/** Broadcast a (POSIX threads) signal to all running threads, where the
|
|
* number of threads can be specified on the command line. This test program
|
|
* is intended not only to test the correctness of drd but also to test
|
|
* whether performance does not degrade too much when the number of threads
|
|
* increases.
|
|
*/
|
|
|
|
|
|
#include <assert.h>
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
|
|
// Counting semaphore.
|
|
|
|
struct csema
|
|
{
|
|
pthread_mutex_t m_mutex;
|
|
pthread_cond_t m_cond;
|
|
int m_count;
|
|
};
|
|
|
|
void csema_ctr(struct csema* p)
|
|
{
|
|
memset(p, 0, sizeof(*p));
|
|
pthread_mutex_init(&p->m_mutex, 0);
|
|
pthread_cond_init(&p->m_cond, 0);
|
|
}
|
|
|
|
void csema_dtr(struct csema* p)
|
|
{
|
|
pthread_cond_destroy(&p->m_cond);
|
|
pthread_mutex_destroy(&p->m_mutex);
|
|
}
|
|
|
|
void csema_p(struct csema* p, const int n)
|
|
{
|
|
pthread_mutex_lock(&p->m_mutex);
|
|
while (p->m_count < n)
|
|
pthread_cond_wait(&p->m_cond, &p->m_mutex);
|
|
p->m_count -= n;
|
|
pthread_cond_signal(&p->m_cond);
|
|
pthread_mutex_unlock(&p->m_mutex);
|
|
}
|
|
|
|
void csema_v(struct csema* p)
|
|
{
|
|
pthread_mutex_lock(&p->m_mutex);
|
|
p->m_count++;
|
|
pthread_cond_signal(&p->m_cond);
|
|
pthread_mutex_unlock(&p->m_mutex);
|
|
}
|
|
|
|
|
|
struct cthread
|
|
{
|
|
pthread_t m_thread;
|
|
int m_threadnum;
|
|
struct csema* m_sema;
|
|
};
|
|
|
|
void cthread_ctr(struct cthread* p)
|
|
{
|
|
p->m_thread = 0;
|
|
p->m_sema = 0;
|
|
}
|
|
|
|
void cthread_dtr(struct cthread* p)
|
|
{ }
|
|
|
|
|
|
// Local variables.
|
|
|
|
static int s_debug = 0;
|
|
static int s_trace = 0;
|
|
static int s_signal_count;
|
|
static pthread_mutex_t s_mutex;
|
|
static pthread_cond_t s_cond;
|
|
|
|
|
|
// Function definitions.
|
|
|
|
static void thread_func(struct cthread* thread_info)
|
|
{
|
|
int i;
|
|
|
|
pthread_mutex_lock(&s_mutex);
|
|
|
|
for (i = 0; i < s_signal_count; i++)
|
|
{
|
|
if (s_trace)
|
|
{
|
|
printf("thread %d [%d] (1)\n", thread_info->m_threadnum, i);
|
|
}
|
|
csema_v(thread_info->m_sema);
|
|
|
|
// Wait until the main thread signals us via pthread_cond_broadcast().
|
|
pthread_cond_wait(&s_cond, &s_mutex);
|
|
if (s_trace)
|
|
{
|
|
printf("thread %d [%d] (2)\n", thread_info->m_threadnum, i);
|
|
}
|
|
}
|
|
|
|
pthread_mutex_unlock(&s_mutex);
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
int optchar;
|
|
int thread_count;
|
|
|
|
while ((optchar = getopt(argc, argv, "d")) != EOF)
|
|
{
|
|
switch (optchar)
|
|
{
|
|
case 'd':
|
|
s_debug = 1;
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* This test should complete in 15s or less. If the test does not complete */
|
|
/* within that time, abort the test via the signal SIGALRM. */
|
|
alarm(100);
|
|
|
|
s_signal_count = argc > optind ? atoi(argv[optind]) : 10;
|
|
thread_count = argc > optind + 1 ? atoi(argv[optind + 1]) : 10;
|
|
|
|
if (s_debug)
|
|
printf("&s_cond = %p\n", &s_cond);
|
|
|
|
pthread_mutex_init(&s_mutex, 0);
|
|
pthread_cond_init(&s_cond, 0);
|
|
{
|
|
int i;
|
|
struct csema sema;
|
|
struct cthread* p;
|
|
struct cthread* thread_vec;
|
|
|
|
csema_ctr(&sema);
|
|
thread_vec = malloc(sizeof(struct cthread) * thread_count);
|
|
for (p = thread_vec; p != thread_vec + thread_count; p++)
|
|
{
|
|
cthread_ctr(p);
|
|
p->m_threadnum = p - thread_vec;
|
|
p->m_sema = &sema;
|
|
pthread_create(&p->m_thread, 0,
|
|
(void*(*)(void*))thread_func, &*p);
|
|
}
|
|
for (i = 0; i < s_signal_count; i++)
|
|
{
|
|
if (s_trace)
|
|
printf("main [%d] (1)\n", i);
|
|
csema_p(&sema, thread_count);
|
|
if (s_trace)
|
|
printf("main [%d] (2)\n", i);
|
|
pthread_mutex_lock(&s_mutex);
|
|
pthread_cond_broadcast(&s_cond);
|
|
pthread_mutex_unlock(&s_mutex);
|
|
if (s_trace)
|
|
printf("main [%d] (3)\n", i);
|
|
}
|
|
for (i = 0; i < thread_count; i++)
|
|
{
|
|
pthread_join(thread_vec[i].m_thread, 0);
|
|
cthread_dtr(&thread_vec[i]);
|
|
}
|
|
free(thread_vec);
|
|
csema_dtr(&sema);
|
|
}
|
|
pthread_cond_destroy(&s_cond);
|
|
pthread_mutex_destroy(&s_mutex);
|
|
|
|
fprintf(stderr, "Done.\n");
|
|
|
|
return 0;
|
|
}
|