aboutsummaryrefslogtreecommitdiff
path: root/source/Host/macosx/HostThreadMacOSX.mm
blob: c84a78efd9e6cfb02c23c3c684fb7a07d2b6cd36 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//===-- HostThreadMacOSX.cpp ------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Host/macosx/HostThreadMacOSX.h"
#include "lldb/Host/Host.h"

#include <CoreFoundation/CoreFoundation.h>
#include <Foundation/Foundation.h>

#include <objc/objc-auto.h>
#include <pthread.h>

using namespace lldb_private;

namespace
{

pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT;
pthread_key_t g_thread_create_key = 0;

class MacOSXDarwinThread
{
  public:
    MacOSXDarwinThread()
        : m_pool(nil)
    {
        // Register our thread with the collector if garbage collection is enabled.
        if (objc_collectingEnabled())
        {
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
            // On Leopard and earlier there is no way objc_registerThreadWithCollector
            // function, so we do it manually.
            auto_zone_register_thread(auto_zone());
#else
            // On SnowLeopard and later we just call the thread registration function.
            objc_registerThreadWithCollector();
#endif
        }
        else
        {
            m_pool = [[NSAutoreleasePool alloc] init];
        }
    }

    ~MacOSXDarwinThread()
    {
        if (m_pool)
        {
            [m_pool drain];
            m_pool = nil;
        }
    }

    static void
    PThreadDestructor(void *v)
    {
        if (v)
            delete static_cast<MacOSXDarwinThread *>(v);
        ::pthread_setspecific(g_thread_create_key, NULL);
    }

  protected:
    NSAutoreleasePool *m_pool;

  private:
    DISALLOW_COPY_AND_ASSIGN(MacOSXDarwinThread);
};

void
InitThreadCreated()
{
    ::pthread_key_create(&g_thread_create_key, MacOSXDarwinThread::PThreadDestructor);
}
} // namespace

HostThreadMacOSX::HostThreadMacOSX()
    : HostThreadPosix()
{
}

HostThreadMacOSX::HostThreadMacOSX(lldb::thread_t thread)
    : HostThreadPosix(thread)
{
}

lldb::thread_result_t
HostThreadMacOSX::ThreadCreateTrampoline(lldb::thread_arg_t arg)
{
    ::pthread_once(&g_thread_create_once, InitThreadCreated);
    if (g_thread_create_key)
    {
        ::pthread_setspecific(g_thread_create_key, new MacOSXDarwinThread());
    }

    return HostThreadPosix::ThreadCreateTrampoline(arg);
}