[threading linux] Wait for thread start
This commit is contained in:
parent
b91203a0b5
commit
b2912e7891
|
@ -435,8 +435,18 @@ struct ThreadStartData {
|
|||
|
||||
template <>
|
||||
class PosixCondition<Thread> : public PosixConditionBase {
|
||||
enum class State {
|
||||
kUninitialized,
|
||||
kRunning,
|
||||
kFinished,
|
||||
};
|
||||
|
||||
public:
|
||||
PosixCondition() : thread_(0), signaled_(false), exit_code_(0) {}
|
||||
PosixCondition()
|
||||
: thread_(0),
|
||||
signaled_(false),
|
||||
exit_code_(0),
|
||||
state_(State::kUninitialized) {}
|
||||
bool Initialize(Thread::CreationParameters params,
|
||||
ThreadStartData* start_data) {
|
||||
assert_false(params.create_suspended);
|
||||
|
@ -468,7 +478,10 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
/// Constructor for existing thread. This should only happen once called by
|
||||
/// Thread::GetCurrentThread() on the main thread
|
||||
explicit PosixCondition(pthread_t thread)
|
||||
: thread_(thread), signaled_(false), exit_code_(0) {}
|
||||
: thread_(thread),
|
||||
signaled_(false),
|
||||
exit_code_(0),
|
||||
state_(State::kRunning) {}
|
||||
|
||||
virtual ~PosixCondition() {
|
||||
if (thread_ && !signaled_) {
|
||||
|
@ -482,20 +495,29 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
}
|
||||
|
||||
std::string name() const {
|
||||
WaitStarted();
|
||||
auto result = std::array<char, 17>{'\0'};
|
||||
if (pthread_getname_np(thread_, result.data(), result.size() - 1) != 0)
|
||||
assert_always();
|
||||
std::unique_lock<std::mutex> lock(state_mutex_);
|
||||
if (state_ != State::kUninitialized && state_ != State::kFinished) {
|
||||
if (pthread_getname_np(thread_, result.data(), result.size() - 1) != 0)
|
||||
assert_always();
|
||||
}
|
||||
return std::string(result.data());
|
||||
}
|
||||
|
||||
void set_name(const std::string& name) {
|
||||
threading::set_name(static_cast<std::thread::native_handle_type>(thread_),
|
||||
name);
|
||||
WaitStarted();
|
||||
std::unique_lock<std::mutex> lock(state_mutex_);
|
||||
if (state_ != State::kUninitialized && state_ != State::kFinished) {
|
||||
threading::set_name(static_cast<std::thread::native_handle_type>(thread_),
|
||||
name);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t system_id() const { return static_cast<uint32_t>(thread_); }
|
||||
|
||||
uint64_t affinity_mask() {
|
||||
WaitStarted();
|
||||
cpu_set_t cpu_set;
|
||||
if (pthread_getaffinity_np(thread_, sizeof(cpu_set_t), &cpu_set) != 0)
|
||||
assert_always();
|
||||
|
@ -509,6 +531,7 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
}
|
||||
|
||||
void set_affinity_mask(uint64_t mask) {
|
||||
WaitStarted();
|
||||
cpu_set_t cpu_set;
|
||||
CPU_ZERO(&cpu_set);
|
||||
for (auto i = 0u; i < 64; i++) {
|
||||
|
@ -522,6 +545,7 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
}
|
||||
|
||||
int priority() {
|
||||
WaitStarted();
|
||||
int policy;
|
||||
sched_param param{};
|
||||
int ret = pthread_getschedparam(thread_, &policy, ¶m);
|
||||
|
@ -533,6 +557,7 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
}
|
||||
|
||||
void set_priority(int new_priority) {
|
||||
WaitStarted();
|
||||
sched_param param{};
|
||||
param.sched_priority = new_priority;
|
||||
if (pthread_setschedparam(thread_, SCHED_FIFO, ¶m) != 0)
|
||||
|
@ -557,6 +582,11 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
}
|
||||
|
||||
void Terminate(int exit_code) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(state_mutex_);
|
||||
state_ = State::kFinished;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
// Sometimes the thread can call terminate twice before stopping
|
||||
|
@ -570,6 +600,12 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
if (pthread_cancel(thread) != 0) assert_always();
|
||||
}
|
||||
|
||||
void WaitStarted() const {
|
||||
std::unique_lock<std::mutex> lock(state_mutex_);
|
||||
state_signal_.wait(lock,
|
||||
[this] { return state_ != State::kUninitialized; });
|
||||
}
|
||||
|
||||
private:
|
||||
static void* ThreadStartRoutine(void* parameter);
|
||||
inline bool signaled() const override { return signaled_; }
|
||||
|
@ -582,6 +618,9 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
pthread_t thread_;
|
||||
bool signaled_;
|
||||
int exit_code_;
|
||||
State state_;
|
||||
mutable std::mutex state_mutex_;
|
||||
mutable std::condition_variable state_signal_;
|
||||
};
|
||||
|
||||
// This wraps a condition object as our handle because posix has no single
|
||||
|
@ -752,6 +791,7 @@ class PosixThread : public PosixConditionHandle<Thread> {
|
|||
}
|
||||
|
||||
void set_name(std::string name) override {
|
||||
handle_.WaitStarted();
|
||||
Thread::set_name(name);
|
||||
if (name.length() > 15) {
|
||||
name = name.substr(0, 15);
|
||||
|
@ -803,8 +843,19 @@ void* PosixCondition<Thread>::ThreadStartRoutine(void* parameter) {
|
|||
delete start_data;
|
||||
|
||||
current_thread_ = thread;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(thread->handle_.state_mutex_);
|
||||
thread->handle_.state_ = State::kRunning;
|
||||
thread->handle_.state_signal_.notify_all();
|
||||
}
|
||||
|
||||
start_routine();
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(thread->handle_.state_mutex_);
|
||||
thread->handle_.state_ = State::kFinished;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
thread->handle_.exit_code_ = 0;
|
||||
thread->handle_.signaled_ = true;
|
||||
|
|
Loading…
Reference in New Issue