Refactor mutex, library loader and complement Windows thread API

Signed-off-by: huangyu <huangyu76@huawei.com>
Change-Id: I662463d239f6d050ef6908de70e0e98cf85bf2a6
This commit is contained in:
huangyu 2022-06-10 16:25:49 +08:00
parent 633c83d2b0
commit f76f983336
19 changed files with 395 additions and 296 deletions

View File

@ -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(

View File

@ -17,9 +17,9 @@
#define PANDA_LIBPANDABASE_OS_LIBRARY_LOADER_H_
#ifdef PANDA_TARGET_UNIX
#include "os/unix/library_loader.h"
#elif PANDA_TARGET_WINDOWS
#include "os/windows/library_loader.h"
#include <dlfcn.h>
#elif defined PANDA_TARGET_WINDOWS
// No platform-specific includes
#else
#error "Unsupported platform"
#endif
@ -30,8 +30,53 @@
#include <string_view>
namespace panda::os::library_loader {
class LibraryHandle;
Expected<LibraryHandle, Error> Load(std::string_view filename);
Expected<void *, Error> 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_

View File

@ -19,7 +19,7 @@
#include <cstring>
#include <ctime>
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

View File

@ -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 <pthread.h>
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_

View File

@ -23,27 +23,31 @@
#include <memory>
#include <thread>
#include <pthread.h>
#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 {
using ThreadId = uint32_t;
using native_handle_type = std::thread::native_handle_type;
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 GetPid();
int SetThreadName(native_handle_type pthread_handle, const char *name);
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
namespace internal {
template <typename T>
struct SharedPtrStruct;
@ -103,7 +107,6 @@ static void *ProxyFunc(void *args)
CallFunc<Func, Tuple, N>(*func, args_tuple);
return nullptr;
}
} // namespace internal
template <typename Func, typename... Args>
@ -135,7 +138,6 @@ native_handle_type ThreadStart(Func *func, Args... args)
return reinterpret_cast<native_handle_type>(tid);
#endif
}
} // namespace panda::os::thread
#endif // PANDA_LIBPANDABASE_OS_THREAD_H_

View File

@ -39,4 +39,10 @@ Expected<void *, Error> ResolveSymbol(const LibraryHandle &handle, std::string_v
return msg != nullptr ? Unexpected(Error(msg)) : Unexpected(Error("no error message"));
}
void CloseHandle(void *handle)
{
if (handle != nullptr) {
dlclose(handle);
}
}
} // namespace panda::os::library_loader

View File

@ -1,71 +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 "macros.h"
#include <dlfcn.h>
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_

View File

@ -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 <pthread.h>
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_

View File

@ -15,11 +15,17 @@
#include "os/thread.h"
#include "utils/span.h"
#include <array>
#include <cstdint>
#include "os/failure_retry.h"
#ifdef PANDA_TARGET_UNIX
#include <fcntl.h>
#include <sys/syscall.h>
#include <sys/resource.h>
#endif
#include <securec.h>
#include <unistd.h>
namespace panda::os::thread {
@ -38,8 +44,15 @@ ThreadId GetCurrentThreadId()
#endif
}
int GetPid()
{
return 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);
}
@ -48,13 +61,13 @@ 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
}
@ -73,18 +86,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

View File

@ -0,0 +1,24 @@
/*
* 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_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_

View File

@ -14,6 +14,7 @@
*/
#include "os/error.h"
#include <string.h>
namespace panda::os {

View File

@ -39,13 +39,11 @@ Expected<void *, Error> 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<HMODULE>(handle_));
if (handle != nullptr) {
FreeLibrary(reinterpret_cast<HMODULE>(handle));
}
}
} // namespace panda::os::windows::library_loader
} // namespace panda::os::library_loader

View File

@ -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_

View File

@ -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;

View File

@ -14,31 +14,59 @@
*/
#include "os/thread.h"
#include "utils/logger.h"
#include <thread>
#include <errhandlingapi.h>
#include <handleapi.h>
#include <processthreadsapi.h>
#include <thread>
namespace panda::os::thread {
ThreadId GetCurrentThreadId()
{
return static_cast<ThreadId>(std::hash<std::thread::id>()(std::this_thread::get_id()));
// The function is provided by mingw
return ::GetCurrentThreadId();
}
int SetPriority([[maybe_unused]] int thread_id, int prio)
int GetPid()
{
return SetThreadPriority(GetCurrentThread(), prio);
return _getpid();
}
int GetPriority([[maybe_unused]] int thread_id)
int SetPriority(DWORD thread_id, int prio)
{
return GetThreadPriority(GetCurrentThread());
// 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);
// The return value is nonzero if the function succeeds, and zero if it fails.
return ret;
}
int SetThreadName([[maybe_unused]] native_handle_type pthread_id, const char *name)
int GetPriority(DWORD thread_id)
{
ASSERT(pthread_id != 0);
return pthread_setname_np(pthread_self(), name);
HANDLE thread = OpenThread(THREAD_QUERY_INFORMATION, false, thread_id);
if (thread == NULL) {
LOG(FATAL, COMMON) << "OpenThread failed, error code " << GetLastError();
}
auto ret = GetThreadPriority(thread);
CloseHandle(thread);
return ret;
}
int SetThreadName(native_handle_type pthread_handle, const char *name)
{
ASSERT(pthread_handle != 0);
pthread_t thread = reinterpret_cast<pthread_t>(pthread_handle);
return pthread_setname_np(thread, name);
}
native_handle_type GetNativeHandle()
{
return reinterpret_cast<native_handle_type>(pthread_self());
}
void Yield()
@ -51,9 +79,18 @@ void NativeSleep(unsigned int ms)
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}
void ThreadJoin(native_handle_type pthread_id, void **retval)
void ThreadDetach(native_handle_type pthread_handle)
{
pthread_join(reinterpret_cast<pthread_t>(pthread_id), retval);
pthread_detach(reinterpret_cast<pthread_t>(pthread_handle));
}
void ThreadExit(void *ret)
{
pthread_exit(ret);
}
void ThreadJoin(native_handle_type pthread_handle, void **ret)
{
pthread_join(reinterpret_cast<pthread_t>(pthread_handle), ret);
}
} // namespace panda::os::thread

View File

@ -0,0 +1,26 @@
/*
* 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_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_

View File

@ -0,0 +1,106 @@
/*
* 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 <condition_variable>
#include "gtest/gtest.h"
#include "os/thread.h"
namespace panda::os::thread {
class ThreadTest : public testing::Test {};
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.
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()
{
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)
{
// Since setting higher priority needs "sudo" right, we only test lower one here.
auto ret1 = SetPriority(GetCurrentThreadId(), LOWER_PRIOIRITY);
auto prio1 = GetPriority(GetCurrentThreadId());
ASSERT_EQ(prio1, LOWER_PRIOIRITY);
auto ret2 = SetPriority(GetCurrentThreadId(), LOWEST_PRIORITY);
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)
{
auto parent_pid = GetCurrentThreadId();
auto parent_prio_before = GetPriority(parent_pid);
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);
auto child_prio_after = GetPriority(child_pid);
auto parent_prio_after = GetPriority(parent_pid);
operated = true;
lk.unlock();
cv.notify_one();
void *res;
ThreadJoin(new_thread, &res);
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
}
} // namespace panda::os::thread

View File

@ -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<void *>(reinterpret_cast<uintptr_t>(mem) + PAGE_SIZE), PAGE_SIZE, PROT_NONE);
reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(mem) + PAGE_SIZE), PAGE_SIZE, os::mem::MMAP_PROT_NONE);
char *string =
reinterpret_cast<char *>((reinterpret_cast<uintptr_t>(mem) + PAGE_SIZE) - sizeof(char) * string_size);
string[0] = 'O';

View File

@ -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;