MachThreadList.cpp revision 7cbdcfb0cefcfd877b507ff2d83e51a1bde3fcc7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===-- MachThreadList.cpp --------------------------------------*- C++ -*-===//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Created by Greg Clayton on 6/19/07.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "MachThreadList.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/sysctl.h>
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "DNBLog.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "DNBThreadResumeActions.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "MachProcess.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::MachThreadList() :
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_threads(),
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_threads_mutex(PTHREAD_MUTEX_RECURSIVE)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::~MachThreadList()
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nub_state_t
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::GetState(thread_t tid)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MachThreadSP thread_sp (GetThreadByID (tid));
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (thread_sp)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return thread_sp->GetState();
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return eStateInvalid;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char *
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MachThreadList::GetName (thread_t tid)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MachThreadSP thread_sp (GetThreadByID (tid));
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (thread_sp)
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return thread_sp->GetName();
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return NULL;
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)nub_thread_t
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MachThreadList::SetCurrentThread(thread_t tid)
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MachThreadSP thread_sp (GetThreadByID (tid));
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (thread_sp)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    {
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        m_current_thread = thread_sp;
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return tid;
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return INVALID_NUB_THREAD;
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MachThreadList::GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MachThreadSP thread_sp (GetThreadByID (tid));
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (thread_sp)
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return thread_sp->GetStopException().GetStopInfo(stop_info);
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)MachThreadList::GetIdentifierInfo (nub_thread_t tid, thread_identifier_info_data_t *ident_info)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ::thread_info (tid, THREAD_IDENTIFIER_INFO, (thread_info_t)ident_info, &count) == KERN_SUCCESS;
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MachThreadList::DumpThreadStoppedReason (nub_thread_t tid) const
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MachThreadSP thread_sp (GetThreadByID (tid));
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (thread_sp)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        thread_sp->GetStopException().DumpStopReason();
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char *
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MachThreadList::GetThreadInfo (nub_thread_t tid) const
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MachThreadSP thread_sp (GetThreadByID (tid));
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (thread_sp)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return thread_sp->GetBasicInfoAsString();
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return NULL;
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MachThreadSP
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)MachThreadList::GetThreadByID (nub_thread_t tid) const
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MachThreadSP thread_sp;
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const size_t num_threads = m_threads.size();
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (size_t idx = 0; idx < num_threads; ++idx)
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    {
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (m_threads[idx]->ThreadID() == tid)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        {
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            thread_sp = m_threads[idx];
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            break;
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return thread_sp;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MachThreadList::GetRegisterValue ( nub_thread_t tid, uint32_t reg_set_idx, uint32_t reg_idx, DNBRegisterValue *reg_value ) const
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MachThreadSP thread_sp (GetThreadByID (tid));
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (thread_sp)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return thread_sp->GetRegisterValue(reg_set_idx, reg_idx, reg_value);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MachThreadList::SetRegisterValue ( nub_thread_t tid, uint32_t reg_set_idx, uint32_t reg_idx, const DNBRegisterValue *reg_value ) const
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MachThreadSP thread_sp (GetThreadByID (tid));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (thread_sp)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return thread_sp->SetRegisterValue(reg_set_idx, reg_idx, reg_value);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return false;
1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)nub_size_t
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)MachThreadList::GetRegisterContext (nub_thread_t tid, void *buf, size_t buf_len)
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles){
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    MachThreadSP thread_sp (GetThreadByID (tid));
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (thread_sp)
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return thread_sp->GetRegisterContext (buf, buf_len);
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return 0;
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)nub_size_t
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MachThreadList::SetRegisterContext (nub_thread_t tid, const void *buf, size_t buf_len)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MachThreadSP thread_sp (GetThreadByID (tid));
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (thread_sp)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return thread_sp->SetRegisterContext (buf, buf_len);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nub_size_t
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MachThreadList::NumThreads () const
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return m_threads.size();
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nub_thread_t
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::ThreadIDAtIndex (nub_size_t idx) const
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (idx < m_threads.size())
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return m_threads[idx]->ThreadID();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return INVALID_NUB_THREAD;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)nub_thread_t
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::CurrentThreadID ( )
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MachThreadSP thread_sp;
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CurrentThread(thread_sp);
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (thread_sp.get())
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        return thread_sp->ThreadID();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return INVALID_NUB_THREAD;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::NotifyException(MachException::Data& exc)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MachThreadSP thread_sp (GetThreadByID (exc.thread_port));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (thread_sp)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        thread_sp->NotifyException(exc);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::Clear()
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_threads.clear();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::UpdateThreadList(MachProcess *process, bool update, MachThreadList::collection *new_threads)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // locker will keep a mutex locked until it goes out of scope
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DNBLogThreadedIf (LOG_THREAD, "MachThreadList::UpdateThreadList (pid = %4.4x, update = %u) process stop count = %u", process->ProcessID(), update, process->StopCount());
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined (__i386__) || defined (__x86_64__)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (process->StopCount() == 0)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process->ProcessID() };
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        struct kinfo_proc processInfo;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t bufsize = sizeof(processInfo);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bool is_64_bit = false;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (processInfo.kp_proc.p_flag & P_LP64)
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                is_64_bit = true;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (is_64_bit)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DNBArchProtocol::SetArchitecture(CPU_TYPE_X86_64);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            DNBArchProtocol::SetArchitecture(CPU_TYPE_I386);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (m_threads.empty() || update)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        thread_array_t thread_list = NULL;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mach_msg_type_number_t thread_list_count = 0;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        task_t task = process->Task().TaskPort();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DNBError err(::task_threads (task, &thread_list, &thread_list_count), DNBError::MachKernel);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail())
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            err.LogThreaded("::task_threads ( task = 0x%4.4x, thread_list => %p, thread_list_count => %u )", task, thread_list, thread_list_count);
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (err.Error() == KERN_SUCCESS && thread_list_count > 0)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            MachThreadList::collection currThreads;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            size_t idx;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // Iterator through the current thread list and see which threads
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // we already have in our list (keep them), which ones we don't
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            // (add them), and which ones are not around anymore (remove them).
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            for (idx = 0; idx < thread_list_count; ++idx)
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const thread_t tid = thread_list[idx];
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                MachThreadSP thread_sp (GetThreadByID (tid));
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                if (thread_sp)
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                {
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    // Keep the existing thread class
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    currThreads.push_back(thread_sp);
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                }
24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                else
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    // We don't have this thread, lets add it.
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    thread_sp.reset(new MachThread(process, tid));
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    // Add the new thread regardless of its is user ready state...
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    // Make sure the thread is ready to be displayed and shown to users
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    // before we add this thread to our list...
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if (thread_sp->IsUserReady())
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if (new_threads)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            new_threads->push_back(thread_sp);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        currThreads.push_back(thread_sp);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    }
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                }
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            m_threads.swap(currThreads);
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            m_current_thread.reset();
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // Free the vm memory given to us by ::task_threads()
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t));
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            ::vm_deallocate (::mach_task_self(),
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             (vm_address_t)thread_list,
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             thread_list_size);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return m_threads.size();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::CurrentThread (MachThreadSP& thread_sp)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // locker will keep a mutex locked until it goes out of scope
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (m_current_thread.get() == NULL)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Figure out which thread is going to be our current thread.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // This is currently done by finding the first thread in the list
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // that has a valid exception.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const uint32_t num_threads = m_threads.size();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (uint32_t idx = 0; idx < num_threads; ++idx)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (m_threads[idx]->GetStopException().IsValid())
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                m_current_thread = m_threads[idx];
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
300d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    }
301d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    thread_sp = m_current_thread;
302d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::Dump() const
30623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles){
30723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
30823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const uint32_t num_threads = m_threads.size();
30923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    for (uint32_t idx = 0; idx < num_threads; ++idx)
31023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    {
31123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        m_threads[idx]->Dump(idx);
31223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
313d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
314d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::ProcessWillResume(MachProcess *process, const DNBThreadResumeActions &thread_actions)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update our thread list, because sometimes libdispatch or the kernel
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // will spawn threads while a task is suspended.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MachThreadList::collection new_threads;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First figure out if we were planning on running only one thread, and if so force that thread to resume.
326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool run_one_thread;
327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    nub_thread_t solo_thread = INVALID_NUB_THREAD;
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (thread_actions.GetSize() > 0
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        && thread_actions.NumActionsWithState(eStateStepping) + thread_actions.NumActionsWithState (eStateRunning) == 1)
330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    {
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        run_one_thread = true;
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        const DNBThreadResumeAction *action_ptr = thread_actions.GetFirst();
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        size_t num_actions = thread_actions.GetSize();
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        for (size_t i = 0; i < num_actions; i++, action_ptr++)
335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        {
336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            if (action_ptr->state == eStateStepping || action_ptr->state == eStateRunning)
337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            {
338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                solo_thread = action_ptr->tid;
339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                break;
340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            }
341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        run_one_thread = false;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateThreadList(process, true, &new_threads);
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DNBThreadResumeAction resume_new_threads = { -1U, eStateRunning, 0, INVALID_NUB_ADDRESS };
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If we are planning to run only one thread, any new threads should be suspended.
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (run_one_thread)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resume_new_threads.state = eStateSuspended;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const uint32_t num_new_threads = new_threads.size();
35423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const uint32_t num_threads = m_threads.size();
35523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    for (uint32_t idx = 0; idx < num_threads; ++idx)
35623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    {
35723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        MachThread *thread = m_threads[idx].get();
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bool handled = false;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (uint32_t new_idx = 0; new_idx < num_new_threads; ++new_idx)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (thread == new_threads[new_idx].get())
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                thread->ThreadWillResume(&resume_new_threads);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                handled = true;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!handled)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const DNBThreadResumeAction *thread_action = thread_actions.GetActionForThread (thread->ThreadID(), true);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // There must always be a thread action for every thread.
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            assert (thread_action);
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            bool others_stopped = false;
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (solo_thread == thread->ThreadID())
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                others_stopped = true;
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            thread->ThreadWillResume (thread_action, others_stopped);
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (new_threads.size())
382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        for (uint32_t idx = 0; idx < num_new_threads; ++idx)
384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        {
385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            DNBLogThreadedIf (LOG_THREAD, "MachThreadList::ProcessWillResume (pid = %4.4x) stop-id=%u, resuming newly discovered thread: 0x%4.4x, thread-is-user-ready=%i)",
3863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              process->ProcessID(),
3873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              process->StopCount(),
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              new_threads[idx]->ThreadID(),
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              new_threads[idx]->IsUserReady());
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        }
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)uint32_t
395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)MachThreadList::ProcessDidStop(MachProcess *process)
396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles){
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Update our thread list
399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const uint32_t num_threads = UpdateThreadList(process, true);
400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (uint32_t idx = 0; idx < num_threads; ++idx)
4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    {
4023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        m_threads[idx]->ThreadDidStop();
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return num_threads;
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//----------------------------------------------------------------------
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Check each thread in our thread list to see if we should notify our
409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// client of the current halt in execution.
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Breakpoints can have callback functions associated with them than
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// can return true to stop, or false to continue executing the inferior.
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// RETURNS
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//    true if we should stop and notify our clients
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//    false if we should resume our child process and skip notification
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//----------------------------------------------------------------------
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MachThreadList::ShouldStop(bool &step_more)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t should_stop = false;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t num_threads = m_threads.size();
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx)
42523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    {
42623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        should_stop = m_threads[idx]->ShouldStop(step_more);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return should_stop;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::NotifyBreakpointChanged (const DNBBreakpoint *bp)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t num_threads = m_threads.size();
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (uint32_t idx = 0; idx < num_threads; ++idx)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        m_threads[idx]->NotifyBreakpointChanged(bp);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MachThreadList::EnableHardwareBreakpoint (const DNBBreakpoint* bp) const
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bp != NULL)
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
449a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        MachThreadSP thread_sp (GetThreadByID (bp->ThreadID()));
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (thread_sp)
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return thread_sp->EnableHardwareBreakpoint(bp);
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return INVALID_NUB_HW_INDEX;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MachThreadList::DisableHardwareBreakpoint (const DNBBreakpoint* bp) const
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (bp != NULL)
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    {
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        MachThreadSP thread_sp (GetThreadByID (bp->ThreadID()));
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (thread_sp)
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            return thread_sp->DisableHardwareBreakpoint(bp);
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DNBWatchpointSet() -> MachProcess::CreateWatchpoint() -> MachProcess::EnableWatchpoint()
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// -> MachThreadList::EnableHardwareWatchpoint().
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)uint32_t
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MachThreadList::EnableHardwareWatchpoint (const DNBBreakpoint* wp) const
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (wp != NULL)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32_t hw_index;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const uint32_t num_threads = m_threads.size();
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (uint32_t idx = 0; idx < num_threads; ++idx)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint(wp)) == INVALID_NUB_HW_INDEX)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return INVALID_NUB_HW_INDEX;
482a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        }
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Use an arbitrary thread to signal the completion of our transaction.
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (num_threads)
485a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            m_threads[0]->HardwareWatchpointStateChanged();
486a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return hw_index;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return INVALID_NUB_HW_INDEX;
489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool
492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochMachThreadList::DisableHardwareWatchpoint (const DNBBreakpoint* wp) const
493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{
494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (wp != NULL)
495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    {
496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        const uint32_t num_threads = m_threads.size();
498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        for (uint32_t idx = 0; idx < num_threads; ++idx)
499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        {
500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            if (!m_threads[idx]->DisableHardwareWatchpoint(wp))
501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                return false;
502c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        }
503c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        // Use an arbitrary thread to signal the completion of our transaction.
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (num_threads)
505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            m_threads[0]->HardwareWatchpointStateChanged();
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)uint32_t
512a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MachThreadList::NumSupportedHardwareWatchpoints () const
5133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles){
5143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
5153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const uint32_t num_threads = m_threads.size();
5163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Use an arbitrary thread to retrieve the number of supported hardware watchpoints.
5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (num_threads)
5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        return m_threads[0]->NumSupportedHardwareWatchpoints();
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return 0;
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)uint32_t
5233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)MachThreadList::GetThreadIndexForThreadStoppedWithSignal (const int signo) const
5243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles){
5253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
5263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    uint32_t should_stop = false;
5273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const uint32_t num_threads = m_threads.size();
5283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx)
5293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    {
5303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        if (m_threads[idx]->GetStopException().SoftSignal () == signo)
5311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            return idx;
5323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
5333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return UINT32_MAX;
5343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)