int
__cxa_guard_acquire (__guard *g)
{
if
(_GLIBCXX_GUARD_TEST_AND_ACQUIRE (g))
return
0;
if
(__gnu_cxx::__is_single_threaded())
{
int
*gi = (
int
*) (
void
*) g;
if
(*gi == 0)
{
*gi = _GLIBCXX_GUARD_PENDING_BIT;
return
1;
}
else
{
throw_recursive_init_exception();
}
}
else
{
int
*gi = (
int
*) (
void
*) g;
const
int
guard_bit = _GLIBCXX_GUARD_BIT;
const
int
pending_bit = _GLIBCXX_GUARD_PENDING_BIT;
const
int
waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
while
(1)
{
int
expected(0);
if
(__atomic_compare_exchange_n(gi, &expected, pending_bit,
false
,
__ATOMIC_ACQ_REL,
__ATOMIC_ACQUIRE))
{
return
1;
}
if
(expected == guard_bit)
{
return
0;
}
if
(expected == pending_bit)
{
int
newv = expected | waiting_bit;
if
(!__atomic_compare_exchange_n(gi, &expected, newv,
false
,
__ATOMIC_ACQ_REL,
__ATOMIC_ACQUIRE))
{
if
(expected == guard_bit)
{
return
0;
}
if
(expected == 0)
continue
;
}
expected = newv;
}
syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAIT, expected, 0);
}
}
return
acquire (g);
}