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->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_sp->SetKind (GetQueueKind (thread_sp->GetQueueLibdispatchQueueAddress())); queue_sp->SetLibdispatchQueueAddress (thread_sp->GetQueueLibdispatchQueueAddress()); queue_list.AddQueue (queue_sp); } } } }
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++; } } }