2014-01-16 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / libsanitizer / lsan / lsan_thread.cc
blob07f9d0ab4398165e65366a8350005e9370e4e70a
1 //=-- lsan_thread.cc ------------------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of LeakSanitizer.
9 // See lsan_thread.h for details.
11 //===----------------------------------------------------------------------===//
13 #include "lsan_thread.h"
15 #include "sanitizer_common/sanitizer_common.h"
16 #include "sanitizer_common/sanitizer_placement_new.h"
17 #include "sanitizer_common/sanitizer_thread_registry.h"
18 #include "lsan_allocator.h"
20 namespace __lsan {
22 const u32 kInvalidTid = (u32) -1;
24 static ThreadRegistry *thread_registry;
25 static THREADLOCAL u32 current_thread_tid = kInvalidTid;
27 static ThreadContextBase *CreateThreadContext(u32 tid) {
28 void *mem = MmapOrDie(sizeof(ThreadContext), "ThreadContext");
29 return new(mem) ThreadContext(tid);
32 static const uptr kMaxThreads = 1 << 13;
33 static const uptr kThreadQuarantineSize = 64;
35 void InitializeThreadRegistry() {
36 static char thread_registry_placeholder[sizeof(ThreadRegistry)] ALIGNED(64);
37 thread_registry = new(thread_registry_placeholder)
38 ThreadRegistry(CreateThreadContext, kMaxThreads, kThreadQuarantineSize);
41 u32 GetCurrentThread() {
42 return current_thread_tid;
45 void SetCurrentThread(u32 tid) {
46 current_thread_tid = tid;
49 ThreadContext::ThreadContext(int tid)
50 : ThreadContextBase(tid),
51 stack_begin_(0),
52 stack_end_(0),
53 cache_begin_(0),
54 cache_end_(0),
55 tls_begin_(0),
56 tls_end_(0) {}
58 struct OnStartedArgs {
59 uptr stack_begin, stack_end,
60 cache_begin, cache_end,
61 tls_begin, tls_end;
64 void ThreadContext::OnStarted(void *arg) {
65 OnStartedArgs *args = reinterpret_cast<OnStartedArgs *>(arg);
66 stack_begin_ = args->stack_begin;
67 stack_end_ = args->stack_end;
68 tls_begin_ = args->tls_begin;
69 tls_end_ = args->tls_end;
70 cache_begin_ = args->cache_begin;
71 cache_end_ = args->cache_end;
74 void ThreadContext::OnFinished() {
75 AllocatorThreadFinish();
78 u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached) {
79 return thread_registry->CreateThread(user_id, detached, parent_tid,
80 /* arg */ 0);
83 void ThreadStart(u32 tid, uptr os_id) {
84 OnStartedArgs args;
85 uptr stack_size = 0;
86 uptr tls_size = 0;
87 GetThreadStackAndTls(tid == 0, &args.stack_begin, &stack_size,
88 &args.tls_begin, &tls_size);
89 args.stack_end = args.stack_begin + stack_size;
90 args.tls_end = args.tls_begin + tls_size;
91 GetAllocatorCacheRange(&args.cache_begin, &args.cache_end);
92 thread_registry->StartThread(tid, os_id, &args);
95 void ThreadFinish() {
96 thread_registry->FinishThread(GetCurrentThread());
99 ThreadContext *CurrentThreadContext() {
100 if (!thread_registry) return 0;
101 if (GetCurrentThread() == kInvalidTid)
102 return 0;
103 // No lock needed when getting current thread.
104 return (ThreadContext *)thread_registry->GetThreadLocked(GetCurrentThread());
107 static bool FindThreadByUid(ThreadContextBase *tctx, void *arg) {
108 uptr uid = (uptr)arg;
109 if (tctx->user_id == uid && tctx->status != ThreadStatusInvalid) {
110 return true;
112 return false;
115 u32 ThreadTid(uptr uid) {
116 return thread_registry->FindThread(FindThreadByUid, (void*)uid);
119 void ThreadJoin(u32 tid) {
120 CHECK_NE(tid, kInvalidTid);
121 thread_registry->JoinThread(tid, /* arg */0);
124 void EnsureMainThreadIDIsCorrect() {
125 if (GetCurrentThread() == 0)
126 CurrentThreadContext()->os_id = GetTid();
129 ///// Interface to the common LSan module. /////
131 bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
132 uptr *tls_begin, uptr *tls_end,
133 uptr *cache_begin, uptr *cache_end) {
134 ThreadContext *context = static_cast<ThreadContext *>(
135 thread_registry->FindThreadContextByOsIDLocked(os_id));
136 if (!context) return false;
137 *stack_begin = context->stack_begin();
138 *stack_end = context->stack_end();
139 *tls_begin = context->tls_begin();
140 *tls_end = context->tls_end();
141 *cache_begin = context->cache_begin();
142 *cache_end = context->cache_end();
143 return true;
146 void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback,
147 void *arg) {
150 void LockThreadRegistry() {
151 thread_registry->Lock();
154 void UnlockThreadRegistry() {
155 thread_registry->Unlock();
158 } // namespace __lsan