1 /*
2 * Copyright (c) 2022-2024 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
16 #include "gtest/gtest.h"
17 #include "os/thread.h"
18 #include "os/mutex.h"
19
20 namespace ark::os::thread {
21 class ThreadTest : public testing::Test {};
22
23 uint32_t g_curThreadId = 0;
24 bool g_updated = false;
25 bool g_operated = false;
26 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
27 os::memory::Mutex g_mu;
28 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
29 os::memory::ConditionVariable g_cv;
30
31 #ifdef PANDA_TARGET_UNIX
32 constexpr int LOWER_PRIOIRITY = 1;
33 #elif defined(PANDA_TARGET_WINDOWS)
34 constexpr int LOWER_PRIOIRITY = -1;
35 #endif
36
ThreadFunc()37 void ThreadFunc()
38 {
39 g_curThreadId = GetCurrentThreadId();
40 {
41 os::memory::LockHolder lk(g_mu);
42 g_updated = true;
43 }
44 g_cv.Signal();
45 {
46 // wait for the main thread to Set/GetPriority
47 os::memory::LockHolder lk(g_mu);
48 while (!g_operated) {
49 g_cv.Wait(&g_mu);
50 }
51 }
52 }
53
TEST_F(ThreadTest,SetCurrentThreadPriorityTest)54 TEST_F(ThreadTest, SetCurrentThreadPriorityTest)
55 {
56 // Since setting higher priority needs "sudo" right, we only test lower one here.
57 auto ret1 = SetPriority(GetCurrentThreadId(), LOWER_PRIOIRITY);
58 auto prio1 = GetPriority(GetCurrentThreadId());
59 ASSERT_EQ(prio1, LOWER_PRIOIRITY);
60
61 auto ret2 = SetPriority(GetCurrentThreadId(), LOWEST_PRIORITY);
62 auto prio2 = GetPriority(GetCurrentThreadId());
63 ASSERT_EQ(prio2, LOWEST_PRIORITY);
64
65 #ifdef PANDA_TARGET_UNIX
66 ASSERT_EQ(ret1, 0U);
67 ASSERT_EQ(ret2, 0U);
68 #elif defined(PANDA_TARGET_WINDOWS)
69 ASSERT_NE(ret1, 0U);
70 ASSERT_NE(ret2, 0U);
71 #endif
72 }
73
TEST_F(ThreadTest,SetOtherThreadPriorityTest)74 TEST_F(ThreadTest, SetOtherThreadPriorityTest)
75 {
76 auto parentPid = GetCurrentThreadId();
77 auto parentPrioBefore = GetPriority(parentPid);
78
79 auto newThread = ThreadStart(ThreadFunc);
80 // wait for the new_thread to update CUR_THREAD_ID
81 g_mu.Lock();
82 while (!g_updated) {
83 g_cv.Wait(&g_mu);
84 }
85 auto childPid = g_curThreadId;
86
87 auto childPrioBefore = GetPriority(childPid);
88 (void)childPrioBefore;
89 auto ret = SetPriority(childPid, LOWEST_PRIORITY);
90
91 auto childPrioAfter = GetPriority(childPid);
92 (void)childPrioAfter;
93 auto parentPrioAfter = GetPriority(parentPid);
94
95 g_operated = true;
96 g_mu.Unlock();
97 g_cv.Signal();
98 void *res;
99 ThreadJoin(newThread, &res);
100
101 ASSERT_EQ(parentPrioBefore, parentPrioAfter);
102 #ifdef PANDA_TARGET_UNIX
103 ASSERT_EQ(ret, 0U);
104 ASSERT(childPrioBefore <= childPrioAfter);
105 #elif defined(PANDA_TARGET_WINDOWS)
106 ASSERT_NE(ret, 0U);
107 ASSERT(childPrioAfter <= childPrioBefore);
108 #endif
109 }
110 } // namespace ark::os::thread
111