Skip to content

Commit

Permalink
Introduce pthread_mutex APIs.
Browse files Browse the repository at this point in the history
- Add support for pthread_mutex_init, pthread_mutex_destroy,
  pthread_mutex_lock, pthread_mutex_unlock and pthread_mutex_trylock.

b/302335657

Change-Id: I8774ddb8ad466b7342e045402b170a719f2e1a81
  • Loading branch information
y4vor committed Jan 25, 2024
1 parent 61c20a2 commit 2e3528d
Show file tree
Hide file tree
Showing 17 changed files with 638 additions and 2 deletions.
5 changes: 5 additions & 0 deletions starboard/build/config/modular/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ config("modular") {
"-Wl,--wrap=clock_gettime",
"-Wl,--wrap=gettimeofday",
"-Wl,--wrap=mmap",
"-Wl,--wrap=pthread_mutex_destroy",
"-Wl,--wrap=pthread_mutex_init",
"-Wl,--wrap=pthread_mutex_lock",
"-Wl,--wrap=pthread_mutex_unlock",
"-Wl,--wrap=pthread_mutex_trylock",
]
}
}
Expand Down
11 changes: 11 additions & 0 deletions starboard/elf_loader/exported_symbols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "starboard/player.h"
#if SB_API_VERSION >= 16
#include "starboard/shared/modular/posix_mmap_wrappers.h"
#include "starboard/shared/modular/posix_pthread_wrappers.h"
#include "starboard/shared/modular/posix_time_wrappers.h"
#endif // SB_API_VERSION >= 16
#include "starboard/socket.h"
Expand Down Expand Up @@ -431,6 +432,16 @@ ExportedSymbols::ExportedSymbols() {
map_["clock_gettime"] = reinterpret_cast<const void*>(&__wrap_clock_gettime);
map_["gettimeofday"] = reinterpret_cast<const void*>(&__wrap_gettimeofday);
map_["mmap"] = reinterpret_cast<const void*>(&__wrap_mmap);
map_["pthread_mutex_destroy"] =
reinterpret_cast<const void*>(&__wrap_pthread_mutex_destroy);
map_["pthread_mutex_init"] =
reinterpret_cast<const void*>(&__wrap_pthread_mutex_init);
map_["pthread_mutex_lock"] =
reinterpret_cast<const void*>(&__wrap_pthread_mutex_lock);
map_["pthread_mutex_unlock"] =
reinterpret_cast<const void*>(&__wrap_pthread_mutex_unlock);
map_["pthread_mutex_trylock"] =
reinterpret_cast<const void*>(&__wrap_pthread_mutex_trylock);

REGISTER_SYMBOL(sprintf);
REGISTER_SYMBOL(snprintf);
Expand Down
4 changes: 4 additions & 0 deletions starboard/nplb/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ target(gtest_target_type, "nplb") {
"player_write_sample_test.cc",
"posix_compliance/posix_arpa_inet_test.cc",
"posix_compliance/posix_memory_map_test.cc",
"posix_compliance/posix_mutex_acquire_test.cc",
"posix_compliance/posix_mutex_acquire_try_test.cc",
"posix_compliance/posix_mutex_create_test.cc",
"posix_compliance/posix_mutex_destroy_test.cc",
"posix_compliance/posix_string_compare_no_case_n_test.cc",
"posix_compliance/posix_string_compare_no_case_test.cc",
"posix_compliance/posix_string_format_test.cc",
Expand Down
98 changes: 98 additions & 0 deletions starboard/nplb/posix_compliance/posix_mutex_acquire_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright 2015 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.

#if SB_API_VERSION >= 16

#include <pthread.h>

#include "starboard/configuration.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace starboard {
namespace nplb {
namespace {

struct TestContext {
TestContext() : count(0) {}
pthread_mutex_t mutex;
int count;
};

const int kLoops = 10000;

void* EntryPoint(void* parameter) {
TestContext* context = static_cast<TestContext*>(parameter);

for (int i = 0; i < kLoops; ++i) {
pthread_mutex_lock(&context->mutex);
int k = context->count;
k = k + 1;
context->count = k;
pthread_mutex_unlock(&context->mutex);
}

return NULL;
}

// This test just tries to acquire a mutex repeatedly while other threads are
// doing the same.
TEST(PosixMutexAcquireTest, SunnyDayContended) {
TestContext context;
EXPECT_EQ(pthread_mutex_init(&context.mutex, NULL), 0);
const int kThreads = 4;
SbThread threads[kThreads];
for (int i = 0; i < kThreads; ++i) {
threads[i] = SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity,
true, NULL, EntryPoint, &context);
}

for (int i = 0; i < kLoops; ++i) {
for (int j = 0; j < kThreads; ++j) {
EXPECT_EQ(pthread_mutex_lock(&context.mutex), 0);
int k = context.count;
k = k - 1;
context.count = k;
EXPECT_EQ(pthread_mutex_unlock(&context.mutex), 0);
}
}

// Join other threads and clean up.
for (int i = 0; i < kThreads; ++i) {
EXPECT_TRUE(SbThreadJoin(threads[i], NULL));
}
EXPECT_EQ(pthread_mutex_destroy(&context.mutex), 0);
EXPECT_EQ(0, context.count);
}

TEST(PosixMutexAcquireTest, SunnyDayUncontended) {
pthread_mutex_t mutex;
EXPECT_EQ(pthread_mutex_init(&mutex, NULL), 0);

EXPECT_EQ(pthread_mutex_lock(&mutex), 0);
EXPECT_EQ(pthread_mutex_unlock(&mutex), 0);
EXPECT_EQ(pthread_mutex_destroy(&mutex), 0);
}

TEST(PosixMutexAcquireTest, SunnyDayStaticallyInitialized) {
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
EXPECT_EQ(pthread_mutex_lock(&mutex), 0);
EXPECT_EQ(pthread_mutex_unlock(&mutex), 0);
EXPECT_EQ(pthread_mutex_destroy(&mutex), 0);
}

} // namespace
} // namespace nplb
} // namespace starboard

#endif // SB_API_VERSION >= 16
81 changes: 81 additions & 0 deletions starboard/nplb/posix_compliance/posix_mutex_acquire_try_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2015 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.

#if SB_API_VERSION >= 16

#include <pthread.h>

#include "starboard/configuration.h"
#include "testing/gtest/include/gtest/gtest.h"

#include "starboard/nplb/thread_helpers.h"
#include "starboard/thread.h"

namespace starboard {
namespace nplb {
namespace {

struct TestContext {
explicit TestContext(pthread_mutex_t* mutex)
: was_locked_(false), mutex_(mutex) {}
bool was_locked_;
pthread_mutex_t* mutex_;
};

void* EntryPoint(void* parameter) {
TestContext* context = static_cast<TestContext*>(parameter);
context->was_locked_ = (pthread_mutex_lock(context->mutex_) == 0);
return NULL;
}

TEST(SbMutexAcquireTryTest, SunnyDayUncontended) {
pthread_mutex_t mutex;
EXPECT_EQ(pthread_mutex_init(&mutex, NULL), 0);

EXPECT_EQ(pthread_mutex_trylock(&mutex), 0);
EXPECT_EQ(pthread_mutex_unlock(&mutex), 0);
EXPECT_EQ(pthread_mutex_destroy(&mutex), 0);
}

TEST(SbMutexAcquireTest, SunnyDayAutoInit) {
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
EXPECT_EQ(pthread_mutex_trylock(&mutex), 0);
EXPECT_EQ(pthread_mutex_unlock(&mutex), 0);
EXPECT_EQ(pthread_mutex_destroy(&mutex), 0);
}

TEST(SbMutexAcquireTryTest, RainyDayReentrant) {
pthread_mutex_t mutex;
EXPECT_EQ(pthread_mutex_init(&mutex, NULL), 0);

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

EXPECT_TRUE(SbThreadIsValid(thread));
EXPECT_TRUE(SbThreadJoin(thread, NULL));
EXPECT_FALSE(context.was_locked_);
EXPECT_EQ(pthread_mutex_unlock(&mutex), 0);
EXPECT_EQ(pthread_mutex_destroy(&mutex), 0);
}

} // namespace
} // namespace nplb
} // namespace starboard

#endif // SB_API_VERSION >= 16
65 changes: 65 additions & 0 deletions starboard/nplb/posix_compliance/posix_mutex_create_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2015 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.

#if SB_API_VERSION >= 16

#include <pthread.h>

#include "starboard/configuration.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace starboard {
namespace nplb {
namespace {

const int kALot = 128 * 1024;
const int kABunch = 2 * 1024;

TEST(PosixMutexCreateTest, SunnyDay) {
pthread_mutex_t mutex;
EXPECT_EQ(pthread_mutex_init(&mutex, NULL), 0);
EXPECT_EQ(pthread_mutex_destroy(&mutex), 0);
}

TEST(PosixMutexCreateTest, SunnyDayAutoInit) {
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

EXPECT_EQ(pthread_mutex_init(&mutex, NULL), 0);
EXPECT_EQ(pthread_mutex_destroy(&mutex), 0);
}

TEST(PosixMutexCreateTest, SunnyDayALot) {
for (int i = 0; i < kALot; ++i) {
pthread_mutex_t mutex;
EXPECT_EQ(pthread_mutex_init(&mutex, NULL), 0);
EXPECT_EQ(pthread_mutex_destroy(&mutex), 0);
}
}

TEST(PosixMutexCreateTest, SunnyDayABunchAtOnce) {
pthread_mutex_t mutexes[kABunch];
for (int i = 0; i < kABunch; ++i) {
EXPECT_EQ(pthread_mutex_init(&mutexes[i], NULL), 0);
}

for (int i = 0; i < kABunch; ++i) {
EXPECT_EQ(pthread_mutex_destroy(&mutexes[i]), 0);
}
}

} // namespace
} // namespace nplb
} // namespace starboard

#endif // SB_API_VERSION >= 16
35 changes: 35 additions & 0 deletions starboard/nplb/posix_compliance/posix_mutex_destroy_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2015 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.

#if SB_API_VERSION >= 16

#include <pthread.h>

#include "starboard/configuration.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace starboard {
namespace nplb {
namespace {

TEST(PosixMutexDestroyTest, SunnyDayAutoInit) {
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
EXPECT_EQ(pthread_mutex_destroy(&mutex), 0);
}

} // namespace
} // namespace nplb
} // namespace starboard

#endif // SB_API_VERSION >= 16
7 changes: 6 additions & 1 deletion starboard/shared/modular/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@ source_set("posix_wrappers") {
sources = [
"posix_mmap_wrappers.cc",
"posix_mmap_wrappers.h",
"posix_pthread_wrappers.cc",
"posix_pthread_wrappers.h",
"posix_time_wrappers.cc",
"posix_time_wrappers.h",
]

configs += [ "//starboard/build/config:starboard_implementation" ]

deps = [ "//starboard:starboard_headers_only" ]
deps = [
"//starboard:starboard_headers_only",
"//starboard/common",
]
}
Loading

0 comments on commit 2e3528d

Please sign in to comment.