mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-11 08:48:12 +00:00
[hwasan] Madvise away thread aux data
Summary: Release memory pages for thread data (allocator cache, stack allocations ring buffer, etc) when a thread exits. We can not simply munmap them because this memory is custom allocated within a limited address range, and it needs to stay "reserved". This change alters thread storage layout by putting the ring buffer before Thread instead of after it. This makes it possible to find the start of the thread aux allocation given only the Thread pointer. Reviewers: kcc, pcc Subscribers: kubamracek, llvm-commits Differential Revision: https://reviews.llvm.org/D56621 llvm-svn: 352151
This commit is contained in:
parent
9ea001401c
commit
f4e7051c67
@ -108,38 +108,52 @@ struct ThreadStats {
|
||||
class HwasanThreadList {
|
||||
public:
|
||||
HwasanThreadList(uptr storage, uptr size)
|
||||
: free_space_(storage),
|
||||
free_space_end_(storage + size),
|
||||
ring_buffer_size_(RingBufferSize()) {}
|
||||
: free_space_(storage), free_space_end_(storage + size) {
|
||||
// [storage, storage + size) is used as a vector of
|
||||
// thread_alloc_size_-sized, ring_buffer_size_*2-aligned elements.
|
||||
// Each element contains
|
||||
// * a ring buffer at offset 0,
|
||||
// * a Thread object at offset ring_buffer_size_.
|
||||
ring_buffer_size_ = RingBufferSize();
|
||||
thread_alloc_size_ =
|
||||
RoundUpTo(ring_buffer_size_ + sizeof(Thread), ring_buffer_size_ * 2);
|
||||
}
|
||||
|
||||
Thread *CreateCurrentThread() {
|
||||
Thread *t;
|
||||
{
|
||||
SpinMutexLock l(&list_mutex_);
|
||||
t = free_list_.Pop();
|
||||
if (t)
|
||||
internal_memset((void *)t, 0, sizeof(Thread) + ring_buffer_size_);
|
||||
else
|
||||
if (t) {
|
||||
uptr start = (uptr)t - ring_buffer_size_;
|
||||
internal_memset((void *)start, 0, ring_buffer_size_ + sizeof(Thread));
|
||||
} else {
|
||||
t = AllocThread();
|
||||
}
|
||||
live_list_.Push(t);
|
||||
}
|
||||
t->Init((uptr)(t + 1), ring_buffer_size_);
|
||||
t->Init((uptr)t - ring_buffer_size_, ring_buffer_size_);
|
||||
AddThreadStats(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
void DontNeedThread(Thread *t) {
|
||||
uptr start = (uptr)t - ring_buffer_size_;
|
||||
ReleaseMemoryPagesToOS(start, start + thread_alloc_size_);
|
||||
}
|
||||
|
||||
void ReleaseThread(Thread *t) {
|
||||
// FIXME: madvise away the ring buffer?
|
||||
RemoveThreadStats(t);
|
||||
t->Destroy();
|
||||
SpinMutexLock l(&list_mutex_);
|
||||
live_list_.Remove(t);
|
||||
free_list_.Push(t);
|
||||
DontNeedThread(t);
|
||||
}
|
||||
|
||||
Thread *GetThreadByBufferAddress(uptr p) {
|
||||
uptr align = ring_buffer_size_ * 2;
|
||||
return (Thread *)(RoundDownTo(p, align) - sizeof(Thread));
|
||||
return (Thread *)(RoundDownTo(p, ring_buffer_size_ * 2) +
|
||||
ring_buffer_size_);
|
||||
}
|
||||
|
||||
uptr MemoryUsedPerThread() {
|
||||
@ -175,15 +189,17 @@ class HwasanThreadList {
|
||||
private:
|
||||
Thread *AllocThread() {
|
||||
uptr align = ring_buffer_size_ * 2;
|
||||
uptr ring_buffer_start = RoundUpTo(free_space_ + sizeof(Thread), align);
|
||||
free_space_ = ring_buffer_start + ring_buffer_size_;
|
||||
CHECK(IsAligned(free_space_, align));
|
||||
Thread *t = (Thread *)(free_space_ + ring_buffer_size_);
|
||||
free_space_ += thread_alloc_size_;
|
||||
CHECK(free_space_ <= free_space_end_ && "out of thread memory");
|
||||
return (Thread *)(ring_buffer_start - sizeof(Thread));
|
||||
return t;
|
||||
}
|
||||
|
||||
uptr free_space_;
|
||||
uptr free_space_end_;
|
||||
uptr ring_buffer_size_;
|
||||
uptr thread_alloc_size_;
|
||||
|
||||
ThreadListHead free_list_;
|
||||
ThreadListHead live_list_;
|
||||
|
Loading…
Reference in New Issue
Block a user