/** * Changes an alias to point to a new address space. * * Not all the aliases can be changed, currently it's only DBGF_AS_GLOBAL * and DBGF_AS_KERNEL. * * @returns VBox status code. * @param pUVM The user mode VM handle. * @param hAlias The alias to change. * @param hAliasFor The address space hAlias should be an alias for. This * can be an alias. The caller's reference to this address * space will NOT be consumed. */ VMMR3DECL(int) DBGFR3AsSetAlias(PUVM pUVM, RTDBGAS hAlias, RTDBGAS hAliasFor) { /* * Input validation. */ UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); AssertMsgReturn(DBGF_AS_IS_ALIAS(hAlias), ("%p\n", hAlias), VERR_INVALID_PARAMETER); AssertMsgReturn(!DBGF_AS_IS_FIXED_ALIAS(hAlias), ("%p\n", hAlias), VERR_INVALID_PARAMETER); RTDBGAS hRealAliasFor = DBGFR3AsResolveAndRetain(pUVM, hAliasFor); if (hRealAliasFor == NIL_RTDBGAS) return VERR_INVALID_HANDLE; /* * Make sure the handle has is already in the database. */ int rc = VERR_NOT_FOUND; DBGF_AS_DB_LOCK_WRITE(pUVM); if (RTAvlPVGet(&pUVM->dbgf.s.AsHandleTree, hRealAliasFor)) { /* * Update the alias table and release the current address space. */ RTDBGAS hAsOld; ASMAtomicXchgHandle(&pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(hAlias)], hRealAliasFor, &hAsOld); uint32_t cRefs = RTDbgAsRelease(hAsOld); Assert(cRefs > 0); Assert(cRefs != UINT32_MAX); NOREF(cRefs); rc = VINF_SUCCESS; } DBGF_AS_DB_UNLOCK_WRITE(pUVM); return rc; }
/** * Gets a block. */ DECLINLINE(PRTMEMBLOCK) rtmemBlockGet(void *pv) { rtmemBlockLock(); PRTMEMBLOCK pBlock = (PRTMEMBLOCK)RTAvlPVGet(&g_BlocksTree, pv); rtmemBlockUnlock(); return pBlock; }
/** * Gets a thread by it's native ID. * * @returns pointer to the thread structure. * @returns NULL if not a thread IPRT knows. * @param NativeThread The native thread id. */ DECLHIDDEN(PRTTHREADINT) rtThreadGetByNative(RTNATIVETHREAD NativeThread) { PRTTHREADINT pThread; /* * Simple tree lookup. */ RT_THREAD_LOCK_RD(); pThread = (PRTTHREADINT)RTAvlPVGet(&g_ThreadTree, (void *)NativeThread); RT_THREAD_UNLOCK_RD(); return pThread; }
/** * Insert the per thread data structure into the tree. * * This can be called from both the thread it self and the parent, * thus it must handle insertion failures in a nice manner. * * @param pThread Pointer to thread structure allocated by rtThreadAlloc(). * @param NativeThread The native thread id. */ DECLHIDDEN(void) rtThreadInsert(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread) { Assert(pThread); Assert(pThread->u32Magic == RTTHREADINT_MAGIC); { RT_THREAD_LOCK_RW(); /* * Do not insert a terminated thread. * * This may happen if the thread finishes before the RTThreadCreate call * gets this far. Since the OS may quickly reuse the native thread ID * it should not be reinserted at this point. */ if (rtThreadGetState(pThread) != RTTHREADSTATE_TERMINATED) { /* * Before inserting we must check if there is a thread with this id * in the tree already. We're racing parent and child on insert here * so that the handle is valid in both ends when they return / start. * * If it's not ourself we find, it's a dead alien thread and we will * unlink it from the tree. Alien threads will be released at this point. */ PRTTHREADINT pThreadOther = (PRTTHREADINT)RTAvlPVGet(&g_ThreadTree, (void *)NativeThread); if (pThreadOther != pThread) { bool fRc; /* remove dead alien if any */ if (pThreadOther) { AssertMsg(pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN, ("%p:%s; %p:%s\n", pThread, pThread->szName, pThreadOther, pThreadOther->szName)); ASMAtomicBitClear(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT); rtThreadRemoveLocked(pThreadOther); if (pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN) rtThreadRelease(pThreadOther); } /* insert the thread */ ASMAtomicWritePtr(&pThread->Core.Key, (void *)NativeThread); fRc = RTAvlPVInsert(&g_ThreadTree, &pThread->Core); ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE); if (fRc) ASMAtomicIncU32(&g_cThreadInTree); AssertReleaseMsg(fRc, ("Lock problem? %p (%RTnthrd) %s\n", pThread, NativeThread, pThread->szName)); NOREF(fRc); } } RT_THREAD_UNLOCK_RW(); } }