Skip to content

Commit

Permalink
Switch the posix_compliance tests to use pthread_create (#3107)
Browse files Browse the repository at this point in the history
b/302335657

Test-On-Device: true

Change-Id: I785845e79e1954e81e77eac8dac2d6fc853d2c24
  • Loading branch information
y4vor committed Apr 30, 2024
1 parent 4d34dd9 commit 86ca328
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 69 deletions.
Expand Up @@ -47,9 +47,8 @@ TEST(PosixConditionVariableWaitTest, SunnyDayAutoInit) {
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_COND_INITIALIZER};
// Start the thread.
SbThread thread =
SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity, true, NULL,
posix::TakeThenSignalEntryPoint, &context);
pthread_t thread = 0;
pthread_create(&thread, NULL, posix::TakeThenSignalEntryPoint, &context);

EXPECT_EQ(pthread_mutex_lock(&context.mutex), 0);

Expand All @@ -65,7 +64,7 @@ TEST(PosixConditionVariableWaitTest, SunnyDayAutoInit) {
EXPECT_EQ(pthread_mutex_unlock(&context.mutex), 0);

// Now we wait for the thread to exit.
EXPECT_TRUE(SbThreadJoin(thread, NULL));
EXPECT_TRUE(pthread_join(thread, NULL) == 0);
EXPECT_EQ(pthread_cond_destroy(&context.condition), 0);
EXPECT_EQ(pthread_mutex_destroy(&context.mutex), 0);
}
Expand All @@ -74,10 +73,9 @@ TEST(PosixConditionVariableWaitTest, SunnyDay) {
const int kMany = kSbMaxThreads > 64 ? 64 : kSbMaxThreads;
posix::WaiterContext context;

std::vector<SbThread> threads(kMany);
std::vector<pthread_t> threads(kMany);
for (int i = 0; i < kMany; ++i) {
threads[i] = SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity,
true, NULL, posix::WaiterEntryPoint, &context);
pthread_create(&threads[i], NULL, posix::WaiterEntryPoint, &context);
}

for (int i = 0; i < kMany; ++i) {
Expand All @@ -89,7 +87,8 @@ TEST(PosixConditionVariableWaitTest, SunnyDay) {

// Now we wait for the threads to exit.
for (int i = 0; i < kMany; ++i) {
EXPECT_TRUE(SbThreadJoin(threads[i], NULL)) << "thread = " << threads[i];
EXPECT_TRUE(pthread_join(threads[i], NULL) == 0)
<< "thread = " << threads[i];
}
}

Expand Down
Expand Up @@ -98,9 +98,8 @@ struct timespec CalculateDelayTimestamp(int64_t delay, bool use_monotonic) {
void DoSunnyDay(posix::TakeThenSignalContext* context,
bool check_timeout,
bool use_monotonic) {
SbThread thread =
SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity, true, NULL,
posix::TakeThenSignalEntryPoint, context);
pthread_t thread = 0;
pthread_create(&thread, NULL, posix::TakeThenSignalEntryPoint, context);

const int64_t kDelayUs = 10'000; // 10ms
// Allow two-millisecond-level precision.
Expand Down Expand Up @@ -156,7 +155,7 @@ void DoSunnyDay(posix::TakeThenSignalContext* context,
}

// Now we wait for the thread to exit.
EXPECT_TRUE(SbThreadJoin(thread, NULL));
EXPECT_TRUE(pthread_join(thread, NULL) == 0);
EXPECT_EQ(pthread_cond_destroy(&context->condition), 0);
EXPECT_EQ(pthread_mutex_destroy(&context->mutex), 0);
}
Expand Down Expand Up @@ -212,9 +211,8 @@ TEST(PosixConditionVariableWaitTimedTest, FLAKY_SunnyDayNearMaxTime) {
EXPECT_EQ(pthread_mutex_init(&context.mutex, NULL), 0);

InitCondition(&context.condition, false /* use_monotonic */);
SbThread thread =
SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity, true, NULL,
posix::TakeThenSignalEntryPoint, &context);
pthread_t thread = 0;
pthread_create(&thread, NULL, posix::TakeThenSignalEntryPoint, &context);

EXPECT_EQ(pthread_mutex_lock(&context.mutex), 0);

Expand Down Expand Up @@ -243,7 +241,7 @@ TEST(PosixConditionVariableWaitTimedTest, FLAKY_SunnyDayNearMaxTime) {
EXPECT_EQ(pthread_mutex_unlock(&context.mutex), 0);

// Now we wait for the thread to exit.
EXPECT_TRUE(SbThreadJoin(thread, NULL));
EXPECT_TRUE(pthread_join(thread, NULL) == 0);
EXPECT_EQ(pthread_cond_destroy(&context.condition), 0);
EXPECT_EQ(pthread_mutex_destroy(&context.mutex), 0);
}
Expand Down
7 changes: 3 additions & 4 deletions starboard/nplb/posix_compliance/posix_mutex_acquire_test.cc
Expand Up @@ -48,10 +48,9 @@ TEST(PosixMutexAcquireTest, SunnyDayContended) {
TestContext context;
EXPECT_EQ(pthread_mutex_init(&context.mutex, NULL), 0);
const int kThreads = 4;
SbThread threads[kThreads];
pthread_t threads[kThreads];
for (int i = 0; i < kThreads; ++i) {
threads[i] = SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity,
true, NULL, EntryPoint, &context);
pthread_create(&threads[i], NULL, EntryPoint, &context);
}

for (int i = 0; i < kLoops; ++i) {
Expand All @@ -64,7 +63,7 @@ TEST(PosixMutexAcquireTest, SunnyDayContended) {

// Join other threads and clean up.
for (int i = 0; i < kThreads; ++i) {
EXPECT_TRUE(SbThreadJoin(threads[i], NULL));
EXPECT_TRUE(pthread_join(threads[i], NULL) == 0);
}
EXPECT_EQ(pthread_mutex_destroy(&context.mutex), 0);
EXPECT_EQ(0, context.count);
Expand Down
11 changes: 5 additions & 6 deletions starboard/nplb/posix_compliance/posix_mutex_acquire_try_test.cc
Expand Up @@ -32,6 +32,7 @@ struct TestContext {
};

void* EntryPoint(void* parameter) {
pthread_setname_np(pthread_self(), nplb::kThreadName);
TestContext* context = static_cast<TestContext*>(parameter);
context->was_locked_ = (pthread_mutex_trylock(context->mutex_) == 0);
return NULL;
Expand Down Expand Up @@ -60,13 +61,11 @@ TEST(PosixMutexAcquireTryTest, RainyDayReentrant) {
EXPECT_EQ(pthread_mutex_trylock(&mutex), 0);

TestContext context(&mutex);
// TODO: Migrate to pthread_create when available.
SbThread thread =
SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity, true,
nplb::kThreadName, &EntryPoint, &context);
pthread_t thread = 0;
pthread_create(&thread, NULL, &EntryPoint, &context);

EXPECT_TRUE(SbThreadIsValid(thread));
EXPECT_TRUE(SbThreadJoin(thread, NULL));
EXPECT_TRUE(thread != 0);
EXPECT_TRUE(pthread_join(thread, NULL) == 0);
EXPECT_FALSE(context.was_locked_);
EXPECT_EQ(pthread_mutex_unlock(&mutex), 0);
EXPECT_EQ(pthread_mutex_destroy(&mutex), 0);
Expand Down
10 changes: 5 additions & 5 deletions starboard/nplb/posix_compliance/posix_once_test.cc
Expand Up @@ -73,6 +73,8 @@ struct RunPosixOnceContext {
};

void* RunPosixOnceEntryPoint(void* context) {
pthread_setname_np(pthread_self(), posix::kThreadName);

RunPosixOnceContext* run_sbonce_context =
reinterpret_cast<RunPosixOnceContext*>(context);

Expand All @@ -98,7 +100,7 @@ void* RunPosixOnceEntryPoint(void* context) {
// initialization routine got called exactly one time.
TEST(PosixOnceTest, SunnyDayMultipleThreadsInit) {
const int kMany = kSbMaxThreads;
std::vector<SbThread> threads(kMany);
std::vector<pthread_t> threads(kMany);

const int kIterationCount = 10;
for (int i = 0; i < kIterationCount; ++i) {
Expand All @@ -107,9 +109,7 @@ TEST(PosixOnceTest, SunnyDayMultipleThreadsInit) {

s_global_value = 0;
for (int j = 0; j < kMany; ++j) {
threads[j] =
SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity, true,
posix::kThreadName, RunPosixOnceEntryPoint, &context);
pthread_create(&threads[j], NULL, RunPosixOnceEntryPoint, &context);
}

// Wait for all threads to finish initializing and become ready, then
Expand All @@ -127,7 +127,7 @@ TEST(PosixOnceTest, SunnyDayMultipleThreadsInit) {
// Signal threads to beginWait for all threads to complete.
for (int i = 0; i < kMany; ++i) {
void* result;
SbThreadJoin(threads[i], &result);
pthread_join(threads[i], &result);
}

EXPECT_EQ(s_global_value, 1);
Expand Down
12 changes: 7 additions & 5 deletions starboard/nplb/posix_compliance/posix_socket_send_test.cc
Expand Up @@ -16,6 +16,7 @@
// this is hooked up to something.

#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#include "starboard/nplb/posix_compliance/posix_socket_helpers.h"
#include "starboard/thread.h"
Expand All @@ -40,6 +41,8 @@ void* PosixSocketSendToServerSocketEntryPoint(void* trio_as_void_ptr) {
char* send_buf = new char[kBufSize];
memset(send_buf, 0, kBufSize);

pthread_setname_np(pthread_self(), "SendToTest");

// Continue sending to the socket until it fails to send. It's expected that
// SbSocketSendTo will fail when the server socket closes, but the application
// should not terminate.
Expand Down Expand Up @@ -95,17 +98,16 @@ TEST(PosixSocketSendTest, RainyDaySendToClosedSocket) {

// Start a thread to write to the client socket.
const bool kJoinable = true;
SbThread send_thread =
SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity, kJoinable,
"SendToTest", PosixSocketSendToServerSocketEntryPoint,
static_cast<void*>(&trio_as_void_ptr));
pthread_t send_thread = 0;
pthread_create(&send_thread, NULL, PosixSocketSendToServerSocketEntryPoint,
static_cast<void*>(&trio_as_void_ptr));

// Close the client, which should cause writes to the server socket to fail.
EXPECT_TRUE(close(client_socket_fd) == 0);

// Wait for the thread to exit and check the last socket error.
void* thread_result;
EXPECT_TRUE(SbThreadJoin(send_thread, &thread_result));
EXPECT_TRUE(pthread_join(send_thread, &thread_result) == 0);

// TODO: errno: EXPECT_TRUE(errno == ECONNRESET || errno == ENETRESET || errno
// == EPIPE);
Expand Down
12 changes: 7 additions & 5 deletions starboard/nplb/posix_compliance/posix_socket_sendto_test.cc
Expand Up @@ -16,6 +16,7 @@
// this is hooked up to something.

#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>

#include "starboard/nplb/posix_compliance/posix_socket_helpers.h"
Expand All @@ -41,6 +42,8 @@ void* PosixSocketSendToServerSocketEntryPoint(void* trio_as_void_ptr) {
char* send_buf = new char[kBufSize];
memset(send_buf, 0, kBufSize);

pthread_setname_np(pthread_self(), "SendToTest");

// Continue sending to the socket until it fails to send. It's expected that
// SbSocketSendTo will fail when the server socket closes, but the application
// should not terminate.
Expand Down Expand Up @@ -98,17 +101,16 @@ TEST(PosixSocketSendtoTest, RainyDaySendToClosedSocket) {

// Start a thread to write to the client socket.
const bool kJoinable = true;
SbThread send_thread =
SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity, kJoinable,
"SendToTest", PosixSocketSendToServerSocketEntryPoint,
static_cast<void*>(&trio_as_void_ptr));
pthread_t send_thread = 0;
pthread_create(&send_thread, NULL, PosixSocketSendToServerSocketEntryPoint,
static_cast<void*>(&trio_as_void_ptr));

// Close the client, which should cause writes to the server socket to fail.
EXPECT_TRUE(close(client_socket_fd) == 0);

// Wait for the thread to exit and check the last socket error.
void* thread_result;
EXPECT_TRUE(SbThreadJoin(send_thread, &thread_result));
EXPECT_TRUE(pthread_join(send_thread, &thread_result) == 0);

// TODO: errno: EXPECT_TRUE(errno == ECONNRESET || errno == ENETRESET || errno
// == EPIPE);
Expand Down
22 changes: 8 additions & 14 deletions starboard/nplb/posix_compliance/posix_thread_helpers.h
Expand Up @@ -158,44 +158,38 @@ struct TakeThenSignalContext {
// thread. Subclasses must override Run().
class AbstractTestThread {
public:
AbstractTestThread() : thread_(kSbThreadInvalid) {}
AbstractTestThread() : thread_(0) {}
virtual ~AbstractTestThread() {}

// Subclasses should override the Run method.
virtual void Run() = 0;

// Calls SbThreadCreate() with default parameters.
// Calls pthread_create() with default parameters.
void Start() {
SbThreadEntryPoint entry_point = ThreadEntryPoint;

thread_ = SbThreadCreate(0, // default stack_size.
kSbThreadNoPriority, // default priority.
kSbThreadNoAffinity, // default affinity.
true, // joinable.
"AbstractTestThread", entry_point, this);

if (kSbThreadInvalid == thread_) {
pthread_create(&thread_, NULL, ThreadEntryPoint, this);
if (0 == thread_) {
ADD_FAILURE_AT(__FILE__, __LINE__) << "Invalid thread.";
}
return;
}

void Join() {
if (!SbThreadJoin(thread_, NULL)) {
if (pthread_join(thread_, NULL) != 0) {
ADD_FAILURE_AT(__FILE__, __LINE__) << "Could not join thread.";
}
}

SbThread GetThread() { return thread_; }
pthread_t GetThread() { return thread_; }

private:
static void* ThreadEntryPoint(void* ptr) {
pthread_setname_np(pthread_self(), "AbstractTestThread");
AbstractTestThread* this_ptr = static_cast<AbstractTestThread*>(ptr);
this_ptr->Run();
return NULL;
}

SbThread thread_;
pthread_t thread_;

AbstractTestThread(const AbstractTestThread&) = delete;
void operator=(const AbstractTestThread&) = delete;
Expand Down
24 changes: 10 additions & 14 deletions starboard/nplb/posix_compliance/posix_thread_local_value_test.cc
Expand Up @@ -53,6 +53,7 @@ void* EntryPoint(void* context) {

// Sets a thread local non-NULL value, and then sets it back to NULL.
static void* ThreadEntryPoint(void* ptr) {
pthread_setname_np(pthread_self(), "TestThread");
pthread_key_t key = *static_cast<pthread_key_t*>(ptr);
EXPECT_EQ(NULL, pthread_getspecific(key));
// Set the value and then NULL it out. We expect that because the final
Expand All @@ -67,7 +68,7 @@ void DoSunnyDayTest(bool use_destructor) {
const int kThreads = 16;
ThreadLocalValue values[kThreads];
Context contexts[kThreads];
SbThread threads[kThreads];
pthread_t threads[kThreads];
ThreadLocalValue my_value;

pthread_key_t key = 0;
Expand All @@ -81,13 +82,12 @@ void DoSunnyDayTest(bool use_destructor) {
}

for (int i = 0; i < kThreads; ++i) {
threads[i] = SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity,
true, NULL, EntryPoint, &contexts[i]);
pthread_create(&threads[i], NULL, EntryPoint, &contexts[i]);
}

for (int i = 0; i < kThreads; ++i) {
EXPECT_TRUE(SbThreadIsValid(threads[i]));
EXPECT_TRUE(SbThreadJoin(threads[i], NULL));
EXPECT_TRUE(threads[i] != 0);
EXPECT_TRUE(pthread_join(threads[i], NULL) == 0);
EXPECT_EQ(contexts[i].in_value, contexts[i].out_value);

// The destructor for all thread-local values will be called at thread exit
Expand Down Expand Up @@ -132,16 +132,12 @@ TEST(PosixThreadLocalValueTest, NoDestructorsForNullValue) {
EXPECT_EQ(NULL, pthread_getspecific(key));

// Spawn the thread.
SbThread thread =
SbThreadCreate(0, // Signals automatic thread stack size.
kSbThreadNoPriority, // Signals default priority.
kSbThreadNoAffinity, // Signals default affinity.
true, // joinable thread.
"TestThread", ThreadEntryPoint, static_cast<void*>(&key));

ASSERT_NE(kSbThreadInvalid, thread) << "Thread creation not successful";
pthread_t thread = 0;
pthread_create(&thread, NULL, ThreadEntryPoint, static_cast<void*>(&key));

ASSERT_TRUE(thread != 0) << "Thread creation not successful";
// 2nd param is return value from ThreadEntryPoint, which is always NULL.
ASSERT_TRUE(SbThreadJoin(thread, NULL));
ASSERT_TRUE(pthread_join(thread, NULL) == 0);

// No destructors should have run.
EXPECT_EQ(0, s_num_destructor_calls);
Expand Down

0 comments on commit 86ca328

Please sign in to comment.