1// { dg-do compile { target i?86-*-* x86_64-*-* } }
2// { dg-options "-std=gnu++11 -g0 -fno-exceptions -fno-asynchronous-unwind-tables" }
3// { dg-options "-std=gnu++11 -g0 -fno-exceptions -fno-asynchronous-unwind-tables -march=i486" { target ia32 } }
4// { dg-final { scan-assembler-times "xacquire\|\.byte\[^\n\r]*0xf2" 14 } }
5// { dg-final { scan-assembler-times "xrelease\|\.byte\[^\n\r]*0xf3" 14 } }
6
7// Copyright (C) 2008-2015 Free Software Foundation, Inc.
8//
9// This file is part of the GNU ISO C++ Library.  This library is free
10// software; you can redistribute it and/or modify it under the
11// terms of the GNU General Public License as published by the
12// Free Software Foundation; either version 3, or (at your option)
13// any later version.
14
15// This library is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18// GNU General Public License for more details.
19
20// You should have received a copy of the GNU General Public License along
21// with this library; see the file COPYING3.  If not see
22// <http://www.gnu.org/licenses/>.
23
24#include <atomic>
25
26#define ACQ memory_order_acquire | __memory_order_hle_acquire
27#define REL memory_order_release | __memory_order_hle_release
28
29int main()
30{
31  unsigned zero, one;
32  using namespace std;
33  atomic_flag af = ATOMIC_FLAG_INIT;
34
35  if (!af.test_and_set(ACQ))
36    af.clear(REL);
37
38  atomic_uint au = ATOMIC_VAR_INIT(0);
39
40  if (au.exchange(1, ACQ))
41    au.store(0, REL);
42
43  if (au.exchange(1, ACQ))
44    au.exchange(0, REL);
45
46  zero = 0;
47  one = 1;
48  if (au.compare_exchange_weak(zero, 1, ACQ, memory_order_consume))
49    au.compare_exchange_weak(one, 0, REL, memory_order_consume);
50
51  zero = 0;
52  one = 1;
53  if (au.compare_exchange_strong(zero, 1, ACQ, memory_order_consume))
54    au.compare_exchange_strong(one, 0, REL, memory_order_consume);
55
56  if (!au.fetch_add(1, ACQ))
57    au.fetch_add(-1, REL);
58
59  if (!au.fetch_sub(1, ACQ))
60    au.fetch_sub(-1, REL);
61
62#if 0 /* broken in underlying target */
63  if (!au.fetch_and(1, ACQ))
64    au.fetch_and(-1, REL);
65
66  if (!au.fetch_or(1, ACQ))
67    au.fetch_or(-1, REL);
68
69  if (!au.fetch_xor(1, ACQ))
70    au.fetch_xor(-1, REL);
71
72  if (!au.fetch_nand(1, ACQ))
73    au.fetch_nand(-1, REL);
74#endif
75
76  volatile atomic_flag vaf = ATOMIC_FLAG_INIT;
77
78  if (!vaf.test_and_set(ACQ))
79    vaf.clear(REL);
80
81  volatile atomic_uint vau = ATOMIC_VAR_INIT(0);
82
83  if (!vau.exchange(1, ACQ))
84    vau.store(0, REL);
85
86  if (!vau.exchange(1, ACQ))
87    vau.exchange(0, REL);
88
89  zero = 0;
90  one = 1;
91  if (vau.compare_exchange_weak(zero, 1, ACQ, memory_order_consume))
92    vau.compare_exchange_weak(one, 0, REL, memory_order_consume);
93
94  zero = 0;
95  one = 1;
96  if (vau.compare_exchange_strong(zero, 1, ACQ, memory_order_consume))
97    vau.compare_exchange_strong(one, 0, REL, memory_order_consume);
98
99  if (!vau.fetch_add(1, ACQ))
100    vau.fetch_add(-1, REL);
101
102  if (!vau.fetch_sub(1, ACQ))
103    vau.fetch_sub(-1, REL);
104
105#if 0 /* broken in underlying target */
106
107  if (!vau.fetch_and(1, ACQ))
108    vau.fetch_and(-1, REL);
109
110  if (!vau.fetch_or(1, ACQ))
111    vau.fetch_or(-1, REL);
112
113  if (!vau.fetch_xor(1, ACQ))
114    vau.fetch_xor(-1, REL);
115
116  if (!vau.fetch_nand(1, ACQ))
117    vau.fetch_nand(-1, REL);
118#endif
119
120  return 0;
121}
122