1 /**************************************************************************
2 *
3 * Copyright 2014 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <gtest/gtest.h>
29 #include <stdint.h>
30 #include <inttypes.h>
31
32 #include "u_atomic.h"
33
34 #ifdef _MSC_VER
35 #pragma warning( disable : 28112 ) /* Accessing a local variable via an Interlocked function */
36 #pragma warning( disable : 28113 ) /* A variable which is accessed via an Interlocked function must always be accessed via an Interlocked function */
37 #endif
38
39 template <typename T> class AtomicAssignment : public testing::Test {};
40
41 using AtomicAssignmentTypes =
42 testing::Types<int, unsigned, bool,
43 int8_t, uint8_t, int16_t, uint16_t,
44 int32_t, uint32_t, int64_t, uint64_t>;
45
46 TYPED_TEST_SUITE(AtomicAssignment, AtomicAssignmentTypes);
47
TYPED_TEST(AtomicAssignment, Test)48 TYPED_TEST(AtomicAssignment, Test)
49 {
50 TypeParam v, r;
51 const TypeParam ones = TypeParam(-1);
52
53 p_atomic_set(&v, ones);
54 ASSERT_EQ(v, ones) << "p_atomic_set";
55
56 r = p_atomic_read(&v);
57 ASSERT_EQ(r, ones) << "p_atomic_read";
58
59 v = ones;
60 r = p_atomic_cmpxchg(&v, 0, 1);
61 ASSERT_EQ(v, ones) << "p_atomic_cmpxchg";
62 ASSERT_EQ(r, ones) << "p_atomic_cmpxchg";
63
64 r = p_atomic_cmpxchg(&v, ones, 0);
65 ASSERT_EQ(v, 0) << "p_atomic_cmpxchg";
66 ASSERT_EQ(r, ones) << "p_atomic_cmpxchg";
67 }
68
69
70 template <typename T> class AtomicIncrementDecrement : public testing::Test {};
71
72 using AtomicIncrementDecrementTypes =
73 testing::Types<int, unsigned,
74 int16_t, uint16_t,
75 int32_t, uint32_t, int64_t, uint64_t>;
76
77 TYPED_TEST_SUITE(AtomicIncrementDecrement, AtomicIncrementDecrementTypes);
78
TYPED_TEST(AtomicIncrementDecrement, Test)79 TYPED_TEST(AtomicIncrementDecrement, Test)
80 {
81 TypeParam v, r;
82 bool b;
83
84 const TypeParam ones = TypeParam(-1);
85
86 v = 2;
87
88 b = p_atomic_dec_zero(&v);
89 ASSERT_EQ(v, 1) << "p_atomic_dec_zero";
90 ASSERT_FALSE(b) << "p_atomic_dec_zero";
91
92 b = p_atomic_dec_zero(&v);
93 ASSERT_EQ(v, 0) << "p_atomic_dec_zero";
94 ASSERT_TRUE(b) << "p_atomic_dec_zero";
95
96 b = p_atomic_dec_zero(&v);
97 ASSERT_EQ(v, ones) << "p_atomic_dec_zero";
98 ASSERT_FALSE(b) << "p_atomic_dec_zero";
99
100 v = ones;
101 p_atomic_inc(&v);
102 ASSERT_EQ(v, 0) << "p_atomic_inc";
103
104 v = ones;
105 r = p_atomic_inc_return(&v);
106 ASSERT_EQ(v, 0) << "p_atomic_inc_return";
107 ASSERT_EQ(r, v) << "p_atomic_inc_return";
108
109 v = 0;
110 p_atomic_dec(&v);
111 ASSERT_EQ(v, ones) << "p_atomic_dec";
112
113 v = 0;
114 r = p_atomic_dec_return(&v);
115 ASSERT_EQ(v, ones) << "p_atomic_dec_return";
116 ASSERT_EQ(v, r) << "p_atomic_dec_return";
117 }
118
119 template <typename T> class AtomicAdd : public testing::Test {};
120
121 using AtomicAddTypes =
122 testing::Types<int, unsigned,
123 int8_t, uint8_t, int16_t, uint16_t,
124 int32_t, uint32_t, int64_t, uint64_t>;
125
126 TYPED_TEST_SUITE(AtomicAdd, AtomicAddTypes);
127
TYPED_TEST(AtomicAdd, Test)128 TYPED_TEST(AtomicAdd, Test)
129 {
130 TypeParam v, r;
131
132 v = 23;
133
134 p_atomic_add(&v, 42);
135 r = p_atomic_read(&v);
136
137 ASSERT_EQ(r, 65) << "p_atomic_add";
138 }
139