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