mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			117 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			117 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
| /* Quick stress test for proxy privatization.  */
 | |
| 
 | |
| /* We need to use a TM method that has to enforce privatization safety
 | |
|    explicitly.  */
 | |
| /* { dg-set-target-env-var ITM_DEFAULT_METHOD "ml_wt" } */
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <stdio.h>
 | |
| #include <pthread.h>
 | |
| 
 | |
| /* Make them likely to be mapped to different orecs.  */
 | |
| #define ALIGN __attribute__((aligned (256)))
 | |
| /* Don't make these static to work around PR 68591.  */
 | |
| int x ALIGN;
 | |
| int *ptr ALIGN;
 | |
| int *priv_ptr ALIGN;
 | |
| int priv_value ALIGN;
 | |
| int barrier ALIGN = 0;
 | |
| const int iters = 100;
 | |
| 
 | |
| static void arrive_and_wait (int expected_value)
 | |
| {
 | |
|   int now = __atomic_add_fetch (&barrier, 1, __ATOMIC_ACQ_REL);
 | |
|   while (now < expected_value)
 | |
|     __atomic_load (&barrier, &now, __ATOMIC_ACQUIRE);
 | |
| }
 | |
| 
 | |
| static void __attribute__((transaction_pure,noinline)) delay (int i)
 | |
| {
 | |
|   for (volatile int v = 0; v < i; v++);
 | |
| }
 | |
| 
 | |
| /* This tries to catch a case in which proxy privatization safety is not
 | |
|    ensured by privatization_user.  Specifically, it's access to the value
 | |
|    of it's transactional snapshot of ptr must read from an uncommitted write
 | |
|    by writer; thus, writer must still be active but must have read ptr before
 | |
|    proxy can privatize *ptr by assigning to ptr.
 | |
|    We try to make this interleaving more likely by delaying the commit of
 | |
|    writer and the start of proxy.  */
 | |
| static void *writer (void *dummy __attribute__((unused)))
 | |
| {
 | |
|   for (int i = 0; i < iters; i++)
 | |
|     {
 | |
|       /* Initialize state in each round.  */
 | |
|       x = 0;
 | |
|       ptr = &x;
 | |
|       priv_ptr = NULL;
 | |
|       int wrote = 1;
 | |
|       arrive_and_wait (i * 6 + 3);
 | |
|       /* Interference by another writer.  Has a conflict with the proxy
 | |
| 	 privatizer.  */
 | |
|       __transaction_atomic
 | |
| 	{
 | |
| 	  if (ptr != NULL)
 | |
| 	    *ptr = 1;
 | |
| 	  else
 | |
| 	    wrote = 0;
 | |
| 	  delay (2000000);
 | |
| 	}
 | |
|       arrive_and_wait (i * 6 + 6);
 | |
|       /* If the previous transaction committed first, wrote == 1 and x == 1;
 | |
| 	 otherwise, if the proxy came first, wrote == 0 and priv_value == 0.
 | |
|        */
 | |
|       if (wrote != priv_value)
 | |
| 	abort ();
 | |
|     }
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| static void *proxy (void *dummy __attribute__((unused)))
 | |
| {
 | |
|   for (int i = 0; i < iters; i++)
 | |
|     {
 | |
|       arrive_and_wait (i * 6 + 3);
 | |
|       delay(1000000);
 | |
|       __transaction_atomic
 | |
| 	{
 | |
| 	  /* Hand-off to privatization-user and its read-only transaction and
 | |
| 	     subsequent use of privatization.  */
 | |
| 	  priv_ptr = ptr;
 | |
| 	  ptr = NULL;
 | |
| 	}
 | |
|       arrive_and_wait (i * 6 + 6);
 | |
|     }
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| static void *privatization_user (void *dummy __attribute__((unused)))
 | |
| {
 | |
|   for (int i = 0; i < iters; i++)
 | |
|     {
 | |
|       arrive_and_wait (i * 6 + 3);
 | |
|       /* Spin until we have gotten a pointer from the proxy.  Then access
 | |
| 	 the value pointed to nontransactionally.  */
 | |
|       int *p = NULL;
 | |
|       while (p == NULL)
 | |
| 	__transaction_atomic { p = priv_ptr; }
 | |
|       priv_value = *p;
 | |
|       arrive_and_wait (i * 6 + 6);
 | |
|     }
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| int main()
 | |
| {
 | |
|   pthread_t p[3];
 | |
| 
 | |
|   pthread_create (p+0, NULL, writer, NULL);
 | |
|   pthread_create (p+1, NULL, proxy, NULL);
 | |
|   pthread_create (p+2, NULL, privatization_user, NULL);
 | |
| 
 | |
|   for (int i = 0; i < 3; ++i)
 | |
|     pthread_join  (p[i], NULL);
 | |
| 
 | |
|   return 0;
 | |
| }
 |