forked from OSchip/llvm-project
parent
e24f3ff8de
commit
34794a9669
|
@ -916,7 +916,7 @@ ThreadLister::ThreadLister(int pid) : pid_(pid), buffer_(4096) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThreadLister::ListThreads(InternalMmapVector<int> *threads) {
|
bool ThreadLister::ListThreads(InternalMmapVector<tid_t> *threads) {
|
||||||
if (internal_iserror(descriptor_))
|
if (internal_iserror(descriptor_))
|
||||||
return false;
|
return false;
|
||||||
internal_lseek(descriptor_, 0, SEEK_SET);
|
internal_lseek(descriptor_, 0, SEEK_SET);
|
||||||
|
|
|
@ -74,12 +74,12 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
|
||||||
// This class reads thread IDs from /proc/<pid>/task using only syscalls.
|
// This class reads thread IDs from /proc/<pid>/task using only syscalls.
|
||||||
class ThreadLister {
|
class ThreadLister {
|
||||||
public:
|
public:
|
||||||
explicit ThreadLister(int pid);
|
explicit ThreadLister(pid_t pid);
|
||||||
~ThreadLister();
|
~ThreadLister();
|
||||||
bool ListThreads(InternalMmapVector<int> *threads);
|
bool ListThreads(InternalMmapVector<tid_t> *threads);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int pid_;
|
pid_t pid_;
|
||||||
int descriptor_ = -1;
|
int descriptor_ = -1;
|
||||||
InternalMmapVector<char> buffer_;
|
InternalMmapVector<char> buffer_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -211,7 +211,7 @@ bool ThreadSuspender::SuspendAllThreads() {
|
||||||
ThreadLister thread_lister(pid_);
|
ThreadLister thread_lister(pid_);
|
||||||
bool added_threads;
|
bool added_threads;
|
||||||
bool first_iteration = true;
|
bool first_iteration = true;
|
||||||
InternalMmapVector<int> threads;
|
InternalMmapVector<tid_t> threads;
|
||||||
threads.reserve(128);
|
threads.reserve(128);
|
||||||
do {
|
do {
|
||||||
// Run through the directory entries once.
|
// Run through the directory entries once.
|
||||||
|
@ -220,7 +220,7 @@ bool ThreadSuspender::SuspendAllThreads() {
|
||||||
ResumeAllThreads();
|
ResumeAllThreads();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (int tid : threads)
|
for (tid_t tid : threads)
|
||||||
if (SuspendThread(tid))
|
if (SuspendThread(tid))
|
||||||
added_threads = true;
|
added_threads = true;
|
||||||
if (first_iteration && !added_threads) {
|
if (first_iteration && !added_threads) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ struct TidReporterArgument {
|
||||||
pthread_cond_destroy(&tid_reported_cond);
|
pthread_cond_destroy(&tid_reported_cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t reported_tid;
|
tid_t reported_tid;
|
||||||
// For signaling to spawned threads that they should terminate.
|
// For signaling to spawned threads that they should terminate.
|
||||||
pthread_cond_t terminate_thread_cond;
|
pthread_cond_t terminate_thread_cond;
|
||||||
pthread_mutex_t terminate_thread_mutex;
|
pthread_mutex_t terminate_thread_mutex;
|
||||||
|
@ -64,7 +64,7 @@ class ThreadListerTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
pthread_t pthread_id;
|
pthread_t pthread_id;
|
||||||
pid_t tid;
|
tid_t tid;
|
||||||
for (uptr i = 0; i < kThreadCount; i++) {
|
for (uptr i = 0; i < kThreadCount; i++) {
|
||||||
SpawnTidReporter(&pthread_id, &tid);
|
SpawnTidReporter(&pthread_id, &tid);
|
||||||
pthread_ids_.push_back(pthread_id);
|
pthread_ids_.push_back(pthread_id);
|
||||||
|
@ -81,12 +81,12 @@ class ThreadListerTest : public ::testing::Test {
|
||||||
pthread_join(pthread_ids_[i], NULL);
|
pthread_join(pthread_ids_[i], NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpawnTidReporter(pthread_t *pthread_id, pid_t *tid);
|
void SpawnTidReporter(pthread_t *pthread_id, tid_t *tid);
|
||||||
|
|
||||||
static const uptr kThreadCount = 20;
|
static const uptr kThreadCount = 20;
|
||||||
|
|
||||||
std::vector<pthread_t> pthread_ids_;
|
std::vector<pthread_t> pthread_ids_;
|
||||||
std::vector<pid_t> tids_;
|
std::vector<tid_t> tids_;
|
||||||
|
|
||||||
TidReporterArgument thread_arg;
|
TidReporterArgument thread_arg;
|
||||||
};
|
};
|
||||||
|
@ -107,44 +107,43 @@ void *TidReporterThread(void *argument) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadListerTest::SpawnTidReporter(pthread_t *pthread_id,
|
void ThreadListerTest::SpawnTidReporter(pthread_t *pthread_id, tid_t *tid) {
|
||||||
pid_t *tid) {
|
|
||||||
pthread_mutex_lock(&thread_arg.tid_reported_mutex);
|
pthread_mutex_lock(&thread_arg.tid_reported_mutex);
|
||||||
thread_arg.reported_tid = -1;
|
thread_arg.reported_tid = -1;
|
||||||
ASSERT_EQ(0, pthread_create(pthread_id, NULL,
|
ASSERT_EQ(0, pthread_create(pthread_id, NULL,
|
||||||
TidReporterThread,
|
TidReporterThread,
|
||||||
&thread_arg));
|
&thread_arg));
|
||||||
while (thread_arg.reported_tid == -1)
|
while (thread_arg.reported_tid == (tid_t)(-1))
|
||||||
pthread_cond_wait(&thread_arg.tid_reported_cond,
|
pthread_cond_wait(&thread_arg.tid_reported_cond,
|
||||||
&thread_arg.tid_reported_mutex);
|
&thread_arg.tid_reported_mutex);
|
||||||
pthread_mutex_unlock(&thread_arg.tid_reported_mutex);
|
pthread_mutex_unlock(&thread_arg.tid_reported_mutex);
|
||||||
*tid = thread_arg.reported_tid;
|
*tid = thread_arg.reported_tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<pid_t> ReadTidsToVector(ThreadLister *thread_lister) {
|
static std::vector<tid_t> ReadTidsToVector(ThreadLister *thread_lister) {
|
||||||
std::vector<pid_t> listed_tids;
|
std::vector<tid_t> listed_tids;
|
||||||
InternalMmapVector<int> threads(128);
|
InternalMmapVector<tid_t> threads(128);
|
||||||
EXPECT_TRUE(thread_lister->ListThreads(&threads));
|
EXPECT_TRUE(thread_lister->ListThreads(&threads));
|
||||||
return std::vector<pid_t>(threads.begin(), threads.end());
|
return std::vector<tid_t>(threads.begin(), threads.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Includes(std::vector<pid_t> first, std::vector<pid_t> second) {
|
static bool Includes(std::vector<tid_t> first, std::vector<tid_t> second) {
|
||||||
std::sort(first.begin(), first.end());
|
std::sort(first.begin(), first.end());
|
||||||
std::sort(second.begin(), second.end());
|
std::sort(second.begin(), second.end());
|
||||||
return std::includes(first.begin(), first.end(),
|
return std::includes(first.begin(), first.end(),
|
||||||
second.begin(), second.end());
|
second.begin(), second.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool HasElement(std::vector<pid_t> vector, pid_t element) {
|
static bool HasElement(const std::vector<tid_t> &vector, tid_t element) {
|
||||||
return std::find(vector.begin(), vector.end(), element) != vector.end();
|
return std::find(vector.begin(), vector.end(), element) != vector.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ThreadLister's output should include the current thread's TID and the TID of
|
// ThreadLister's output should include the current thread's TID and the TID of
|
||||||
// every thread we spawned.
|
// every thread we spawned.
|
||||||
TEST_F(ThreadListerTest, ThreadListerSeesAllSpawnedThreads) {
|
TEST_F(ThreadListerTest, ThreadListerSeesAllSpawnedThreads) {
|
||||||
pid_t self_tid = GetTid();
|
tid_t self_tid = GetTid();
|
||||||
ThreadLister thread_lister(getpid());
|
ThreadLister thread_lister(getpid());
|
||||||
std::vector<pid_t> listed_tids = ReadTidsToVector(&thread_lister);
|
std::vector<tid_t> listed_tids = ReadTidsToVector(&thread_lister);
|
||||||
ASSERT_TRUE(HasElement(listed_tids, self_tid));
|
ASSERT_TRUE(HasElement(listed_tids, self_tid));
|
||||||
ASSERT_TRUE(Includes(listed_tids, tids_));
|
ASSERT_TRUE(Includes(listed_tids, tids_));
|
||||||
}
|
}
|
||||||
|
@ -155,7 +154,7 @@ TEST_F(ThreadListerTest, DoNotForgetThreads) {
|
||||||
// Run the loop body twice, because ThreadLister might behave differently if
|
// Run the loop body twice, because ThreadLister might behave differently if
|
||||||
// called on a freshly created object.
|
// called on a freshly created object.
|
||||||
for (uptr i = 0; i < 2; i++) {
|
for (uptr i = 0; i < 2; i++) {
|
||||||
std::vector<pid_t> listed_tids = ReadTidsToVector(&thread_lister);
|
std::vector<tid_t> listed_tids = ReadTidsToVector(&thread_lister);
|
||||||
ASSERT_TRUE(Includes(listed_tids, tids_));
|
ASSERT_TRUE(Includes(listed_tids, tids_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,10 +163,10 @@ TEST_F(ThreadListerTest, DoNotForgetThreads) {
|
||||||
// relisting should cause ThreadLister to recognize their existence.
|
// relisting should cause ThreadLister to recognize their existence.
|
||||||
TEST_F(ThreadListerTest, NewThreads) {
|
TEST_F(ThreadListerTest, NewThreads) {
|
||||||
ThreadLister thread_lister(getpid());
|
ThreadLister thread_lister(getpid());
|
||||||
std::vector<pid_t> threads_before_extra = ReadTidsToVector(&thread_lister);
|
std::vector<tid_t> threads_before_extra = ReadTidsToVector(&thread_lister);
|
||||||
|
|
||||||
pthread_t extra_pthread_id;
|
pthread_t extra_pthread_id;
|
||||||
pid_t extra_tid;
|
tid_t extra_tid;
|
||||||
SpawnTidReporter(&extra_pthread_id, &extra_tid);
|
SpawnTidReporter(&extra_pthread_id, &extra_tid);
|
||||||
// Register the new thread so it gets terminated in TearDown().
|
// Register the new thread so it gets terminated in TearDown().
|
||||||
pthread_ids_.push_back(extra_pthread_id);
|
pthread_ids_.push_back(extra_pthread_id);
|
||||||
|
@ -177,7 +176,7 @@ TEST_F(ThreadListerTest, NewThreads) {
|
||||||
// so better check for that.
|
// so better check for that.
|
||||||
ASSERT_FALSE(HasElement(threads_before_extra, extra_tid));
|
ASSERT_FALSE(HasElement(threads_before_extra, extra_tid));
|
||||||
|
|
||||||
std::vector<pid_t> threads_after_extra = ReadTidsToVector(&thread_lister);
|
std::vector<tid_t> threads_after_extra = ReadTidsToVector(&thread_lister);
|
||||||
ASSERT_TRUE(HasElement(threads_after_extra, extra_tid));
|
ASSERT_TRUE(HasElement(threads_after_extra, extra_tid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue