This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RE: [PATCH] Fix sporadic failure in g++.dg/tsan/aligned_vs_unaligned_race.C


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.
 		 	   		  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]