Added another regression test.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8837
This commit is contained in:
Bart Van Assche
2008-12-17 19:21:17 +00:00
parent 66d69c2025
commit 8ca92c847d
4 changed files with 155 additions and 0 deletions

144
drd/tests/circular_buffer.c Normal file
View File

@@ -0,0 +1,144 @@
/* Test program that performs producer-consumer style communication through
* a circular buffer. This test program is a slightly modified version of the
* test program made available by Miguel Ojeda
* -- see also http://article.gmane.org/gmane.comp.debugging.valgrind/8782.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_MAX (2)
typedef int data_t;
typedef struct {
/* Counting semaphore representing the number of data items in the buffer. */
sem_t data;
/* Counting semaphore representing the number of free elements. */
sem_t free;
/* Position where a new elements should be written. */
size_t in;
/* Position from where an element can be removed. */
size_t out;
/* Mutex that protects 'in'. */
pthread_mutex_t mutex_in;
/* Mutex that protects 'out'. */
pthread_mutex_t mutex_out;
/* Data buffer. */
data_t buffer[BUFFER_MAX];
} buffer_t;
static int quiet = 0;
void buffer_init(buffer_t * b)
{
sem_init(&b->data, 0, 0);
sem_init(&b->free, 0, BUFFER_MAX);
pthread_mutex_init(&b->mutex_in, NULL);
pthread_mutex_init(&b->mutex_out, NULL);
b->in = 0;
b->out = 0;
}
void buffer_recv(buffer_t * b, data_t * d)
{
sem_wait(&b->data);
pthread_mutex_lock(&b->mutex_out);
memcpy(d, b->buffer + b->out, sizeof(data_t));
b->out = (b->out + 1) % BUFFER_MAX;
pthread_mutex_unlock(&b->mutex_out);
sem_post(&b->free);
}
void buffer_send(buffer_t * b, data_t * d)
{
sem_wait(&b->free);
pthread_mutex_lock(&b->mutex_in);
memcpy(b->buffer + b->in, d, sizeof(data_t));
b->in = (b->in + 1) % BUFFER_MAX;
pthread_mutex_unlock(&b->mutex_in);
sem_post(&b->data);
}
void buffer_destroy(buffer_t * b)
{
sem_destroy(&b->data);
sem_destroy(&b->free);
pthread_mutex_destroy(&b->mutex_in);
pthread_mutex_destroy(&b->mutex_out);
}
buffer_t b;
void producer(int* id)
{
buffer_send(&b, id);
pthread_exit(NULL);
}
#define MAXSLEEP (100 * 1000)
void consumer(int* id)
{
int d;
usleep(rand() % MAXSLEEP);
buffer_recv(&b, &d);
if (! quiet)
printf("%i: %i\n", *id, d);
pthread_exit(NULL);
}
#define THREADS (10)
int main(int argc, char** argv)
{
pthread_t producers[THREADS];
pthread_t consumers[THREADS];
int thread_arg[THREADS];
int i;
int optchar;
while ((optchar = getopt(argc, argv, "q")) != EOF)
{
switch (optchar)
{
case 'q':
quiet = 1;
break;
}
}
srand(time(NULL));
buffer_init(&b);
for (i = 0; i < THREADS; ++i)
{
thread_arg[i] = i;
pthread_create(producers + i, NULL,
(void * (*)(void *)) producer, &thread_arg[i]);
}
for (i = 0; i < THREADS; ++i)
pthread_create(consumers + i, NULL,
(void * (*)(void *)) consumer, &thread_arg[i]);
for (i = 0; i < THREADS; ++i)
{
pthread_join(producers[i], NULL);
pthread_join(consumers[i], NULL);
}
buffer_destroy(&b);
return 0;
}