status_t set_port_owner(port_id id, team_id newTeamID) { TRACE(("set_port_owner(id = %ld, team = %ld)\n", id, newTeamID)); if (id < 0) return B_BAD_PORT_ID; int32 slot = id % sMaxPorts; MutexLocker locker(sPorts[slot].lock); if (sPorts[slot].id != id) { TRACE(("set_port_owner: invalid port_id %ld\n", id)); return B_BAD_PORT_ID; } InterruptsSpinLocker teamLocker(gTeamSpinlock); struct team* team = team_get_team_struct_locked(newTeamID); if (team == NULL) { T(OwnerChange(sPorts[slot], newTeamID, B_BAD_TEAM_ID)); return B_BAD_TEAM_ID; } // transfer ownership to other team list_remove_link(&sPorts[slot].team_link); list_add_item(&team->port_list, &sPorts[slot].team_link); sPorts[slot].owner = newTeamID; T(OwnerChange(sPorts[slot], newTeamID, B_OK)); return B_OK; }
void BreakpointManager::UninstallTemporaryBreakpoint(target_addr_t address, BreakpointClient* client) { AutoLocker<BLocker> installLocker(fLock); AutoLocker<Team> teamLocker(fTeam); Breakpoint* breakpoint = fTeam->BreakpointAtAddress(address); if (breakpoint == NULL) return; // remove the client breakpoint->RemoveClient(client); // check whether the breakpoint needs to be uninstalled bool uninstall = !breakpoint->ShouldBeInstalled() && breakpoint->IsInstalled(); // if unused remove it BReference<Breakpoint> breakpointReference(breakpoint); if (breakpoint->IsUnused()) fTeam->RemoveBreakpoint(breakpoint); teamLocker.Unlock(); if (uninstall) { fDebuggerInterface->UninstallBreakpoint(address); breakpoint->SetInstalled(false); } }
void BreakpointsView::_UpdateButtons() { AutoLocker<Team> teamLocker(fTeam); bool hasEnabled = false; bool hasDisabled = false; bool valid = false; for (int32 i = 0; i < fSelectedBreakpoints.CountItems(); i++) { BreakpointProxy* proxy = fSelectedBreakpoints.ItemAt(i); switch (proxy->Type()) { case BREAKPOINT_PROXY_TYPE_BREAKPOINT: { UserBreakpoint* breakpoint = proxy->GetBreakpoint(); if (breakpoint->IsValid()) { valid = true; if (breakpoint->IsEnabled()) hasEnabled = true; else hasDisabled = true; } break; } case BREAKPOINT_PROXY_TYPE_WATCHPOINT: { Watchpoint* watchpoint = proxy->GetWatchpoint(); valid = true; if (watchpoint->IsEnabled()) hasEnabled = true; else hasDisabled = true; break; } default: break; } } if (valid) { // if we have at least one disabled breakpoint in the // selection, we leave the button as an Enable button if (hasEnabled && !hasDisabled) { fToggleBreakpointButton->SetLabel("Disable"); fToggleBreakpointButton->SetMessage( new BMessage(MSG_DISABLE_BREAKPOINT)); } else { fToggleBreakpointButton->SetLabel("Enable"); fToggleBreakpointButton->SetMessage( new BMessage(MSG_ENABLE_BREAKPOINT)); } fToggleBreakpointButton->SetEnabled(true); fRemoveBreakpointButton->SetEnabled(true); } else { fToggleBreakpointButton->SetLabel("Enable"); fToggleBreakpointButton->SetEnabled(false); fRemoveBreakpointButton->SetEnabled(false); } }
void BreakpointEditWindow::_Init() { fConditionInput = new BTextControl(NULL, NULL, NULL); BLayoutItem* textLayoutItem = fConditionInput->CreateTextViewLayoutItem(); textLayoutItem->SetExplicitMinSize(BSize(200.0, B_SIZE_UNSET)); BLayoutBuilder::Group<>(this, B_VERTICAL) .SetInsets(B_USE_DEFAULT_SPACING) .Add((fAlwaysRadio = new BRadioButton("Break always", new BMessage(MSG_SET_BREAK_ALWAYS)))) .AddGroup(B_HORIZONTAL) .Add((fConditionRadio = new BRadioButton("Break on condition: ", new BMessage(MSG_SET_BREAK_ON_CONDITION)))) .Add(textLayoutItem) .End() .AddGroup(B_HORIZONTAL) .AddGlue() .Add((fSaveButton = new BButton("Save", new BMessage(MSG_SAVE_BREAKPOINT_SETTINGS)))) .Add((fCancelButton = new BButton("Cancel", new BMessage(B_CANCEL)))) .End() .End(); AutoLocker< ::Team> teamLocker(fTeam); if (fTargetBreakpoint->HasCondition()) { fConditionRadio->SetValue(B_CONTROL_ON); fConditionInput->SetText(fTargetBreakpoint->Condition()); } else { fAlwaysRadio->SetValue(B_CONTROL_ON); fConditionInput->SetEnabled(false); } }
status_t DebugReportGenerator::_GenerateReport(const entry_ref& outputPath) { BFile file(&outputPath, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); status_t result = file.InitCheck(); if (result != B_OK) return result; result = _GenerateReportHeader(file); if (result != B_OK) return result; result = _DumpRunningThreads(file); if (result != B_OK) return result; result = _DumpLoadedImages(file); if (result != B_OK) return result; result = _DumpAreas(file); if (result != B_OK) return result; result = _DumpSemaphores(file); if (result != B_OK) return result; BPath path(&outputPath); AutoLocker< ::Team> teamLocker(fTeam); fTeam->NotifyDebugReportChanged(path.Path()); return B_OK; }
static void notify_loading_app(status_t result, bool suspend) { Team* team = thread_get_current_thread()->team; TeamLocker teamLocker(team); if (team->loading_info) { // there's indeed someone waiting struct team_loading_info* loadingInfo = team->loading_info; team->loading_info = NULL; loadingInfo->result = result; loadingInfo->done = true; // we're done with the team stuff, get the scheduler lock instead teamLocker.Unlock(); InterruptsSpinLocker schedulerLocker(gSchedulerLock); // wake up the waiting thread if (loadingInfo->thread->state == B_THREAD_SUSPENDED) scheduler_enqueue_in_run_queue(loadingInfo->thread); // suspend ourselves, if desired if (suspend) { thread_get_current_thread()->next_state = B_THREAD_SUSPENDED; scheduler_reschedule(); } } }
bool _GetBreakpointValueAt(UserBreakpoint* breakpoint, int32 rowIndex, int32 columnIndex, BVariant &value) { const UserBreakpointLocation& location = breakpoint->Location(); switch (columnIndex) { case 0: value.SetTo((int32)breakpoint->IsEnabled()); return true; case 1: value.SetTo(location.GetFunctionID()->FunctionName(), B_VARIANT_DONT_COPY_DATA); return true; case 2: { LocatableFile* sourceFile = location.SourceFile(); BString data; if (sourceFile != NULL) { data.SetToFormat("%s:%" B_PRId32, sourceFile->Name(), location.GetSourceLocation().Line() + 1); } else { AutoLocker<Team> teamLocker(fTeam); if (UserBreakpointInstance* instance = breakpoint->InstanceAt(0)) { data.SetToFormat("%#" B_PRIx64, instance->Address()); } } value.SetTo(data); return true; } default: return false; } }
void CliContext::PrintCurrentThread() { AutoLocker<Team> teamLocker(fTeam); if (fCurrentThread != NULL) { printf("current thread: %" B_PRId32 " \"%s\"\n", fCurrentThread->ID(), fCurrentThread->Name()); } else printf("no current thread\n"); }
void DebugReportGenerator::FunctionSourceCodeChanged(Function* function) { AutoLocker< ::Team> teamLocker(fTeam); if (function == fSourceWaitingFunction) { if (function->FirstInstance()->SourceCodeState() == FUNCTION_SOURCE_LOADED || function->FirstInstance()->SourceCodeState() == FUNCTION_SOURCE_UNAVAILABLE) { release_sem(fTeamDataSem); } } }
void InspectorWindow::_SetCurrentBlock(TeamMemoryBlock* block) { AutoLocker< ::Team> teamLocker(fTeam); if (fCurrentBlock != NULL) { fCurrentBlock->RemoveListener(this); fCurrentBlock->ReleaseReference(); } fCurrentBlock = block; fMemoryView->SetTargetAddress(fCurrentBlock, fCurrentAddress); _UpdateWritableOptions(); }
status_t BreakpointManager::InstallTemporaryBreakpoint(target_addr_t address, BreakpointClient* client) { AutoLocker<BLocker> installLocker(fLock); AutoLocker<Team> teamLocker(fTeam); // create a breakpoint, if it doesn't exist yet Breakpoint* breakpoint = fTeam->BreakpointAtAddress(address); if (breakpoint == NULL) { Image* image = fTeam->ImageByAddress(address); if (image == NULL) return B_BAD_ADDRESS; breakpoint = new(std::nothrow) Breakpoint(image, address); if (breakpoint == NULL) return B_NO_MEMORY; if (!fTeam->AddBreakpoint(breakpoint)) return B_NO_MEMORY; } BReference<Breakpoint> breakpointReference(breakpoint); // add the client status_t error; if (breakpoint->AddClient(client)) { if (breakpoint->IsInstalled()) return B_OK; // install teamLocker.Unlock(); error = fDebuggerInterface->InstallBreakpoint(address); if (error == B_OK) { breakpoint->SetInstalled(true); return B_OK; } teamLocker.Lock(); breakpoint->RemoveClient(client); } else error = B_NO_MEMORY; // clean up on error if (breakpoint->IsUnused()) fTeam->RemoveBreakpoint(breakpoint); return error; }
bool CommandLineUserInterface::_ReportTargetThreadStopNeeded() const { if (fReportTargetThread < 0) return false; Team* team = fContext.GetTeam(); AutoLocker<Team> teamLocker(team); Thread* thread = team->ThreadByID(fReportTargetThread); if (thread == NULL) return false; return thread->State() != THREAD_STATE_STOPPED; }
void core_dump_trap_thread() { Thread* thread = thread_get_current_thread(); ConditionVariableEntry conditionVariableEntry; TeamLocker teamLocker(thread->team); while ((atomic_get(&thread->flags) & THREAD_FLAGS_TRAP_FOR_CORE_DUMP) != 0) { thread->team->CoreDumpCondition()->Add(&conditionVariableEntry); teamLocker.Unlock(); conditionVariableEntry.Wait(); teamLocker.Lock(); } }
InspectorWindow::~InspectorWindow() { _SetCurrentBlock(NULL); if (fLanguage != NULL) fLanguage->ReleaseReference(); if (fExpressionInfo != NULL) { fExpressionInfo->RemoveListener(this); fExpressionInfo->ReleaseReference(); } AutoLocker< ::Team> teamLocker(fTeam); fTeam->RemoveListener(this); }
status_t ThreadHandler::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info) { AutoLocker<Team> teamLocker(fThread->GetTeam()); if (image->GetImageDebugInfo() != NULL) { _info = image->GetImageDebugInfo(); _info->AcquireReference(); return B_OK; } // Let's be lazy. If the image debug info has not been loaded yet, the user // can't have seen any source code either. return B_ENTRY_NOT_FOUND; }
void BreakpointManager::UninstallUserBreakpoint(UserBreakpoint* userBreakpoint) { AutoLocker<BLocker> installLocker(fLock); AutoLocker<Team> teamLocker(fTeam); if (!userBreakpoint->IsValid()) return; fTeam->RemoveUserBreakpoint(userBreakpoint); userBreakpoint->SetValid(false); userBreakpoint->SetEnabled(false); teamLocker.Unlock(); // uninstall the breakpoints as needed for (int32 i = 0; UserBreakpointInstance* instance = userBreakpoint->InstanceAt(i); i++) { if (Breakpoint* breakpoint = instance->GetBreakpoint()) _UpdateBreakpointInstallation(breakpoint); } teamLocker.Lock(); // detach the breakpoints from the user breakpoint instances for (int32 i = 0; UserBreakpointInstance* instance = userBreakpoint->InstanceAt(i); i++) { if (Breakpoint* breakpoint = instance->GetBreakpoint()) { instance->SetBreakpoint(NULL); breakpoint->RemoveUserBreakpoint(instance); if (breakpoint->IsUnused()) fTeam->RemoveBreakpoint(breakpoint); } } fTeam->NotifyUserBreakpointChanged(userBreakpoint); teamLocker.Unlock(); installLocker.Unlock(); // release the reference from InstallUserBreakpoint() userBreakpoint->ReleaseReference(); }
void CliStackTraceCommand::Execute(int argc, const char* const* argv, CliContext& context) { // get the current thread Team* team = context.GetTeam(); AutoLocker<Team> teamLocker(team); Thread* thread = context.CurrentThread(); if (thread == NULL) { printf("no current thread\n"); return; } if (thread->State() != THREAD_STATE_STOPPED) { printf("Current thread is not stopped. Can't get stack trace.\n"); return; } // get its stack trace StackTrace* stackTrace = thread->GetStackTrace(); while (stackTrace == NULL) { context.WaitForEvents(CliContext::EVENT_THREAD_STACK_TRACE_CHANGED); if (context.IsTerminating()) return; stackTrace = thread->GetStackTrace(); } BReference<StackTrace> stackTraceReference(stackTrace); // hold a reference until we're done teamLocker.Unlock(); // print the stack trace int32 frameCount = stackTrace->CountFrames(); for (int32 i = 0; i < frameCount; i++) { StackFrame* frame = stackTrace->FrameAt(i); printf("%3" B_PRId32 " %#" B_PRIx64 " %#" B_PRIx64, i, (uint64)frame->FrameAddress(), (uint64)frame->InstructionPointer()); char functionName[512]; UiUtils::FunctionNameForFrame(frame, functionName, sizeof(functionName)); printf(" %s\n", functionName); } }
void BreakConditionConfigWindow::_UpdateThrownBreakpoints(bool enable) { AutoLocker< ::Team> teamLocker(fTeam); for (ImageList::ConstIterator it = fTeam->Images().GetIterator(); it.HasNext();) { Image* image = it.Next(); ImageDebugInfo* info = image->GetImageDebugInfo(); target_addr_t address; if (_FindExceptionFunction(info, address) != B_OK) continue; if (enable) fListener->SetBreakpointRequested(address, true, true); else fListener->ClearBreakpointRequested(address); } }
/*static*/ status_t LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, ImageDebugInfo** _imageDebugInfo) { AutoLocker<Team> teamLocker(image->GetTeam()); // If already loaded, we're done. if (image->GetImageDebugInfo() != NULL) { if (_imageDebugInfo != NULL) { *_imageDebugInfo = image->GetImageDebugInfo(); (*_imageDebugInfo)->AcquireReference(); } return B_OK; } // If already loading, the caller has to wait, if desired. if (image->ImageDebugInfoState() == IMAGE_DEBUG_INFO_LOADING) { if (_imageDebugInfo != NULL) *_imageDebugInfo = NULL; return B_OK; } // If an earlier load attempt failed, bail out. if (image->ImageDebugInfoState() != IMAGE_DEBUG_INFO_NOT_LOADED) return B_ERROR; // schedule a job LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(image); if (job == NULL) return B_NO_MEMORY; status_t error = worker->ScheduleJob(job); if (error != B_OK) { image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE); return error; } image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_LOADING); if (_imageDebugInfo != NULL) *_imageDebugInfo = NULL; return B_OK; }
void ThreadSignalEvent::DoDPC(DPCQueue* queue) { fSignal->AcquireReference(); // one reference is transferred to send_signal_to_team_locked InterruptsReadSpinLocker teamLocker(fThread->team_lock); SpinLocker locker(fThread->team->signal_lock); status_t error = send_signal_to_thread_locked(fThread, fSignal->Number(), fSignal, B_DO_NOT_RESCHEDULE); locker.Unlock(); teamLocker.Unlock(); // There are situations (for certain signals), in which // send_signal_to_team_locked() succeeds without queuing the signal. if (error != B_OK || !fSignal->IsPending()) fSignal->SetUnused(); // We're no longer queued in the DPC queue, so we can be reused. atomic_set(&fPendingDPC, 0); }
virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value) { UserBreakpoint* breakpoint = fBreakpoints.ItemAt(rowIndex); if (breakpoint == NULL) return false; const UserBreakpointLocation& location = breakpoint->Location(); switch (columnIndex) { case 0: value.SetTo((int32)breakpoint->IsEnabled()); return true; case 1: value.SetTo(location.GetFunctionID()->FunctionName(), B_VARIANT_DONT_COPY_DATA); return true; case 2: if (LocatableFile* sourceFile = location.SourceFile()) { value.SetTo(sourceFile->Name(), B_VARIANT_DONT_COPY_DATA); return true; } return false; case 3: if (location.SourceFile() != NULL) { value.SetTo(location.GetSourceLocation().Line() + 1); return true; } return false; case 4: if (location.SourceFile() == NULL) { AutoLocker<Team> teamLocker(fTeam); if (UserBreakpointInstance* instance = breakpoint->InstanceAt(0)) { value.SetTo(instance->Address()); return true; } } return false; default: return false; } }
void CliContext::WaitForThreadOrUser() { ProcessPendingEvents(); // TODO: Deal with SIGINT as well! for (;;) { _PrepareToWaitForEvents( EVENT_USER_INTERRUPT | EVENT_THREAD_STOPPED); // check whether there are any threads stopped already Thread* stoppedThread = NULL; BReference<Thread> stoppedThreadReference; AutoLocker<Team> teamLocker(fTeam); for (ThreadList::ConstIterator it = fTeam->Threads().GetIterator(); Thread* thread = it.Next();) { if (thread->State() == THREAD_STATE_STOPPED) { stoppedThread = thread; stoppedThreadReference.SetTo(thread); break; } } teamLocker.Unlock(); if (stoppedThread != NULL) { if (fCurrentThread == NULL) SetCurrentThread(stoppedThread); _SignalInputLoop(EVENT_THREAD_STOPPED); } uint32 events = _WaitForEvents(); if ((events & EVENT_QUIT) != 0 || stoppedThread != NULL) { ProcessPendingEvents(); return; } } }
status_t GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info) { AutoLocker<Team> teamLocker(fThread->GetTeam()); while (image->GetImageDebugInfo() == NULL) { // schedule a job, if not loaded ImageDebugInfo* info; status_t error = LoadImageDebugInfoJob::ScheduleIfNecessary(GetWorker(), image, &info); if (error != B_OK) return error; if (info != NULL) { _info = info; return B_OK; } teamLocker.Unlock(); // wait for the job to finish switch (WaitFor(SimpleJobKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO))) { case JOB_DEPENDENCY_SUCCEEDED: case JOB_DEPENDENCY_NOT_FOUND: // "Not found" can happen due to a race condition between // unlocking the worker and starting to wait. break; case JOB_DEPENDENCY_FAILED: case JOB_DEPENDENCY_ABORTED: default: return B_ERROR; } teamLocker.Lock(); } _info = image->GetImageDebugInfo(); _info->AcquireReference(); return B_OK; }
InspectorWindow::InspectorWindow(::Team* team, UserInterfaceListener* listener, BHandler* target) : BWindow(BRect(100, 100, 700, 500), "Inspector", B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), fListener(listener), fAddressInput(NULL), fHexMode(NULL), fTextMode(NULL), fWritableBlockIndicator(NULL), fMemoryView(NULL), fCurrentBlock(NULL), fCurrentAddress(0LL), fTeam(team), fLanguage(NULL), fExpressionInfo(NULL), fTarget(target) { AutoLocker< ::Team> teamLocker(fTeam); fTeam->AddListener(this); }
bool SystemProfiler::_TeamRemoved(Team* team) { // TODO: It is possible that we get remove notifications for teams that // had already been removed from the global team list when we did the // initial scan, but were still in the process of dying. ATM it is not // really possible to identify such a case. TeamLocker teamLocker(team); InterruptsSpinLocker locker(fLock); system_profiler_team_removed* event = (system_profiler_team_removed*) _AllocateBuffer(sizeof(system_profiler_team_removed), B_SYSTEM_PROFILER_TEAM_REMOVED, 0, 0); if (event == NULL) return false; event->team = team->id; fHeader->size = fBufferSize; return true; }
status_t delete_port(port_id id) { TRACE(("delete_port(id = %ld)\n", id)); if (!sPortsActive || id < 0) return B_BAD_PORT_ID; int32 slot = id % sMaxPorts; MutexLocker locker(sPorts[slot].lock); if (sPorts[slot].id != id) { TRACE(("delete_port: invalid port_id %ld\n", id)); return B_BAD_PORT_ID; } T(Delete(sPorts[slot])); { InterruptsSpinLocker teamLocker(gTeamSpinlock); list_remove_link(&sPorts[slot].team_link); } uninit_port_locked(sPorts[slot]); locker.Unlock(); MutexLocker _(sPortsLock); // update the first free slot hint in the array if (slot < sFirstFreeSlot) sFirstFreeSlot = slot; sUsedPorts--; return B_OK; }
bool SystemProfiler::_TeamExec(Team* team) { TeamLocker teamLocker(team); size_t argsLen = strlen(team->Args()); InterruptsSpinLocker locker(fLock); system_profiler_team_exec* event = (system_profiler_team_exec*) _AllocateBuffer(sizeof(system_profiler_team_exec) + argsLen, B_SYSTEM_PROFILER_TEAM_EXEC, 0, 0); if (event == NULL) return false; event->team = team->id; strlcpy(event->thread_name, team->main_thread->name, sizeof(event->thread_name)); strcpy(event->args, team->Args()); fHeader->size = fBufferSize; return true; }
void TeamDebugger::_HandleInspectAddress(target_addr_t address, TeamMemoryBlock::Listener* listener) { TRACE_CONTROL("TeamDebugger::_HandleInspectAddress(%" B_PRIx64 ", %p)\n", address, listener); TeamMemoryBlock* memoryBlock = fMemoryBlockManager ->GetMemoryBlock(address); if (memoryBlock == NULL) { _NotifyUser("Inspect Address", "Failed to allocate memory block"); return; } if (!memoryBlock->HasListener(listener)) memoryBlock->AddListener(listener); if (!memoryBlock->IsValid()) { AutoLocker< ::Team> teamLocker(fTeam); TeamMemory* memory = fTeam->GetTeamMemory(); // schedule the job status_t result; if ((result = fWorker->ScheduleJob( new(std::nothrow) RetrieveMemoryBlockJob(fTeam, memory, memoryBlock), this)) != B_OK) { memoryBlock->ReleaseReference(); _NotifyUser("Inspect Address", "Failed to retrieve memory data: %s", strerror(result)); } } else memoryBlock->NotifyDataRetrieved(); }
status_t Architecture::CreateStackTrace(Team* team, ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState, StackTrace*& _stackTrace, int32 maxStackDepth, bool useExistingTrace) { BReference<CpuState> cpuStateReference(cpuState); StackTrace* stackTrace = NULL; ObjectDeleter<StackTrace> stackTraceDeleter; StackFrame* frame = NULL; if (useExistingTrace) stackTrace = _stackTrace; else { // create the object stackTrace = new(std::nothrow) StackTrace; if (stackTrace == NULL) return B_NO_MEMORY; stackTraceDeleter.SetTo(stackTrace); } // if we're passed an already existing partial stack trace, // attempt to continue building it from where it left off. if (stackTrace->CountFrames() > 0) { frame = stackTrace->FrameAt(stackTrace->CountFrames() - 1); cpuState = frame->GetCpuState(); } while (cpuState != NULL) { // get the instruction pointer target_addr_t instructionPointer = cpuState->InstructionPointer(); if (instructionPointer == 0) break; // get the image for the instruction pointer AutoLocker<Team> teamLocker(team); Image* image = team->ImageByAddress(instructionPointer); BReference<Image> imageReference(image); teamLocker.Unlock(); // get the image debug info ImageDebugInfo* imageDebugInfo = NULL; if (image != NULL) imageInfoProvider->GetImageDebugInfo(image, imageDebugInfo); BReference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo, true); // get the function teamLocker.Lock(); FunctionInstance* function = NULL; FunctionDebugInfo* functionDebugInfo = NULL; if (imageDebugInfo != NULL) { function = imageDebugInfo->FunctionAtAddress(instructionPointer); if (function != NULL) functionDebugInfo = function->GetFunctionDebugInfo(); } BReference<FunctionInstance> functionReference(function); teamLocker.Unlock(); // If the CPU state's instruction pointer is actually the return address // of the next frame, we let the architecture fix that. if (frame != NULL && frame->ReturnAddress() == cpuState->InstructionPointer()) { UpdateStackFrameCpuState(frame, image, functionDebugInfo, cpuState); } // create the frame using the debug info StackFrame* previousFrame = NULL; CpuState* previousCpuState = NULL; if (function != NULL) { status_t error = functionDebugInfo->GetSpecificImageDebugInfo() ->CreateFrame(image, function, cpuState, previousFrame, previousCpuState); if (error != B_OK && error != B_UNSUPPORTED) break; } // If we have no frame yet, let the architecture create it. if (previousFrame == NULL) { status_t error = CreateStackFrame(image, functionDebugInfo, cpuState, frame == NULL, previousFrame, previousCpuState); if (error != B_OK) break; } cpuStateReference.SetTo(previousCpuState, true); previousFrame->SetImage(image); previousFrame->SetFunction(function); if (!stackTrace->AddFrame(previousFrame)) { delete previousFrame; return B_NO_MEMORY; } frame = previousFrame; cpuState = previousCpuState; if (--maxStackDepth == 0) break; } stackTraceDeleter.Detach(); _stackTrace = stackTrace; return B_OK; }
port_id create_port(int32 queueLength, const char* name) { TRACE(("create_port(queueLength = %ld, name = \"%s\")\n", queueLength, name)); if (!sPortsActive) { panic("ports used too early!\n"); return B_BAD_PORT_ID; } if (queueLength < 1 || queueLength > MAX_QUEUE_LENGTH) return B_BAD_VALUE; struct team* team = thread_get_current_thread()->team; if (team == NULL) return B_BAD_TEAM_ID; MutexLocker locker(sPortsLock); // check early on if there are any free port slots to use if (sUsedPorts >= sMaxPorts) return B_NO_MORE_PORTS; // check & dup name char* nameBuffer = strdup(name != NULL ? name : "unnamed port"); if (nameBuffer == NULL) return B_NO_MEMORY; sUsedPorts++; // find the first empty spot for (int32 slot = 0; slot < sMaxPorts; slot++) { int32 i = (slot + sFirstFreeSlot) % sMaxPorts; if (sPorts[i].id == -1) { // make the port_id be a multiple of the slot it's in if (i >= sNextPort % sMaxPorts) sNextPort += i - sNextPort % sMaxPorts; else sNextPort += sMaxPorts - (sNextPort % sMaxPorts - i); sFirstFreeSlot = slot + 1; MutexLocker portLocker(sPorts[i].lock); sPorts[i].id = sNextPort++; locker.Unlock(); sPorts[i].capacity = queueLength; sPorts[i].owner = team_get_current_team_id(); sPorts[i].lock.name = nameBuffer; sPorts[i].read_count = 0; sPorts[i].write_count = queueLength; sPorts[i].total_count = 0; sPorts[i].select_infos = NULL; { InterruptsSpinLocker teamLocker(gTeamSpinlock); list_add_item(&team->port_list, &sPorts[i].team_link); } port_id id = sPorts[i].id; T(Create(sPorts[i])); portLocker.Unlock(); TRACE(("create_port() done: port created %ld\n", id)); sNotificationService.Notify(PORT_ADDED, id); return id; } } // Still not enough ports... - due to sUsedPorts, this cannot really // happen anymore. panic("out of ports, but sUsedPorts is broken"); return B_NO_MORE_PORTS; }