mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-08 08:26:14 +00:00
90 lines
2.6 KiB
C
90 lines
2.6 KiB
C
|
|
/* This program checks that Helgrind reports the five degenerate
|
|
uses of the barrier functions shown. */
|
|
#define _GNU_SOURCE
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
|
|
void* child1 ( void* arg )
|
|
{
|
|
pthread_barrier_wait( (pthread_barrier_t*)arg );
|
|
return NULL;
|
|
}
|
|
|
|
int main ( void )
|
|
{
|
|
pthread_barrier_t *bar1, *bar2, *bar3, *bar4, *bar5;
|
|
pthread_t thr1, thr2;
|
|
int r;
|
|
|
|
/* possibly set up a watchdog timer thread here. */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* initialise a barrier with a zero count */
|
|
fprintf(stderr, "\ninitialise a barrier with zero count\n");
|
|
bar1 = malloc(sizeof(pthread_barrier_t));
|
|
pthread_barrier_init(bar1, NULL, 0);
|
|
|
|
/* initialise a barrier twice */
|
|
fprintf(stderr, "\ninitialise a barrier twice\n");
|
|
bar2 = malloc(sizeof(pthread_barrier_t));
|
|
pthread_barrier_init(bar2, NULL, 1);
|
|
pthread_barrier_init(bar2, NULL, 1);
|
|
|
|
/* initialise a barrier which has threads waiting on it.
|
|
This isn't too simple. */
|
|
fprintf(stderr, "\ninitialise a barrier which has threads waiting on it\n");
|
|
bar3 = malloc(sizeof(pthread_barrier_t));
|
|
pthread_barrier_init(bar3, NULL, 2);
|
|
/* create a thread, whose only purpose is to block on the barrier */
|
|
pthread_create(&thr1, NULL, child1, (void*)bar3);
|
|
/* guarantee that it gets there first */
|
|
sleep(1);
|
|
/* and now reinitialise */
|
|
pthread_barrier_init(bar3, NULL, 3);
|
|
|
|
/* destroy a barrier that has threads waiting at it */
|
|
fprintf(stderr, "\ndestroy a barrier that has waiting threads\n");
|
|
/* once again, create a thread, whose only purpose is to block. */
|
|
bar4 = malloc(sizeof(pthread_barrier_t));
|
|
pthread_barrier_init(bar4, NULL, 2);
|
|
/* create a thread, whose only purpose is to block on the barrier */
|
|
pthread_create(&thr2, NULL, child1, (void*)bar4);
|
|
/* guarantee that it gets there first */
|
|
sleep(1);
|
|
/* and now destroy */
|
|
pthread_barrier_destroy(bar4);
|
|
|
|
/* destroy a barrier that was never initialised. This is a bit
|
|
tricky, in that we have to fill the barrier with bytes which
|
|
ensure that the pthread_barrier_destroy call doesn't hang for
|
|
some reason. Zero-fill seems to work ok on amd64-linux (glibc
|
|
2.8). */
|
|
fprintf(stderr, "\ndestroy a barrier that was never initialised\n");
|
|
bar5 = malloc(sizeof(pthread_barrier_t));
|
|
assert(bar5);
|
|
memset(bar5, 0, sizeof(*bar5));
|
|
pthread_barrier_destroy(bar5);
|
|
|
|
/* now we need to clean up the mess .. */
|
|
r= pthread_cancel(thr1); assert(!r);
|
|
r= pthread_cancel(thr2); assert(!r);
|
|
|
|
free(bar1); free(bar2); free(bar3); free(bar4); free(bar5);
|
|
|
|
return 0;
|
|
}
|