sanitizer_linux_test.cc revision 6fb47af2d2d305adbfc3d41bea589d1527a364a9
1//===-- sanitizer_linux_test.cc -------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Tests for sanitizer_linux.h
11//
12//===----------------------------------------------------------------------===//
13
14#ifdef __linux__
15
16#include "sanitizer_common/sanitizer_linux.h"
17#include "gtest/gtest.h"
18
19#include "sanitizer_common/sanitizer_common.h"
20
21#include <pthread.h>
22#include <sched.h>
23
24#include <set>
25
26namespace __sanitizer {
27// In a single-threaded process, ThreadLister should produce the TID (which
28// coincides with the PID) of the current task.
29TEST(SanitizerLinux, ThreadListerSingleThread) {
30  pid_t pid = getpid();
31  ThreadLister thread_lister(pid);
32  EXPECT_FALSE(thread_lister.error());
33  EXPECT_EQ(thread_lister.GetNextTID(), pid);
34  EXPECT_FALSE(thread_lister.error());
35  EXPECT_LT(thread_lister.GetNextTID(), 0);
36  EXPECT_FALSE(thread_lister.error());
37}
38
39static pthread_cond_t thread_exit_cond = PTHREAD_COND_INITIALIZER;
40static pthread_mutex_t thread_exit_mutex = PTHREAD_MUTEX_INITIALIZER;
41static pthread_cond_t tid_reported_cond = PTHREAD_COND_INITIALIZER;
42static pthread_mutex_t tid_reported_mutex = PTHREAD_MUTEX_INITIALIZER;
43static bool thread_exit;
44
45void *TIDReporterThread(void *tid_storage) {
46  pthread_mutex_lock(&tid_reported_mutex);
47  *(pid_t *)tid_storage = GetTid();
48  pthread_cond_broadcast(&tid_reported_cond);
49  pthread_mutex_unlock(&tid_reported_mutex);
50
51  pthread_mutex_lock(&thread_exit_mutex);
52  while (!thread_exit)
53    pthread_cond_wait(&thread_exit_cond, &thread_exit_mutex);
54  pthread_mutex_unlock(&thread_exit_mutex);
55  return NULL;
56}
57
58// In a process with multiple threads, ThreadLister should produce their TIDs
59// in some order.
60// Calling ThreadLister::Reset() should not change this.
61TEST(SanitizerLinux, ThreadListerMultiThreaded) {
62  const uptr kThreadCount = 20; // does not include the main thread
63  pthread_t thread_ids[kThreadCount];
64  pid_t  thread_tids[kThreadCount];
65  pid_t pid = getpid();
66  pid_t self_tid = GetTid();
67  thread_exit = false;
68  pthread_mutex_lock(&tid_reported_mutex);
69  for (uptr i = 0; i < kThreadCount; i++) {
70    int pthread_create_result;
71    thread_tids[i] = -1;
72    pthread_create_result = pthread_create(&thread_ids[i], NULL,
73                                           TIDReporterThread,
74                                           &thread_tids[i]);
75    ASSERT_EQ(pthread_create_result, 0);
76    while (thread_tids[i] == -1)
77      pthread_cond_wait(&tid_reported_cond, &tid_reported_mutex);
78  }
79  pthread_mutex_unlock(&tid_reported_mutex);
80  std::set<pid_t> reported_tids(thread_tids, thread_tids + kThreadCount);
81  reported_tids.insert(self_tid);
82
83  ThreadLister thread_lister(pid);
84  // There's a Reset() call between the first and second iteration.
85  for (uptr i = 0; i < 2; i++) {
86    std::set<pid_t> listed_tids;
87
88    EXPECT_FALSE(thread_lister.error());
89    for (uptr i = 0; i < kThreadCount + 1; i++) {
90      pid_t tid = thread_lister.GetNextTID();
91      EXPECT_GE(tid, 0);
92      EXPECT_FALSE(thread_lister.error());
93      listed_tids.insert(tid);
94    }
95    pid_t tid = thread_lister.GetNextTID();
96    EXPECT_LT(tid, 0);
97    EXPECT_FALSE(thread_lister.error());
98
99    EXPECT_EQ(listed_tids, reported_tids);
100    thread_lister.Reset();
101  }
102  pthread_mutex_lock(&thread_exit_mutex);
103  thread_exit = true;
104  pthread_cond_broadcast(&thread_exit_cond);
105  pthread_mutex_unlock(&thread_exit_mutex);
106}
107}  // namespace __sanitizer
108
109#endif  // __linux__
110