#include <fcntl.h>
#include <unistd.h>
-#include <new>
-
namespace __asan {
extern dispatch_async_f_f real_dispatch_async_f;
// It's incorrect to assert that the current thread is not dying: at least
// the callbacks from dispatch_sync() are sometimes called after the TSD is
// destroyed.
- t = (AsanThread*)asan_malloc(sizeof(AsanThread), &stack);
- new(t) AsanThread(context->parent_tid,
- /*start_routine*/NULL, /*arg*/NULL, &stack);
+ AsanThread *t = AsanThread::Create(context->parent_tid, NULL, NULL);
+ asanThreadRegistry().RegisterThread(t, context->parent_tid, &stack);
t->Init();
asanThreadRegistry().SetCurrent(t);
}
int WRAP(pthread_create)(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg) {
GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false);
- AsanThread *t = (AsanThread*)asan_malloc(sizeof(AsanThread), &stack);
AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
CHECK(curr_thread || asanThreadRegistry().IsCurrentThreadDying());
- new(t) AsanThread(asanThreadRegistry().GetCurrentTidOrMinusOne(),
- start_routine, arg, &stack);
+ int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
+ AsanThread *t = AsanThread::Create(current_tid, start_routine, arg);
+ asanThreadRegistry().RegisterThread(t, current_tid, &stack);
return real_pthread_create(thread, attr, asan_thread_start, t);
}
#include "asan_interceptors.h"
#include "asan_procmaps.h"
#include "asan_thread.h"
-#include "asan_thread_registry.h"
#include "asan_mapping.h"
#include <pthread.h>
malloc_storage_(x),
stats_(x) { }
-AsanThread::AsanThread(int parent_tid, void *(*start_routine) (void *),
- void *arg, AsanStackTrace *stack)
- : start_routine_(start_routine),
- arg_(arg) {
- asanThreadRegistry().RegisterThread(this, parent_tid, stack);
+AsanThread *AsanThread::Create(int parent_tid, void *(*start_routine) (void *),
+ void *arg) {
+ size_t size = RoundUpTo(sizeof(AsanThread), kPageSize);
+ AsanThread *res = (AsanThread*)AsanMmapSomewhereOrDie(size, __FUNCTION__);
+ res->start_routine_ = start_routine;
+ res->arg_ = arg;
+ return res;
}
-AsanThread::~AsanThread() {
- asanThreadRegistry().UnregisterThread(this);
+void AsanThread::Destroy() {
fake_stack().Cleanup();
// We also clear the shadow on thread destruction because
// some code may still be executing in later TSD destructors
// and we don't want it to have any poisoned stack.
ClearShadowForThreadStack();
+ size_t size = RoundUpTo(sizeof(AsanThread), kPageSize);
+ AsanUnmapOrDie(this, size);
}
void AsanThread::ClearShadowForThreadStack() {
class AsanThread {
public:
explicit AsanThread(LinkerInitialized); // for T0.
- AsanThread(int parent_tid, void *(*start_routine) (void *),
- void *arg, AsanStackTrace *stack);
- ~AsanThread();
+ static AsanThread *Create(int parent_tid, void *(*start_routine) (void *),
+ void *arg);
+ void Destroy();
void Init(); // Should be called from the thread itself.
void *ThreadStart();
// The pointer is valid.
AsanThread *t = (AsanThread*)tsd;
if (t != asanThreadRegistry().GetMain()) {
- delete t;
+ asanThreadRegistry().UnregisterThread(t);
+ t->Destroy();
}
iter = 1;
} else {