(root)/
gcc-13.2.0/
libitm/
testsuite/
libitm.c/
priv-1.c
       1  /* Quick stress test for proxy privatization.  */
       2  
       3  /* We need to use a TM method that has to enforce privatization safety
       4     explicitly.  */
       5  /* { dg-set-target-env-var ITM_DEFAULT_METHOD "ml_wt" } */
       6  
       7  #include <stdlib.h>
       8  #include <stdio.h>
       9  #include <pthread.h>
      10  
      11  /* Make them likely to be mapped to different orecs.  */
      12  #define ALIGN __attribute__((aligned (256)))
      13  /* Don't make these static to work around PR 68591.  */
      14  int x ALIGN;
      15  int *ptr ALIGN;
      16  int *priv_ptr ALIGN;
      17  int priv_value ALIGN;
      18  int barrier ALIGN = 0;
      19  const int iters = 100;
      20  
      21  static void arrive_and_wait (int expected_value)
      22  {
      23    int now = __atomic_add_fetch (&barrier, 1, __ATOMIC_ACQ_REL);
      24    while (now < expected_value)
      25      __atomic_load (&barrier, &now, __ATOMIC_ACQUIRE);
      26  }
      27  
      28  static void __attribute__((transaction_pure,noinline)) delay (int i)
      29  {
      30    for (volatile int v = 0; v < i; v++);
      31  }
      32  
      33  /* This tries to catch a case in which proxy privatization safety is not
      34     ensured by privatization_user.  Specifically, it's access to the value
      35     of it's transactional snapshot of ptr must read from an uncommitted write
      36     by writer; thus, writer must still be active but must have read ptr before
      37     proxy can privatize *ptr by assigning to ptr.
      38     We try to make this interleaving more likely by delaying the commit of
      39     writer and the start of proxy.  */
      40  static void *writer (void *dummy __attribute__((unused)))
      41  {
      42    for (int i = 0; i < iters; i++)
      43      {
      44        /* Initialize state in each round.  */
      45        x = 0;
      46        ptr = &x;
      47        priv_ptr = NULL;
      48        int wrote = 1;
      49        arrive_and_wait (i * 6 + 3);
      50        /* Interference by another writer.  Has a conflict with the proxy
      51  	 privatizer.  */
      52        __transaction_atomic
      53  	{
      54  	  if (ptr != NULL)
      55  	    *ptr = 1;
      56  	  else
      57  	    wrote = 0;
      58  	  delay (2000000);
      59  	}
      60        arrive_and_wait (i * 6 + 6);
      61        /* If the previous transaction committed first, wrote == 1 and x == 1;
      62  	 otherwise, if the proxy came first, wrote == 0 and priv_value == 0.
      63         */
      64        if (wrote != priv_value)
      65  	abort ();
      66      }
      67    return NULL;
      68  }
      69  
      70  static void *proxy (void *dummy __attribute__((unused)))
      71  {
      72    for (int i = 0; i < iters; i++)
      73      {
      74        arrive_and_wait (i * 6 + 3);
      75        delay(1000000);
      76        __transaction_atomic
      77  	{
      78  	  /* Hand-off to privatization-user and its read-only transaction and
      79  	     subsequent use of privatization.  */
      80  	  priv_ptr = ptr;
      81  	  ptr = NULL;
      82  	}
      83        arrive_and_wait (i * 6 + 6);
      84      }
      85    return NULL;
      86  }
      87  
      88  static void *privatization_user (void *dummy __attribute__((unused)))
      89  {
      90    for (int i = 0; i < iters; i++)
      91      {
      92        arrive_and_wait (i * 6 + 3);
      93        /* Spin until we have gotten a pointer from the proxy.  Then access
      94  	 the value pointed to nontransactionally.  */
      95        int *p = NULL;
      96        while (p == NULL)
      97  	__transaction_atomic { p = priv_ptr; }
      98        priv_value = *p;
      99        arrive_and_wait (i * 6 + 6);
     100      }
     101    return NULL;
     102  }
     103  
     104  int main()
     105  {
     106    pthread_t p[3];
     107  
     108    pthread_create (p+0, NULL, writer, NULL);
     109    pthread_create (p+1, NULL, proxy, NULL);
     110    pthread_create (p+2, NULL, privatization_user, NULL);
     111  
     112    for (int i = 0; i < 3; ++i)
     113      pthread_join  (p[i], NULL);
     114  
     115    return 0;
     116  }