2012-01-05 15:14:29 +01:00
|
|
|
/* { dg-do run } */
|
2011-11-10 18:15:33 +01:00
|
|
|
/* { dg-options "-pthread" } */
|
2011-11-08 12:13:41 +01:00
|
|
|
|
|
|
|
/* Tests that new transactions can be started from both transaction_pure and
|
|
|
|
transaction_unsafe code. This also requires proper handling of reentrant
|
|
|
|
nesting in the serial_lock implementation. */
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <libitm.h>
|
|
|
|
|
|
|
|
int x = 0;
|
|
|
|
|
|
|
|
int __attribute__((transaction_pure)) pure(int i)
|
|
|
|
{
|
|
|
|
__transaction_atomic {
|
|
|
|
x++;
|
|
|
|
}
|
|
|
|
if (_ITM_inTransaction() == outsideTransaction)
|
|
|
|
abort();
|
|
|
|
return i+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int __attribute__((transaction_unsafe)) unsafe(int i)
|
|
|
|
{
|
|
|
|
if (_ITM_inTransaction() != inIrrevocableTransaction)
|
|
|
|
abort();
|
|
|
|
__transaction_atomic {
|
|
|
|
x++;
|
|
|
|
}
|
|
|
|
if (_ITM_inTransaction() != inIrrevocableTransaction)
|
|
|
|
abort();
|
|
|
|
return i+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *thread (void *dummy __attribute__((unused)))
|
|
|
|
{
|
|
|
|
__transaction_atomic {
|
2012-01-05 15:14:29 +01:00
|
|
|
pure(x);
|
2011-11-08 12:13:41 +01:00
|
|
|
}
|
|
|
|
__transaction_relaxed {
|
|
|
|
unsafe(1);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
pthread_t pt;
|
|
|
|
int r = 0;
|
|
|
|
|
|
|
|
__transaction_atomic {
|
|
|
|
r += pure(1) + x;
|
|
|
|
}
|
|
|
|
__transaction_relaxed {
|
|
|
|
r += unsafe(1) + x;
|
|
|
|
}
|
|
|
|
if (r != 7)
|
|
|
|
abort();
|
|
|
|
|
|
|
|
// Spawn a new thread to check that the serial lock is not held.
|
|
|
|
pthread_create(&pt, NULL, thread, NULL);
|
|
|
|
pthread_join(pt, NULL);
|
|
|
|
if (x != 4)
|
|
|
|
abort();
|
|
|
|
return 0;
|
|
|
|
}
|