Mercurial > hg > CbC > CbC_gcc
comparison libsanitizer/lsan/lsan_thread.cpp @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 //=-- lsan_thread.cpp -----------------------------------------------------===// | |
2 // | |
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
4 // See https://llvm.org/LICENSE.txt for license information. | |
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
6 // | |
7 //===----------------------------------------------------------------------===// | |
8 // | |
9 // This file is a part of LeakSanitizer. | |
10 // See lsan_thread.h for details. | |
11 // | |
12 //===----------------------------------------------------------------------===// | |
13 | |
14 #include "lsan_thread.h" | |
15 | |
16 #include "sanitizer_common/sanitizer_common.h" | |
17 #include "sanitizer_common/sanitizer_placement_new.h" | |
18 #include "sanitizer_common/sanitizer_thread_registry.h" | |
19 #include "sanitizer_common/sanitizer_tls_get_addr.h" | |
20 #include "lsan_allocator.h" | |
21 #include "lsan_common.h" | |
22 | |
23 namespace __lsan { | |
24 | |
25 static ThreadRegistry *thread_registry; | |
26 | |
27 static ThreadContextBase *CreateThreadContext(u32 tid) { | |
28 void *mem = MmapOrDie(sizeof(ThreadContext), "ThreadContext"); | |
29 return new(mem) ThreadContext(tid); | |
30 } | |
31 | |
32 static const uptr kMaxThreads = 1 << 13; | |
33 static const uptr kThreadQuarantineSize = 64; | |
34 | |
35 void InitializeThreadRegistry() { | |
36 static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)]; | |
37 thread_registry = new(thread_registry_placeholder) | |
38 ThreadRegistry(CreateThreadContext, kMaxThreads, kThreadQuarantineSize); | |
39 } | |
40 | |
41 ThreadContext::ThreadContext(int tid) | |
42 : ThreadContextBase(tid), | |
43 stack_begin_(0), | |
44 stack_end_(0), | |
45 cache_begin_(0), | |
46 cache_end_(0), | |
47 tls_begin_(0), | |
48 tls_end_(0), | |
49 dtls_(nullptr) {} | |
50 | |
51 struct OnStartedArgs { | |
52 uptr stack_begin, stack_end, | |
53 cache_begin, cache_end, | |
54 tls_begin, tls_end; | |
55 DTLS *dtls; | |
56 }; | |
57 | |
58 void ThreadContext::OnStarted(void *arg) { | |
59 OnStartedArgs *args = reinterpret_cast<OnStartedArgs *>(arg); | |
60 stack_begin_ = args->stack_begin; | |
61 stack_end_ = args->stack_end; | |
62 tls_begin_ = args->tls_begin; | |
63 tls_end_ = args->tls_end; | |
64 cache_begin_ = args->cache_begin; | |
65 cache_end_ = args->cache_end; | |
66 dtls_ = args->dtls; | |
67 } | |
68 | |
69 void ThreadContext::OnFinished() { | |
70 AllocatorThreadFinish(); | |
71 DTLS_Destroy(); | |
72 } | |
73 | |
74 u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached) { | |
75 return thread_registry->CreateThread(user_id, detached, parent_tid, | |
76 /* arg */ nullptr); | |
77 } | |
78 | |
79 void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type) { | |
80 OnStartedArgs args; | |
81 uptr stack_size = 0; | |
82 uptr tls_size = 0; | |
83 GetThreadStackAndTls(tid == 0, &args.stack_begin, &stack_size, | |
84 &args.tls_begin, &tls_size); | |
85 args.stack_end = args.stack_begin + stack_size; | |
86 args.tls_end = args.tls_begin + tls_size; | |
87 GetAllocatorCacheRange(&args.cache_begin, &args.cache_end); | |
88 args.dtls = DTLS_Get(); | |
89 thread_registry->StartThread(tid, os_id, thread_type, &args); | |
90 } | |
91 | |
92 void ThreadFinish() { | |
93 thread_registry->FinishThread(GetCurrentThread()); | |
94 SetCurrentThread(kInvalidTid); | |
95 } | |
96 | |
97 ThreadContext *CurrentThreadContext() { | |
98 if (!thread_registry) return nullptr; | |
99 if (GetCurrentThread() == kInvalidTid) | |
100 return nullptr; | |
101 // No lock needed when getting current thread. | |
102 return (ThreadContext *)thread_registry->GetThreadLocked(GetCurrentThread()); | |
103 } | |
104 | |
105 static bool FindThreadByUid(ThreadContextBase *tctx, void *arg) { | |
106 uptr uid = (uptr)arg; | |
107 if (tctx->user_id == uid && tctx->status != ThreadStatusInvalid) { | |
108 return true; | |
109 } | |
110 return false; | |
111 } | |
112 | |
113 u32 ThreadTid(uptr uid) { | |
114 return thread_registry->FindThread(FindThreadByUid, (void*)uid); | |
115 } | |
116 | |
117 void ThreadJoin(u32 tid) { | |
118 CHECK_NE(tid, kInvalidTid); | |
119 thread_registry->JoinThread(tid, /* arg */nullptr); | |
120 } | |
121 | |
122 void EnsureMainThreadIDIsCorrect() { | |
123 if (GetCurrentThread() == 0) | |
124 CurrentThreadContext()->os_id = GetTid(); | |
125 } | |
126 | |
127 ///// Interface to the common LSan module. ///// | |
128 | |
129 bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end, | |
130 uptr *tls_begin, uptr *tls_end, uptr *cache_begin, | |
131 uptr *cache_end, DTLS **dtls) { | |
132 ThreadContext *context = static_cast<ThreadContext *>( | |
133 thread_registry->FindThreadContextByOsIDLocked(os_id)); | |
134 if (!context) return false; | |
135 *stack_begin = context->stack_begin(); | |
136 *stack_end = context->stack_end(); | |
137 *tls_begin = context->tls_begin(); | |
138 *tls_end = context->tls_end(); | |
139 *cache_begin = context->cache_begin(); | |
140 *cache_end = context->cache_end(); | |
141 *dtls = context->dtls(); | |
142 return true; | |
143 } | |
144 | |
145 void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback, | |
146 void *arg) { | |
147 } | |
148 | |
149 void LockThreadRegistry() { | |
150 thread_registry->Lock(); | |
151 } | |
152 | |
153 void UnlockThreadRegistry() { | |
154 thread_registry->Unlock(); | |
155 } | |
156 | |
157 ThreadRegistry *GetThreadRegistryLocked() { | |
158 thread_registry->CheckLocked(); | |
159 return thread_registry; | |
160 } | |
161 | |
162 } // namespace __lsan |