status_t DebugReportGenerator::_DumpRunningThreads(BFile& _output) { AutoLocker< ::Team> locker(fTeam); BString data("\nActive Threads:\n"); WRITE_AND_CHECK(_output, data); BObjectList< ::Thread> threads; ::Thread* thread; for (ThreadList::ConstIterator it = fTeam->Threads().GetIterator(); (thread = it.Next());) { threads.AddItem(thread); } threads.SortItems(&_CompareThreads); for (int32 i = 0; (thread = threads.ItemAt(i)) != NULL; i++) { try { data.SetToFormat("\tthread %" B_PRId32 ": %s %s\n", thread->ID(), thread->Name(), thread->IsMainThread() ? "(main)" : ""); WRITE_AND_CHECK(_output, data); if (thread->State() == THREAD_STATE_STOPPED) { data.SetToFormat("\t\tstate: %s", UiUtils::ThreadStateToString(thread->State(), thread->StoppedReason())); const BString& stoppedInfo = thread->StoppedReasonInfo(); if (stoppedInfo.Length() != 0) data << " (" << stoppedInfo << ")"; data << "\n\n"; WRITE_AND_CHECK(_output, data); // we need to release our lock on the team here // since we might need to block and wait // on the stack trace. BReference< ::Thread> threadRef(thread); locker.Unlock(); status_t error = _DumpDebuggedThreadInfo(_output, thread); if (error != B_OK) return error; locker.Lock(); } } catch (...) { return B_NO_MEMORY; } } return B_OK; }
status_t DebugReportGenerator::_DumpLoadedImages(BFile& _output) { AutoLocker< ::Team> locker(fTeam); BString data("\nLoaded Images:\n"); WRITE_AND_CHECK(_output, data); BObjectList<Image> images; for (ImageList::ConstIterator it = fTeam->Images().GetIterator(); Image* image = it.Next();) { images.AddItem(image); } images.SortItems(&_CompareImages); Image* image = NULL; data.SetToFormat("\tID\t\tText Base\tText End\tData Base\tData" " End\tType\tName\n\t"); WRITE_AND_CHECK(_output, data); data.Truncate(0L); data.Append('-', 80); data.Append("\n"); WRITE_AND_CHECK(_output, data); for (int32 i = 0; (image = images.ItemAt(i)) != NULL; i++) { const ImageInfo& info = image->Info(); char buffer[32]; try { target_addr_t textBase = info.TextBase(); target_addr_t dataBase = info.DataBase(); data.SetToFormat("\t%" B_PRId32 "\t0x%08" B_PRIx64 "\t" "0x%08" B_PRIx64 "\t0x%08" B_PRIx64 "\t0x%08" B_PRIx64 "\t" "%-7s\t%s\n", info.ImageID(), textBase, textBase + info.TextSize(), dataBase, dataBase + info.DataSize(), UiUtils::ImageTypeToString(info.Type(), buffer, sizeof(buffer)), info.Name().String()); WRITE_AND_CHECK(_output, data); } catch (...) { return B_NO_MEMORY; } } return B_OK; }
// --------------------------------------------------------------- // AddTranslationItems // // Envious of that "Save As" menu in ShowImage? Well, you can have your own! // AddTranslationItems will add menu items for all translations from the // basic format you specify (B_TRANSLATOR_BITMAP, B_TRANSLATOR_TEXT etc). // The translator ID and format constant chosen will be added to the message // that is sent to you when the menu item is selected. // // The following code is a modified version of code // written by Jon Watte from // http://www.b500.com/bepage/TranslationKit2.html // // Preconditions: // // Parameters: intoMenu, the menu where the entries are created // fromType, the type of translators to put on // intoMenu // kModel, the BMessage model for creating the menu // if NULL, B_TRANSLATION_MENU is used // kTranslationIdName, the name used for // translator_id in the menuitem, // if NULL, be:translator is used // kTranslatorTypeName, the name used for // output format id in the menuitem // roster, BTranslatorRoster used to find translators // if NULL, the default translators are used // // // Postconditions: // // Returns: B_BAD_VALUE, if intoMenu is NULL // B_OK, if successful // error value if not successful // --------------------------------------------------------------- status_t BTranslationUtils::AddTranslationItems(BMenu *intoMenu, uint32 fromType, const BMessage *kModel, const char *kTranslatorIdName, const char *kTranslatorTypeName, BTranslatorRoster *roster) { if (!intoMenu) return B_BAD_VALUE; if (!roster) roster = BTranslatorRoster::Default(); if (!kTranslatorIdName) kTranslatorIdName = "be:translator"; if (!kTranslatorTypeName) kTranslatorTypeName = "be:type"; translator_id * ids = NULL; int32 count = 0; status_t err = roster->GetAllTranslators(&ids, &count); if (err < B_OK) return err; BObjectList<translator_info> infoList; for (int tix = 0; tix < count; tix++) { const translation_format *formats = NULL; int32 numFormats = 0; bool ok = false; err = roster->GetInputFormats(ids[tix], &formats, &numFormats); if (err == B_OK) { for (int iix = 0; iix < numFormats; iix++) { if (formats[iix].type == fromType) { ok = true; break; } } } if (!ok) continue; // Get supported output formats err = roster->GetOutputFormats(ids[tix], &formats, &numFormats); if (err == B_OK) { for (int oix = 0; oix < numFormats; oix++) { if (formats[oix].type != fromType) { infoList.AddItem(_BuildTranslatorInfo(ids[tix], const_cast<translation_format*>(&formats[oix]))); } } } } // Sort alphabetically by name infoList.SortItems(&_CompareTranslatorInfoByName); // Now add the menu items for (int i = 0; i < infoList.CountItems(); i++) { translator_info* info = infoList.ItemAt(i); BMessage *itemmsg; if (kModel) itemmsg = new BMessage(*kModel); else itemmsg = new BMessage(B_TRANSLATION_MENU); itemmsg->AddInt32(kTranslatorIdName, info->translator); itemmsg->AddInt32(kTranslatorTypeName, info->type); intoMenu->AddItem(new BMenuItem(info->name, itemmsg)); // Delete object created in _BuildTranslatorInfo delete info; } delete[] ids; return B_OK; }
status_t ThreadModelLoader::_Load() { // create a model fThreadModel = new(std::nothrow) ThreadModel(fModel, fThread); if (fThreadModel == NULL) return B_NO_MEMORY; // collect all wait objects BObjectList<Model::ThreadWaitObject> waitObjects; int32 groupCount = fThread->CountThreadWaitObjectGroups(); for (int32 i = 0; i < groupCount; i++) { Model::ThreadWaitObjectGroup* group = fThread->ThreadWaitObjectGroupAt(i); if (!group->GetThreadWaitObjects(waitObjects)) return B_NO_MEMORY; } // sort them by type and name waitObjects.SortItems(&compare_by_type_and_name); // create the groups int32 waitObjectCount = waitObjects.CountItems(); printf("%" B_PRId32 " wait objects\n", waitObjectCount); for (int32 i = 0; i < waitObjectCount;) { printf("new wait object group at %" B_PRId32 "\n", i); // collect the objects for this group Model::ThreadWaitObject* firstObject = waitObjects.ItemAt(i); int32 k = i + 1; for (; k < waitObjectCount; k++) { if (compare_by_type_and_name(firstObject, waitObjects.ItemAt(k)) != 0) { break; } } if (fThreadModel->AddWaitObjectGroup(waitObjects, i, k) == NULL) return B_NO_MEMORY; i = k; } // filter the events thread_id threadID = fThread->ID(); bool done = false; uint32 count = 0; system_profiler_event_header** events = fModel->Events(); size_t eventCount = fModel->CountEvents(); for (size_t i = 0; i < eventCount; i++) { system_profiler_event_header* header = events[i]; void* buffer = header + 1; // process the event bool keepEvent = false; switch (header->event) { case B_SYSTEM_PROFILER_THREAD_REMOVED: { system_profiler_thread_removed* event = (system_profiler_thread_removed*)buffer; if (event->thread == threadID) done = true; break; } case B_SYSTEM_PROFILER_THREAD_SCHEDULED: { system_profiler_thread_scheduled* event = (system_profiler_thread_scheduled*)buffer; keepEvent = event->thread == threadID || event->previous_thread == threadID ; break; } case B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE: { thread_enqueued_in_run_queue* event = (thread_enqueued_in_run_queue*)buffer; keepEvent = event->thread == threadID; break; } case B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE: { thread_removed_from_run_queue* event = (thread_removed_from_run_queue*)buffer; keepEvent = event->thread == threadID; break; } default: break; } if (keepEvent) fThreadModel->AddSchedulingEvent(header); // periodically check whether we're supposed to abort if (++count % 32 == 0) { AutoLocker<BLocker> locker(fLock); if (fAborted) return B_ERROR; } } return B_OK; }