1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include <climits> 16#include <thread> 17#include <cstdint> 18#include <gtest/gtest.h> 19 20#include "param_atomic.h" 21#include "param_common.h" 22#include "param_utils.h" 23 24using namespace testing::ext; 25const int THREAD_NUM = 5; 26const int MAX_NUM = 10; 27 28namespace init_ut { 29class AtomicUnitTest : public testing::Test { 30public: 31 static void SetUpTestCase(void) {}; 32 static void TearDownTestCase(void) {}; 33 void SetUp(void) {}; 34 void TearDown(void) {}; 35}; 36 37/** 38 * 测试方法: 39 * 1,create 线程,执行全局变量写操作 40 * store with dirty 41 * sleep 42 * store clear dirty 43 * store commit ++ 44 * 2,read 现成,执行全局变量读参数 45 * 46 */ 47using AtomicTestData = struct { 48 ATOMIC_UINT32 commitId; 49 uint32_t data; 50}; 51 52static AtomicTestData g_testData = { 0, 0 }; 53 54static void *TestSetData(void *args) 55{ 56 while (g_testData.data < MAX_NUM) { 57 uint32_t commitId = ATOMIC_LOAD_EXPLICIT(&g_testData.commitId, MEMORY_ORDER_RELAXED); 58 ATOMIC_STORE_EXPLICIT(&g_testData.commitId, commitId | PARAM_FLAGS_MODIFY, MEMORY_ORDER_RELAXED); 59 g_testData.data++; 60 usleep(200 * 1000); // 200 * 1000 wait 61 printf("TestSetData data: %d commit: %d \n", g_testData.data, g_testData.commitId & PARAM_FLAGS_COMMITID); 62 uint32_t flags = commitId & ~PARAM_FLAGS_COMMITID; 63 ATOMIC_STORE_EXPLICIT(&g_testData.commitId, (++commitId) | flags, MEMORY_ORDER_RELEASE); 64 futex_wake(&g_testData.commitId, INT_MAX); 65 usleep(100); // 100 wait 66 } 67 return nullptr; 68} 69 70static inline uint32_t TestReadCommitId(AtomicTestData *entry) 71{ 72 uint32_t commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_ACQUIRE); 73 while (commitId & PARAM_FLAGS_MODIFY) { 74 futex_wait(&entry->commitId, commitId); 75 commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_ACQUIRE); 76 } 77 return commitId & PARAM_FLAGS_COMMITID; 78} 79 80static inline int TestReadParamValue(AtomicTestData *entry, uint32_t *commitId) 81{ 82 uint32_t data; 83 uint32_t id = *commitId; 84 do { 85 *commitId = id; 86 data = entry->data; 87 id = TestReadCommitId(entry); 88 } while (*commitId != id); // if change, must read 89 return data; 90} 91 92static void *TestReadData(void *args) 93{ 94 uint32_t data = 0; 95 while (data < MAX_NUM) { 96 uint32_t commitId = TestReadCommitId(&g_testData); 97 data = TestReadParamValue(&g_testData, &commitId); 98 printf("[ %d] TestReadData data: %d commit: %d \n", gettid(), data, commitId); 99 usleep(10); // 10 wait 100 } 101 return nullptr; 102} 103 104HWTEST_F(AtomicUnitTest, Init_AtomicUnitTest_001, TestSize.Level0) 105{ 106 printf("AtomicUnitTest_001 \n"); 107 pthread_t writeThread = 0; 108 pthread_t readThread[THREAD_NUM] = { 0 }; 109 pthread_create(&writeThread, nullptr, TestSetData, nullptr); 110 for (size_t i = 0; i < THREAD_NUM; i++) { 111 pthread_create(&readThread[i], nullptr, TestReadData, nullptr); 112 } 113 pthread_join(writeThread, nullptr); 114 printf("AtomicUnitTest_001 end \n"); 115} 116}