On Sun, 4 Jan 2015 11:04:34, Mike Stump wrote:

>
> Ah, even more curious. So, for testing, it would be best if we had a way to 
> synchronize the threads so that they reliably can show what you want to show, 
> and reliably pick which thread will run first and which second and so on. The 
> problem is of course, the synchronization primitives can’t get in the way (be 
> seen by) of normal tsan functioning. I’m thinking asm() can so obscure 
> arbitrary things, but I’m not sure I can’t think of a way to do that with 
> anything less. sleep is close, and, at least portable and simple. What it 
> isn’t is bullet proof. The tsan test cases would be enhanced if we could find 
> a way to synchronize the threads invisibly to tsan. I’d like to think that 
> someone can propose a better scheme than sleep. My thought would be something 
> like:
>
> int order = 0;
>
> void sync(int i) {
> while (++order != i) { /* atomic inc */
> --order; /* atomic dec */
> sleep(1); /* or some type of operative yield */
> }
> }
>
>
>
> thread 1:
> asm (“call sync(1)”);
> action1;
> asm (“call sync(3)”);
> action3;
>
> thread 2:
>
> asm (“call sync(2)”);
> action2;
>
> where the order executed would be action1, action2, action3. The asm hides 
> all details of the synchronization from everyone, optimizer, tsan.
>
> Now, why go to all this work? Simply, determinism in gcc and the test suite, 
> is, well, nice. I understand that user programs won’t be so nice, and that in 
> the wild, it won’t be 100%.

Hmm,,,,

that could work....

I would need a way to link the test case two helper functions, that are not 
compiled with -fsanitize=thread

like tsan-helper.C
void set(int * a , int b)
{
  *a = b;
}
int get(int *a)
{
  return *a;
}

uint64_t Global[2];
int z=0;
int get(int*);
void set(int*,int);

void *Thread1(void *x) {
  /* We have to sleep here, to make it somewhat easier for tsan to
     detect the race condition.  */
  while (get(&z) == 0);
  Global[1]++;
  return NULL;
}

void *Thread2(void *x) {
  char *p1 = reinterpret_cast<char *>(&Global[0]);
  struct __attribute__((packed, aligned(1))) u_uint64_t { uint64_t val; };
  u_uint64_t *p4 = reinterpret_cast<u_uint64_t *>(p1 + 1);
  (*p4).val++;
  set(&z,1);
  return NULL;
}


I tried, it and it works 10.000 times without one failure.

But I have no idea how to do that in our test framework.



Bernd.
                                          

Reply via email to