/**
 * 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;
}
Beispiel #3
0
/**
 * 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;
}
Beispiel #4
0
/**
 * 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();
    }
}