void
SystemRuntimeMacOSX::PopulateQueueList (lldb_private::QueueList &queue_list)
{
    if (BacktraceRecordingHeadersInitialized())
    {
        AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer;
        ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
        if (cur_thread_sp)
        {
            Error error;
            queue_info_pointer = m_get_queues_handler.GetCurrentQueues (*cur_thread_sp.get(), m_page_to_free, m_page_to_free_size, error);
            m_page_to_free = LLDB_INVALID_ADDRESS;
            m_page_to_free_size = 0;
            if (error.Success())
            {

                if (queue_info_pointer.count > 0
                        && queue_info_pointer.queues_buffer_size > 0
                        && queue_info_pointer.queues_buffer_ptr != 0
                        && queue_info_pointer.queues_buffer_ptr != LLDB_INVALID_ADDRESS)
                {
                    PopulateQueuesUsingLibBTR (queue_info_pointer.queues_buffer_ptr, queue_info_pointer.queues_buffer_size, queue_info_pointer.count, queue_list);
                }
            }
        }
    }

    // We either didn't have libBacktraceRecording (and need to create the queues list based on threads)
    // or we did get the queues list from libBacktraceRecording but some special queues may not be
    // included in its information.  This is needed because libBacktraceRecording
    // will only list queues with pending or running items by default - but the magic com.apple.main-thread
    // queue on thread 1 is always around.

    for (ThreadSP thread_sp : m_process->Threads())
    {
        if (thread_sp->GetAssociatedWithLibdispatchQueue () != eLazyBoolNo)
        {
            if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID)
            {
                if (queue_list.FindQueueByID (thread_sp->GetQueueID()).get() == NULL)
                {
                    QueueSP queue_sp (new Queue(m_process->shared_from_this(), thread_sp->GetQueueID(), thread_sp->GetQueueName()));
                    if (thread_sp->ThreadHasQueueInformation ())
                    {
                        queue_sp->SetKind (thread_sp->GetQueueKind ());
                        queue_sp->SetLibdispatchQueueAddress (thread_sp->GetQueueLibdispatchQueueAddress());
                        queue_list.AddQueue (queue_sp);
                    }
                    else
                    {
                        queue_sp->SetKind (GetQueueKind (thread_sp->GetQueueLibdispatchQueueAddress()));
                        queue_sp->SetLibdispatchQueueAddress (thread_sp->GetQueueLibdispatchQueueAddress());
                        queue_list.AddQueue (queue_sp);
                    }
                }
            }
        }
    }
}
Beispiel #2
0
void
SystemRuntimeMacOSX::PopulateQueueList (lldb_private::QueueList &queue_list)
{
    // For now, iterate over the threads and see what queue each thread is associated with.
    // If we haven't already added this queue, add it to the QueueList.
    // (a single libdispatch queue may be using multiple threads simultaneously.)

    for (ThreadSP thread_sp : m_process->Threads())
    {
        if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID)
        {
            if (queue_list.FindQueueByID (thread_sp->GetQueueID()).get() == NULL)
            {
                QueueSP queue_sp (new Queue(m_process->shared_from_this(), thread_sp->GetQueueID(), thread_sp->GetQueueName()));
                queue_list.AddQueue (queue_sp);
            }
        }
    }
}
void
SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR (lldb::addr_t queues_buffer, uint64_t queues_buffer_size,
        uint64_t count, lldb_private::QueueList &queue_list)
{
    Error error;
    DataBufferHeap data (queues_buffer_size, 0);
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME));
    if (m_process->ReadMemory (queues_buffer, data.GetBytes(), queues_buffer_size, error) == queues_buffer_size && error.Success())
    {
        // We've read the information out of inferior memory; free it on the next call we make
        m_page_to_free = queues_buffer;
        m_page_to_free_size = queues_buffer_size;

        DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
        offset_t offset = 0;
        uint64_t queues_read = 0;

        // The information about the queues is stored in this format (v1):
        // typedef struct introspection_dispatch_queue_info_s {
        //     uint32_t offset_to_next;
        //     dispatch_queue_t queue;
        //     uint64_t serialnum;     // queue's serialnum in the process, as provided by libdispatch
        //     uint32_t running_work_items_count;
        //     uint32_t pending_work_items_count;
        //
        //     char data[];     // Starting here, we have variable-length data:
        //     // char queue_label[];
        // } introspection_dispatch_queue_info_s;

        while (queues_read < count && offset < queues_buffer_size)
        {
            offset_t    start_of_this_item = offset;

            uint32_t    offset_to_next = extractor.GetU32 (&offset);

            offset += 4; // Skip over the 4 bytes of reserved space
            addr_t      queue = extractor.GetPointer (&offset);
            uint64_t    serialnum = extractor.GetU64 (&offset);
            uint32_t    running_work_items_count = extractor.GetU32 (&offset);
            uint32_t    pending_work_items_count = extractor.GetU32 (&offset);

            // Read the first field of the variable length data
            offset = start_of_this_item + m_lib_backtrace_recording_info.queue_info_data_offset;
            const char *queue_label = extractor.GetCStr (&offset);
            if (queue_label == NULL)
                queue_label = "";

            offset_t    start_of_next_item = start_of_this_item + offset_to_next;
            offset = start_of_next_item;

            if (log)
                log->Printf ("SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR added queue with dispatch_queue_t 0x%" PRIx64 ", serial number 0x%" PRIx64 ", running items %d, pending items %d, name '%s'", queue, serialnum, running_work_items_count, pending_work_items_count, queue_label);

            QueueSP queue_sp (new Queue (m_process->shared_from_this(), serialnum, queue_label));
            queue_sp->SetNumRunningWorkItems (running_work_items_count);
            queue_sp->SetNumPendingWorkItems (pending_work_items_count);
            queue_sp->SetLibdispatchQueueAddress (queue);
            queue_sp->SetKind (GetQueueKind (queue));
            queue_list.AddQueue (queue_sp);
            queues_read++;
        }
    }
}