1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "gtest/gtest.h"
18 
19 #include <atomic>
20 #include <cstdint>
21 #include <thread>
22 
23 namespace {
24 
LockContentionWorkLoad(std::atomic<uint32_t> * data,int data_size)25 void LockContentionWorkLoad(std::atomic<uint32_t>* data, int data_size) {
26   for (int k = 0; k < 10000; k++) {
27     // Contend for the set of the atomics to make sure they are locked independently.
28     for (int i = 0; i < data_size; i++) {
29       data[i].fetch_add(1, std::memory_order_relaxed);
30     }
31   }
32 }
33 
34 }  // namespace
35 
TEST(Atomics,CompareAndSwap)36 TEST(Atomics, CompareAndSwap) {
37   std::atomic<int> data = {0};
38   int data_expected = 1;
39   int data_desired = -1;
40   // data != data_expected, data_expected is assigned with the value of data, data is unchanged.
41   ASSERT_FALSE(data.compare_exchange_strong(data_expected, data_desired));
42   ASSERT_EQ(data_expected, 0);
43   ASSERT_EQ(data.load(), 0);
44   // data == data_expected, data is assigned with the value of data_desired, data_expected is
45   // unchanged.
46   ASSERT_TRUE(data.compare_exchange_strong(data_expected, data_desired));
47   ASSERT_EQ(data_expected, 0);
48   ASSERT_EQ(data.load(), -1);
49 }
50 
TEST(Atomics,LockContentionTest)51 TEST(Atomics, LockContentionTest) {
52   std::atomic<uint32_t> data[10];
53   std::thread threads[16];
54   for (int i = 0; i < 10; i++) {
55     data[i].store(0, std::memory_order_relaxed);
56   }
57   for (int i = 0; i < 16; i++) {
58     threads[i] = std::thread(LockContentionWorkLoad, data, 10);
59   }
60   for (int i = 0; i < 16; i++) {
61     threads[i].join();
62   }
63   for (int i = 0; i < 10; i++) {
64     ASSERT_EQ(data[i].load(std::memory_order_relaxed), 160000U);
65   }
66 }
67