130fdc8d8SChris Lattner //===-- MachThread.cpp ------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner //
1030fdc8d8SChris Lattner //  Created by Greg Clayton on 6/19/07.
1130fdc8d8SChris Lattner //
1230fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
1330fdc8d8SChris Lattner 
141c73911dSJason Molenda #include <inttypes.h>
1530fdc8d8SChris Lattner #include "MachThread.h"
1630fdc8d8SChris Lattner #include "MachProcess.h"
1730fdc8d8SChris Lattner #include "DNBLog.h"
1830fdc8d8SChris Lattner #include "DNB.h"
1930fdc8d8SChris Lattner 
2030fdc8d8SChris Lattner static uint32_t
2130fdc8d8SChris Lattner GetSequenceID()
2230fdc8d8SChris Lattner {
2330fdc8d8SChris Lattner     static uint32_t g_nextID = 0;
2430fdc8d8SChris Lattner     return ++g_nextID;
2530fdc8d8SChris Lattner }
2630fdc8d8SChris Lattner 
271c73911dSJason Molenda MachThread::MachThread (MachProcess *process, uint64_t unique_thread_id, thread_t mach_port_num) :
2830fdc8d8SChris Lattner     m_process (process),
291c73911dSJason Molenda     m_unique_id (unique_thread_id),
301c73911dSJason Molenda     m_mach_port_number (mach_port_num),
3130fdc8d8SChris Lattner     m_seq_id (GetSequenceID()),
3230fdc8d8SChris Lattner     m_state (eStateUnloaded),
3330fdc8d8SChris Lattner     m_state_mutex (PTHREAD_MUTEX_RECURSIVE),
34c235ac76SGreg Clayton     m_suspend_count (0),
35c235ac76SGreg Clayton     m_stop_exception (),
363af9ea56SGreg Clayton     m_arch_ap (DNBArchProtocol::Create (this)),
37c235ac76SGreg Clayton     m_reg_sets (NULL),
381c73911dSJason Molenda     m_num_reg_sets (0),
391c73911dSJason Molenda     m_ident_info(),
40c235ac76SGreg Clayton     m_proc_threadinfo(),
41c235ac76SGreg Clayton     m_dispatch_queue_name()
4230fdc8d8SChris Lattner {
43c235ac76SGreg Clayton     nub_size_t num_reg_sets = 0;
44c235ac76SGreg Clayton     m_reg_sets = m_arch_ap->GetRegisterSetInfo (&num_reg_sets);
45c235ac76SGreg Clayton     m_num_reg_sets = num_reg_sets;
46c235ac76SGreg Clayton 
471b946bf6SGreg Clayton     // Get the thread state so we know if a thread is in a state where we can't
481b946bf6SGreg Clayton     // muck with it and also so we get the suspend count correct in case it was
491b946bf6SGreg Clayton     // already suspended
50cdc7322bSGreg Clayton     GetBasicInfo();
511c73911dSJason Molenda     DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::MachThread ( process = %p, tid = 0x%8.8" PRIx64 ", seq_id = %u )", &m_process, m_unique_id, m_seq_id);
5230fdc8d8SChris Lattner }
5330fdc8d8SChris Lattner 
5430fdc8d8SChris Lattner MachThread::~MachThread()
5530fdc8d8SChris Lattner {
561c73911dSJason Molenda     DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::~MachThread() for tid = 0x%8.8" PRIx64 " (%u)", m_unique_id, m_seq_id);
5730fdc8d8SChris Lattner }
5830fdc8d8SChris Lattner 
5930fdc8d8SChris Lattner 
6030fdc8d8SChris Lattner 
619411ddb6SJim Ingham void
6230fdc8d8SChris Lattner MachThread::Suspend()
6330fdc8d8SChris Lattner {
6430fdc8d8SChris Lattner     DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__);
651c73911dSJason Molenda     if (MachPortNumberIsValid(m_mach_port_number))
6630fdc8d8SChris Lattner     {
671c73911dSJason Molenda         DNBError err(::thread_suspend (m_mach_port_number), DNBError::MachKernel);
6830fdc8d8SChris Lattner         if (err.Success())
69c235ac76SGreg Clayton             m_suspend_count++;
7030fdc8d8SChris Lattner         if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail())
711c73911dSJason Molenda             err.LogThreaded("::thread_suspend (%4.4" PRIx32 ")", m_mach_port_number);
7230fdc8d8SChris Lattner     }
7330fdc8d8SChris Lattner }
7430fdc8d8SChris Lattner 
759411ddb6SJim Ingham void
769411ddb6SJim Ingham MachThread::Resume(bool others_stopped)
7730fdc8d8SChris Lattner {
7830fdc8d8SChris Lattner     DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__);
791c73911dSJason Molenda     if (MachPortNumberIsValid(m_mach_port_number))
8030fdc8d8SChris Lattner     {
819411ddb6SJim Ingham         SetSuspendCountBeforeResume(others_stopped);
8230fdc8d8SChris Lattner     }
8330fdc8d8SChris Lattner }
8430fdc8d8SChris Lattner 
8530fdc8d8SChris Lattner bool
869411ddb6SJim Ingham MachThread::SetSuspendCountBeforeResume(bool others_stopped)
8730fdc8d8SChris Lattner {
88cdc7322bSGreg Clayton     DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__);
8930fdc8d8SChris Lattner     DNBError err;
901c73911dSJason Molenda     if (MachPortNumberIsValid(m_mach_port_number) == false)
9130fdc8d8SChris Lattner         return false;
929411ddb6SJim Ingham 
939411ddb6SJim Ingham     size_t times_to_resume;
949411ddb6SJim Ingham 
959411ddb6SJim Ingham     if (others_stopped)
969411ddb6SJim Ingham     {
9782283e8eSJim Ingham         if (GetBasicInfo())
9882283e8eSJim Ingham         {
9982283e8eSJim Ingham             times_to_resume = m_basic_info.suspend_count;
100c235ac76SGreg Clayton             m_suspend_count = - (times_to_resume - m_suspend_count);
1019411ddb6SJim Ingham         }
1029411ddb6SJim Ingham         else
10382283e8eSJim Ingham             times_to_resume = 0;
10482283e8eSJim Ingham     }
10582283e8eSJim Ingham     else
1069411ddb6SJim Ingham     {
107c235ac76SGreg Clayton         times_to_resume = m_suspend_count;
108c235ac76SGreg Clayton         m_suspend_count = 0;
1099411ddb6SJim Ingham     }
1109411ddb6SJim Ingham 
1119411ddb6SJim Ingham     if (times_to_resume > 0)
1129411ddb6SJim Ingham     {
1139411ddb6SJim Ingham         while (times_to_resume > 0)
1149411ddb6SJim Ingham         {
1151c73911dSJason Molenda             err = ::thread_resume (m_mach_port_number);
1169411ddb6SJim Ingham             if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail())
1171c73911dSJason Molenda                 err.LogThreaded("::thread_resume (%4.4" PRIx32 ")", m_mach_port_number);
1189411ddb6SJim Ingham             if (err.Success())
1199411ddb6SJim Ingham                 --times_to_resume;
1209411ddb6SJim Ingham             else
1219411ddb6SJim Ingham             {
1229411ddb6SJim Ingham                 if (GetBasicInfo())
123c235ac76SGreg Clayton                     times_to_resume = m_basic_info.suspend_count;
1249411ddb6SJim Ingham                 else
1259411ddb6SJim Ingham                     times_to_resume = 0;
1269411ddb6SJim Ingham             }
1279411ddb6SJim Ingham         }
1289411ddb6SJim Ingham     }
1299411ddb6SJim Ingham     return true;
1309411ddb6SJim Ingham }
1319411ddb6SJim Ingham 
1329411ddb6SJim Ingham bool
1339411ddb6SJim Ingham MachThread::RestoreSuspendCountAfterStop ()
1349411ddb6SJim Ingham {
1359411ddb6SJim Ingham     DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__);
1369411ddb6SJim Ingham     DNBError err;
1371c73911dSJason Molenda     if (MachPortNumberIsValid(m_mach_port_number) == false)
1389411ddb6SJim Ingham         return false;
1399411ddb6SJim Ingham 
140c235ac76SGreg Clayton     if (m_suspend_count > 0)
14130fdc8d8SChris Lattner     {
142c235ac76SGreg Clayton         while (m_suspend_count > 0)
14330fdc8d8SChris Lattner         {
1441c73911dSJason Molenda             err = ::thread_resume (m_mach_port_number);
14530fdc8d8SChris Lattner             if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail())
1461c73911dSJason Molenda                 err.LogThreaded("::thread_resume (%4.4" PRIx32 ")", m_mach_port_number);
14730fdc8d8SChris Lattner             if (err.Success())
148c235ac76SGreg Clayton                 --m_suspend_count;
1490dd2c627SGreg Clayton             else
1500dd2c627SGreg Clayton             {
151cdc7322bSGreg Clayton                 if (GetBasicInfo())
152c235ac76SGreg Clayton                     m_suspend_count = m_basic_info.suspend_count;
1530dd2c627SGreg Clayton                 else
154c235ac76SGreg Clayton                     m_suspend_count = 0;
1550dd2c627SGreg Clayton                 return false; // ???
15630fdc8d8SChris Lattner             }
15730fdc8d8SChris Lattner         }
1580dd2c627SGreg Clayton     }
159c235ac76SGreg Clayton     else if (m_suspend_count < 0)
1609411ddb6SJim Ingham     {
161c235ac76SGreg Clayton         while (m_suspend_count < 0)
1629411ddb6SJim Ingham         {
1631c73911dSJason Molenda             err = ::thread_suspend (m_mach_port_number);
1649411ddb6SJim Ingham             if (err.Success())
165c235ac76SGreg Clayton                 ++m_suspend_count;
1669411ddb6SJim Ingham             if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail())
167478235d8SJim Ingham             {
1681c73911dSJason Molenda                 err.LogThreaded("::thread_suspend (%4.4" PRIx32 ")", m_mach_port_number);
169478235d8SJim Ingham                 return false;
170478235d8SJim Ingham             }
1719411ddb6SJim Ingham         }
1729411ddb6SJim Ingham     }
1730dd2c627SGreg Clayton     return true;
17430fdc8d8SChris Lattner }
17530fdc8d8SChris Lattner 
17630fdc8d8SChris Lattner 
17730fdc8d8SChris Lattner const char *
17830fdc8d8SChris Lattner MachThread::GetBasicInfoAsString () const
17930fdc8d8SChris Lattner {
18030fdc8d8SChris Lattner     static char g_basic_info_string[1024];
18130fdc8d8SChris Lattner     struct thread_basic_info basicInfo;
18230fdc8d8SChris Lattner 
1831c73911dSJason Molenda     if (GetBasicInfo(m_mach_port_number, &basicInfo))
18430fdc8d8SChris Lattner     {
18530fdc8d8SChris Lattner 
18630fdc8d8SChris Lattner //        char run_state_str[32];
18730fdc8d8SChris Lattner //        size_t run_state_str_size = sizeof(run_state_str);
18830fdc8d8SChris Lattner //        switch (basicInfo.run_state)
18930fdc8d8SChris Lattner //        {
19030fdc8d8SChris Lattner //        case TH_STATE_RUNNING:          strncpy(run_state_str, "running", run_state_str_size); break;
19130fdc8d8SChris Lattner //        case TH_STATE_STOPPED:          strncpy(run_state_str, "stopped", run_state_str_size); break;
19230fdc8d8SChris Lattner //        case TH_STATE_WAITING:          strncpy(run_state_str, "waiting", run_state_str_size); break;
19330fdc8d8SChris Lattner //        case TH_STATE_UNINTERRUPTIBLE:  strncpy(run_state_str, "uninterruptible", run_state_str_size); break;
19430fdc8d8SChris Lattner //        case TH_STATE_HALTED:           strncpy(run_state_str, "halted", run_state_str_size); break;
19530fdc8d8SChris Lattner //        default:                        snprintf(run_state_str, run_state_str_size, "%d", basicInfo.run_state); break;    // ???
19630fdc8d8SChris Lattner //        }
19730fdc8d8SChris Lattner         float user = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f;
19830fdc8d8SChris Lattner         float system = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f;
1991c73911dSJason Molenda         snprintf(g_basic_info_string, sizeof(g_basic_info_string), "Thread 0x%8.8" PRIx64 ": user=%f system=%f cpu=%d sleep_time=%d",
2001c73911dSJason Molenda             m_unique_id,
20130fdc8d8SChris Lattner             user,
20230fdc8d8SChris Lattner             system,
20330fdc8d8SChris Lattner             basicInfo.cpu_usage,
20430fdc8d8SChris Lattner             basicInfo.sleep_time);
20530fdc8d8SChris Lattner 
20630fdc8d8SChris Lattner         return g_basic_info_string;
20730fdc8d8SChris Lattner     }
20830fdc8d8SChris Lattner     return NULL;
20930fdc8d8SChris Lattner }
21030fdc8d8SChris Lattner 
2111c73911dSJason Molenda // Finds the Mach port number for a given thread in the inferior process' port namespace.
21230fdc8d8SChris Lattner thread_t
21330fdc8d8SChris Lattner MachThread::InferiorThreadID() const
21430fdc8d8SChris Lattner {
21530fdc8d8SChris Lattner     mach_msg_type_number_t i;
21630fdc8d8SChris Lattner     mach_port_name_array_t names;
21730fdc8d8SChris Lattner     mach_port_type_array_t types;
21830fdc8d8SChris Lattner     mach_msg_type_number_t ncount, tcount;
21930fdc8d8SChris Lattner     thread_t inferior_tid = INVALID_NUB_THREAD;
22030fdc8d8SChris Lattner     task_t my_task = ::mach_task_self();
22130fdc8d8SChris Lattner     task_t task = m_process->Task().TaskPort();
22230fdc8d8SChris Lattner 
22330fdc8d8SChris Lattner     kern_return_t kret = ::mach_port_names (task, &names, &ncount, &types, &tcount);
22430fdc8d8SChris Lattner     if (kret == KERN_SUCCESS)
22530fdc8d8SChris Lattner     {
22630fdc8d8SChris Lattner 
22730fdc8d8SChris Lattner         for (i = 0; i < ncount; i++)
22830fdc8d8SChris Lattner         {
22930fdc8d8SChris Lattner             mach_port_t my_name;
23030fdc8d8SChris Lattner             mach_msg_type_name_t my_type;
23130fdc8d8SChris Lattner 
23230fdc8d8SChris Lattner             kret = ::mach_port_extract_right (task, names[i], MACH_MSG_TYPE_COPY_SEND, &my_name, &my_type);
23330fdc8d8SChris Lattner             if (kret == KERN_SUCCESS)
23430fdc8d8SChris Lattner             {
23530fdc8d8SChris Lattner                 ::mach_port_deallocate (my_task, my_name);
2361c73911dSJason Molenda                 if (my_name == m_mach_port_number)
23730fdc8d8SChris Lattner                 {
23830fdc8d8SChris Lattner                     inferior_tid = names[i];
23930fdc8d8SChris Lattner                     break;
24030fdc8d8SChris Lattner                 }
24130fdc8d8SChris Lattner             }
24230fdc8d8SChris Lattner         }
24330fdc8d8SChris Lattner         // Free up the names and types
24430fdc8d8SChris Lattner         ::vm_deallocate (my_task, (vm_address_t) names, ncount * sizeof (mach_port_name_t));
24530fdc8d8SChris Lattner         ::vm_deallocate (my_task, (vm_address_t) types, tcount * sizeof (mach_port_type_t));
24630fdc8d8SChris Lattner     }
24730fdc8d8SChris Lattner     return inferior_tid;
24830fdc8d8SChris Lattner }
24930fdc8d8SChris Lattner 
25030fdc8d8SChris Lattner bool
2511b946bf6SGreg Clayton MachThread::IsUserReady()
2521b946bf6SGreg Clayton {
253c235ac76SGreg Clayton     if (m_basic_info.run_state == 0)
254cdc7322bSGreg Clayton         GetBasicInfo ();
2551b946bf6SGreg Clayton 
256c235ac76SGreg Clayton     switch (m_basic_info.run_state)
2571b946bf6SGreg Clayton     {
2581b946bf6SGreg Clayton     default:
2591b946bf6SGreg Clayton     case TH_STATE_UNINTERRUPTIBLE:
2601b946bf6SGreg Clayton         break;
2611b946bf6SGreg Clayton 
2621b946bf6SGreg Clayton     case TH_STATE_RUNNING:
2631b946bf6SGreg Clayton     case TH_STATE_STOPPED:
2641b946bf6SGreg Clayton     case TH_STATE_WAITING:
2651b946bf6SGreg Clayton     case TH_STATE_HALTED:
2661b946bf6SGreg Clayton         return true;
2671b946bf6SGreg Clayton     }
2681b946bf6SGreg Clayton     return false;
2691b946bf6SGreg Clayton }
2701b946bf6SGreg Clayton 
2711b946bf6SGreg Clayton struct thread_basic_info *
272cdc7322bSGreg Clayton MachThread::GetBasicInfo ()
2731b946bf6SGreg Clayton {
2741c73911dSJason Molenda     if (MachThread::GetBasicInfo(m_mach_port_number, &m_basic_info))
275c235ac76SGreg Clayton         return &m_basic_info;
2761b946bf6SGreg Clayton     return NULL;
2771b946bf6SGreg Clayton }
2781b946bf6SGreg Clayton 
2791b946bf6SGreg Clayton 
2801b946bf6SGreg Clayton bool
28130fdc8d8SChris Lattner MachThread::GetBasicInfo(thread_t thread, struct thread_basic_info *basicInfoPtr)
28230fdc8d8SChris Lattner {
2831c73911dSJason Molenda     if (MachPortNumberIsValid(thread))
28430fdc8d8SChris Lattner     {
28530fdc8d8SChris Lattner         unsigned int info_count = THREAD_BASIC_INFO_COUNT;
28630fdc8d8SChris Lattner         kern_return_t err = ::thread_info (thread, THREAD_BASIC_INFO, (thread_info_t) basicInfoPtr, &info_count);
28730fdc8d8SChris Lattner         if (err == KERN_SUCCESS)
28830fdc8d8SChris Lattner             return true;
28930fdc8d8SChris Lattner     }
29030fdc8d8SChris Lattner     ::memset (basicInfoPtr, 0, sizeof (struct thread_basic_info));
29130fdc8d8SChris Lattner     return false;
29230fdc8d8SChris Lattner }
29330fdc8d8SChris Lattner 
29430fdc8d8SChris Lattner 
29530fdc8d8SChris Lattner bool
2961c73911dSJason Molenda MachThread::ThreadIDIsValid(uint64_t thread)
2971c73911dSJason Molenda {
2981c73911dSJason Molenda     return thread != 0;
2991c73911dSJason Molenda }
3001c73911dSJason Molenda 
3011c73911dSJason Molenda bool
3021c73911dSJason Molenda MachThread::MachPortNumberIsValid(thread_t thread)
30330fdc8d8SChris Lattner {
30430fdc8d8SChris Lattner     return thread != THREAD_NULL;
30530fdc8d8SChris Lattner }
30630fdc8d8SChris Lattner 
30730fdc8d8SChris Lattner bool
30830fdc8d8SChris Lattner MachThread::GetRegisterState(int flavor, bool force)
30930fdc8d8SChris Lattner {
3103af9ea56SGreg Clayton     return m_arch_ap->GetRegisterState(flavor, force) == KERN_SUCCESS;
31130fdc8d8SChris Lattner }
31230fdc8d8SChris Lattner 
31330fdc8d8SChris Lattner bool
31430fdc8d8SChris Lattner MachThread::SetRegisterState(int flavor)
31530fdc8d8SChris Lattner {
3163af9ea56SGreg Clayton     return m_arch_ap->SetRegisterState(flavor) == KERN_SUCCESS;
31730fdc8d8SChris Lattner }
31830fdc8d8SChris Lattner 
31930fdc8d8SChris Lattner uint64_t
32030fdc8d8SChris Lattner MachThread::GetPC(uint64_t failValue)
32130fdc8d8SChris Lattner {
32230fdc8d8SChris Lattner     // Get program counter
3233af9ea56SGreg Clayton     return m_arch_ap->GetPC(failValue);
32430fdc8d8SChris Lattner }
32530fdc8d8SChris Lattner 
32630fdc8d8SChris Lattner bool
32730fdc8d8SChris Lattner MachThread::SetPC(uint64_t value)
32830fdc8d8SChris Lattner {
32930fdc8d8SChris Lattner     // Set program counter
3303af9ea56SGreg Clayton     return m_arch_ap->SetPC(value);
33130fdc8d8SChris Lattner }
33230fdc8d8SChris Lattner 
33330fdc8d8SChris Lattner uint64_t
33430fdc8d8SChris Lattner MachThread::GetSP(uint64_t failValue)
33530fdc8d8SChris Lattner {
33630fdc8d8SChris Lattner     // Get stack pointer
3373af9ea56SGreg Clayton     return m_arch_ap->GetSP(failValue);
33830fdc8d8SChris Lattner }
33930fdc8d8SChris Lattner 
34030fdc8d8SChris Lattner nub_process_t
34130fdc8d8SChris Lattner MachThread::ProcessID() const
34230fdc8d8SChris Lattner {
34330fdc8d8SChris Lattner     if (m_process)
34430fdc8d8SChris Lattner         return m_process->ProcessID();
34530fdc8d8SChris Lattner     return INVALID_NUB_PROCESS;
34630fdc8d8SChris Lattner }
34730fdc8d8SChris Lattner 
34830fdc8d8SChris Lattner void
34930fdc8d8SChris Lattner MachThread::Dump(uint32_t index)
35030fdc8d8SChris Lattner {
35130fdc8d8SChris Lattner     const char * thread_run_state = NULL;
35230fdc8d8SChris Lattner 
353c235ac76SGreg Clayton     switch (m_basic_info.run_state)
35430fdc8d8SChris Lattner     {
35530fdc8d8SChris Lattner     case TH_STATE_RUNNING:          thread_run_state = "running"; break;    // 1 thread is running normally
35630fdc8d8SChris Lattner     case TH_STATE_STOPPED:          thread_run_state = "stopped"; break;    // 2 thread is stopped
35730fdc8d8SChris Lattner     case TH_STATE_WAITING:          thread_run_state = "waiting"; break;    // 3 thread is waiting normally
35830fdc8d8SChris Lattner     case TH_STATE_UNINTERRUPTIBLE:  thread_run_state = "uninter"; break;    // 4 thread is in an uninterruptible wait
35930fdc8d8SChris Lattner     case TH_STATE_HALTED:           thread_run_state = "halted "; break;     // 5 thread is halted at a
36030fdc8d8SChris Lattner     default:                        thread_run_state = "???"; break;
36130fdc8d8SChris Lattner     }
36230fdc8d8SChris Lattner 
363*d8cf1a11SGreg Clayton     DNBLogThreaded("[%3u] #%3u tid: 0x%8.8" PRIx64 ", pc: 0x%16.16" PRIx64 ", sp: 0x%16.16" PRIx64 ", user: %d.%6.6d, system: %d.%6.6d, cpu: %2d, policy: %2d, run_state: %2d (%s), flags: %2d, suspend_count: %2d (current %2d), sleep_time: %d",
36430fdc8d8SChris Lattner         index,
36530fdc8d8SChris Lattner         m_seq_id,
3661c73911dSJason Molenda         m_unique_id,
36730fdc8d8SChris Lattner         GetPC(INVALID_NUB_ADDRESS),
36830fdc8d8SChris Lattner         GetSP(INVALID_NUB_ADDRESS),
369c235ac76SGreg Clayton         m_basic_info.user_time.seconds,      m_basic_info.user_time.microseconds,
370c235ac76SGreg Clayton         m_basic_info.system_time.seconds,    m_basic_info.system_time.microseconds,
371c235ac76SGreg Clayton         m_basic_info.cpu_usage,
372c235ac76SGreg Clayton         m_basic_info.policy,
373c235ac76SGreg Clayton         m_basic_info.run_state,
37430fdc8d8SChris Lattner         thread_run_state,
375c235ac76SGreg Clayton         m_basic_info.flags,
376c235ac76SGreg Clayton         m_basic_info.suspend_count, m_suspend_count,
377c235ac76SGreg Clayton         m_basic_info.sleep_time);
37830fdc8d8SChris Lattner     //DumpRegisterState(0);
37930fdc8d8SChris Lattner }
38030fdc8d8SChris Lattner 
38130fdc8d8SChris Lattner void
3829411ddb6SJim Ingham MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action, bool others_stopped)
38330fdc8d8SChris Lattner {
38430fdc8d8SChris Lattner     if (thread_action->addr != INVALID_NUB_ADDRESS)
38530fdc8d8SChris Lattner         SetPC (thread_action->addr);
386cdc7322bSGreg Clayton 
38730fdc8d8SChris Lattner     SetState (thread_action->state);
38830fdc8d8SChris Lattner     switch (thread_action->state)
38930fdc8d8SChris Lattner     {
39030fdc8d8SChris Lattner     case eStateStopped:
39130fdc8d8SChris Lattner     case eStateSuspended:
3929411ddb6SJim Ingham         assert (others_stopped == false);
39330fdc8d8SChris Lattner         Suspend();
39430fdc8d8SChris Lattner         break;
39530fdc8d8SChris Lattner 
39630fdc8d8SChris Lattner     case eStateRunning:
397b1e11121SJim Ingham     case eStateStepping:
3989411ddb6SJim Ingham         Resume(others_stopped);
399b1e11121SJim Ingham         break;
400effe5c95SGreg Clayton     default:
401effe5c95SGreg Clayton         break;
40230fdc8d8SChris Lattner     }
4033af9ea56SGreg Clayton     m_arch_ap->ThreadWillResume();
40430fdc8d8SChris Lattner     m_stop_exception.Clear();
40530fdc8d8SChris Lattner }
40630fdc8d8SChris Lattner 
407*d8cf1a11SGreg Clayton DNBBreakpoint *
408c4e411ffSGreg Clayton MachThread::CurrentBreakpoint()
409c4e411ffSGreg Clayton {
410*d8cf1a11SGreg Clayton     return m_process->Breakpoints().FindByAddress(GetPC());
411c4e411ffSGreg Clayton }
412c4e411ffSGreg Clayton 
41330fdc8d8SChris Lattner bool
41430fdc8d8SChris Lattner MachThread::ShouldStop(bool &step_more)
41530fdc8d8SChris Lattner {
41630fdc8d8SChris Lattner     // See if this thread is at a breakpoint?
417*d8cf1a11SGreg Clayton     DNBBreakpoint *bp = CurrentBreakpoint();
41830fdc8d8SChris Lattner 
419*d8cf1a11SGreg Clayton     if (bp)
42030fdc8d8SChris Lattner     {
42130fdc8d8SChris Lattner         // This thread is sitting at a breakpoint, ask the breakpoint
42230fdc8d8SChris Lattner         // if we should be stopping here.
42330fdc8d8SChris Lattner         return true;
42430fdc8d8SChris Lattner     }
42530fdc8d8SChris Lattner     else
42630fdc8d8SChris Lattner     {
4273af9ea56SGreg Clayton         if (m_arch_ap->StepNotComplete())
42830fdc8d8SChris Lattner         {
42930fdc8d8SChris Lattner             step_more = true;
43030fdc8d8SChris Lattner             return false;
43130fdc8d8SChris Lattner         }
43230fdc8d8SChris Lattner         // The thread state is used to let us know what the thread was
43330fdc8d8SChris Lattner         // trying to do. MachThread::ThreadWillResume() will set the
43430fdc8d8SChris Lattner         // thread state to various values depending if the thread was
43530fdc8d8SChris Lattner         // the current thread and if it was to be single stepped, or
43630fdc8d8SChris Lattner         // resumed.
43730fdc8d8SChris Lattner         if (GetState() == eStateRunning)
43830fdc8d8SChris Lattner         {
43930fdc8d8SChris Lattner             // If our state is running, then we should continue as we are in
44030fdc8d8SChris Lattner             // the process of stepping over a breakpoint.
44130fdc8d8SChris Lattner             return false;
44230fdc8d8SChris Lattner         }
44330fdc8d8SChris Lattner         else
44430fdc8d8SChris Lattner         {
44530fdc8d8SChris Lattner             // Stop if we have any kind of valid exception for this
44630fdc8d8SChris Lattner             // thread.
44730fdc8d8SChris Lattner             if (GetStopException().IsValid())
44830fdc8d8SChris Lattner                 return true;
44930fdc8d8SChris Lattner         }
45030fdc8d8SChris Lattner     }
45130fdc8d8SChris Lattner     return false;
45230fdc8d8SChris Lattner }
45330fdc8d8SChris Lattner bool
45430fdc8d8SChris Lattner MachThread::IsStepping()
45530fdc8d8SChris Lattner {
456c4e411ffSGreg Clayton #if ENABLE_AUTO_STEPPING_OVER_BP
45730fdc8d8SChris Lattner     // Return true if this thread is currently being stepped.
45830fdc8d8SChris Lattner     // MachThread::ThreadWillResume currently determines this by looking if we
45930fdc8d8SChris Lattner     // have been asked to single step, or if we are at a breakpoint instruction
46030fdc8d8SChris Lattner     // and have been asked to resume. In the latter case we need to disable the
46130fdc8d8SChris Lattner     // breakpoint we are at, single step, re-enable and continue.
46230fdc8d8SChris Lattner     nub_state_t state = GetState();
463c4e411ffSGreg Clayton     return ((state == eStateStepping) ||
464c4e411ffSGreg Clayton             (state == eStateRunning && NUB_BREAK_ID_IS_VALID(CurrentBreakpoint())));
465c4e411ffSGreg Clayton #else
466c4e411ffSGreg Clayton     return GetState() == eStateStepping;
467c4e411ffSGreg Clayton #endif
46830fdc8d8SChris Lattner }
46930fdc8d8SChris Lattner 
47030fdc8d8SChris Lattner 
47130fdc8d8SChris Lattner bool
47230fdc8d8SChris Lattner MachThread::ThreadDidStop()
47330fdc8d8SChris Lattner {
47430fdc8d8SChris Lattner     // This thread has existed prior to resuming under debug nub control,
47530fdc8d8SChris Lattner     // and has just been stopped. Do any cleanup that needs to be done
47630fdc8d8SChris Lattner     // after running.
47730fdc8d8SChris Lattner 
47830fdc8d8SChris Lattner     // The thread state and breakpoint will still have the same values
47930fdc8d8SChris Lattner     // as they had prior to resuming the thread, so it makes it easy to check
48030fdc8d8SChris Lattner     // if we were trying to step a thread, or we tried to resume while being
48130fdc8d8SChris Lattner     // at a breakpoint.
48230fdc8d8SChris Lattner 
48330fdc8d8SChris Lattner     // When this method gets called, the process state is still in the
48430fdc8d8SChris Lattner     // state it was in while running so we can act accordingly.
4853af9ea56SGreg Clayton     m_arch_ap->ThreadDidStop();
48630fdc8d8SChris Lattner 
48730fdc8d8SChris Lattner 
48830fdc8d8SChris Lattner     // We may have suspended this thread so the primary thread could step
48930fdc8d8SChris Lattner     // without worrying about race conditions, so lets restore our suspend
49030fdc8d8SChris Lattner     // count.
4919411ddb6SJim Ingham     RestoreSuspendCountAfterStop();
49230fdc8d8SChris Lattner 
49330fdc8d8SChris Lattner     // Update the basic information for a thread
4941c73911dSJason Molenda     MachThread::GetBasicInfo(m_mach_port_number, &m_basic_info);
49530fdc8d8SChris Lattner 
496c4e411ffSGreg Clayton #if ENABLE_AUTO_STEPPING_OVER_BP
49730fdc8d8SChris Lattner     // See if we were at a breakpoint when we last resumed that we disabled,
49830fdc8d8SChris Lattner     // re-enable it.
49930fdc8d8SChris Lattner     nub_break_t breakID = CurrentBreakpoint();
50030fdc8d8SChris Lattner 
50130fdc8d8SChris Lattner     if (NUB_BREAK_ID_IS_VALID(breakID))
50230fdc8d8SChris Lattner     {
50330fdc8d8SChris Lattner         m_process->EnableBreakpoint(breakID);
504c235ac76SGreg Clayton         if (m_basic_info.suspend_count > 0)
50530fdc8d8SChris Lattner         {
50630fdc8d8SChris Lattner             SetState(eStateSuspended);
50730fdc8d8SChris Lattner         }
50830fdc8d8SChris Lattner         else
50930fdc8d8SChris Lattner         {
51030fdc8d8SChris Lattner             // If we last were at a breakpoint and we single stepped, our state
51130fdc8d8SChris Lattner             // will be "running" to indicate we need to continue after stepping
51230fdc8d8SChris Lattner             // over the breakpoint instruction. If we step over a breakpoint
51330fdc8d8SChris Lattner             // instruction, we need to stop.
51430fdc8d8SChris Lattner             if (GetState() == eStateRunning)
51530fdc8d8SChris Lattner             {
51630fdc8d8SChris Lattner                 // Leave state set to running so we will continue automatically
51730fdc8d8SChris Lattner                 // from this breakpoint
51830fdc8d8SChris Lattner             }
51930fdc8d8SChris Lattner             else
52030fdc8d8SChris Lattner             {
52130fdc8d8SChris Lattner                 SetState(eStateStopped);
52230fdc8d8SChris Lattner             }
52330fdc8d8SChris Lattner         }
52430fdc8d8SChris Lattner     }
52530fdc8d8SChris Lattner     else
52630fdc8d8SChris Lattner     {
527c235ac76SGreg Clayton         if (m_basic_info.suspend_count > 0)
52830fdc8d8SChris Lattner         {
52930fdc8d8SChris Lattner             SetState(eStateSuspended);
53030fdc8d8SChris Lattner         }
53130fdc8d8SChris Lattner         else
53230fdc8d8SChris Lattner         {
53330fdc8d8SChris Lattner             SetState(eStateStopped);
53430fdc8d8SChris Lattner         }
53530fdc8d8SChris Lattner     }
536c4e411ffSGreg Clayton #else
537c235ac76SGreg Clayton     if (m_basic_info.suspend_count > 0)
538c4e411ffSGreg Clayton         SetState(eStateSuspended);
539c4e411ffSGreg Clayton     else
540c4e411ffSGreg Clayton         SetState(eStateStopped);
541c4e411ffSGreg Clayton #endif
54230fdc8d8SChris Lattner     return true;
54330fdc8d8SChris Lattner }
54430fdc8d8SChris Lattner 
54530fdc8d8SChris Lattner bool
54630fdc8d8SChris Lattner MachThread::NotifyException(MachException::Data& exc)
54730fdc8d8SChris Lattner {
54888c1b77fSJohnny Chen     // Allow the arch specific protocol to process (MachException::Data &)exc
54988c1b77fSJohnny Chen     // first before possible reassignment of m_stop_exception with exc.
55076abb3b5SJohnny Chen     // See also MachThread::GetStopException().
55188c1b77fSJohnny Chen     bool handled = m_arch_ap->NotifyException(exc);
55288c1b77fSJohnny Chen 
55330fdc8d8SChris Lattner     if (m_stop_exception.IsValid())
55430fdc8d8SChris Lattner     {
55530fdc8d8SChris Lattner         // We may have more than one exception for a thread, but we need to
55630fdc8d8SChris Lattner         // only remember the one that we will say is the reason we stopped.
55730fdc8d8SChris Lattner         // We may have been single stepping and also gotten a signal exception,
55830fdc8d8SChris Lattner         // so just remember the most pertinent one.
55930fdc8d8SChris Lattner         if (m_stop_exception.IsBreakpoint())
56030fdc8d8SChris Lattner             m_stop_exception = exc;
56130fdc8d8SChris Lattner     }
56230fdc8d8SChris Lattner     else
56330fdc8d8SChris Lattner     {
56430fdc8d8SChris Lattner         m_stop_exception = exc;
56530fdc8d8SChris Lattner     }
56688c1b77fSJohnny Chen 
56730fdc8d8SChris Lattner     return handled;
56830fdc8d8SChris Lattner }
56930fdc8d8SChris Lattner 
57030fdc8d8SChris Lattner 
57130fdc8d8SChris Lattner nub_state_t
57230fdc8d8SChris Lattner MachThread::GetState()
57330fdc8d8SChris Lattner {
57430fdc8d8SChris Lattner     // If any other threads access this we will need a mutex for it
57530fdc8d8SChris Lattner     PTHREAD_MUTEX_LOCKER (locker, m_state_mutex);
57630fdc8d8SChris Lattner     return m_state;
57730fdc8d8SChris Lattner }
57830fdc8d8SChris Lattner 
57930fdc8d8SChris Lattner void
58030fdc8d8SChris Lattner MachThread::SetState(nub_state_t state)
58130fdc8d8SChris Lattner {
58230fdc8d8SChris Lattner     PTHREAD_MUTEX_LOCKER (locker, m_state_mutex);
58330fdc8d8SChris Lattner     m_state = state;
5841c73911dSJason Molenda     DNBLogThreadedIf(LOG_THREAD, "MachThread::SetState ( %s ) for tid = 0x%8.8" PRIx64 "", DNBStateAsString(state), m_unique_id);
58530fdc8d8SChris Lattner }
58630fdc8d8SChris Lattner 
58730fdc8d8SChris Lattner uint32_t
58830fdc8d8SChris Lattner MachThread::GetNumRegistersInSet(int regSet) const
58930fdc8d8SChris Lattner {
590c235ac76SGreg Clayton     if (regSet < m_num_reg_sets)
5913af9ea56SGreg Clayton         return m_reg_sets[regSet].num_registers;
59230fdc8d8SChris Lattner     return 0;
59330fdc8d8SChris Lattner }
59430fdc8d8SChris Lattner 
59530fdc8d8SChris Lattner const char *
59630fdc8d8SChris Lattner MachThread::GetRegisterSetName(int regSet) const
59730fdc8d8SChris Lattner {
598c235ac76SGreg Clayton     if (regSet < m_num_reg_sets)
5993af9ea56SGreg Clayton         return m_reg_sets[regSet].name;
60030fdc8d8SChris Lattner     return NULL;
60130fdc8d8SChris Lattner }
60230fdc8d8SChris Lattner 
60330fdc8d8SChris Lattner const DNBRegisterInfo *
60430fdc8d8SChris Lattner MachThread::GetRegisterInfo(int regSet, int regIndex) const
60530fdc8d8SChris Lattner {
606c235ac76SGreg Clayton     if (regSet < m_num_reg_sets)
6073af9ea56SGreg Clayton         if (regIndex < m_reg_sets[regSet].num_registers)
6083af9ea56SGreg Clayton             return &m_reg_sets[regSet].registers[regIndex];
60930fdc8d8SChris Lattner     return NULL;
61030fdc8d8SChris Lattner }
61130fdc8d8SChris Lattner void
61230fdc8d8SChris Lattner MachThread::DumpRegisterState(int regSet)
61330fdc8d8SChris Lattner {
61430fdc8d8SChris Lattner     if (regSet == REGISTER_SET_ALL)
61530fdc8d8SChris Lattner     {
616c235ac76SGreg Clayton         for (regSet = 1; regSet < m_num_reg_sets; regSet++)
61730fdc8d8SChris Lattner             DumpRegisterState(regSet);
61830fdc8d8SChris Lattner     }
61930fdc8d8SChris Lattner     else
62030fdc8d8SChris Lattner     {
6213af9ea56SGreg Clayton         if (m_arch_ap->RegisterSetStateIsValid(regSet))
62230fdc8d8SChris Lattner         {
62330fdc8d8SChris Lattner             const size_t numRegisters = GetNumRegistersInSet(regSet);
62430fdc8d8SChris Lattner             size_t regIndex = 0;
62530fdc8d8SChris Lattner             DNBRegisterValueClass reg;
62630fdc8d8SChris Lattner             for (regIndex = 0; regIndex < numRegisters; ++regIndex)
62730fdc8d8SChris Lattner             {
6283af9ea56SGreg Clayton                 if (m_arch_ap->GetRegisterValue(regSet, regIndex, &reg))
62930fdc8d8SChris Lattner                 {
63030fdc8d8SChris Lattner                     reg.Dump(NULL, NULL);
63130fdc8d8SChris Lattner                 }
63230fdc8d8SChris Lattner             }
63330fdc8d8SChris Lattner         }
63430fdc8d8SChris Lattner         else
63530fdc8d8SChris Lattner         {
63630fdc8d8SChris Lattner             DNBLog("%s: registers are not currently valid.", GetRegisterSetName(regSet));
63730fdc8d8SChris Lattner         }
63830fdc8d8SChris Lattner     }
63930fdc8d8SChris Lattner }
64030fdc8d8SChris Lattner 
64130fdc8d8SChris Lattner const DNBRegisterSetInfo *
64230fdc8d8SChris Lattner MachThread::GetRegisterSetInfo(nub_size_t *num_reg_sets ) const
64330fdc8d8SChris Lattner {
644c235ac76SGreg Clayton     *num_reg_sets = m_num_reg_sets;
6453af9ea56SGreg Clayton     return &m_reg_sets[0];
64630fdc8d8SChris Lattner }
64730fdc8d8SChris Lattner 
64830fdc8d8SChris Lattner bool
64930fdc8d8SChris Lattner MachThread::GetRegisterValue ( uint32_t set, uint32_t reg, DNBRegisterValue *value )
65030fdc8d8SChris Lattner {
6513af9ea56SGreg Clayton     return m_arch_ap->GetRegisterValue(set, reg, value);
65230fdc8d8SChris Lattner }
65330fdc8d8SChris Lattner 
65430fdc8d8SChris Lattner bool
65530fdc8d8SChris Lattner MachThread::SetRegisterValue ( uint32_t set, uint32_t reg, const DNBRegisterValue *value )
65630fdc8d8SChris Lattner {
6573af9ea56SGreg Clayton     return m_arch_ap->SetRegisterValue(set, reg, value);
65830fdc8d8SChris Lattner }
65930fdc8d8SChris Lattner 
66030fdc8d8SChris Lattner nub_size_t
66130fdc8d8SChris Lattner MachThread::GetRegisterContext (void *buf, nub_size_t buf_len)
66230fdc8d8SChris Lattner {
6633af9ea56SGreg Clayton     return m_arch_ap->GetRegisterContext(buf, buf_len);
66430fdc8d8SChris Lattner }
66530fdc8d8SChris Lattner 
66630fdc8d8SChris Lattner nub_size_t
66730fdc8d8SChris Lattner MachThread::SetRegisterContext (const void *buf, nub_size_t buf_len)
66830fdc8d8SChris Lattner {
6693af9ea56SGreg Clayton     return m_arch_ap->SetRegisterContext(buf, buf_len);
67030fdc8d8SChris Lattner }
67130fdc8d8SChris Lattner 
67230fdc8d8SChris Lattner uint32_t
67330fdc8d8SChris Lattner MachThread::EnableHardwareBreakpoint (const DNBBreakpoint *bp)
67430fdc8d8SChris Lattner {
67530fdc8d8SChris Lattner     if (bp != NULL && bp->IsBreakpoint())
6763af9ea56SGreg Clayton         return m_arch_ap->EnableHardwareBreakpoint(bp->Address(), bp->ByteSize());
67730fdc8d8SChris Lattner     return INVALID_NUB_HW_INDEX;
67830fdc8d8SChris Lattner }
67930fdc8d8SChris Lattner 
68030fdc8d8SChris Lattner uint32_t
68130fdc8d8SChris Lattner MachThread::EnableHardwareWatchpoint (const DNBBreakpoint *wp)
68230fdc8d8SChris Lattner {
68330fdc8d8SChris Lattner     if (wp != NULL && wp->IsWatchpoint())
6843af9ea56SGreg Clayton         return m_arch_ap->EnableHardwareWatchpoint(wp->Address(), wp->ByteSize(), wp->WatchpointRead(), wp->WatchpointWrite());
68530fdc8d8SChris Lattner     return INVALID_NUB_HW_INDEX;
68630fdc8d8SChris Lattner }
68730fdc8d8SChris Lattner 
688a9b68f4dSJohnny Chen // Provide a chance to update the global view of the hardware watchpoint state.
689a9b68f4dSJohnny Chen void
690a9b68f4dSJohnny Chen MachThread::HardwareWatchpointStateChanged ()
691a9b68f4dSJohnny Chen {
692a9b68f4dSJohnny Chen     m_arch_ap->HardwareWatchpointStateChanged();
693a9b68f4dSJohnny Chen }
694a9b68f4dSJohnny Chen 
69530fdc8d8SChris Lattner bool
69684707560SJohnny Chen MachThread::RollbackTransForHWP()
69784707560SJohnny Chen {
69884707560SJohnny Chen     return m_arch_ap->RollbackTransForHWP();
69984707560SJohnny Chen }
70084707560SJohnny Chen 
70184707560SJohnny Chen bool
70284707560SJohnny Chen MachThread::FinishTransForHWP()
70384707560SJohnny Chen {
70484707560SJohnny Chen     return m_arch_ap->FinishTransForHWP();
70584707560SJohnny Chen }
70684707560SJohnny Chen 
70784707560SJohnny Chen bool
70830fdc8d8SChris Lattner MachThread::DisableHardwareBreakpoint (const DNBBreakpoint *bp)
70930fdc8d8SChris Lattner {
71030fdc8d8SChris Lattner     if (bp != NULL && bp->IsHardware())
7113af9ea56SGreg Clayton         return m_arch_ap->DisableHardwareBreakpoint(bp->GetHardwareIndex());
71230fdc8d8SChris Lattner     return false;
71330fdc8d8SChris Lattner }
71430fdc8d8SChris Lattner 
71530fdc8d8SChris Lattner bool
71630fdc8d8SChris Lattner MachThread::DisableHardwareWatchpoint (const DNBBreakpoint *wp)
71730fdc8d8SChris Lattner {
71830fdc8d8SChris Lattner     if (wp != NULL && wp->IsHardware())
7193af9ea56SGreg Clayton         return m_arch_ap->DisableHardwareWatchpoint(wp->GetHardwareIndex());
72030fdc8d8SChris Lattner     return false;
72130fdc8d8SChris Lattner }
72230fdc8d8SChris Lattner 
72364637205SJohnny Chen uint32_t
72464637205SJohnny Chen MachThread::NumSupportedHardwareWatchpoints () const
72564637205SJohnny Chen {
72664637205SJohnny Chen     return m_arch_ap->NumSupportedHardwareWatchpoints();
72764637205SJohnny Chen }
72864637205SJohnny Chen 
72930fdc8d8SChris Lattner bool
73030fdc8d8SChris Lattner MachThread::GetIdentifierInfo ()
73130fdc8d8SChris Lattner {
732f2c6ccf0SJim Ingham         // Don't try to get the thread info once and cache it for the life of the thread.  It changes over time, for instance
733f2c6ccf0SJim Ingham         // if the thread name changes, then the thread_handle also changes...  So you have to refetch it every time.
73430fdc8d8SChris Lattner         mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
7351c73911dSJason Molenda         kern_return_t kret = ::thread_info (m_mach_port_number, THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count);
736f2c6ccf0SJim Ingham         return kret == KERN_SUCCESS;
73730fdc8d8SChris Lattner 
73830fdc8d8SChris Lattner     return false;
73930fdc8d8SChris Lattner }
74030fdc8d8SChris Lattner 
74130fdc8d8SChris Lattner 
74230fdc8d8SChris Lattner const char *
74330fdc8d8SChris Lattner MachThread::GetName ()
74430fdc8d8SChris Lattner {
74530fdc8d8SChris Lattner     if (GetIdentifierInfo ())
74630fdc8d8SChris Lattner     {
74730fdc8d8SChris Lattner         int len = ::proc_pidinfo (m_process->ProcessID(), PROC_PIDTHREADINFO, m_ident_info.thread_handle, &m_proc_threadinfo, sizeof (m_proc_threadinfo));
74830fdc8d8SChris Lattner 
74930fdc8d8SChris Lattner         if (len && m_proc_threadinfo.pth_name[0])
75030fdc8d8SChris Lattner             return m_proc_threadinfo.pth_name;
75130fdc8d8SChris Lattner     }
75230fdc8d8SChris Lattner     return NULL;
75330fdc8d8SChris Lattner }
75430fdc8d8SChris Lattner 
7551c73911dSJason Molenda 
7561c73911dSJason Molenda uint64_t
7571c73911dSJason Molenda MachThread::GetGloballyUniqueThreadIDForMachPortID (thread_t mach_port_id)
7581c73911dSJason Molenda {
7591c73911dSJason Molenda     kern_return_t kr;
7601c73911dSJason Molenda     thread_identifier_info_data_t tident;
7611c73911dSJason Molenda     mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT;
7621c73911dSJason Molenda     kr = thread_info (mach_port_id, THREAD_IDENTIFIER_INFO,
7631c73911dSJason Molenda                       (thread_info_t) &tident, &tident_count);
7641c73911dSJason Molenda     if (kr != KERN_SUCCESS)
7651c73911dSJason Molenda     {
7661c73911dSJason Molenda         return mach_port_id;
7671c73911dSJason Molenda     }
7681c73911dSJason Molenda     return tident.thread_id;
7691c73911dSJason Molenda }
770