From 0cf0effde3eb751d1c0e9cd395a9ee47631d7b50 Mon Sep 17 00:00:00 2001 From: huangyu Date: Mon, 9 May 2022 22:11:54 +0800 Subject: [PATCH 01/28] Move common mutex for Windows/Unix to libpandabase/os Signed-off-by: huangyu Change-Id: I13544d512688881dc2448a9a29de459d0feec490 --- libpandabase/os/mutex.cpp | 4 +- libpandabase/os/mutex.h | 93 ++++++++++++++++++++++++++---- libpandabase/os/unix/mutex.h | 108 ----------------------------------- 3 files changed, 85 insertions(+), 120 deletions(-) delete mode 100644 libpandabase/os/unix/mutex.h diff --git a/libpandabase/os/mutex.cpp b/libpandabase/os/mutex.cpp index f8cad440c7..d331352882 100644 --- a/libpandabase/os/mutex.cpp +++ b/libpandabase/os/mutex.cpp @@ -19,7 +19,7 @@ #include #include -namespace panda::os::unix::memory { +namespace panda::os::memory { const int64_t MILLISECONDS_PER_SEC = 1000; const int64_t NANOSECONDS_PER_MILLISEC = 1000000; const int64_t NANOSECONDS_PER_SEC = 1000000000; @@ -196,4 +196,4 @@ bool ConditionVariable::TimedWait(Mutex *mutex, uint64_t ms, uint64_t ns, bool i FatalIfError("pthread_cond_timedwait", rc); return false; } -} // namespace panda::os::unix::memory +} // namespace panda::os::memory diff --git a/libpandabase/os/mutex.h b/libpandabase/os/mutex.h index 3929d4fd1f..0a1ffc9052 100644 --- a/libpandabase/os/mutex.h +++ b/libpandabase/os/mutex.h @@ -18,17 +18,16 @@ #if defined(PANDA_USE_FUTEX) #include "os/unix/futex/mutex.h" -#elif defined(PANDA_TARGET_UNIX) || defined(PANDA_TARGET_WINDOWS) -#include "os/unix/mutex.h" -#else +#elif !defined(PANDA_TARGET_UNIX) && !defined(PANDA_TARGET_WINDOWS) #error "Unsupported platform" #endif #include "clang.h" #include "macros.h" -namespace panda::os::memory { +#include +namespace panda::os::memory { // Dummy lock which locks nothing // but has the same methods as RWLock and Mutex. // Can be used in Locks Holders. @@ -46,12 +45,87 @@ using RecursiveMutex = panda::os::unix::memory::futex::RecursiveMutex; using RWLock = panda::os::unix::memory::futex::RWLock; using ConditionVariable = panda::os::unix::memory::futex::ConditionVariable; #else -using Mutex = panda::os::unix::memory::Mutex; -using RecursiveMutex = panda::os::unix::memory::RecursiveMutex; -using RWLock = panda::os::unix::memory::RWLock; +class ConditionVariable; + +class CAPABILITY("mutex") Mutex { +public: + explicit Mutex(bool is_init = true); + + ~Mutex(); + + void Lock() ACQUIRE(); + + bool TryLock() TRY_ACQUIRE(true); + + void Unlock() RELEASE(); + +protected: + void Init(pthread_mutexattr_t *attrs); + +private: + pthread_mutex_t mutex_; + + NO_COPY_SEMANTIC(Mutex); + NO_MOVE_SEMANTIC(Mutex); + + friend ConditionVariable; +}; + +class CAPABILITY("mutex") RecursiveMutex : public Mutex { +public: + RecursiveMutex(); + + ~RecursiveMutex() = default; + + NO_COPY_SEMANTIC(RecursiveMutex); + NO_MOVE_SEMANTIC(RecursiveMutex); +}; + +class CAPABILITY("mutex") RWLock { +public: + RWLock(); + + ~RWLock(); + + void ReadLock() ACQUIRE_SHARED(); + + void WriteLock() ACQUIRE(); + + bool TryReadLock() TRY_ACQUIRE_SHARED(true); + + bool TryWriteLock() TRY_ACQUIRE(true); + + void Unlock() RELEASE_GENERIC(); + +private: + pthread_rwlock_t rwlock_; + + NO_COPY_SEMANTIC(RWLock); + NO_MOVE_SEMANTIC(RWLock); +}; + // Some RTOS could not have support for condition variables, so this primitive should be used carefully -using ConditionVariable = panda::os::unix::memory::ConditionVariable; -#endif +class ConditionVariable { +public: + ConditionVariable(); + + ~ConditionVariable(); + + void Signal(); + + void SignalAll(); + + void Wait(Mutex *mutex); + + bool TimedWait(Mutex *mutex, uint64_t ms, uint64_t ns = 0, bool is_absolute = false); + +private: + pthread_cond_t cond_; + + NO_COPY_SEMANTIC(ConditionVariable); + NO_MOVE_SEMANTIC(ConditionVariable); +}; +#endif // PANDA_USE_FUTEX using PandaThreadKey = pthread_key_t; const auto PandaGetspecific = pthread_getspecific; // NOLINT(readability-identifier-naming) @@ -117,7 +191,6 @@ private: NO_COPY_SEMANTIC(WriteLockHolder); NO_MOVE_SEMANTIC(WriteLockHolder); }; - } // namespace panda::os::memory #endif // PANDA_LIBPANDABASE_OS_MUTEX_H_ diff --git a/libpandabase/os/unix/mutex.h b/libpandabase/os/unix/mutex.h deleted file mode 100644 index 3369424d3c..0000000000 --- a/libpandabase/os/unix/mutex.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PANDA_LIBPANDABASE_OS_UNIX_MUTEX_H_ -#define PANDA_LIBPANDABASE_OS_UNIX_MUTEX_H_ - -#include "clang.h" -#include "macros.h" - -#include - -namespace panda::os::unix::memory { - -class ConditionVariable; - -class CAPABILITY("mutex") Mutex { -public: - explicit Mutex(bool is_init = true); - - ~Mutex(); - - void Lock() ACQUIRE(); - - bool TryLock() TRY_ACQUIRE(true); - - void Unlock() RELEASE(); - -protected: - void Init(pthread_mutexattr_t *attrs); - -private: - pthread_mutex_t mutex_; - - NO_COPY_SEMANTIC(Mutex); - NO_MOVE_SEMANTIC(Mutex); - - friend ConditionVariable; -}; - -class CAPABILITY("mutex") RecursiveMutex : public Mutex { -public: - RecursiveMutex(); - - ~RecursiveMutex() = default; - - NO_COPY_SEMANTIC(RecursiveMutex); - NO_MOVE_SEMANTIC(RecursiveMutex); -}; - -class CAPABILITY("mutex") RWLock { -public: - RWLock(); - - ~RWLock(); - - void ReadLock() ACQUIRE_SHARED(); - - void WriteLock() ACQUIRE(); - - bool TryReadLock() TRY_ACQUIRE_SHARED(true); - - bool TryWriteLock() TRY_ACQUIRE(true); - - void Unlock() RELEASE_GENERIC(); - -private: - pthread_rwlock_t rwlock_; - - NO_COPY_SEMANTIC(RWLock); - NO_MOVE_SEMANTIC(RWLock); -}; - -class ConditionVariable { -public: - ConditionVariable(); - - ~ConditionVariable(); - - void Signal(); - - void SignalAll(); - - void Wait(Mutex *mutex); - - bool TimedWait(Mutex *mutex, uint64_t ms, uint64_t ns = 0, bool is_absolute = false); - -private: - pthread_cond_t cond_; - - NO_COPY_SEMANTIC(ConditionVariable); - NO_MOVE_SEMANTIC(ConditionVariable); -}; - -} // namespace panda::os::unix::memory - -#endif // PANDA_LIBPANDABASE_OS_UNIX_MUTEX_H_ -- Gitee From f3ff0e16696ab8e116db8f221ff30406fc663631 Mon Sep 17 00:00:00 2001 From: huangyu Date: Tue, 10 May 2022 10:46:42 +0800 Subject: [PATCH 02/28] Use common class LibraryHandle for Unix/Windows Signed-off-by: huangyu Change-Id: I2ce7fbd1b47c1e0eb58ed57bbc53ddd529bd129e --- libpandabase/os/library_loader.h | 49 +++++++++++++++-- libpandabase/os/unix/library_loader.cpp | 4 ++ libpandabase/os/unix/library_loader.h | 50 ----------------- libpandabase/os/windows/library_loader.cpp | 10 ++-- libpandabase/os/windows/library_loader.h | 62 ---------------------- 5 files changed, 53 insertions(+), 122 deletions(-) delete mode 100644 libpandabase/os/windows/library_loader.h diff --git a/libpandabase/os/library_loader.h b/libpandabase/os/library_loader.h index e77ced28de..2dc7451e66 100644 --- a/libpandabase/os/library_loader.h +++ b/libpandabase/os/library_loader.h @@ -18,9 +18,7 @@ #ifdef PANDA_TARGET_UNIX #include "os/unix/library_loader.h" -#elif PANDA_TARGET_WINDOWS -#include "os/windows/library_loader.h" -#else +#elif !PANDA_TARGET_WINDOWS #error "Unsupported platform" #endif @@ -30,8 +28,53 @@ #include namespace panda::os::library_loader { +class LibraryHandle; + Expected Load(std::string_view filename); + Expected ResolveSymbol(const LibraryHandle &handle, std::string_view name); + +void CloseHandle(void *handle); + +class LibraryHandle { +public: + explicit LibraryHandle(void *handle) : handle_(handle) {} + + LibraryHandle(LibraryHandle &&handle) noexcept + { + handle_ = handle.handle_; + handle.handle_ = nullptr; + } + + LibraryHandle &operator=(LibraryHandle &&handle) noexcept + { + handle_ = handle.handle_; + handle.handle_ = nullptr; + return *this; + } + + bool IsValid() const + { + return handle_ != nullptr; + } + + void *GetNativeHandle() const + { + return handle_; + } + + ~LibraryHandle() + { + if (handle_ != nullptr) { + CloseHandle(handle_); + } + } + +private: + void *handle_; + + NO_COPY_SEMANTIC(LibraryHandle); +}; } // namespace panda::os::library_loader #endif // PANDA_LIBPANDABASE_OS_LIBRARY_LOADER_H_ diff --git a/libpandabase/os/unix/library_loader.cpp b/libpandabase/os/unix/library_loader.cpp index 541f1ff4b5..9bc041848d 100644 --- a/libpandabase/os/unix/library_loader.cpp +++ b/libpandabase/os/unix/library_loader.cpp @@ -39,4 +39,8 @@ Expected ResolveSymbol(const LibraryHandle &handle, std::string_v return msg != nullptr ? Unexpected(Error(msg)) : Unexpected(Error("no error message")); } +void CloseHandle(void *handle) +{ + dlclose(handle); +} } // namespace panda::os::library_loader diff --git a/libpandabase/os/unix/library_loader.h b/libpandabase/os/unix/library_loader.h index a20f17d773..ae399f9401 100644 --- a/libpandabase/os/unix/library_loader.h +++ b/libpandabase/os/unix/library_loader.h @@ -16,56 +16,6 @@ #ifndef PANDA_LIBPANDABASE_OS_UNIX_LIBRARY_LOADER_H_ #define PANDA_LIBPANDABASE_OS_UNIX_LIBRARY_LOADER_H_ -#include "macros.h" - #include -namespace panda::os::unix::library_loader { - -class LibraryHandle { -public: - explicit LibraryHandle(void *handle) : handle_(handle) {} - - LibraryHandle(LibraryHandle &&handle) noexcept - { - handle_ = handle.handle_; - handle.handle_ = nullptr; - } - - LibraryHandle &operator=(LibraryHandle &&handle) noexcept - { - handle_ = handle.handle_; - handle.handle_ = nullptr; - return *this; - } - - bool IsValid() const - { - return handle_ != nullptr; - } - - void *GetNativeHandle() const - { - return handle_; - } - - ~LibraryHandle() - { - if (handle_ != nullptr) { - dlclose(handle_); - } - } - -private: - void *handle_; - - NO_COPY_SEMANTIC(LibraryHandle); -}; - -} // namespace panda::os::unix::library_loader - -namespace panda::os::library_loader { -using LibraryHandle = panda::os::unix::library_loader::LibraryHandle; -} // namespace panda::os::library_loader - #endif // PANDA_LIBPANDABASE_OS_UNIX_LIBRARY_LOADER_H_ diff --git a/libpandabase/os/windows/library_loader.cpp b/libpandabase/os/windows/library_loader.cpp index 24449ecd35..c3925c96b8 100644 --- a/libpandabase/os/windows/library_loader.cpp +++ b/libpandabase/os/windows/library_loader.cpp @@ -39,13 +39,9 @@ Expected ResolveSymbol(const LibraryHandle &handle, std::string_v return Unexpected(Error(std::string("Failed to resolve symbol ") + name.data() + std::string(", error code ") + std::to_string(GetLastError()))); } -} // namespace panda::os::library_loader -namespace panda::os::windows::library_loader { -LibraryHandle::~LibraryHandle() +void CloseHandle(void *handle) { - if (handle_ != nullptr) { - FreeLibrary(reinterpret_cast(handle_)); - } + FreeLibrary(reinterpret_cast(handle)); } -} // namespace panda::os::windows::library_loader +} // namespace panda::os::library_loader diff --git a/libpandabase/os/windows/library_loader.h b/libpandabase/os/windows/library_loader.h deleted file mode 100644 index 8d8efabb4e..0000000000 --- a/libpandabase/os/windows/library_loader.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PANDA_LIBPANDABASE_OS_WINDOWS_LIBRARY_LOADER_H_ -#define PANDA_LIBPANDABASE_OS_WINDOWS_LIBRARY_LOADER_H_ - -#include "macros.h" - -namespace panda::os::windows::library_loader { -class LibraryHandle { -public: - explicit LibraryHandle(void *handle) : handle_(handle) {} - - LibraryHandle(LibraryHandle &&handle) noexcept - { - handle_ = handle.handle_; - handle.handle_ = nullptr; - } - - LibraryHandle &operator=(LibraryHandle &&handle) noexcept - { - handle_ = handle.handle_; - handle.handle_ = nullptr; - return *this; - } - - bool IsValid() const - { - return handle_ != nullptr; - } - - void *GetNativeHandle() const - { - return handle_; - } - - ~LibraryHandle(); - -private: - void *handle_; - - NO_COPY_SEMANTIC(LibraryHandle); -}; -} // namespace panda::os::windows::library_loader - -namespace panda::os::library_loader { -using LibraryHandle = panda::os::windows::library_loader::LibraryHandle; -} // namespace panda::os::library_loader - -#endif // PANDA_LIBPANDABASE_OS_WINDOWS_LIBRARY_LOADER_H_ -- Gitee From f1cfa29ba067b8ba7fb7ceee66b183da17b3b02c Mon Sep 17 00:00:00 2001 From: huangyu Date: Tue, 10 May 2022 21:58:56 +0800 Subject: [PATCH 03/28] Add gtests for basic thread functions Signed-off-by: huangyu Change-Id: Ia95890fcac5ce09659f89b354c570f94fd5eba3e --- libpandabase/CMakeLists.txt | 1 + libpandabase/os/thread.h | 1 + libpandabase/os/unix/thread.cpp | 54 +++++++++++++++++++ libpandabase/tests/base_thread_test.cpp | 71 +++++++++++++++++++++++++ 4 files changed, 127 insertions(+) create mode 100644 libpandabase/tests/base_thread_test.cpp diff --git a/libpandabase/CMakeLists.txt b/libpandabase/CMakeLists.txt index 30e47bf94a..8ecab08dcd 100644 --- a/libpandabase/CMakeLists.txt +++ b/libpandabase/CMakeLists.txt @@ -226,6 +226,7 @@ set(ARKBASE_TESTS_SOURCES tests/native_bytes_from_mallinfo_test.cpp tests/json_parser_test.cpp tests/alloc_tracker_test.cpp + tests/base_thread_test.cpp ) panda_add_gtest( diff --git a/libpandabase/os/thread.h b/libpandabase/os/thread.h index 3038f7faa9..ee421ac82c 100644 --- a/libpandabase/os/thread.h +++ b/libpandabase/os/thread.h @@ -33,6 +33,7 @@ ThreadId GetCurrentThreadId(); int SetPriority(int thread_id, int prio); int GetPriority(int thread_id); int SetThreadName(native_handle_type pthread_id, const char *name); +int GetThreadName(ThreadId tid, char *name, size_t len); native_handle_type GetNativeHandle(); void Yield(); void NativeSleep(unsigned int ms); diff --git a/libpandabase/os/unix/thread.cpp b/libpandabase/os/unix/thread.cpp index 28d5f1929f..457e634b62 100644 --- a/libpandabase/os/unix/thread.cpp +++ b/libpandabase/os/unix/thread.cpp @@ -15,11 +15,17 @@ #include "os/thread.h" +#include "utils/span.h" + +#include #include +#include "os/failure_retry.h" #ifdef PANDA_TARGET_UNIX +#include #include #include #endif +#include #include namespace panda::os::thread { @@ -58,6 +64,54 @@ int SetThreadName(native_handle_type pthread_id, const char *name) #endif } +int GetThreadName(ThreadId tid, char *name, size_t len) +{ + ASSERT(tid != 0); + + constexpr size_t MAX_TASK_COMM_LEN =16; + + if (len < MAX_TASK_COMM_LEN) { + return ERANGE; + } + + if (GetCurrentThreadId() == tid) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + return pthread_getname_np(pthread_self(), name, len) != 0 ? errno : 0; + } + + constexpr size_t BUF_LEN = 64; + std::array buf = {0}; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + int ret = snprintf_s(buf.data(), BUF_LEN, BUF_LEN -1, "/proc/self/task/%d/comm", tid); + if (ret < 0) { + return ret; + } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-signed-bitwise) + int fd = open(buf.data(), O_CLOEXEC | O_RDONLY); + if (fd < 0) { + return errno; + } + + ssize_t n = PANDA_FAILURE_RETRY(read(fd, name, len)); + close(fd); + + if (n < 0) { + return errno; + } + + Span name_sp(name, n); + if (n > 0 && name_sp[n - 1] == '\n') { + name_sp[n - 1] = '\0'; + return 0; + } + + if (n == static_cast(len)) { + return ERANGE; + } + name_sp[n] = '\0'; + return 0; +} + native_handle_type GetNativeHandle() { return pthread_self(); diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp new file mode 100644 index 0000000000..d7da367722 --- /dev/null +++ b/libpandabase/tests/base_thread_test.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "utils/utf.h" +#include "gtest/gtest.h" +#include "os/thread.h" + +namespace panda::os::thread { +class ThreadTest : public testing::Test {}; + +TEST_F(ThreadTest, GetPriorityTest) +{ + auto priority = GetPriority(getpid()); + // The default priority is 0. + ASSERT_EQ(priority, 0); +} + +TEST_F(ThreadTest, SetCurrentThreadPriorityTest) +{ +#ifdef PANDA_TARGET_UNIX + // On linux, the priority can be set within range [-20, 19], and 19 is the lowest priority. + constexpr int LOWER_PRIOIRITY = 1; + constexpr int LOWEST_PRIORITY = 19; +#elif PANDA_TARGET_WINDOWS + // On Windows, the priority can be set within range [-2, 2], and -2 is the lowest priority. + constexpr int LOWER_PRIOIRITY = -1; + constexpr int LOWEST_PRIORITY = -2; +#endif + // Since setting higher priority needs "sudo" right, we only test lower one here. + auto ret1 = SetPriority(getpid(), LOWER_PRIOIRITY); + ASSERT_EQ(ret1, 0); + auto prio1 = GetPriority(getpid()); + ASSERT_EQ(prio1, LOWER_PRIOIRITY); + auto ret2 = SetPriority(getpid(), LOWEST_PRIORITY); + ASSERT_EQ(ret2, 0); + auto prio2 = GetPriority(getpid()); + ASSERT_EQ(prio2, LOWEST_PRIORITY); +} + +TEST_F(ThreadTest, GetThreadNameTest) +{ + constexpr size_t MAX_LENGTH = 256; + char name[MAX_LENGTH]; + auto ret = GetThreadName(getpid(), name, MAX_LENGTH); + ASSERT_EQ(ret, 0); +} + +TEST_F(ThreadTest, SetThreadNameTest) +{ + auto res = SetThreadName(GetNativeHandle(), "TestThread"); + ASSERT_EQ(res, 0); + constexpr size_t MAX_LENGTH = 256; + char thread_name[MAX_LENGTH]; + auto ret = GetThreadName(getpid(), thread_name, MAX_LENGTH); + ASSERT_EQ(ret, 0); + char set_name[MAX_LENGTH] = "TestThread"; + ASSERT_EQ(*thread_name, *set_name); +} +} // namespace panda::os::thread -- Gitee From 650aea694caaf3f99b9675828c0e82623a25ccea Mon Sep 17 00:00:00 2001 From: huangyu Date: Fri, 13 May 2022 21:38:58 +0800 Subject: [PATCH 04/28] Enable gtest building by mingw Signed-off-by: huangyu Change-Id: I79ca4969fb9f938d7f8de3c6c3507095301be3c0 --- libpandabase/os/windows/error.cpp | 1 + libpandabase/tests/hash_test.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libpandabase/os/windows/error.cpp b/libpandabase/os/windows/error.cpp index b3ee1c51a4..d3dae6e9b8 100644 --- a/libpandabase/os/windows/error.cpp +++ b/libpandabase/os/windows/error.cpp @@ -14,6 +14,7 @@ */ #include "os/error.h" +#include namespace panda::os { diff --git a/libpandabase/tests/hash_test.cpp b/libpandabase/tests/hash_test.cpp index e67c1bfba6..b5f45be208 100644 --- a/libpandabase/tests/hash_test.cpp +++ b/libpandabase/tests/hash_test.cpp @@ -120,7 +120,7 @@ void HashTest::EndOfPageStringHashTest() const void *mem = panda::os::mem::MapRWAnonymousRaw(ALLOC_SIZE); ASAN_UNPOISON_MEMORY_REGION(mem, ALLOC_SIZE); panda::os::mem::MakeMemWithProtFlag( - reinterpret_cast(reinterpret_cast(mem) + PAGE_SIZE), PAGE_SIZE, PROT_NONE); + reinterpret_cast(reinterpret_cast(mem) + PAGE_SIZE), PAGE_SIZE, os::mem::MMAP_PROT_NONE); char *string = reinterpret_cast((reinterpret_cast(mem) + PAGE_SIZE) - sizeof(char) * string_size); string[0] = 'O'; -- Gitee From ddc04e80ca547ddc4998fb180f931d93c279d67d Mon Sep 17 00:00:00 2001 From: huangyu Date: Fri, 13 May 2022 21:39:51 +0800 Subject: [PATCH 05/28] [TMP] Add gtests for Set/GetPriority, Set/GetThreadName Signed-off-by: huangyu Change-Id: I1ea515f1a86f27c02a1af9add32fb15be62e095c --- libpandabase/os/thread.h | 8 ++ libpandabase/os/windows/thread.cpp | 14 ++- libpandabase/os/windows/thread.h | 5 + libpandabase/tests/base_thread_test.cpp | 134 ++++++++++++++++++++++-- 4 files changed, 152 insertions(+), 9 deletions(-) create mode 100644 libpandabase/os/windows/thread.h diff --git a/libpandabase/os/thread.h b/libpandabase/os/thread.h index ee421ac82c..f08fef5b5e 100644 --- a/libpandabase/os/thread.h +++ b/libpandabase/os/thread.h @@ -23,6 +23,9 @@ #include #include #include +#ifdef PANDA_TARGET_WINDOWS +#include +#endif namespace panda::os::thread { @@ -30,8 +33,13 @@ using ThreadId = uint32_t; using native_handle_type = std::thread::native_handle_type; ThreadId GetCurrentThreadId(); +#ifdef PANDA_TARGET_UNIX int SetPriority(int thread_id, int prio); int GetPriority(int thread_id); +#elif PANDA_TARGET_WINDOWS +int SetPriority(DWORD thread_id, int prio); +int GetPriority(HANDLE thread_id); +#endif int SetThreadName(native_handle_type pthread_id, const char *name); int GetThreadName(ThreadId tid, char *name, size_t len); native_handle_type GetNativeHandle(); diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index 1dca1e5559..0814e9c624 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -25,12 +25,15 @@ ThreadId GetCurrentThreadId() return static_cast(std::hash()(std::this_thread::get_id())); } -int SetPriority([[maybe_unused]] int thread_id, int prio) +int SetPriority([[maybe_unused]] DWORD thread_id, int prio) { - return SetThreadPriority(GetCurrentThread(), prio); + auto ret = SetThreadPriority(OpenThread(THREAD_ALL_ACCESS, false, thread_id), prio); + // On linux, the "setpriority" function returns zero if there is no error, or -1 if there is. + // While on windows, the return value is nonzero if the function succeeds. + return (ret != 0) ? 0 : -1; } -int GetPriority([[maybe_unused]] int thread_id) +int GetPriority([[maybe_unused]] HANDLE thread_id) { return GetThreadPriority(GetCurrentThread()); } @@ -41,6 +44,11 @@ int SetThreadName([[maybe_unused]] native_handle_type pthread_id, const char *na return pthread_setname_np(pthread_self(), name); } +native_handle_type GetNativeHandle() +{ + return reinterpret_cast(pthread_self()); +} + void Yield() { std::this_thread::yield(); diff --git a/libpandabase/os/windows/thread.h b/libpandabase/os/windows/thread.h new file mode 100644 index 0000000000..fd2a790a5b --- /dev/null +++ b/libpandabase/os/windows/thread.h @@ -0,0 +1,5 @@ +#include + + +int GetPriority(HANDLE pid); +int SetPriority(HANDLE pid, DWORD priority); diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index d7da367722..adb1578ceb 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -15,11 +15,78 @@ #include "utils/utf.h" #include "gtest/gtest.h" +#include "os/failure_retry.h" #include "os/thread.h" +#ifdef PANDA_TARGET_WINDOWS +#include +#include +#include +#endif + namespace panda::os::thread { class ThreadTest : public testing::Test {}; +#if !PANDA_TARGET_WINDOWS +unsigned __stdcall ThreadFunc([[maybe_unused]] void *args) +{ + printf("In second thread...\n"); + _endthreadex(0); + return 0; +} + +TEST_F(ThreadTest, ThreadStartTest) +{ + HANDLE hThread; + unsigned threadID; + printf("Creating second thread...\n"); + hThread = (HANDLE)_beginthreadex(NULL, 0, &ThreadFunc, NULL, 0, &threadID); + WaitForSingleObject(hThread, INFINITE); + printf("CloseHandle...\n"); + CloseHandle(hThread); +} +/* #elif PANDA_TARGET_UNIX */ +#else +void ThreadFunc(int x, int y) +{ + /* sleep(1); */ + NativeSleep(100); + printf("In second thread...\n"); + while (x < 5) { + x++; + } + while (y < 3) { + y++; + } +} + +TEST_F(ThreadTest, ThreadStartTest) +{ + auto thread_id = ThreadStart(ThreadFunc, 1, 2); + auto ret = SetThreadName(thread_id, "Thread_2"); + ASSERT_EQ(ret, 0); + + /* sleep(2); */ + NativeSleep(200); + + /* constexpr size_t MAX_LENGTH = 256; */ + /* char name1[MAX_LENGTH]; */ + /* auto ret1 = GetThreadName(getpid(), name1, MAX_LENGTH); */ + /* ASSERT_EQ(ret1, 0); */ + /* char set_name2[MAX_LENGTH] = "Thread_2"; */ + /* ASSERT_NE(*name1, *set_name2); */ + + /* char name2[MAX_LENGTH]; */ + /* auto ret2 = GetThreadName(reinterpret_cast(thread_id), name2, MAX_LENGTH); */ + /* ASSERT_EQ(ret2, 0); */ + /* ASSERT_EQ(*name2, *set_name2); */ + printf("ThreadDetach...\n"); + /* ThreadDetach(thread_id); */ + +} +#endif + +#ifndef PANDA_TARGET_WINDOWS TEST_F(ThreadTest, GetPriorityTest) { auto priority = GetPriority(getpid()); @@ -32,23 +99,75 @@ TEST_F(ThreadTest, SetCurrentThreadPriorityTest) #ifdef PANDA_TARGET_UNIX // On linux, the priority can be set within range [-20, 19], and 19 is the lowest priority. constexpr int LOWER_PRIOIRITY = 1; - constexpr int LOWEST_PRIORITY = 19; + /* constexpr int LOWEST_PRIORITY = 19; */ #elif PANDA_TARGET_WINDOWS // On Windows, the priority can be set within range [-2, 2], and -2 is the lowest priority. constexpr int LOWER_PRIOIRITY = -1; - constexpr int LOWEST_PRIORITY = -2; + /* constexpr int LOWEST_PRIORITY = -2; */ #endif // Since setting higher priority needs "sudo" right, we only test lower one here. auto ret1 = SetPriority(getpid(), LOWER_PRIOIRITY); ASSERT_EQ(ret1, 0); auto prio1 = GetPriority(getpid()); ASSERT_EQ(prio1, LOWER_PRIOIRITY); - auto ret2 = SetPriority(getpid(), LOWEST_PRIORITY); - ASSERT_EQ(ret2, 0); - auto prio2 = GetPriority(getpid()); - ASSERT_EQ(prio2, LOWEST_PRIORITY); + /* auto ret2 = SetPriority(getpid(), LOWEST_PRIORITY); */ + /* ASSERT_EQ(ret2, 0); */ + /* auto prio2 = GetPriority(getpid()); */ + /* ASSERT_EQ(prio2, LOWEST_PRIORITY); */ } +#endif +#ifdef PANDA_TARGET_WINDOWS +DWORD WINAPI MyThreadFunction([[maybe_unused]] LPVOID lpParam) +{ + return 0; +} +#endif +TEST_F(ThreadTest, SetOtherThreadPriorityTest) +{ +#ifdef PANDA_TARGET_UNIX + auto parent_pid = getpid(); + auto parent_prio_before = GetPriority(parent_pid); + // On linux, the priority can be set within range [-20, 19], and 19 is the lowest priority. + /* constexpr int LOWER_PRIOIRITY = 1; */ + constexpr int LOWEST_PRIORITY = 19; + auto child_pid = fork(); + ASSERT_NE(child_pid, -1); +#elif PANDA_TARGET_WINDOWS + auto parent_pid = GetCurrentThread(); + auto parent_prio_before = GetPriority(parent_pid); + // On Windows, the priority can be set within range [-2, 2], and -2 is the lowest priority. + /* constexpr int LOWER_PRIOIRITY = -1; */ + constexpr int LOWEST_PRIORITY = -2; + /* STARTUPINFO si; */ + /* PROCESS_INFORMATION pi; */ + /* char cmd[] = "pwd"; */ + /* CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); */ + /* auto child_pid = pi.hProcess; */ + // 创建县城 + HANDLE hThread; + DWORD ThreadId; + hThread = CreateThread(NULL, 0, MyThreadFunction, NULL, 0, &ThreadId); + ASSERT(hThread != NULL); +#endif + + auto child_prio_before = GetPriority(hThread); + + // Since setting higher priority needs "sudo" right, we only test lower one here. + auto ret = SetPriority(ThreadId, LOWEST_PRIORITY); + ASSERT_EQ(ret, 0); + + auto child_prio_after = GetPriority(hThread); + auto parent_prio_after = GetPriority(parent_pid); + ASSERT_EQ(parent_prio_before, parent_prio_after); +#ifdef PANDA_TARGET_UNIX + ASSERT(child_prio_before <= child_prio_after); +#elif PANDA_TARGET_WINDOWS + ASSERT(child_prio_after <= child_prio_before); +#endif +} + +#ifdef PANDA_TARGET_UNIX TEST_F(ThreadTest, GetThreadNameTest) { constexpr size_t MAX_LENGTH = 256; @@ -56,16 +175,19 @@ TEST_F(ThreadTest, GetThreadNameTest) auto ret = GetThreadName(getpid(), name, MAX_LENGTH); ASSERT_EQ(ret, 0); } +#endif TEST_F(ThreadTest, SetThreadNameTest) { auto res = SetThreadName(GetNativeHandle(), "TestThread"); ASSERT_EQ(res, 0); +#ifdef PANDA_TARGET_UNIX constexpr size_t MAX_LENGTH = 256; char thread_name[MAX_LENGTH]; auto ret = GetThreadName(getpid(), thread_name, MAX_LENGTH); ASSERT_EQ(ret, 0); char set_name[MAX_LENGTH] = "TestThread"; ASSERT_EQ(*thread_name, *set_name); +#endif } } // namespace panda::os::thread -- Gitee From 00aff2681fcb2e9e20a4d7946207287d01e0a838 Mon Sep 17 00:00:00 2001 From: huangyu Date: Sat, 14 May 2022 16:18:28 +0800 Subject: [PATCH 06/28] [TMP] Correct Set/GetPriority, Set/GetThreadName on windows Signed-off-by: huangyu Change-Id: If952cd600a0015a2a8fe4d2c9e21762ae764c446 --- libpandabase/os/thread.h | 6 ++-- libpandabase/os/unix/thread.cpp | 2 +- libpandabase/os/windows/thread.cpp | 25 +++++++++++++--- libpandabase/tests/base_thread_test.cpp | 40 ++++++++++++++++--------- 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/libpandabase/os/thread.h b/libpandabase/os/thread.h index f08fef5b5e..304f145793 100644 --- a/libpandabase/os/thread.h +++ b/libpandabase/os/thread.h @@ -32,16 +32,16 @@ namespace panda::os::thread { using ThreadId = uint32_t; using native_handle_type = std::thread::native_handle_type; +int GetPriority(unsigned long thread_id); ThreadId GetCurrentThreadId(); #ifdef PANDA_TARGET_UNIX int SetPriority(int thread_id, int prio); -int GetPriority(int thread_id); +int GetThreadName(ThreadId tid, char *name, size_t len); #elif PANDA_TARGET_WINDOWS int SetPriority(DWORD thread_id, int prio); -int GetPriority(HANDLE thread_id); +int GetThreadName(native_handle_type tid, char *name, size_t len); #endif int SetThreadName(native_handle_type pthread_id, const char *name); -int GetThreadName(ThreadId tid, char *name, size_t len); native_handle_type GetNativeHandle(); void Yield(); void NativeSleep(unsigned int ms); diff --git a/libpandabase/os/unix/thread.cpp b/libpandabase/os/unix/thread.cpp index 457e634b62..9d76ce4fe5 100644 --- a/libpandabase/os/unix/thread.cpp +++ b/libpandabase/os/unix/thread.cpp @@ -49,7 +49,7 @@ int SetPriority(int thread_id, int prio) return setpriority(PRIO_PROCESS, thread_id, prio); } -int GetPriority(int thread_id) +int GetPriority(unsigned long thread_id) { return getpriority(PRIO_PROCESS, thread_id); } diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index 0814e9c624..50efa5ae86 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -25,6 +25,11 @@ ThreadId GetCurrentThreadId() return static_cast(std::hash()(std::this_thread::get_id())); } +/* DWORD GetCurrentThreadIdA() */ +/* { */ +/* return GetCurrentThreadId(); */ +/* } */ + int SetPriority([[maybe_unused]] DWORD thread_id, int prio) { auto ret = SetThreadPriority(OpenThread(THREAD_ALL_ACCESS, false, thread_id), prio); @@ -33,15 +38,27 @@ int SetPriority([[maybe_unused]] DWORD thread_id, int prio) return (ret != 0) ? 0 : -1; } -int GetPriority([[maybe_unused]] HANDLE thread_id) +/* int GetPriority(HANDLE thread_id) */ +int GetPriority(DWORD thread_id) { - return GetThreadPriority(GetCurrentThread()); + /* return GetThreadPriority(thread_id); */ + DWORD win_thread_id = reinterpret_cast(thread_id); + HANDLE hthread = OpenThread(THREAD_QUERY_INFORMATION, false, win_thread_id); + return GetThreadPriority(hthread); } -int SetThreadName([[maybe_unused]] native_handle_type pthread_id, const char *name) +int SetThreadName(native_handle_type pthread_id, const char *name) { ASSERT(pthread_id != 0); - return pthread_setname_np(pthread_self(), name); + pthread_t thread = reinterpret_cast(pthread_id); + return pthread_setname_np(thread, name); +} + +int GetThreadName(native_handle_type tid, char *name, size_t len) +{ + ASSERT(tid != 0); + pthread_t thread = reinterpret_cast(tid); + return pthread_getname_np(thread, name, len); } native_handle_type GetNativeHandle() diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index adb1578ceb..c32311979c 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -19,6 +19,7 @@ #include "os/thread.h" #ifdef PANDA_TARGET_WINDOWS +#include #include #include #include @@ -47,11 +48,23 @@ TEST_F(ThreadTest, ThreadStartTest) } /* #elif PANDA_TARGET_UNIX */ #else + +/* class A { */ +/* public: */ +/* int var_ = 2; */ +/* }; */ + void ThreadFunc(int x, int y) { /* sleep(1); */ - NativeSleep(100); + NativeSleep(300); printf("In second thread...\n"); + /* class A a; */ + /* A *pa = &a; */ + /* pa = nullptr; */ + /* if (pa->var_ == 1) { */ + /* printf("error"); */ + /* } */ while (x < 5) { x++; } @@ -67,7 +80,7 @@ TEST_F(ThreadTest, ThreadStartTest) ASSERT_EQ(ret, 0); /* sleep(2); */ - NativeSleep(200); + NativeSleep(400); /* constexpr size_t MAX_LENGTH = 256; */ /* char name1[MAX_LENGTH]; */ @@ -86,14 +99,15 @@ TEST_F(ThreadTest, ThreadStartTest) } #endif -#ifndef PANDA_TARGET_WINDOWS TEST_F(ThreadTest, GetPriorityTest) { - auto priority = GetPriority(getpid()); + DWORD thread = ::GetCurrentThreadId(); + auto priority = GetPriority(thread); // The default priority is 0. ASSERT_EQ(priority, 0); } +#ifndef PANDA_TARGET_WINDOWS TEST_F(ThreadTest, SetCurrentThreadPriorityTest) { #ifdef PANDA_TARGET_UNIX @@ -134,7 +148,8 @@ TEST_F(ThreadTest, SetOtherThreadPriorityTest) auto child_pid = fork(); ASSERT_NE(child_pid, -1); #elif PANDA_TARGET_WINDOWS - auto parent_pid = GetCurrentThread(); + /* auto parent_pid = getpid(); */ + auto parent_pid = ::GetCurrentThreadId(); auto parent_prio_before = GetPriority(parent_pid); // On Windows, the priority can be set within range [-2, 2], and -2 is the lowest priority. /* constexpr int LOWER_PRIOIRITY = -1; */ @@ -151,13 +166,13 @@ TEST_F(ThreadTest, SetOtherThreadPriorityTest) ASSERT(hThread != NULL); #endif - auto child_prio_before = GetPriority(hThread); + auto child_prio_before = GetPriority(ThreadId); // Since setting higher priority needs "sudo" right, we only test lower one here. auto ret = SetPriority(ThreadId, LOWEST_PRIORITY); ASSERT_EQ(ret, 0); - auto child_prio_after = GetPriority(hThread); + auto child_prio_after = GetPriority(ThreadId); auto parent_prio_after = GetPriority(parent_pid); ASSERT_EQ(parent_prio_before, parent_prio_after); #ifdef PANDA_TARGET_UNIX @@ -167,27 +182,24 @@ TEST_F(ThreadTest, SetOtherThreadPriorityTest) #endif } -#ifdef PANDA_TARGET_UNIX TEST_F(ThreadTest, GetThreadNameTest) { constexpr size_t MAX_LENGTH = 256; char name[MAX_LENGTH]; - auto ret = GetThreadName(getpid(), name, MAX_LENGTH); + auto ret = GetThreadName(GetNativeHandle(), name, MAX_LENGTH); ASSERT_EQ(ret, 0); } -#endif TEST_F(ThreadTest, SetThreadNameTest) { auto res = SetThreadName(GetNativeHandle(), "TestThread"); ASSERT_EQ(res, 0); -#ifdef PANDA_TARGET_UNIX constexpr size_t MAX_LENGTH = 256; char thread_name[MAX_LENGTH]; - auto ret = GetThreadName(getpid(), thread_name, MAX_LENGTH); + auto ret = GetThreadName(GetNativeHandle(), thread_name, MAX_LENGTH); ASSERT_EQ(ret, 0); char set_name[MAX_LENGTH] = "TestThread"; - ASSERT_EQ(*thread_name, *set_name); -#endif + ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(thread_name), utf::CStringAsMutf8(set_name)) == 0); + /* ASSERT_EQ(*thread_name, *set_name); */ } } // namespace panda::os::thread -- Gitee From a1da655807e53c084b0a1f2c836c4e1c9201cc8c Mon Sep 17 00:00:00 2001 From: huangyu Date: Sat, 14 May 2022 23:17:43 +0800 Subject: [PATCH 07/28] Unify Set/GetPriority, Set/GetThreadName for windows/unix Signed-off-by: huangyu Change-Id: I8fed8b79e5e5dffb7704eba7ddfa8d6a6751a6b5 --- libpandabase/os/thread.h | 20 ++- libpandabase/os/unix/thread.cpp | 11 +- libpandabase/os/unix/thread.h | 19 +++ libpandabase/os/windows/thread.cpp | 37 ++++-- libpandabase/os/windows/thread.h | 22 +++- libpandabase/tests/base_thread_test.cpp | 167 +++++++++--------------- 6 files changed, 139 insertions(+), 137 deletions(-) create mode 100644 libpandabase/os/unix/thread.h diff --git a/libpandabase/os/thread.h b/libpandabase/os/thread.h index 304f145793..bf14e71f9e 100644 --- a/libpandabase/os/thread.h +++ b/libpandabase/os/thread.h @@ -23,8 +23,12 @@ #include #include #include -#ifdef PANDA_TARGET_WINDOWS -#include +#ifdef PANDA_TARGET_UNIX +#include "os/unix/thread.h" +#elif PANDA_TARGET_WINDOWS +#include "os/windows/thread.h" +#else +#error "Unsupported platform" #endif namespace panda::os::thread { @@ -32,16 +36,10 @@ namespace panda::os::thread { using ThreadId = uint32_t; using native_handle_type = std::thread::native_handle_type; -int GetPriority(unsigned long thread_id); ThreadId GetCurrentThreadId(); -#ifdef PANDA_TARGET_UNIX -int SetPriority(int thread_id, int prio); -int GetThreadName(ThreadId tid, char *name, size_t len); -#elif PANDA_TARGET_WINDOWS -int SetPriority(DWORD thread_id, int prio); -int GetThreadName(native_handle_type tid, char *name, size_t len); -#endif +int GetPid(); int SetThreadName(native_handle_type pthread_id, const char *name); +int GetThreadName(ThreadId tid, native_handle_type pthread_id, char *name, size_t len); native_handle_type GetNativeHandle(); void Yield(); void NativeSleep(unsigned int ms); @@ -141,7 +139,7 @@ native_handle_type ThreadStart(Func *func, Args... args) #ifdef PANDA_TARGET_UNIX return tid; #else - return reinterpret_cast(tid); + return static_cast(tid); #endif } diff --git a/libpandabase/os/unix/thread.cpp b/libpandabase/os/unix/thread.cpp index 9d76ce4fe5..c636bd5ca7 100644 --- a/libpandabase/os/unix/thread.cpp +++ b/libpandabase/os/unix/thread.cpp @@ -44,12 +44,17 @@ ThreadId GetCurrentThreadId() #endif } +int GetPid() +{ + return getpid(); +} + int SetPriority(int thread_id, int prio) { return setpriority(PRIO_PROCESS, thread_id, prio); } -int GetPriority(unsigned long thread_id) +int GetPriority(int thread_id) { return getpriority(PRIO_PROCESS, thread_id); } @@ -64,7 +69,7 @@ int SetThreadName(native_handle_type pthread_id, const char *name) #endif } -int GetThreadName(ThreadId tid, char *name, size_t len) +int GetThreadName(ThreadId tid, native_handle_type pthread_id, char *name, size_t len) { ASSERT(tid != 0); @@ -76,7 +81,7 @@ int GetThreadName(ThreadId tid, char *name, size_t len) if (GetCurrentThreadId() == tid) { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) - return pthread_getname_np(pthread_self(), name, len) != 0 ? errno : 0; + return pthread_getname_np(pthread_id, name, len) != 0 ? errno : 0; } constexpr size_t BUF_LEN = 64; diff --git a/libpandabase/os/unix/thread.h b/libpandabase/os/unix/thread.h new file mode 100644 index 0000000000..68c968fea5 --- /dev/null +++ b/libpandabase/os/unix/thread.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace panda::os::thread { +int GetPriority(int thread_id); +int SetPriority(int thread_id, int prio); +} // namespace panda::os::thread diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index 50efa5ae86..2a3c779fa3 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -19,29 +19,29 @@ #include namespace panda::os::thread { - ThreadId GetCurrentThreadId() { - return static_cast(std::hash()(std::this_thread::get_id())); + std::cout << "GetCurrentThreadId() before = " << static_cast(std::hash()(std::this_thread::get_id())) << std::endl; + std::cout << "GetCurrentThreadId() now = " << ::GetCurrentThreadId() << std::endl; + // The function is provided by mingw + return ::GetCurrentThreadId(); } -/* DWORD GetCurrentThreadIdA() */ -/* { */ -/* return GetCurrentThreadId(); */ -/* } */ +int GetPid() +{ + return ::GetCurrentProcessId(); +} -int SetPriority([[maybe_unused]] DWORD thread_id, int prio) +int SetPriority(DWORD thread_id, int prio) { - auto ret = SetThreadPriority(OpenThread(THREAD_ALL_ACCESS, false, thread_id), prio); + auto ret = SetThreadPriority(OpenThread(THREAD_SET_INFORMATION, false, thread_id), prio); // On linux, the "setpriority" function returns zero if there is no error, or -1 if there is. // While on windows, the return value is nonzero if the function succeeds. return (ret != 0) ? 0 : -1; } -/* int GetPriority(HANDLE thread_id) */ int GetPriority(DWORD thread_id) { - /* return GetThreadPriority(thread_id); */ DWORD win_thread_id = reinterpret_cast(thread_id); HANDLE hthread = OpenThread(THREAD_QUERY_INFORMATION, false, win_thread_id); return GetThreadPriority(hthread); @@ -54,10 +54,10 @@ int SetThreadName(native_handle_type pthread_id, const char *name) return pthread_setname_np(thread, name); } -int GetThreadName(native_handle_type tid, char *name, size_t len) +int GetThreadName([[maybe_unused]] ThreadId tid, native_handle_type pthread_id, char *name, size_t len) { - ASSERT(tid != 0); - pthread_t thread = reinterpret_cast(tid); + ASSERT(pthread_id != 0); + pthread_t thread = reinterpret_cast(pthread_id); return pthread_getname_np(thread, name, len); } @@ -76,9 +76,18 @@ void NativeSleep(unsigned int ms) std::this_thread::sleep_for(std::chrono::milliseconds(ms)); } +void ThreadDetach(native_handle_type pthread_id) +{ + pthread_detach(reinterpret_cast(pthread_id)); +} + +void ThreadExit(void *retval) +{ + pthread_exit(retval); +} + void ThreadJoin(native_handle_type pthread_id, void **retval) { pthread_join(reinterpret_cast(pthread_id), retval); } - } // namespace panda::os::thread diff --git a/libpandabase/os/windows/thread.h b/libpandabase/os/windows/thread.h index fd2a790a5b..b0eeb984d0 100644 --- a/libpandabase/os/windows/thread.h +++ b/libpandabase/os/windows/thread.h @@ -1,5 +1,21 @@ -#include +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include -int GetPriority(HANDLE pid); -int SetPriority(HANDLE pid, DWORD priority); +namespace panda::os::thread { +int GetPriority(DWORD thread_id); +int SetPriority(DWORD thread_id, int prio); +} // namespace panda::os::thread diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index c32311979c..a99b04275e 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -28,108 +28,66 @@ namespace panda::os::thread { class ThreadTest : public testing::Test {}; -#if !PANDA_TARGET_WINDOWS -unsigned __stdcall ThreadFunc([[maybe_unused]] void *args) -{ - printf("In second thread...\n"); - _endthreadex(0); - return 0; -} +uint32_t thread_id_ = 0; -TEST_F(ThreadTest, ThreadStartTest) -{ - HANDLE hThread; - unsigned threadID; - printf("Creating second thread...\n"); - hThread = (HANDLE)_beginthreadex(NULL, 0, &ThreadFunc, NULL, 0, &threadID); - WaitForSingleObject(hThread, INFINITE); - printf("CloseHandle...\n"); - CloseHandle(hThread); -} -/* #elif PANDA_TARGET_UNIX */ -#else +#ifdef PANDA_TARGET_UNIX +//TODO(huangyu): wrap the condition judgement for windows into SetPriority +// On linux, the priority can be set within range [-20, 19], and 19 is the lowest priority. +constexpr int LOWER_PRIOIRITY = 1; +constexpr int LOWEST_PRIORITY = 19; +#elif PANDA_TARGET_WINDOWS +// On Windows, the priority can be set within range [-2, 2], and -2 is the lowest priority. +constexpr int LOWER_PRIOIRITY = -1; +constexpr int LOWEST_PRIORITY = -2; +#endif -/* class A { */ -/* public: */ -/* int var_ = 2; */ -/* }; */ -void ThreadFunc(int x, int y) +void ThreadFunc(std::string message) { - /* sleep(1); */ - NativeSleep(300); - printf("In second thread...\n"); - /* class A a; */ - /* A *pa = &a; */ - /* pa = nullptr; */ - /* if (pa->var_ == 1) { */ - /* printf("error"); */ - /* } */ - while (x < 5) { - x++; - } - while (y < 3) { - y++; - } + std::cout << "Print from the second thread:\n" << message << std::endl; + NativeSleep(100); + std::cout << "ThreadFunc before thread_id_ = " << thread_id_ << std::endl; + thread_id_ = GetCurrentThreadId(); + std::cout << "ThreadFunc after thread_id_ = " << thread_id_ << std::endl; + NativeSleep(400); } TEST_F(ThreadTest, ThreadStartTest) { - auto thread_id = ThreadStart(ThreadFunc, 1, 2); - auto ret = SetThreadName(thread_id, "Thread_2"); - ASSERT_EQ(ret, 0); - - /* sleep(2); */ + auto thread_id = ThreadStart(ThreadFunc, "Start thread..."); + std::cout << "======== ThreadStartTest =========" << std::endl; + std::cout << "thread_id = " << thread_id << std::endl; NativeSleep(400); + std::cout << "thread_id tid = " << thread_id_ << std::endl; - /* constexpr size_t MAX_LENGTH = 256; */ - /* char name1[MAX_LENGTH]; */ - /* auto ret1 = GetThreadName(getpid(), name1, MAX_LENGTH); */ - /* ASSERT_EQ(ret1, 0); */ - /* char set_name2[MAX_LENGTH] = "Thread_2"; */ - /* ASSERT_NE(*name1, *set_name2); */ - - /* char name2[MAX_LENGTH]; */ - /* auto ret2 = GetThreadName(reinterpret_cast(thread_id), name2, MAX_LENGTH); */ - /* ASSERT_EQ(ret2, 0); */ - /* ASSERT_EQ(*name2, *set_name2); */ - printf("ThreadDetach...\n"); - /* ThreadDetach(thread_id); */ - + ThreadDetach(thread_id); + ASSERT(GetCurrentThreadId() != thread_id_); } -#endif TEST_F(ThreadTest, GetPriorityTest) { - DWORD thread = ::GetCurrentThreadId(); + auto thread = GetCurrentThreadId(); + std::cout << "======== GetPriorityTest ========" << std::endl; + std::cout << "thread = " << thread << std::endl; auto priority = GetPriority(thread); // The default priority is 0. ASSERT_EQ(priority, 0); } -#ifndef PANDA_TARGET_WINDOWS TEST_F(ThreadTest, SetCurrentThreadPriorityTest) { -#ifdef PANDA_TARGET_UNIX - // On linux, the priority can be set within range [-20, 19], and 19 is the lowest priority. - constexpr int LOWER_PRIOIRITY = 1; - /* constexpr int LOWEST_PRIORITY = 19; */ -#elif PANDA_TARGET_WINDOWS - // On Windows, the priority can be set within range [-2, 2], and -2 is the lowest priority. - constexpr int LOWER_PRIOIRITY = -1; - /* constexpr int LOWEST_PRIORITY = -2; */ -#endif // Since setting higher priority needs "sudo" right, we only test lower one here. - auto ret1 = SetPriority(getpid(), LOWER_PRIOIRITY); + std::cout << "======== SetCurrentThreadPriorityTest ========" << std::endl; + std::cout << "GetCurrentThreadId() = " << GetCurrentThreadId() << std::endl; + auto ret1 = SetPriority(GetCurrentThreadId(), LOWER_PRIOIRITY); ASSERT_EQ(ret1, 0); - auto prio1 = GetPriority(getpid()); + auto prio1 = GetPriority(GetCurrentThreadId()); ASSERT_EQ(prio1, LOWER_PRIOIRITY); - /* auto ret2 = SetPriority(getpid(), LOWEST_PRIORITY); */ - /* ASSERT_EQ(ret2, 0); */ - /* auto prio2 = GetPriority(getpid()); */ - /* ASSERT_EQ(prio2, LOWEST_PRIORITY); */ + auto ret2 = SetPriority(GetCurrentThreadId(), LOWEST_PRIORITY); + ASSERT_EQ(ret2, 0); + auto prio2 = GetPriority(GetCurrentThreadId()); + ASSERT_EQ(prio2, LOWEST_PRIORITY); } -#endif #ifdef PANDA_TARGET_WINDOWS DWORD WINAPI MyThreadFunction([[maybe_unused]] LPVOID lpParam) @@ -137,42 +95,37 @@ DWORD WINAPI MyThreadFunction([[maybe_unused]] LPVOID lpParam) return 0; } #endif + TEST_F(ThreadTest, SetOtherThreadPriorityTest) { -#ifdef PANDA_TARGET_UNIX - auto parent_pid = getpid(); + std::cout << "======== SetOtherThreadPriorityTest ========" << std::endl; + auto parent_pid = GetCurrentThreadId(); + std::cout << "parent_pid = " << parent_pid << std::endl; auto parent_prio_before = GetPriority(parent_pid); +#ifdef PANDA_TARGET_UNIX // On linux, the priority can be set within range [-20, 19], and 19 is the lowest priority. - /* constexpr int LOWER_PRIOIRITY = 1; */ + // TODO(huangyu): move const values to class ThreadTest constexpr int LOWEST_PRIORITY = 19; - auto child_pid = fork(); - ASSERT_NE(child_pid, -1); + /* auto child_pid = fork(); */ + /* ASSERT_NE(child_pid, -1); */ #elif PANDA_TARGET_WINDOWS - /* auto parent_pid = getpid(); */ - auto parent_pid = ::GetCurrentThreadId(); - auto parent_prio_before = GetPriority(parent_pid); // On Windows, the priority can be set within range [-2, 2], and -2 is the lowest priority. - /* constexpr int LOWER_PRIOIRITY = -1; */ constexpr int LOWEST_PRIORITY = -2; - /* STARTUPINFO si; */ - /* PROCESS_INFORMATION pi; */ - /* char cmd[] = "pwd"; */ - /* CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); */ - /* auto child_pid = pi.hProcess; */ - // 创建县城 - HANDLE hThread; - DWORD ThreadId; - hThread = CreateThread(NULL, 0, MyThreadFunction, NULL, 0, &ThreadId); - ASSERT(hThread != NULL); -#endif - auto child_prio_before = GetPriority(ThreadId); - - // Since setting higher priority needs "sudo" right, we only test lower one here. - auto ret = SetPriority(ThreadId, LOWEST_PRIORITY); + // 创建线程 + /* HANDLE hThread; */ + /* DWORD ThreadId; */ + /* hThread = CreateThread(NULL, 0, MyThreadFunction, NULL, 0, &ThreadId); */ + /* ASSERT(hThread != NULL); */ +#endif + auto new_thread = ThreadStart(ThreadFunc, "Start thread..."); + std::cout << "new_thread = " << new_thread << std::endl; + NativeSleep(200); + auto child_prio_before = GetPriority(thread_id_); + auto ret = SetPriority(thread_id_, LOWEST_PRIORITY); ASSERT_EQ(ret, 0); - auto child_prio_after = GetPriority(ThreadId); + auto child_prio_after = GetPriority(thread_id_); auto parent_prio_after = GetPriority(parent_pid); ASSERT_EQ(parent_prio_before, parent_prio_after); #ifdef PANDA_TARGET_UNIX @@ -186,20 +139,22 @@ TEST_F(ThreadTest, GetThreadNameTest) { constexpr size_t MAX_LENGTH = 256; char name[MAX_LENGTH]; - auto ret = GetThreadName(GetNativeHandle(), name, MAX_LENGTH); + auto ret = GetThreadName(GetCurrentThreadId(), GetNativeHandle(), name, MAX_LENGTH); ASSERT_EQ(ret, 0); } -TEST_F(ThreadTest, SetThreadNameTest) +TEST_F(ThreadTest, SetCurrentThreadNameTest) { + std::cout << "======== SetCurrentThreadNameTest ========" << std::endl; auto res = SetThreadName(GetNativeHandle(), "TestThread"); + std::cout << "GetNativeHandle() = " << GetNativeHandle() << std::endl; + std::cout << "GetCurrentThreadId() = " << GetCurrentThreadId() << std::endl; ASSERT_EQ(res, 0); constexpr size_t MAX_LENGTH = 256; char thread_name[MAX_LENGTH]; - auto ret = GetThreadName(GetNativeHandle(), thread_name, MAX_LENGTH); + auto ret = GetThreadName(GetCurrentThreadId(), GetNativeHandle(), thread_name, MAX_LENGTH); ASSERT_EQ(ret, 0); char set_name[MAX_LENGTH] = "TestThread"; ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(thread_name), utf::CStringAsMutf8(set_name)) == 0); - /* ASSERT_EQ(*thread_name, *set_name); */ } } // namespace panda::os::thread -- Gitee From 68bc80b273eeec2bf2eabb77e6634894332bb27a Mon Sep 17 00:00:00 2001 From: huangyu Date: Sun, 15 May 2022 21:10:03 +0800 Subject: [PATCH 08/28] Fix compiling issue for ark_js_vm.exe Signed-off-by: huangyu Change-Id: Ie982c11c368c4a7cd92d7b22edf40100c314359d --- libpandabase/os/thread.h | 2 +- libpandabase/os/windows/thread.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libpandabase/os/thread.h b/libpandabase/os/thread.h index bf14e71f9e..b2335ff41e 100644 --- a/libpandabase/os/thread.h +++ b/libpandabase/os/thread.h @@ -139,7 +139,7 @@ native_handle_type ThreadStart(Func *func, Args... args) #ifdef PANDA_TARGET_UNIX return tid; #else - return static_cast(tid); + return reinterpret_cast(tid); #endif } diff --git a/libpandabase/os/windows/thread.h b/libpandabase/os/windows/thread.h index b0eeb984d0..138a818eb7 100644 --- a/libpandabase/os/windows/thread.h +++ b/libpandabase/os/windows/thread.h @@ -13,9 +13,9 @@ * limitations under the License. */ -#include - namespace panda::os::thread { +using DWORD = unsigned long; + int GetPriority(DWORD thread_id); int SetPriority(DWORD thread_id, int prio); } // namespace panda::os::thread -- Gitee From e1880f5ab546619b15d84dc50e07a4c310da14b2 Mon Sep 17 00:00:00 2001 From: huangyu Date: Wed, 18 May 2022 11:32:43 +0800 Subject: [PATCH 09/28] Modiy SetPriority for windows and remove unuseful test Signed-off-by: huangyu Change-Id: I31cebf4b38a64c32e158048ca6e9200665233eed --- libpandabase/os/windows/thread.cpp | 16 ++++++++++++ libpandabase/os/windows/thread.h | 7 ++++++ libpandabase/tests/base_thread_test.cpp | 33 ------------------------- 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index 2a3c779fa3..7fff4c8be5 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -34,7 +34,23 @@ int GetPid() int SetPriority(DWORD thread_id, int prio) { + // On linux, by "setpriority" function, the priority can be set within range [-20, 19], and 19 is the lowest priority. + // While on Windows, the priority can only be set as the following values. + // See https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadpriority. + if (prio <= 19 && prio >= 11) { + prio = THREAD_PRIORITY_LOWEST; + } else if (prio <= 10 && prio >=1 ) { + prio = THREAD_PRIORITY_BELOW_NORMAL; + } else if (prio == 0) { + prio = THREAD_PRIORITY_NORMAL; + } else if (prio <= -1 && prio >= -10) { + prio = THREAD_PRIORITY_ABOVE_NORMAL; + } else if (prio <= -11 && prio >= -20) { + prio = THREAD_PRIORITY_HIGHEST; + } + auto ret = SetThreadPriority(OpenThread(THREAD_SET_INFORMATION, false, thread_id), prio); + // On linux, the "setpriority" function returns zero if there is no error, or -1 if there is. // While on windows, the return value is nonzero if the function succeeds. return (ret != 0) ? 0 : -1; diff --git a/libpandabase/os/windows/thread.h b/libpandabase/os/windows/thread.h index 138a818eb7..e8182d305e 100644 --- a/libpandabase/os/windows/thread.h +++ b/libpandabase/os/windows/thread.h @@ -14,6 +14,13 @@ */ namespace panda::os::thread { + +constexpr int THREAD_PRIORITY_LOWEST = -2; +constexpr int THREAD_PRIORITY_BELOW_NORMAL = -1; +constexpr int THREAD_PRIORITY_NORMAL = 0; +constexpr int THREAD_PRIORITY_ABOVE_NORMAL = 1; +constexpr int THREAD_PRIORITY_HIGHEST = 2; + using DWORD = unsigned long; int GetPriority(DWORD thread_id); diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index a99b04275e..31eb31b010 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -29,18 +29,8 @@ namespace panda::os::thread { class ThreadTest : public testing::Test {}; uint32_t thread_id_ = 0; - -#ifdef PANDA_TARGET_UNIX -//TODO(huangyu): wrap the condition judgement for windows into SetPriority -// On linux, the priority can be set within range [-20, 19], and 19 is the lowest priority. constexpr int LOWER_PRIOIRITY = 1; constexpr int LOWEST_PRIORITY = 19; -#elif PANDA_TARGET_WINDOWS -// On Windows, the priority can be set within range [-2, 2], and -2 is the lowest priority. -constexpr int LOWER_PRIOIRITY = -1; -constexpr int LOWEST_PRIORITY = -2; -#endif - void ThreadFunc(std::string message) { @@ -89,35 +79,12 @@ TEST_F(ThreadTest, SetCurrentThreadPriorityTest) ASSERT_EQ(prio2, LOWEST_PRIORITY); } -#ifdef PANDA_TARGET_WINDOWS -DWORD WINAPI MyThreadFunction([[maybe_unused]] LPVOID lpParam) -{ - return 0; -} -#endif - TEST_F(ThreadTest, SetOtherThreadPriorityTest) { std::cout << "======== SetOtherThreadPriorityTest ========" << std::endl; auto parent_pid = GetCurrentThreadId(); std::cout << "parent_pid = " << parent_pid << std::endl; auto parent_prio_before = GetPriority(parent_pid); -#ifdef PANDA_TARGET_UNIX - // On linux, the priority can be set within range [-20, 19], and 19 is the lowest priority. - // TODO(huangyu): move const values to class ThreadTest - constexpr int LOWEST_PRIORITY = 19; - /* auto child_pid = fork(); */ - /* ASSERT_NE(child_pid, -1); */ -#elif PANDA_TARGET_WINDOWS - // On Windows, the priority can be set within range [-2, 2], and -2 is the lowest priority. - constexpr int LOWEST_PRIORITY = -2; - - // 创建线程 - /* HANDLE hThread; */ - /* DWORD ThreadId; */ - /* hThread = CreateThread(NULL, 0, MyThreadFunction, NULL, 0, &ThreadId); */ - /* ASSERT(hThread != NULL); */ -#endif auto new_thread = ThreadStart(ThreadFunc, "Start thread..."); std::cout << "new_thread = " << new_thread << std::endl; NativeSleep(200); -- Gitee From 6195dd7acad39ade6206147f6cc31515473a48ea Mon Sep 17 00:00:00 2001 From: huangyu Date: Wed, 18 May 2022 12:15:59 +0800 Subject: [PATCH 10/28] Revert wrap SetPrioirty on windows and fix typos Signed-off-by: huangyu Change-Id: Icfbe760e211853a385c43aa9b29da28d3ca7db6a --- libpandabase/os/unix/thread.cpp | 1 - libpandabase/os/windows/thread.cpp | 21 ++------------------- libpandabase/os/windows/thread.h | 7 ------- libpandabase/tests/base_thread_test.cpp | 8 ++++++++ 4 files changed, 10 insertions(+), 27 deletions(-) diff --git a/libpandabase/os/unix/thread.cpp b/libpandabase/os/unix/thread.cpp index c636bd5ca7..c4be4107cf 100644 --- a/libpandabase/os/unix/thread.cpp +++ b/libpandabase/os/unix/thread.cpp @@ -72,7 +72,6 @@ int SetThreadName(native_handle_type pthread_id, const char *name) int GetThreadName(ThreadId tid, native_handle_type pthread_id, char *name, size_t len) { ASSERT(tid != 0); - constexpr size_t MAX_TASK_COMM_LEN =16; if (len < MAX_TASK_COMM_LEN) { diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index 7fff4c8be5..7d1c874710 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -29,28 +29,12 @@ ThreadId GetCurrentThreadId() int GetPid() { - return ::GetCurrentProcessId(); + return _getpid(); } int SetPriority(DWORD thread_id, int prio) { - // On linux, by "setpriority" function, the priority can be set within range [-20, 19], and 19 is the lowest priority. - // While on Windows, the priority can only be set as the following values. - // See https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadpriority. - if (prio <= 19 && prio >= 11) { - prio = THREAD_PRIORITY_LOWEST; - } else if (prio <= 10 && prio >=1 ) { - prio = THREAD_PRIORITY_BELOW_NORMAL; - } else if (prio == 0) { - prio = THREAD_PRIORITY_NORMAL; - } else if (prio <= -1 && prio >= -10) { - prio = THREAD_PRIORITY_ABOVE_NORMAL; - } else if (prio <= -11 && prio >= -20) { - prio = THREAD_PRIORITY_HIGHEST; - } - auto ret = SetThreadPriority(OpenThread(THREAD_SET_INFORMATION, false, thread_id), prio); - // On linux, the "setpriority" function returns zero if there is no error, or -1 if there is. // While on windows, the return value is nonzero if the function succeeds. return (ret != 0) ? 0 : -1; @@ -58,8 +42,7 @@ int SetPriority(DWORD thread_id, int prio) int GetPriority(DWORD thread_id) { - DWORD win_thread_id = reinterpret_cast(thread_id); - HANDLE hthread = OpenThread(THREAD_QUERY_INFORMATION, false, win_thread_id); + HANDLE hthread = OpenThread(THREAD_QUERY_INFORMATION, false, thread_id); return GetThreadPriority(hthread); } diff --git a/libpandabase/os/windows/thread.h b/libpandabase/os/windows/thread.h index e8182d305e..138a818eb7 100644 --- a/libpandabase/os/windows/thread.h +++ b/libpandabase/os/windows/thread.h @@ -14,13 +14,6 @@ */ namespace panda::os::thread { - -constexpr int THREAD_PRIORITY_LOWEST = -2; -constexpr int THREAD_PRIORITY_BELOW_NORMAL = -1; -constexpr int THREAD_PRIORITY_NORMAL = 0; -constexpr int THREAD_PRIORITY_ABOVE_NORMAL = 1; -constexpr int THREAD_PRIORITY_HIGHEST = 2; - using DWORD = unsigned long; int GetPriority(DWORD thread_id); diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index 31eb31b010..870e14da19 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -29,8 +29,16 @@ namespace panda::os::thread { class ThreadTest : public testing::Test {}; uint32_t thread_id_ = 0; + +#ifdef PANDA_TARGET_UNIX +// On linux, the priority can be set within range [-20, 19], and 19 is the lowest priority. constexpr int LOWER_PRIOIRITY = 1; constexpr int LOWEST_PRIORITY = 19; +#elif PANDA_TARGET_WINDOWS +// On Windows, the priority can be set within range [-2, 2], and -2 is the lowest priority. +constexpr int LOWER_PRIOIRITY = -1; +constexpr int LOWEST_PRIORITY = -2; +#endif void ThreadFunc(std::string message) { -- Gitee From 70c0bb3b051cd3d69598cdab8a73de0356a936c4 Mon Sep 17 00:00:00 2001 From: huangyu Date: Wed, 18 May 2022 15:21:19 +0800 Subject: [PATCH 11/28] Add SetOtherThreadNameTest Change-Id: Id3407c050e7c7d813b23994877d0df82e46a8a81 --- libpandabase/tests/base_thread_test.cpp | 38 +++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index 870e14da19..cda949d4b0 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -132,4 +132,42 @@ TEST_F(ThreadTest, SetCurrentThreadNameTest) char set_name[MAX_LENGTH] = "TestThread"; ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(thread_name), utf::CStringAsMutf8(set_name)) == 0); } + +TEST_F(ThreadTest, SetOtherThreadNameTest) +{ + std::cout << "======== SetOtherThreadNameTest ========" << std::endl; + auto pid1 = GetCurrentThreadId(); + auto handle1 = GetNativeHandle(); + std::cout << "pid1 = " << pid1 << std::endl; + + // TODO(huangyu): move MAX_LENGTH to above, only use one, and be smaller + constexpr size_t MAX_LENGTH = 256; + char name1_before[MAX_LENGTH]; + auto ret = GetThreadName(pid1, handle1, name1_before, MAX_LENGTH); + ASSERT_EQ(ret, 0); + + auto handle2 = ThreadStart(ThreadFunc, "Start thread..."); + std::cout << "handle2 = " << handle2 << std::endl; + NativeSleep(200); + auto pid2 = thread_id_; + char name2_before[MAX_LENGTH]; + ret = GetThreadName(pid2, handle2, name2_before, MAX_LENGTH); + ASSERT_EQ(ret, 0); + + ret = SetThreadName(handle2, "thread2"); + ASSERT_EQ(ret, 0); + + char name1_after[MAX_LENGTH]; + char name2_after[MAX_LENGTH]; + ret = GetThreadName(pid1, handle1, name1_after, MAX_LENGTH); + ASSERT_EQ(ret, 0); + ret = GetThreadName(pid2, handle2, name2_after, MAX_LENGTH); + ASSERT_EQ(ret, 0); + ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(name1_before), utf::CStringAsMutf8(name1_after)) == 0); + ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(name2_before), utf::CStringAsMutf8(name2_after)) != 0); + + char set_name[MAX_LENGTH] = "thread2"; + ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(name2_after), utf::CStringAsMutf8(set_name)) == 0); +} + } // namespace panda::os::thread -- Gitee From 743a600d95c73140bb1dd9b7f42e54409fdf7683 Mon Sep 17 00:00:00 2001 From: huangyu Date: Wed, 18 May 2022 17:05:13 +0800 Subject: [PATCH 12/28] Simplify base_thread_test Signed-off-by: huangyu Change-Id: Ie6a59be4afab7d54e9db3ee81615ad6dd9be2f10 --- libpandabase/os/windows/thread.cpp | 2 - libpandabase/tests/base_thread_test.cpp | 85 +++++++++++-------------- 2 files changed, 36 insertions(+), 51 deletions(-) diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index 7d1c874710..fcafe8b087 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -21,8 +21,6 @@ namespace panda::os::thread { ThreadId GetCurrentThreadId() { - std::cout << "GetCurrentThreadId() before = " << static_cast(std::hash()(std::this_thread::get_id())) << std::endl; - std::cout << "GetCurrentThreadId() now = " << ::GetCurrentThreadId() << std::endl; // The function is provided by mingw return ::GetCurrentThreadId(); } diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index cda949d4b0..05c55032d0 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -29,6 +29,10 @@ namespace panda::os::thread { class ThreadTest : public testing::Test {}; uint32_t thread_id_ = 0; +constexpr size_t MAX_LENGTH = 64; +const char *const_set_name1 = "TestThread"; +const char *const_set_name2 = "NewThread"; +char set_name[MAX_LENGTH] = "TestThread"; #ifdef PANDA_TARGET_UNIX // On linux, the priority can be set within range [-20, 19], and 19 is the lowest priority. @@ -40,68 +44,56 @@ constexpr int LOWER_PRIOIRITY = -1; constexpr int LOWEST_PRIORITY = -2; #endif -void ThreadFunc(std::string message) +void ThreadFunc(std::string message, int sleep_time) { - std::cout << "Print from the second thread:\n" << message << std::endl; - NativeSleep(100); - std::cout << "ThreadFunc before thread_id_ = " << thread_id_ << std::endl; thread_id_ = GetCurrentThreadId(); - std::cout << "ThreadFunc after thread_id_ = " << thread_id_ << std::endl; - NativeSleep(400); + std::cout << "[Thread " << thread_id_ << "] " << message << std::endl; + NativeSleep(sleep_time); } TEST_F(ThreadTest, ThreadStartTest) { - auto thread_id = ThreadStart(ThreadFunc, "Start thread..."); - std::cout << "======== ThreadStartTest =========" << std::endl; - std::cout << "thread_id = " << thread_id << std::endl; - NativeSleep(400); - std::cout << "thread_id tid = " << thread_id_ << std::endl; - - ThreadDetach(thread_id); + auto thread_id = ThreadStart(ThreadFunc, "Start thread...", 200); + // Waiting for thread_id_ updates to the new thread id + NativeSleep(300); ASSERT(GetCurrentThreadId() != thread_id_); -} - -TEST_F(ThreadTest, GetPriorityTest) -{ - auto thread = GetCurrentThreadId(); - std::cout << "======== GetPriorityTest ========" << std::endl; - std::cout << "thread = " << thread << std::endl; - auto priority = GetPriority(thread); - // The default priority is 0. - ASSERT_EQ(priority, 0); + ThreadDetach(thread_id); } TEST_F(ThreadTest, SetCurrentThreadPriorityTest) { // Since setting higher priority needs "sudo" right, we only test lower one here. - std::cout << "======== SetCurrentThreadPriorityTest ========" << std::endl; - std::cout << "GetCurrentThreadId() = " << GetCurrentThreadId() << std::endl; auto ret1 = SetPriority(GetCurrentThreadId(), LOWER_PRIOIRITY); ASSERT_EQ(ret1, 0); + auto prio1 = GetPriority(GetCurrentThreadId()); ASSERT_EQ(prio1, LOWER_PRIOIRITY); + auto ret2 = SetPriority(GetCurrentThreadId(), LOWEST_PRIORITY); ASSERT_EQ(ret2, 0); + auto prio2 = GetPriority(GetCurrentThreadId()); ASSERT_EQ(prio2, LOWEST_PRIORITY); } TEST_F(ThreadTest, SetOtherThreadPriorityTest) { - std::cout << "======== SetOtherThreadPriorityTest ========" << std::endl; auto parent_pid = GetCurrentThreadId(); - std::cout << "parent_pid = " << parent_pid << std::endl; auto parent_prio_before = GetPriority(parent_pid); - auto new_thread = ThreadStart(ThreadFunc, "Start thread..."); - std::cout << "new_thread = " << new_thread << std::endl; - NativeSleep(200); + + auto new_thread = ThreadStart(ThreadFunc, "Start thread...", 200); + // Waiting for thread_id_ updates to the new thread id, and before the new thread exited + NativeSleep(100); + auto child_prio_before = GetPriority(thread_id_); auto ret = SetPriority(thread_id_, LOWEST_PRIORITY); ASSERT_EQ(ret, 0); auto child_prio_after = GetPriority(thread_id_); auto parent_prio_after = GetPriority(parent_pid); + + ThreadDetach(new_thread); + ASSERT_EQ(parent_prio_before, parent_prio_after); #ifdef PANDA_TARGET_UNIX ASSERT(child_prio_before <= child_prio_after); @@ -112,7 +104,6 @@ TEST_F(ThreadTest, SetOtherThreadPriorityTest) TEST_F(ThreadTest, GetThreadNameTest) { - constexpr size_t MAX_LENGTH = 256; char name[MAX_LENGTH]; auto ret = GetThreadName(GetCurrentThreadId(), GetNativeHandle(), name, MAX_LENGTH); ASSERT_EQ(ret, 0); @@ -120,54 +111,50 @@ TEST_F(ThreadTest, GetThreadNameTest) TEST_F(ThreadTest, SetCurrentThreadNameTest) { - std::cout << "======== SetCurrentThreadNameTest ========" << std::endl; - auto res = SetThreadName(GetNativeHandle(), "TestThread"); - std::cout << "GetNativeHandle() = " << GetNativeHandle() << std::endl; - std::cout << "GetCurrentThreadId() = " << GetCurrentThreadId() << std::endl; + auto res = SetThreadName(GetNativeHandle(), const_set_name1); ASSERT_EQ(res, 0); - constexpr size_t MAX_LENGTH = 256; + char thread_name[MAX_LENGTH]; auto ret = GetThreadName(GetCurrentThreadId(), GetNativeHandle(), thread_name, MAX_LENGTH); + ASSERT_EQ(ret, 0); - char set_name[MAX_LENGTH] = "TestThread"; ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(thread_name), utf::CStringAsMutf8(set_name)) == 0); } TEST_F(ThreadTest, SetOtherThreadNameTest) { - std::cout << "======== SetOtherThreadNameTest ========" << std::endl; auto pid1 = GetCurrentThreadId(); auto handle1 = GetNativeHandle(); - std::cout << "pid1 = " << pid1 << std::endl; - // TODO(huangyu): move MAX_LENGTH to above, only use one, and be smaller - constexpr size_t MAX_LENGTH = 256; char name1_before[MAX_LENGTH]; auto ret = GetThreadName(pid1, handle1, name1_before, MAX_LENGTH); ASSERT_EQ(ret, 0); - auto handle2 = ThreadStart(ThreadFunc, "Start thread..."); - std::cout << "handle2 = " << handle2 << std::endl; - NativeSleep(200); + auto handle2 = ThreadStart(ThreadFunc, "Start thread...", 300); + // Waiting for thread_id_ updates to the new thread id, and before the new thread exited + NativeSleep(100); auto pid2 = thread_id_; + char name2_before[MAX_LENGTH]; ret = GetThreadName(pid2, handle2, name2_before, MAX_LENGTH); ASSERT_EQ(ret, 0); - ret = SetThreadName(handle2, "thread2"); + ret = SetThreadName(handle2, "NewThread"); ASSERT_EQ(ret, 0); char name1_after[MAX_LENGTH]; - char name2_after[MAX_LENGTH]; ret = GetThreadName(pid1, handle1, name1_after, MAX_LENGTH); ASSERT_EQ(ret, 0); + + char name2_after[MAX_LENGTH]; ret = GetThreadName(pid2, handle2, name2_after, MAX_LENGTH); ASSERT_EQ(ret, 0); + + ThreadDetach(handle2); + ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(name1_before), utf::CStringAsMutf8(name1_after)) == 0); ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(name2_before), utf::CStringAsMutf8(name2_after)) != 0); - - char set_name[MAX_LENGTH] = "thread2"; - ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(name2_after), utf::CStringAsMutf8(set_name)) == 0); + ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(name2_after), utf::CStringAsMutf8(const_set_name2)) == 0); } } // namespace panda::os::thread -- Gitee From 47be5681aef4303b0ac2996f3bf68d5097427533 Mon Sep 17 00:00:00 2001 From: huangyu Date: Fri, 20 May 2022 12:40:07 +0800 Subject: [PATCH 13/28] Fix typos Signed-off-by: huangyu Change-Id: I18933471bce0b04f1e748237294adc2e960fc4a5 --- libpandabase/os/thread.h | 10 ++++---- libpandabase/os/unix/library_loader.cpp | 4 ++- libpandabase/os/unix/thread.cpp | 26 +++++++++---------- libpandabase/os/unix/thread.h | 5 ++++ libpandabase/os/windows/library_loader.cpp | 4 ++- libpandabase/os/windows/mem_hooks.cpp | 4 +-- libpandabase/os/windows/thread.cpp | 29 +++++++++++----------- libpandabase/os/windows/thread.h | 5 ++++ libpandabase/tests/base_thread_test.cpp | 9 +++---- 9 files changed, 55 insertions(+), 41 deletions(-) diff --git a/libpandabase/os/thread.h b/libpandabase/os/thread.h index b2335ff41e..38aa963eac 100644 --- a/libpandabase/os/thread.h +++ b/libpandabase/os/thread.h @@ -38,14 +38,14 @@ using native_handle_type = std::thread::native_handle_type; ThreadId GetCurrentThreadId(); int GetPid(); -int SetThreadName(native_handle_type pthread_id, const char *name); -int GetThreadName(ThreadId tid, native_handle_type pthread_id, char *name, size_t len); +int SetThreadName(native_handle_type pthread_handle, const char *name); +int GetThreadName(ThreadId tid, native_handle_type pthread_handle, char *name, size_t len); native_handle_type GetNativeHandle(); void Yield(); void NativeSleep(unsigned int ms); -void ThreadDetach(native_handle_type pthread_id); -void ThreadExit(void *retval); -void ThreadJoin(native_handle_type pthread_id, void **retval); +void ThreadDetach(native_handle_type pthread_handle); +void ThreadExit(void *ret); +void ThreadJoin(native_handle_type pthread_handle, void **ret); // Templated functions need to be defined here to be accessible everywhere diff --git a/libpandabase/os/unix/library_loader.cpp b/libpandabase/os/unix/library_loader.cpp index 9bc041848d..01b1907485 100644 --- a/libpandabase/os/unix/library_loader.cpp +++ b/libpandabase/os/unix/library_loader.cpp @@ -41,6 +41,8 @@ Expected ResolveSymbol(const LibraryHandle &handle, std::string_v void CloseHandle(void *handle) { - dlclose(handle); + if (handle != nullptr) { + dlclose(handle); + } } } // namespace panda::os::library_loader diff --git a/libpandabase/os/unix/thread.cpp b/libpandabase/os/unix/thread.cpp index c4be4107cf..f73be4bfe4 100644 --- a/libpandabase/os/unix/thread.cpp +++ b/libpandabase/os/unix/thread.cpp @@ -59,20 +59,20 @@ int GetPriority(int thread_id) return getpriority(PRIO_PROCESS, thread_id); } -int SetThreadName(native_handle_type pthread_id, const char *name) +int SetThreadName(native_handle_type pthread_handle, const char *name) { - ASSERT(pthread_id != 0); + ASSERT(pthread_handle != 0); #if defined(PANDA_TARGET_MACOS) return pthread_setname_np(name); #else - return pthread_setname_np(pthread_id, name); + return pthread_setname_np(pthread_handle, name); #endif } -int GetThreadName(ThreadId tid, native_handle_type pthread_id, char *name, size_t len) +int GetThreadName(ThreadId tid, native_handle_type pthread_handle, char *name, size_t len) { ASSERT(tid != 0); - constexpr size_t MAX_TASK_COMM_LEN =16; + constexpr size_t MAX_TASK_COMM_LEN = 16; if (len < MAX_TASK_COMM_LEN) { return ERANGE; @@ -80,13 +80,13 @@ int GetThreadName(ThreadId tid, native_handle_type pthread_id, char *name, size_ if (GetCurrentThreadId() == tid) { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) - return pthread_getname_np(pthread_id, name, len) != 0 ? errno : 0; + return pthread_getname_np(pthread_handle, name, len) != 0 ? errno : 0; } constexpr size_t BUF_LEN = 64; std::array buf = {0}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) - int ret = snprintf_s(buf.data(), BUF_LEN, BUF_LEN -1, "/proc/self/task/%d/comm", tid); + int ret = snprintf_s(buf.data(), BUF_LEN, BUF_LEN - 1, "/proc/self/task/%d/comm", tid); if (ret < 0) { return ret; } @@ -131,18 +131,18 @@ void NativeSleep(unsigned int ms) std::this_thread::sleep_for(std::chrono::milliseconds(ms)); } -void ThreadDetach(native_handle_type pthread_id) +void ThreadDetach(native_handle_type pthread_handle) { - pthread_detach(pthread_id); + pthread_detach(pthread_handle); } -void ThreadExit(void *retval) +void ThreadExit(void *ret) { - pthread_exit(retval); + pthread_exit(ret); } -void ThreadJoin(native_handle_type pthread_id, void **retval) +void ThreadJoin(native_handle_type pthread_handle, void **ret) { - pthread_join(pthread_id, retval); + pthread_join(pthread_handle, ret); } } // namespace panda::os::thread diff --git a/libpandabase/os/unix/thread.h b/libpandabase/os/unix/thread.h index 68c968fea5..f56cfb2467 100644 --- a/libpandabase/os/unix/thread.h +++ b/libpandabase/os/unix/thread.h @@ -13,7 +13,12 @@ * limitations under the License. */ +#ifndef PANDA_LIBPANDABASE_OS_UNIX_THREAD_H_ +#define PANDA_LIBPANDABASE_OS_UNIX_THREAD_H_ + namespace panda::os::thread { int GetPriority(int thread_id); int SetPriority(int thread_id, int prio); } // namespace panda::os::thread + +#endif // PANDA_LIBPANDABASE_OS_UNIX_THREAD_H_ diff --git a/libpandabase/os/windows/library_loader.cpp b/libpandabase/os/windows/library_loader.cpp index c3925c96b8..f2a7ecd286 100644 --- a/libpandabase/os/windows/library_loader.cpp +++ b/libpandabase/os/windows/library_loader.cpp @@ -42,6 +42,8 @@ Expected ResolveSymbol(const LibraryHandle &handle, std::string_v void CloseHandle(void *handle) { - FreeLibrary(reinterpret_cast(handle)); + if (handle != nullptr) { + FreeLibrary(reinterpret_cast(handle)); + } } } // namespace panda::os::library_loader diff --git a/libpandabase/os/windows/mem_hooks.cpp b/libpandabase/os/windows/mem_hooks.cpp index 741f7a8959..41cfd43c8d 100644 --- a/libpandabase/os/windows/mem_hooks.cpp +++ b/libpandabase/os/windows/mem_hooks.cpp @@ -75,8 +75,8 @@ int PandaHooks::PandaAllocHook(int alloctype, [[maybe_unused]] void *data, std:: first = false; } - const char* alloctype_name = GetAllocTypeName(alloctype); - const char* blocktype_name = GetBlockTypeName(blocktype); + const char *alloctype_name = GetAllocTypeName(alloctype); + const char *blocktype_name = GetBlockTypeName(blocktype); std::cout << std::left << std::setfill(' ') << std::setw(ALIGN_SIZE) << alloctype_name; std::cout << std::left << std::setfill(' ') << std::setw(ALIGN_SIZE) << blocktype_name; diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index fcafe8b087..b11d305a4d 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -40,21 +40,22 @@ int SetPriority(DWORD thread_id, int prio) int GetPriority(DWORD thread_id) { - HANDLE hthread = OpenThread(THREAD_QUERY_INFORMATION, false, thread_id); - return GetThreadPriority(hthread); + HANDLE thread = OpenThread(THREAD_QUERY_INFORMATION, false, thread_id); + return GetThreadPriority(thread); } -int SetThreadName(native_handle_type pthread_id, const char *name) +int SetThreadName(native_handle_type pthread_handle, const char *name) { - ASSERT(pthread_id != 0); - pthread_t thread = reinterpret_cast(pthread_id); + ASSERT(pthread_handle != 0); + pthread_t thread = reinterpret_cast(pthread_handle); return pthread_setname_np(thread, name); } -int GetThreadName([[maybe_unused]] ThreadId tid, native_handle_type pthread_id, char *name, size_t len) +int GetThreadName([[maybe_unused]] ThreadId tid, native_handle_type pthread_handle, char *name, size_t len) { - ASSERT(pthread_id != 0); - pthread_t thread = reinterpret_cast(pthread_id); + ASSERT(pthread_handle != 0); + ASSERT(name != nullptr); + pthread_t thread = reinterpret_cast(pthread_handle); return pthread_getname_np(thread, name, len); } @@ -73,18 +74,18 @@ void NativeSleep(unsigned int ms) std::this_thread::sleep_for(std::chrono::milliseconds(ms)); } -void ThreadDetach(native_handle_type pthread_id) +void ThreadDetach(native_handle_type pthread_handle) { - pthread_detach(reinterpret_cast(pthread_id)); + pthread_detach(reinterpret_cast(pthread_handle)); } -void ThreadExit(void *retval) +void ThreadExit(void *ret) { - pthread_exit(retval); + pthread_exit(ret); } -void ThreadJoin(native_handle_type pthread_id, void **retval) +void ThreadJoin(native_handle_type pthread_handle, void **ret) { - pthread_join(reinterpret_cast(pthread_id), retval); + pthread_join(reinterpret_cast(pthread_handle), ret); } } // namespace panda::os::thread diff --git a/libpandabase/os/windows/thread.h b/libpandabase/os/windows/thread.h index 138a818eb7..e6435c3c02 100644 --- a/libpandabase/os/windows/thread.h +++ b/libpandabase/os/windows/thread.h @@ -13,9 +13,14 @@ * limitations under the License. */ +#ifndef PANDA_LIBPANDABASE_OS_WINDOWS_THREAD_H_ +#define PANDA_LIBPANDABASE_OS_WINDOWS_THREAD_H_ + namespace panda::os::thread { using DWORD = unsigned long; int GetPriority(DWORD thread_id); int SetPriority(DWORD thread_id, int prio); } // namespace panda::os::thread + +#endif // PANDA_LIBPANDABASE_OS_WINDOWS_THREAD_H_ diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index 05c55032d0..7a156aa069 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -44,16 +44,15 @@ constexpr int LOWER_PRIOIRITY = -1; constexpr int LOWEST_PRIORITY = -2; #endif -void ThreadFunc(std::string message, int sleep_time) +void ThreadFunc(int sleep_time) { thread_id_ = GetCurrentThreadId(); - std::cout << "[Thread " << thread_id_ << "] " << message << std::endl; NativeSleep(sleep_time); } TEST_F(ThreadTest, ThreadStartTest) { - auto thread_id = ThreadStart(ThreadFunc, "Start thread...", 200); + auto thread_id = ThreadStart(ThreadFunc, 200); // Waiting for thread_id_ updates to the new thread id NativeSleep(300); ASSERT(GetCurrentThreadId() != thread_id_); @@ -81,7 +80,7 @@ TEST_F(ThreadTest, SetOtherThreadPriorityTest) auto parent_pid = GetCurrentThreadId(); auto parent_prio_before = GetPriority(parent_pid); - auto new_thread = ThreadStart(ThreadFunc, "Start thread...", 200); + auto new_thread = ThreadStart(ThreadFunc, 200); // Waiting for thread_id_ updates to the new thread id, and before the new thread exited NativeSleep(100); @@ -130,7 +129,7 @@ TEST_F(ThreadTest, SetOtherThreadNameTest) auto ret = GetThreadName(pid1, handle1, name1_before, MAX_LENGTH); ASSERT_EQ(ret, 0); - auto handle2 = ThreadStart(ThreadFunc, "Start thread...", 300); + auto handle2 = ThreadStart(ThreadFunc, 300); // Waiting for thread_id_ updates to the new thread id, and before the new thread exited NativeSleep(100); auto pid2 = thread_id_; -- Gitee From 292eb10462d91ca4df311b66cae9a67326853781 Mon Sep 17 00:00:00 2001 From: huangyu Date: Mon, 23 May 2022 14:56:13 +0800 Subject: [PATCH 14/28] Use join instead of sleep to ensure the second indeed exited Signed-off-by: huangyu Change-Id: I02254f2d2ee13671b6a741c7b0cb3443b6172d86 --- libpandabase/tests/base_thread_test.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index 7a156aa069..f3944561b4 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -47,6 +47,7 @@ constexpr int LOWEST_PRIORITY = -2; void ThreadFunc(int sleep_time) { thread_id_ = GetCurrentThreadId(); + // Waiting for SetPriority/SetThreadName operations NativeSleep(sleep_time); } @@ -54,7 +55,8 @@ TEST_F(ThreadTest, ThreadStartTest) { auto thread_id = ThreadStart(ThreadFunc, 200); // Waiting for thread_id_ updates to the new thread id - NativeSleep(300); + void *ret = nullptr; + ThreadJoin(thread_id, &ret); ASSERT(GetCurrentThreadId() != thread_id_); ThreadDetach(thread_id); } -- Gitee From 1c9fd71df7043e676dc0bb6af7782c5fb0abbbe5 Mon Sep 17 00:00:00 2001 From: huangyu Date: Thu, 26 May 2022 20:44:18 +0800 Subject: [PATCH 15/28] Fix data race of read/write in gtest Signed-off-by: huangyu Change-Id: I5de2059f220bab18eb5cf124ad2a012b2471bd40 --- libpandabase/tests/base_thread_test.cpp | 55 ++++++------------------- 1 file changed, 13 insertions(+), 42 deletions(-) diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index f3944561b4..05ad85b76d 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -16,6 +16,7 @@ #include "utils/utf.h" #include "gtest/gtest.h" #include "os/failure_retry.h" +#include "os/mutex.h" #include "os/thread.h" #ifdef PANDA_TARGET_WINDOWS @@ -29,6 +30,7 @@ namespace panda::os::thread { class ThreadTest : public testing::Test {}; uint32_t thread_id_ = 0; +panda::os::memory::Mutex mu; constexpr size_t MAX_LENGTH = 64; const char *const_set_name1 = "TestThread"; const char *const_set_name2 = "NewThread"; @@ -46,7 +48,9 @@ constexpr int LOWEST_PRIORITY = -2; void ThreadFunc(int sleep_time) { + mu.Lock(); thread_id_ = GetCurrentThreadId(); + mu.Unlock(); // Waiting for SetPriority/SetThreadName operations NativeSleep(sleep_time); } @@ -57,8 +61,9 @@ TEST_F(ThreadTest, ThreadStartTest) // Waiting for thread_id_ updates to the new thread id void *ret = nullptr; ThreadJoin(thread_id, &ret); + mu.Lock(); ASSERT(GetCurrentThreadId() != thread_id_); - ThreadDetach(thread_id); + mu.Unlock(); } TEST_F(ThreadTest, SetCurrentThreadPriorityTest) @@ -85,12 +90,15 @@ TEST_F(ThreadTest, SetOtherThreadPriorityTest) auto new_thread = ThreadStart(ThreadFunc, 200); // Waiting for thread_id_ updates to the new thread id, and before the new thread exited NativeSleep(100); + mu.Lock(); + auto child_pid = thread_id_; + mu.Unlock(); - auto child_prio_before = GetPriority(thread_id_); - auto ret = SetPriority(thread_id_, LOWEST_PRIORITY); + auto child_prio_before = GetPriority(child_pid); + auto ret = SetPriority(child_pid, LOWEST_PRIORITY); ASSERT_EQ(ret, 0); - auto child_prio_after = GetPriority(thread_id_); + auto child_prio_after = GetPriority(child_pid); auto parent_prio_after = GetPriority(parent_pid); ThreadDetach(new_thread); @@ -110,7 +118,7 @@ TEST_F(ThreadTest, GetThreadNameTest) ASSERT_EQ(ret, 0); } -TEST_F(ThreadTest, SetCurrentThreadNameTest) +TEST_F(ThreadTest, SetThreadNameTest) { auto res = SetThreadName(GetNativeHandle(), const_set_name1); ASSERT_EQ(res, 0); @@ -121,41 +129,4 @@ TEST_F(ThreadTest, SetCurrentThreadNameTest) ASSERT_EQ(ret, 0); ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(thread_name), utf::CStringAsMutf8(set_name)) == 0); } - -TEST_F(ThreadTest, SetOtherThreadNameTest) -{ - auto pid1 = GetCurrentThreadId(); - auto handle1 = GetNativeHandle(); - - char name1_before[MAX_LENGTH]; - auto ret = GetThreadName(pid1, handle1, name1_before, MAX_LENGTH); - ASSERT_EQ(ret, 0); - - auto handle2 = ThreadStart(ThreadFunc, 300); - // Waiting for thread_id_ updates to the new thread id, and before the new thread exited - NativeSleep(100); - auto pid2 = thread_id_; - - char name2_before[MAX_LENGTH]; - ret = GetThreadName(pid2, handle2, name2_before, MAX_LENGTH); - ASSERT_EQ(ret, 0); - - ret = SetThreadName(handle2, "NewThread"); - ASSERT_EQ(ret, 0); - - char name1_after[MAX_LENGTH]; - ret = GetThreadName(pid1, handle1, name1_after, MAX_LENGTH); - ASSERT_EQ(ret, 0); - - char name2_after[MAX_LENGTH]; - ret = GetThreadName(pid2, handle2, name2_after, MAX_LENGTH); - ASSERT_EQ(ret, 0); - - ThreadDetach(handle2); - - ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(name1_before), utf::CStringAsMutf8(name1_after)) == 0); - ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(name2_before), utf::CStringAsMutf8(name2_after)) != 0); - ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(name2_after), utf::CStringAsMutf8(const_set_name2)) == 0); -} - } // namespace panda::os::thread -- Gitee From adc212c3bab8e17237bcae649db9b6316e46a390 Mon Sep 17 00:00:00 2001 From: huangyu Date: Thu, 26 May 2022 23:00:12 +0800 Subject: [PATCH 16/28] Minify library loader header file Signed-off-by: huangyu Change-Id: I8f68dbfc2c47827a1e42bf35cb33eec926be0f42 --- libpandabase/os/library_loader.h | 6 ++++-- libpandabase/os/unix/library_loader.h | 21 --------------------- 2 files changed, 4 insertions(+), 23 deletions(-) delete mode 100644 libpandabase/os/unix/library_loader.h diff --git a/libpandabase/os/library_loader.h b/libpandabase/os/library_loader.h index 2dc7451e66..60e06abf52 100644 --- a/libpandabase/os/library_loader.h +++ b/libpandabase/os/library_loader.h @@ -17,8 +17,10 @@ #define PANDA_LIBPANDABASE_OS_LIBRARY_LOADER_H_ #ifdef PANDA_TARGET_UNIX -#include "os/unix/library_loader.h" -#elif !PANDA_TARGET_WINDOWS +#include +#elif defined PANDA_TARGET_WINDOWS +// No platform-specific includes +#else #error "Unsupported platform" #endif diff --git a/libpandabase/os/unix/library_loader.h b/libpandabase/os/unix/library_loader.h deleted file mode 100644 index ae399f9401..0000000000 --- a/libpandabase/os/unix/library_loader.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PANDA_LIBPANDABASE_OS_UNIX_LIBRARY_LOADER_H_ -#define PANDA_LIBPANDABASE_OS_UNIX_LIBRARY_LOADER_H_ - -#include - -#endif // PANDA_LIBPANDABASE_OS_UNIX_LIBRARY_LOADER_H_ -- Gitee From 398a586ee66e3be996786b54c1b8e6382cdb4d0f Mon Sep 17 00:00:00 2001 From: huangyu Date: Mon, 30 May 2022 14:58:38 +0800 Subject: [PATCH 17/28] CloseHandle after OpenThread Signed-off-by: huangyu Change-Id: Ia2d209cbefd3060dbd06d762ddeb50cd76c79428 --- libpandabase/os/windows/thread.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index b11d305a4d..2943ba58ad 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -32,7 +32,9 @@ int GetPid() int SetPriority(DWORD thread_id, int prio) { - auto ret = SetThreadPriority(OpenThread(THREAD_SET_INFORMATION, false, thread_id), prio); + HANDLE thread = OpenThread(THREAD_SET_INFORMATION, false, thread_id); + auto ret = SetThreadPriority(thread, prio); + CloseHandle(thread); // On linux, the "setpriority" function returns zero if there is no error, or -1 if there is. // While on windows, the return value is nonzero if the function succeeds. return (ret != 0) ? 0 : -1; @@ -41,7 +43,9 @@ int SetPriority(DWORD thread_id, int prio) int GetPriority(DWORD thread_id) { HANDLE thread = OpenThread(THREAD_QUERY_INFORMATION, false, thread_id); - return GetThreadPriority(thread); + auto ret = GetThreadPriority(thread); + CloseHandle(thread); + return ret; } int SetThreadName(native_handle_type pthread_handle, const char *name) -- Gitee From 491676a28ba4065f1ef2069325719af373cd3eb8 Mon Sep 17 00:00:00 2001 From: huangyu Date: Mon, 30 May 2022 15:06:35 +0800 Subject: [PATCH 18/28] Include windows handleapi Change-Id: I35c60ac00a33381c06b61525203aab236d11e91d --- libpandabase/os/windows/thread.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index 2943ba58ad..561bf7f771 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -15,8 +15,9 @@ #include "os/thread.h" -#include +#include #include +#include namespace panda::os::thread { ThreadId GetCurrentThreadId() -- Gitee From 70248e7064d7eec7088b62ea39deb974d6020135 Mon Sep 17 00:00:00 2001 From: huangyu Date: Mon, 30 May 2022 20:50:00 +0800 Subject: [PATCH 19/28] Implement Set/GetThreadName on windows by WINAPI Signed-off-by: huangyu Change-Id: Id2eba2ca041385085346a79cc8706fe368959e94 --- libpandabase/os/thread.h | 1 - libpandabase/os/unix/thread.cpp | 4 ++-- libpandabase/os/unix/thread.h | 3 +++ libpandabase/os/windows/thread.cpp | 19 ++++++++++++------- libpandabase/os/windows/thread.h | 1 + libpandabase/tests/base_thread_test.cpp | 4 ++-- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/libpandabase/os/thread.h b/libpandabase/os/thread.h index 38aa963eac..9c148e59d4 100644 --- a/libpandabase/os/thread.h +++ b/libpandabase/os/thread.h @@ -39,7 +39,6 @@ using native_handle_type = std::thread::native_handle_type; ThreadId GetCurrentThreadId(); int GetPid(); int SetThreadName(native_handle_type pthread_handle, const char *name); -int GetThreadName(ThreadId tid, native_handle_type pthread_handle, char *name, size_t len); native_handle_type GetNativeHandle(); void Yield(); void NativeSleep(unsigned int ms); diff --git a/libpandabase/os/unix/thread.cpp b/libpandabase/os/unix/thread.cpp index f73be4bfe4..bab483bf22 100644 --- a/libpandabase/os/unix/thread.cpp +++ b/libpandabase/os/unix/thread.cpp @@ -69,7 +69,7 @@ int SetThreadName(native_handle_type pthread_handle, const char *name) #endif } -int GetThreadName(ThreadId tid, native_handle_type pthread_handle, char *name, size_t len) +int GetThreadName(ThreadId tid, char *name, size_t len) { ASSERT(tid != 0); constexpr size_t MAX_TASK_COMM_LEN = 16; @@ -80,7 +80,7 @@ int GetThreadName(ThreadId tid, native_handle_type pthread_handle, char *name, s if (GetCurrentThreadId() == tid) { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) - return pthread_getname_np(pthread_handle, name, len) != 0 ? errno : 0; + return pthread_getname_np(pthread_self(), name, len) != 0 ? errno : 0; } constexpr size_t BUF_LEN = 64; diff --git a/libpandabase/os/unix/thread.h b/libpandabase/os/unix/thread.h index f56cfb2467..35bb23e292 100644 --- a/libpandabase/os/unix/thread.h +++ b/libpandabase/os/unix/thread.h @@ -17,8 +17,11 @@ #define PANDA_LIBPANDABASE_OS_UNIX_THREAD_H_ namespace panda::os::thread { +using ThreadId = uint32_t; + int GetPriority(int thread_id); int SetPriority(int thread_id, int prio); +int GetThreadName(ThreadId tid, char *name, size_t len); } // namespace panda::os::thread #endif // PANDA_LIBPANDABASE_OS_UNIX_THREAD_H_ diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index 561bf7f771..1080e93df7 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -15,9 +15,9 @@ #include "os/thread.h" +#include #include #include -#include namespace panda::os::thread { ThreadId GetCurrentThreadId() @@ -52,16 +52,21 @@ int GetPriority(DWORD thread_id) int SetThreadName(native_handle_type pthread_handle, const char *name) { ASSERT(pthread_handle != 0); - pthread_t thread = reinterpret_cast(pthread_handle); - return pthread_setname_np(thread, name); + pthread_t pthread = reinterpret_cast(pthread_handle); + HANDLE thread = pthread_gethandle(pthread); + auto ret = SetThreadDescription(thread, name); + CloseHandle(ret); + return ret; } -int GetThreadName([[maybe_unused]] ThreadId tid, native_handle_type pthread_handle, char *name, size_t len) +int GetThreadName(DWORD tid, char *name, [[maybe_unused]] size_t len) { - ASSERT(pthread_handle != 0); + ASSERT(tid != 0); ASSERT(name != nullptr); - pthread_t thread = reinterpret_cast(pthread_handle); - return pthread_getname_np(thread, name, len); + HANDLE thread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, false, tid); + auto ret = GetThreadDescription(thread, name); + CloseHandle(thread); + return ret; } native_handle_type GetNativeHandle() diff --git a/libpandabase/os/windows/thread.h b/libpandabase/os/windows/thread.h index e6435c3c02..82d89054b8 100644 --- a/libpandabase/os/windows/thread.h +++ b/libpandabase/os/windows/thread.h @@ -21,6 +21,7 @@ using DWORD = unsigned long; int GetPriority(DWORD thread_id); int SetPriority(DWORD thread_id, int prio); +int GetThreadName(DWORD tid, char *name, size_t len); } // namespace panda::os::thread #endif // PANDA_LIBPANDABASE_OS_WINDOWS_THREAD_H_ diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index 05ad85b76d..422b7d33c3 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -114,7 +114,7 @@ TEST_F(ThreadTest, SetOtherThreadPriorityTest) TEST_F(ThreadTest, GetThreadNameTest) { char name[MAX_LENGTH]; - auto ret = GetThreadName(GetCurrentThreadId(), GetNativeHandle(), name, MAX_LENGTH); + auto ret = GetThreadName(GetCurrentThreadId(), name, MAX_LENGTH); ASSERT_EQ(ret, 0); } @@ -124,7 +124,7 @@ TEST_F(ThreadTest, SetThreadNameTest) ASSERT_EQ(res, 0); char thread_name[MAX_LENGTH]; - auto ret = GetThreadName(GetCurrentThreadId(), GetNativeHandle(), thread_name, MAX_LENGTH); + auto ret = GetThreadName(GetCurrentThreadId(), thread_name, MAX_LENGTH); ASSERT_EQ(ret, 0); ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(thread_name), utf::CStringAsMutf8(set_name)) == 0); -- Gitee From 6cbc7d9ea52d3bcb5c6107454b90b2e2d915f9fb Mon Sep 17 00:00:00 2001 From: huangyu Date: Mon, 30 May 2022 21:02:11 +0800 Subject: [PATCH 20/28] Revert last commit since Set/GetThreadDescription is not provided in MingW for now Signed-off-by: huangyu --- libpandabase/os/thread.h | 1 + libpandabase/os/unix/thread.cpp | 4 ++-- libpandabase/os/unix/thread.h | 3 --- libpandabase/os/windows/thread.cpp | 19 +++++++------------ libpandabase/os/windows/thread.h | 1 - libpandabase/tests/base_thread_test.cpp | 4 ++-- 6 files changed, 12 insertions(+), 20 deletions(-) diff --git a/libpandabase/os/thread.h b/libpandabase/os/thread.h index 9c148e59d4..38aa963eac 100644 --- a/libpandabase/os/thread.h +++ b/libpandabase/os/thread.h @@ -39,6 +39,7 @@ using native_handle_type = std::thread::native_handle_type; ThreadId GetCurrentThreadId(); int GetPid(); int SetThreadName(native_handle_type pthread_handle, const char *name); +int GetThreadName(ThreadId tid, native_handle_type pthread_handle, char *name, size_t len); native_handle_type GetNativeHandle(); void Yield(); void NativeSleep(unsigned int ms); diff --git a/libpandabase/os/unix/thread.cpp b/libpandabase/os/unix/thread.cpp index bab483bf22..f73be4bfe4 100644 --- a/libpandabase/os/unix/thread.cpp +++ b/libpandabase/os/unix/thread.cpp @@ -69,7 +69,7 @@ int SetThreadName(native_handle_type pthread_handle, const char *name) #endif } -int GetThreadName(ThreadId tid, char *name, size_t len) +int GetThreadName(ThreadId tid, native_handle_type pthread_handle, char *name, size_t len) { ASSERT(tid != 0); constexpr size_t MAX_TASK_COMM_LEN = 16; @@ -80,7 +80,7 @@ int GetThreadName(ThreadId tid, char *name, size_t len) if (GetCurrentThreadId() == tid) { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) - return pthread_getname_np(pthread_self(), name, len) != 0 ? errno : 0; + return pthread_getname_np(pthread_handle, name, len) != 0 ? errno : 0; } constexpr size_t BUF_LEN = 64; diff --git a/libpandabase/os/unix/thread.h b/libpandabase/os/unix/thread.h index 35bb23e292..f56cfb2467 100644 --- a/libpandabase/os/unix/thread.h +++ b/libpandabase/os/unix/thread.h @@ -17,11 +17,8 @@ #define PANDA_LIBPANDABASE_OS_UNIX_THREAD_H_ namespace panda::os::thread { -using ThreadId = uint32_t; - int GetPriority(int thread_id); int SetPriority(int thread_id, int prio); -int GetThreadName(ThreadId tid, char *name, size_t len); } // namespace panda::os::thread #endif // PANDA_LIBPANDABASE_OS_UNIX_THREAD_H_ diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index 1080e93df7..561bf7f771 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -15,9 +15,9 @@ #include "os/thread.h" -#include #include #include +#include namespace panda::os::thread { ThreadId GetCurrentThreadId() @@ -52,21 +52,16 @@ int GetPriority(DWORD thread_id) int SetThreadName(native_handle_type pthread_handle, const char *name) { ASSERT(pthread_handle != 0); - pthread_t pthread = reinterpret_cast(pthread_handle); - HANDLE thread = pthread_gethandle(pthread); - auto ret = SetThreadDescription(thread, name); - CloseHandle(ret); - return ret; + pthread_t thread = reinterpret_cast(pthread_handle); + return pthread_setname_np(thread, name); } -int GetThreadName(DWORD tid, char *name, [[maybe_unused]] size_t len) +int GetThreadName([[maybe_unused]] ThreadId tid, native_handle_type pthread_handle, char *name, size_t len) { - ASSERT(tid != 0); + ASSERT(pthread_handle != 0); ASSERT(name != nullptr); - HANDLE thread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, false, tid); - auto ret = GetThreadDescription(thread, name); - CloseHandle(thread); - return ret; + pthread_t thread = reinterpret_cast(pthread_handle); + return pthread_getname_np(thread, name, len); } native_handle_type GetNativeHandle() diff --git a/libpandabase/os/windows/thread.h b/libpandabase/os/windows/thread.h index 82d89054b8..e6435c3c02 100644 --- a/libpandabase/os/windows/thread.h +++ b/libpandabase/os/windows/thread.h @@ -21,7 +21,6 @@ using DWORD = unsigned long; int GetPriority(DWORD thread_id); int SetPriority(DWORD thread_id, int prio); -int GetThreadName(DWORD tid, char *name, size_t len); } // namespace panda::os::thread #endif // PANDA_LIBPANDABASE_OS_WINDOWS_THREAD_H_ diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index 422b7d33c3..05ad85b76d 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -114,7 +114,7 @@ TEST_F(ThreadTest, SetOtherThreadPriorityTest) TEST_F(ThreadTest, GetThreadNameTest) { char name[MAX_LENGTH]; - auto ret = GetThreadName(GetCurrentThreadId(), name, MAX_LENGTH); + auto ret = GetThreadName(GetCurrentThreadId(), GetNativeHandle(), name, MAX_LENGTH); ASSERT_EQ(ret, 0); } @@ -124,7 +124,7 @@ TEST_F(ThreadTest, SetThreadNameTest) ASSERT_EQ(res, 0); char thread_name[MAX_LENGTH]; - auto ret = GetThreadName(GetCurrentThreadId(), thread_name, MAX_LENGTH); + auto ret = GetThreadName(GetCurrentThreadId(), GetNativeHandle(), thread_name, MAX_LENGTH); ASSERT_EQ(ret, 0); ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(thread_name), utf::CStringAsMutf8(set_name)) == 0); -- Gitee From 8970a6b21d685569f6936cbbb5dca2817f746475 Mon Sep 17 00:00:00 2001 From: huangyu Date: Tue, 31 May 2022 10:30:53 +0800 Subject: [PATCH 21/28] Remove GetThreadName functions since no usages Signed-off-by: huangyu Change-Id: I05847fd39682f6d3cc33f64da2c5db94491a1b48 --- libpandabase/os/thread.h | 1 - libpandabase/os/unix/thread.cpp | 47 ------------------------- libpandabase/os/windows/thread.cpp | 8 ----- libpandabase/tests/base_thread_test.cpp | 19 ---------- 4 files changed, 75 deletions(-) diff --git a/libpandabase/os/thread.h b/libpandabase/os/thread.h index 38aa963eac..9c148e59d4 100644 --- a/libpandabase/os/thread.h +++ b/libpandabase/os/thread.h @@ -39,7 +39,6 @@ using native_handle_type = std::thread::native_handle_type; ThreadId GetCurrentThreadId(); int GetPid(); int SetThreadName(native_handle_type pthread_handle, const char *name); -int GetThreadName(ThreadId tid, native_handle_type pthread_handle, char *name, size_t len); native_handle_type GetNativeHandle(); void Yield(); void NativeSleep(unsigned int ms); diff --git a/libpandabase/os/unix/thread.cpp b/libpandabase/os/unix/thread.cpp index f73be4bfe4..eeacf6df3e 100644 --- a/libpandabase/os/unix/thread.cpp +++ b/libpandabase/os/unix/thread.cpp @@ -69,53 +69,6 @@ int SetThreadName(native_handle_type pthread_handle, const char *name) #endif } -int GetThreadName(ThreadId tid, native_handle_type pthread_handle, char *name, size_t len) -{ - ASSERT(tid != 0); - constexpr size_t MAX_TASK_COMM_LEN = 16; - - if (len < MAX_TASK_COMM_LEN) { - return ERANGE; - } - - if (GetCurrentThreadId() == tid) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) - return pthread_getname_np(pthread_handle, name, len) != 0 ? errno : 0; - } - - constexpr size_t BUF_LEN = 64; - std::array buf = {0}; - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) - int ret = snprintf_s(buf.data(), BUF_LEN, BUF_LEN - 1, "/proc/self/task/%d/comm", tid); - if (ret < 0) { - return ret; - } - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-signed-bitwise) - int fd = open(buf.data(), O_CLOEXEC | O_RDONLY); - if (fd < 0) { - return errno; - } - - ssize_t n = PANDA_FAILURE_RETRY(read(fd, name, len)); - close(fd); - - if (n < 0) { - return errno; - } - - Span name_sp(name, n); - if (n > 0 && name_sp[n - 1] == '\n') { - name_sp[n - 1] = '\0'; - return 0; - } - - if (n == static_cast(len)) { - return ERANGE; - } - name_sp[n] = '\0'; - return 0; -} - native_handle_type GetNativeHandle() { return pthread_self(); diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index 561bf7f771..532b31f3d7 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -56,14 +56,6 @@ int SetThreadName(native_handle_type pthread_handle, const char *name) return pthread_setname_np(thread, name); } -int GetThreadName([[maybe_unused]] ThreadId tid, native_handle_type pthread_handle, char *name, size_t len) -{ - ASSERT(pthread_handle != 0); - ASSERT(name != nullptr); - pthread_t thread = reinterpret_cast(pthread_handle); - return pthread_getname_np(thread, name, len); -} - native_handle_type GetNativeHandle() { return reinterpret_cast(pthread_self()); diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index 05ad85b76d..736d44253d 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -110,23 +110,4 @@ TEST_F(ThreadTest, SetOtherThreadPriorityTest) ASSERT(child_prio_after <= child_prio_before); #endif } - -TEST_F(ThreadTest, GetThreadNameTest) -{ - char name[MAX_LENGTH]; - auto ret = GetThreadName(GetCurrentThreadId(), GetNativeHandle(), name, MAX_LENGTH); - ASSERT_EQ(ret, 0); -} - -TEST_F(ThreadTest, SetThreadNameTest) -{ - auto res = SetThreadName(GetNativeHandle(), const_set_name1); - ASSERT_EQ(res, 0); - - char thread_name[MAX_LENGTH]; - auto ret = GetThreadName(GetCurrentThreadId(), GetNativeHandle(), thread_name, MAX_LENGTH); - - ASSERT_EQ(ret, 0); - ASSERT(utf::CompareMUtf8ToMUtf8(utf::CStringAsMutf8(thread_name), utf::CStringAsMutf8(set_name)) == 0); -} } // namespace panda::os::thread -- Gitee From 79f3e05a95eb422ee52c17e1ccc96f7e9a51325b Mon Sep 17 00:00:00 2001 From: huangyu Date: Tue, 31 May 2022 19:42:10 +0800 Subject: [PATCH 22/28] Ensure result of OpenThread is valid Signed-off-by: huangyu Change-Id: Ie6e2de798dcc4ab64bc59f50daed2d4f8d0e9eec --- libpandabase/os/windows/thread.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index 532b31f3d7..436b45c3cb 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -14,7 +14,9 @@ */ #include "os/thread.h" +#include "utils/logger.h" +#include #include #include #include @@ -34,6 +36,9 @@ int GetPid() int SetPriority(DWORD thread_id, int prio) { HANDLE thread = OpenThread(THREAD_SET_INFORMATION, false, thread_id); + if (thread == nullptr) { + LOG(FATAL, COMMON) << "OpenThread failed, error code " << GetLastError(); + } auto ret = SetThreadPriority(thread, prio); CloseHandle(thread); // On linux, the "setpriority" function returns zero if there is no error, or -1 if there is. @@ -44,6 +49,9 @@ int SetPriority(DWORD thread_id, int prio) int GetPriority(DWORD thread_id) { HANDLE thread = OpenThread(THREAD_QUERY_INFORMATION, false, thread_id); + if (thread == nullptr) { + LOG(FATAL, COMMON) << "OpenThread failed, error code " << GetLastError(); + } auto ret = GetThreadPriority(thread); CloseHandle(thread); return ret; -- Gitee From 7efb8545137999b515b4ad6c6479902bc836f869 Mon Sep 17 00:00:00 2001 From: huangyu Date: Tue, 31 May 2022 19:54:00 +0800 Subject: [PATCH 23/28] Correct invalid thread handle indentifier Signed-off-by: huangyu Change-Id: Ibf8c43827f37df49a7d451aa23143a2240becdad --- libpandabase/os/windows/thread.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index 436b45c3cb..c842d3eb75 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -36,7 +36,7 @@ int GetPid() int SetPriority(DWORD thread_id, int prio) { HANDLE thread = OpenThread(THREAD_SET_INFORMATION, false, thread_id); - if (thread == nullptr) { + if (thread == NULL) { LOG(FATAL, COMMON) << "OpenThread failed, error code " << GetLastError(); } auto ret = SetThreadPriority(thread, prio); @@ -49,7 +49,7 @@ int SetPriority(DWORD thread_id, int prio) int GetPriority(DWORD thread_id) { HANDLE thread = OpenThread(THREAD_QUERY_INFORMATION, false, thread_id); - if (thread == nullptr) { + if (thread == NULL) { LOG(FATAL, COMMON) << "OpenThread failed, error code " << GetLastError(); } auto ret = GetThreadPriority(thread); -- Gitee From 39bb3081f1eb9f916ed8cea07ead5f0cd3fa9e57 Mon Sep 17 00:00:00 2001 From: huangyu Date: Mon, 6 Jun 2022 20:39:09 +0800 Subject: [PATCH 24/28] Fix codestyle Signed-off-by: huangyu Change-Id: I7cc8b0c8aeee0cd5cb4f42afff0331681a5bacd0 --- libpandabase/os/thread.h | 4 ---- libpandabase/os/windows/file.cpp | 2 +- libpandabase/tests/base_thread_test.cpp | 6 +----- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/libpandabase/os/thread.h b/libpandabase/os/thread.h index 9c148e59d4..8ac02dde38 100644 --- a/libpandabase/os/thread.h +++ b/libpandabase/os/thread.h @@ -32,7 +32,6 @@ #endif namespace panda::os::thread { - using ThreadId = uint32_t; using native_handle_type = std::thread::native_handle_type; @@ -49,7 +48,6 @@ void ThreadJoin(native_handle_type pthread_handle, void **ret); // Templated functions need to be defined here to be accessible everywhere namespace internal { - template struct SharedPtrStruct; @@ -109,7 +107,6 @@ static void *ProxyFunc(void *args) CallFunc(*func, args_tuple); return nullptr; } - } // namespace internal template @@ -141,7 +138,6 @@ native_handle_type ThreadStart(Func *func, Args... args) return reinterpret_cast(tid); #endif } - } // namespace panda::os::thread #endif // PANDA_LIBPANDABASE_OS_THREAD_H_ diff --git a/libpandabase/os/windows/file.cpp b/libpandabase/os/windows/file.cpp index d773f7b33e..bcd5194355 100644 --- a/libpandabase/os/windows/file.cpp +++ b/libpandabase/os/windows/file.cpp @@ -30,7 +30,7 @@ static int GetFlags(Mode mode) { switch (mode) { case Mode::READONLY: - return _O_RDONLY | _O_BINARY; + return _O_RDONLY; case Mode::READWRITE: return _O_RDWR; diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index 736d44253d..d05afb4149 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -13,8 +13,8 @@ * limitations under the License. */ -#include "utils/utf.h" #include "gtest/gtest.h" +#include "utils/utf.h" #include "os/failure_retry.h" #include "os/mutex.h" #include "os/thread.h" @@ -31,10 +31,6 @@ class ThreadTest : public testing::Test {}; uint32_t thread_id_ = 0; panda::os::memory::Mutex mu; -constexpr size_t MAX_LENGTH = 64; -const char *const_set_name1 = "TestThread"; -const char *const_set_name2 = "NewThread"; -char set_name[MAX_LENGTH] = "TestThread"; #ifdef PANDA_TARGET_UNIX // On linux, the priority can be set within range [-20, 19], and 19 is the lowest priority. -- Gitee From fe179a5bc5287dc76a41e0b658cb412b4bba5e09 Mon Sep 17 00:00:00 2001 From: huangyu Date: Mon, 6 Jun 2022 20:55:17 +0800 Subject: [PATCH 25/28] Use condition variable instead of sleep to ensure test valid Signed-off-by: huangyu Change-Id: I88c57e64c5b199ee375e91f19db137017f1af69a --- libpandabase/tests/base_thread_test.cpp | 63 +++++++++++-------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index d05afb4149..2136bf4c0e 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -13,24 +13,18 @@ * limitations under the License. */ +#include #include "gtest/gtest.h" -#include "utils/utf.h" -#include "os/failure_retry.h" -#include "os/mutex.h" #include "os/thread.h" -#ifdef PANDA_TARGET_WINDOWS -#include -#include -#include -#include -#endif - namespace panda::os::thread { class ThreadTest : public testing::Test {}; -uint32_t thread_id_ = 0; -panda::os::memory::Mutex mu; +uint32_t thread_id = 0; +bool updated = false; +bool operated = false; +std::mutex mu; +std::condition_variable cv; #ifdef PANDA_TARGET_UNIX // On linux, the priority can be set within range [-20, 19], and 19 is the lowest priority. @@ -42,24 +36,19 @@ constexpr int LOWER_PRIOIRITY = -1; constexpr int LOWEST_PRIORITY = -2; #endif -void ThreadFunc(int sleep_time) +void ThreadFunc() { - mu.Lock(); - thread_id_ = GetCurrentThreadId(); - mu.Unlock(); - // Waiting for SetPriority/SetThreadName operations - NativeSleep(sleep_time); -} - -TEST_F(ThreadTest, ThreadStartTest) -{ - auto thread_id = ThreadStart(ThreadFunc, 200); - // Waiting for thread_id_ updates to the new thread id - void *ret = nullptr; - ThreadJoin(thread_id, &ret); - mu.Lock(); - ASSERT(GetCurrentThreadId() != thread_id_); - mu.Unlock(); + thread_id = GetCurrentThreadId(); + { + std::lock_guard lk(mu); + updated = true; + } + cv.notify_one(); + { + // wait for the main thread to Set/GetPriority + std::unique_lock lk(mu); + cv.wait(lk, []{return operated;}); + } } TEST_F(ThreadTest, SetCurrentThreadPriorityTest) @@ -83,22 +72,24 @@ TEST_F(ThreadTest, SetOtherThreadPriorityTest) auto parent_pid = GetCurrentThreadId(); auto parent_prio_before = GetPriority(parent_pid); - auto new_thread = ThreadStart(ThreadFunc, 200); - // Waiting for thread_id_ updates to the new thread id, and before the new thread exited - NativeSleep(100); - mu.Lock(); - auto child_pid = thread_id_; - mu.Unlock(); + auto new_thread = ThreadStart(ThreadFunc); + // wait for the new_thread to update thread_id + std::unique_lock lk(mu); + cv.wait(lk, []{return updated;}); + auto child_pid = thread_id; auto child_prio_before = GetPriority(child_pid); auto ret = SetPriority(child_pid, LOWEST_PRIORITY); - ASSERT_EQ(ret, 0); auto child_prio_after = GetPriority(child_pid); auto parent_prio_after = GetPriority(parent_pid); + operated = true; + lk.unlock(); + cv.notify_one(); ThreadDetach(new_thread); + ASSERT_EQ(ret, 0); ASSERT_EQ(parent_prio_before, parent_prio_after); #ifdef PANDA_TARGET_UNIX ASSERT(child_prio_before <= child_prio_after); -- Gitee From 7f650e274fae2917c425a10c3a3fe0f01926d484 Mon Sep 17 00:00:00 2001 From: huangyu Date: Mon, 6 Jun 2022 21:25:49 +0800 Subject: [PATCH 26/28] Fix newly found codestyle Signed-off-by: huangyu Change-Id: Id4af86af0208642896d6b5cb25b0cd5a8aea0c4e --- libpandabase/tests/base_thread_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index 2136bf4c0e..bd4a523b5c 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -47,7 +47,7 @@ void ThreadFunc() { // wait for the main thread to Set/GetPriority std::unique_lock lk(mu); - cv.wait(lk, []{return operated;}); + cv.wait(lk, [] { return operated; }); } } @@ -75,7 +75,7 @@ TEST_F(ThreadTest, SetOtherThreadPriorityTest) auto new_thread = ThreadStart(ThreadFunc); // wait for the new_thread to update thread_id std::unique_lock lk(mu); - cv.wait(lk, []{return updated;}); + cv.wait(lk, [] { return updated; }); auto child_pid = thread_id; auto child_prio_before = GetPriority(child_pid); -- Gitee From 57cd8cda3bf44f6b3c59a40e4d5805c4430f4233 Mon Sep 17 00:00:00 2001 From: huangyu Date: Fri, 10 Jun 2022 16:31:10 +0800 Subject: [PATCH 27/28] Fix setpriority review comment Signed-off-by: huangyu Change-Id: I94c47ccd0269a6ea6b5e593b51dbb5b23beebc9b --- libpandabase/os/unix/thread.cpp | 2 ++ libpandabase/os/windows/thread.cpp | 6 +++--- libpandabase/tests/base_thread_test.cpp | 18 ++++++++++++------ runtime/thread.cpp | 8 ++++++++ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/libpandabase/os/unix/thread.cpp b/libpandabase/os/unix/thread.cpp index eeacf6df3e..c54c727202 100644 --- a/libpandabase/os/unix/thread.cpp +++ b/libpandabase/os/unix/thread.cpp @@ -51,6 +51,8 @@ int GetPid() int SetPriority(int thread_id, int prio) { + // The priority can be set within range [-20, 19], and 19 is the lowest priority. + // The return value is 0 if the function succeeds, and -1 if it fails. return setpriority(PRIO_PROCESS, thread_id, prio); } diff --git a/libpandabase/os/windows/thread.cpp b/libpandabase/os/windows/thread.cpp index c842d3eb75..97eedde370 100644 --- a/libpandabase/os/windows/thread.cpp +++ b/libpandabase/os/windows/thread.cpp @@ -35,15 +35,15 @@ int GetPid() int SetPriority(DWORD thread_id, int prio) { + // The priority can be set within range [-2, 2], and -2 is the lowest priority. HANDLE thread = OpenThread(THREAD_SET_INFORMATION, false, thread_id); if (thread == NULL) { LOG(FATAL, COMMON) << "OpenThread failed, error code " << GetLastError(); } auto ret = SetThreadPriority(thread, prio); CloseHandle(thread); - // On linux, the "setpriority" function returns zero if there is no error, or -1 if there is. - // While on windows, the return value is nonzero if the function succeeds. - return (ret != 0) ? 0 : -1; + // The return value is nonzero if the function succeeds, and zero if it fails. + return ret; } int GetPriority(DWORD thread_id) diff --git a/libpandabase/tests/base_thread_test.cpp b/libpandabase/tests/base_thread_test.cpp index bd4a523b5c..4c34103605 100644 --- a/libpandabase/tests/base_thread_test.cpp +++ b/libpandabase/tests/base_thread_test.cpp @@ -55,16 +55,20 @@ TEST_F(ThreadTest, SetCurrentThreadPriorityTest) { // Since setting higher priority needs "sudo" right, we only test lower one here. auto ret1 = SetPriority(GetCurrentThreadId(), LOWER_PRIOIRITY); - ASSERT_EQ(ret1, 0); - auto prio1 = GetPriority(GetCurrentThreadId()); ASSERT_EQ(prio1, LOWER_PRIOIRITY); auto ret2 = SetPriority(GetCurrentThreadId(), LOWEST_PRIORITY); - ASSERT_EQ(ret2, 0); - auto prio2 = GetPriority(GetCurrentThreadId()); ASSERT_EQ(prio2, LOWEST_PRIORITY); + +#ifdef PANDA_TARGET_UNIX + ASSERT_EQ(ret1, 0); + ASSERT_EQ(ret2, 0); +#elif PANDA_TARGET_WINDOWS + ASSERT_NE(ret1, 0); + ASSERT_NE(ret2, 0); +#endif } TEST_F(ThreadTest, SetOtherThreadPriorityTest) @@ -87,13 +91,15 @@ TEST_F(ThreadTest, SetOtherThreadPriorityTest) operated = true; lk.unlock(); cv.notify_one(); - ThreadDetach(new_thread); + void *res; + ThreadJoin(new_thread, &res); - ASSERT_EQ(ret, 0); ASSERT_EQ(parent_prio_before, parent_prio_after); #ifdef PANDA_TARGET_UNIX + ASSERT_EQ(ret, 0); ASSERT(child_prio_before <= child_prio_after); #elif PANDA_TARGET_WINDOWS + ASSERT_NE(ret, 0); ASSERT(child_prio_after <= child_prio_before); #endif } diff --git a/runtime/thread.cpp b/runtime/thread.cpp index 294356b1ab..683f330fd6 100644 --- a/runtime/thread.cpp +++ b/runtime/thread.cpp @@ -36,7 +36,11 @@ using TaggedType = coretypes::TaggedType; bool ManagedThread::is_initialized = false; mem::TLAB *ManagedThread::zero_tlab = nullptr; +#ifdef PANDA_TARGET_UNIX static const int MIN_PRIORITY = 19; +#elif PANDA_TARGET_WINDOWS +static const int MIN_PRIORITY = -2; +#endif MTManagedThread::ThreadId MTManagedThread::GetInternalId() { @@ -454,7 +458,11 @@ void ManagedThread::SetThreadPriority(int32_t prio) { ThreadId tid = GetId(); int res = os::thread::SetPriority(tid, prio); +#ifdef PANDA_TARGET_UNIX if (res == 0) { +#elif PANDA_TARGET_WINDOWS + if (res != 0) { +#endif LOG(DEBUG, RUNTIME) << "Successfully changed priority for thread " << tid << " to " << prio; } else { LOG(DEBUG, RUNTIME) << "Cannot change priority for thread " << tid << " to " << prio; -- Gitee From 8e1856abaca7f502284dfda510bcc4ac876eb48d Mon Sep 17 00:00:00 2001 From: huangyu Date: Sat, 11 Jun 2022 17:19:53 +0800 Subject: [PATCH 28/28] Fix libpandafile openmode Signed-off-by: huangyu Change-Id: I5fe50253cc7aa64ca70243b71f97db6b25201b6e --- libpandabase/os/windows/file.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libpandabase/os/windows/file.cpp b/libpandabase/os/windows/file.cpp index bcd5194355..d773f7b33e 100644 --- a/libpandabase/os/windows/file.cpp +++ b/libpandabase/os/windows/file.cpp @@ -30,7 +30,7 @@ static int GetFlags(Mode mode) { switch (mode) { case Mode::READONLY: - return _O_RDONLY; + return _O_RDONLY | _O_BINARY; case Mode::READWRITE: return _O_RDWR; -- Gitee