Skip to content

Commit

Permalink
Add pthread_setname_np/pthread_getname_np (#2885)
Browse files Browse the repository at this point in the history
b/302335657

Test-On-Device: true

Change-Id: I3b3bef9fbcbb671ff44bceaf23fd2a6dbb75afe8
  • Loading branch information
y4vor committed Apr 24, 2024
1 parent eb43364 commit 620f6c9
Show file tree
Hide file tree
Showing 15 changed files with 255 additions and 2 deletions.
6 changes: 6 additions & 0 deletions starboard/android/shared/platform_configuration/BUILD.gn
Expand Up @@ -19,6 +19,12 @@ config("platform_configuration") {
cflags = []

defines = []

include_dirs = [
# POSIX emulation headers
"//starboard/android/shared/posix_emu/include",
]

ldflags = [
# The NDK default "ld" is actually the gold linker for all architectures
# except arm64 (aarch64) where it"s the bfd linker. Don"t use either of
Expand Down
24 changes: 24 additions & 0 deletions starboard/android/shared/posix_emu/include/pthread.h
@@ -0,0 +1,24 @@
// Copyright 2024 The Cobalt Authors. All Rights Reserved.
//
// 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 STARBOARD_ANDROID_SHARED_POSIX_EMU_INCLUDE_PTHREAD_H_
#define STARBOARD_ANDROID_SHARED_POSIX_EMU_INCLUDE_PTHREAD_H_

#include_next <pthread.h>

#if __ANDROID_API__ < 26
int pthread_getname_np(pthread_t thread, char* name, size_t len);
#endif // __ANDROID_API__ < 26

#endif // STARBOARD_ANDROID_SHARED_POSIX_EMU_INCLUDE_PTHREAD_H_
33 changes: 33 additions & 0 deletions starboard/android/shared/posix_emu/pthread.cc
@@ -0,0 +1,33 @@
// Copyright 2024 The Cobalt Authors. All Rights Reserved.
//
// 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 <pthread.h>

#include <errno.h>
#include <fcntl.h>
#include <sys/prctl.h>
#include <unistd.h>

#if __ANDROID_API__ < 26
// The API doesn exist before API Level 26 and we currently target 24
// If this is the current thread we can obtain the name using `prctl`.
int pthread_getname_np(pthread_t thread, char* name, size_t len) {
// The PR_GET_NAME expects a buffer of size 16 bytes.
if (pthread_equal(pthread_self(), thread) && len >= 16) {
prctl(PR_GET_NAME, name, 0L, 0L, 0L);
return 0;
}
return -1;
}
#endif // __ANDROID_API__ < 26
8 changes: 6 additions & 2 deletions starboard/elf_loader/exported_symbols.cc
Expand Up @@ -510,10 +510,12 @@ ExportedSymbols::ExportedSymbols() {
reinterpret_cast<const void*>(&__abi_wrap_pthread_detach);
map_["pthread_equal"] =
reinterpret_cast<const void*>(&__abi_wrap_pthread_equal);
map_["pthread_join"] =
reinterpret_cast<const void*>(&__abi_wrap_pthread_join);
map_["pthread_getname_np"] =
reinterpret_cast<const void*>(&__abi_wrap_pthread_getname_np);
map_["pthread_getspecific"] =
reinterpret_cast<const void*>(&__abi_wrap_pthread_getspecific);
map_["pthread_join"] =
reinterpret_cast<const void*>(&__abi_wrap_pthread_join);
map_["pthread_key_create"] =
reinterpret_cast<const void*>(&__abi_wrap_pthread_key_create);
map_["pthread_key_delete"] =
Expand All @@ -534,6 +536,8 @@ ExportedSymbols::ExportedSymbols() {
reinterpret_cast<const void*>(&__abi_wrap_pthread_self);
map_["pthread_setspecific"] =
reinterpret_cast<const void*>(&__abi_wrap_pthread_setspecific);
map_["pthread_setname_np"] =
reinterpret_cast<const void*>(&__abi_wrap_pthread_setname_np);
map_["stat"] = reinterpret_cast<const void*>(&__abi_wrap_stat);
map_["time"] = reinterpret_cast<const void*>(&__abi_wrap_time);
map_["accept"] = reinterpret_cast<const void*>(&__abi_wrap_accept);
Expand Down
2 changes: 2 additions & 0 deletions starboard/nplb/BUILD.gn
Expand Up @@ -175,10 +175,12 @@ target(gtest_target_type, "nplb") {
"posix_compliance/posix_thread_create_test.cc",
"posix_compliance/posix_thread_detach_test.cc",
"posix_compliance/posix_thread_get_current_test.cc",
"posix_compliance/posix_thread_get_name_test.cc",
"posix_compliance/posix_thread_helpers.cc",
"posix_compliance/posix_thread_is_equal_test.cc",
"posix_compliance/posix_thread_join_test.cc",
"posix_compliance/posix_thread_local_value_test.cc",
"posix_compliance/posix_thread_set_name_test.cc",
"posix_compliance/posix_thread_sleep_test.cc",
"posix_compliance/posix_thread_yield_test.cc",
"posix_compliance/posix_time_test.cc",
Expand Down
47 changes: 47 additions & 0 deletions starboard/nplb/posix_compliance/posix_thread_get_name_test.cc
@@ -0,0 +1,47 @@
// Copyright 2024 The Cobalt Authors. All Rights Reserved.
//
// 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 <pthread.h>

#include "starboard/nplb/thread_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace starboard {
namespace nplb {
namespace {

void* GetThreadNameEntryPoint(void* context) {
pthread_setname_np(pthread_self(), kThreadName);

char name[4096] = {0};
pthread_getname_np(pthread_self(), name, SB_ARRAY_SIZE_INT(name));
std::string* result = static_cast<std::string*>(context);
*result = name;
return NULL;
}

TEST(PosixThreadGetNameTest, SunnyDay) {
std::string result;

pthread_t thread;
EXPECT_EQ(pthread_create(&thread, NULL, GetThreadNameEntryPoint, &result), 0);

EXPECT_TRUE(thread != 0);
EXPECT_EQ(pthread_join(thread, NULL), 0);
EXPECT_EQ(kThreadName, result);
}

} // namespace
} // namespace nplb
} // namespace starboard
60 changes: 60 additions & 0 deletions starboard/nplb/posix_compliance/posix_thread_set_name_test.cc
@@ -0,0 +1,60 @@
// Copyright 2024 The Cobalt Authors. All Rights Reserved.
//
// 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 <pthread.h>

#include "starboard/nplb/thread_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace starboard {
namespace nplb {
namespace {

struct Context {
std::string got_name1;
std::string name_to_set;
std::string got_name2;
};

// Gets the thread's name and sets it in the context.
void* SetThreadNameEntryPoint(void* context) {
char name[4096] = {0};
Context* real_context = static_cast<Context*>(context);

pthread_getname_np(pthread_self(), name, SB_ARRAY_SIZE_INT(name));
real_context->got_name1 = name;

pthread_setname_np(pthread_self(), real_context->name_to_set.c_str());

pthread_getname_np(pthread_self(), name, SB_ARRAY_SIZE_INT(name));
real_context->got_name2 = name;

return NULL;
}

TEST(PosixThreadSetNameTest, SunnyDay) {
Context context;
context.name_to_set = kAltThreadName;
pthread_t thread;
EXPECT_EQ(pthread_create(&thread, NULL, SetThreadNameEntryPoint, &context),
0);
EXPECT_TRUE(thread != 0);
EXPECT_EQ(pthread_join(thread, NULL), 0);
EXPECT_NE(kAltThreadName, context.got_name1);
EXPECT_EQ(kAltThreadName, context.got_name2);
}

} // namespace
} // namespace nplb
} // namespace starboard
Expand Up @@ -185,6 +185,17 @@ int __abi_wrap_pthread_setspecific(pthread_key_t key, const void* value);
int pthread_setspecific(pthread_key_t key, const void* value) {
return __abi_wrap_pthread_setspecific(key, value);
}

int __abi_wrap_pthread_setname_np(pthread_t thread, const char* name);

int pthread_setname_np(pthread_t thread, const char* name) {
return __abi_wrap_pthread_setname_np(thread, name);
}

int __abi_wrap_pthread_getname_np(pthread_t thread, char* name, size_t len);

int pthread_getname_np(pthread_t thread, char* name, size_t len) {
return __abi_wrap_pthread_getname_np(thread, name, len);
}
}
#endif // SB_API_VERSION >= 16
Expand Up @@ -370,3 +370,13 @@ int __abi_wrap_pthread_setspecific(musl_pthread_key_t key, const void* value) {
return pthread_setspecific(
reinterpret_cast<PosixThreadLocalKeyPrivate*>(key)->key, value);
}

int __abi_wrap_pthread_setname_np(musl_pthread_t thread, const char* name) {
return pthread_setname_np(reinterpret_cast<pthread_t>(thread), name);
}

int __abi_wrap_pthread_getname_np(musl_pthread_t thread,
char* name,
size_t len) {
return pthread_getname_np(reinterpret_cast<pthread_t>(thread), name, len);
}
Expand Up @@ -112,6 +112,12 @@ SB_EXPORT void* __abi_wrap_pthread_getspecific(musl_pthread_key_t key);
SB_EXPORT int __abi_wrap_pthread_setspecific(musl_pthread_key_t key,
const void* value);

SB_EXPORT int __abi_wrap_pthread_setname_np(musl_pthread_t thread,
const char* name);
SB_EXPORT int __abi_wrap_pthread_getname_np(musl_pthread_t thread,
char* name,
size_t len);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
2 changes: 2 additions & 0 deletions starboard/shared/win32/posix_emu/include/pthread.h
Expand Up @@ -74,6 +74,8 @@ int pthread_detach(pthread_t thread);
pthread_t pthread_self();
int pthread_equal(pthread_t t1, pthread_t t2);

int pthread_setname_np(pthread_t thread, const char* name);
int pthread_getname_np(pthread_t thread, char* name, size_t len);
#ifdef __cplusplus
}
#endif
Expand Down
23 changes: 23 additions & 0 deletions starboard/shared/win32/posix_emu/pthread.cc
Expand Up @@ -18,10 +18,13 @@
#include <cstdint>

#include "starboard/common/log.h"
#include "starboard/common/string.h"
#include "starboard/common/time.h"
#include "starboard/shared/win32/thread_local_internal.h"
#include "starboard/shared/win32/thread_private.h"
#include "starboard/shared/win32/wchar_utils.h"

using starboard::shared::win32::CStringToWString;
using starboard::shared::win32::GetCurrentSbThreadPrivate;
using starboard::shared::win32::GetThreadSubsystemSingleton;
using starboard::shared::win32::SbThreadPrivate;
Expand Down Expand Up @@ -314,4 +317,24 @@ int pthread_setspecific(pthread_key_t key, const void* value) {
return TlsInternalSetValue(tls_index, const_cast<void*>(value)) ? 0 : -1;
}

int pthread_setname_np(pthread_t thread, const char* name) {
SbThreadPrivate* thread_private = static_cast<SbThreadPrivate*>(thread);
std::wstring wname = CStringToWString(name);

HRESULT hr = SetThreadDescription(thread_private->handle_, wname.c_str());
if (FAILED(hr)) {
return -1;
}
// We store the thread name in our own TLS context as well as telling
// the OS because it's much easier to retrieve from our own TLS context.
thread_private->name_ = name;

return 0;
}

int pthread_getname_np(pthread_t thread, char* name, size_t len) {
SbThreadPrivate* thread_private = static_cast<SbThreadPrivate*>(thread);
starboard::strlcpy(name, thread_private->name_.c_str(), len);
return 0;
}
} // extern "C"
2 changes: 2 additions & 0 deletions starboard/tools/api_leak_detector/api_leak_detector.py
Expand Up @@ -146,6 +146,8 @@
'pthread_key_create',
'pthread_key_delete',
'pthread_setspecific',
'pthread_setname_np',
'pthread_getname_np',
'usleep',
]

Expand Down
20 changes: 20 additions & 0 deletions third_party/musl/src/starboard/pthread/pthread.c
Expand Up @@ -195,4 +195,24 @@ int pthread_setspecific(pthread_key_t key, const void* value) {
return SbThreadSetLocalValue((SbThreadLocalKey)key, value)? 0: -1;
}

int pthread_setname_np(pthread_t thread, const char* name) {
// Starboard 14/15 can only set thread name for the current thread
if (SbThreadGetCurrent() != thread) {
SB_DCHECK(false);
return -1;
}
SbThreadSetName(name);
return 0;
}

int pthread_getname_np(pthread_t thread, char* name, size_t len) {
// Starboard 14/15 can only get the thread name for the current thread
if (SbThreadGetCurrent() != thread) {
SB_DCHECK(false);
return -1;
}
SbThreadGetName(name, len);
return 0;
}

#endif // SB_API_VERSION < 16
3 changes: 3 additions & 0 deletions third_party/musl/src/starboard/pthread/pthread.h
Expand Up @@ -173,6 +173,9 @@ int pthread_detach(pthread_t thread);
pthread_t pthread_self();
int pthread_equal(pthread_t t1, pthread_t t2);

int pthread_setname_np(pthread_t thread, const char* name);
int pthread_getname_np(pthread_t thread, char* name, size_t len);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down

0 comments on commit 620f6c9

Please sign in to comment.