|
From: Konstantin S. <kon...@gm...> - 2010-01-28 19:17:41
|
ahhh.
I again forgot that pthread_barrier is cyclic (resettable).
imho this is error prone and dull, but that's what we have.
I think we will need two annotations to fully support it:
// inserted before the actual barrier_init code
ANNOTATE_CYCLIC_BARRIER_INIT(obj, n)
// inserted before the actual barrier_wait code.
ANNOTATE_CYCLIC_BARRIER_WAIT(obj)
I'll give it a bite on Fri or Mon.
--kcc
On Thu, Jan 28, 2010 at 8:45 PM, Julian Seward <js...@ac...> wrote:
> On Thursday 28 January 2010, Julian Seward wrote:
> > > Yeaaa.
> > > Still, I want a unit test were the current implementation hides a race.
> > > W/o a unittest, how do we test that the new implementation is correct
> (or
> > > at least better)?
> >
> > Fair enough.
> >
> > Something like this [...]
>
> Demo program using libpthread is below.
>
> Helgrind(trunk) says
>
> ==15851== Possible data race during write of size 4 at 0x601060 by thread
> #4
> ==15851== at 0x4007D8: actions_b1 (pthb_reuse_race.c:34)
> ==15851== by 0x4C29752: mythread_wrapper (hg_intercepts.c:202)
> ==15851== by 0x4E3403F: start_thread (in /lib64/libpthread-2.8.so)
> ==15851== by 0x511C08C: clone (in /lib64/libc-2.8.so)
> ==15851== This conflicts with a previous write of size 4 by thread #2
> ==15851== at 0x400812: actions_a1 (pthb_reuse_race.c:19)
> ==15851== by 0x4C29752: mythread_wrapper (hg_intercepts.c:202)
> ==15851== by 0x4E3403F: start_thread (in /lib64/libpthread-2.8.so)
> ==15851== by 0x511C08C: clone (in /lib64/libc-2.8.so)
>
> DRD(trunk) doesn't say anything.
>
> TSan also doesn't say anything.
>
> J
>
>
>
> #define _GNU_SOURCE
>
> #include <assert.h>
> #include <pthread.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
>
> /* Shared location, accessed by A1 (or A2) and B1 (or B2) */
> int L;
>
> /* The barrier, size 2 */
> pthread_barrier_t B;
>
>
> // A1/A2: write L, then wait for barrier, then sleep
> void* actions_a1 ( void* v ) {
> L = 1;
> pthread_barrier_wait(&B);
> sleep(1);
> return NULL;
> }
> void* actions_a2 ( void* v ) {
> pthread_barrier_wait(&B);
> sleep(1);
> return NULL;
> }
>
> // B1/B2: sleep, wait for barrier, then write L
> void* actions_b1 ( void* v ) {
> sleep(1);
> pthread_barrier_wait(&B);
> L = 1;
> return NULL;
> }
> void* actions_b2 ( void* v ) {
> sleep(1);
> pthread_barrier_wait(&B);
> return NULL;
> }
>
>
> int main ( void )
> {
> pthread_t a1, a2, b1, b2;
> pthread_barrier_init(&B, NULL, 2);
>
> pthread_create(&a1, NULL, actions_a1, NULL);
> pthread_create(&a2, NULL, actions_a2, NULL);
> pthread_create(&b1, NULL, actions_b1, NULL);
> pthread_create(&b2, NULL, actions_b2, NULL);
>
> pthread_join(a1, NULL);
> pthread_join(a2, NULL);
> pthread_join(b1, NULL);
> pthread_join(b2, NULL);
>
> return 0;
> }
>
|