Ejemplo n.º 1
0
/**
 * Terminates and cleans up resources allocated by the DBGF.
 *
 * @returns VBox status code.
 * @param   pVM     Pointer to the VM.
 */
VMMR3DECL(int) DBGFR3Term(PVM pVM)
{
    int rc;

    /*
     * Send a termination event to any attached debugger.
     */
    /* wait to become the speaker (we should already be that). */
    if (    pVM->dbgf.s.fAttached
        &&  RTSemPingShouldWait(&pVM->dbgf.s.PingPong))
        RTSemPingWait(&pVM->dbgf.s.PingPong, 5000);

    /* now, send the event if we're the speaker. */
    if (    pVM->dbgf.s.fAttached
        &&  RTSemPingIsSpeaker(&pVM->dbgf.s.PingPong))
    {
        DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
        if (enmCmd == DBGFCMD_DETACH_DEBUGGER)
            /* the debugger beat us to initiating the detaching. */
            rc = VINF_SUCCESS;
        else
        {
            /* ignore the command (if any). */
            enmCmd = DBGFCMD_NO_COMMAND;
            pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_TERMINATING;
            pVM->dbgf.s.DbgEvent.enmCtx  = DBGFEVENTCTX_OTHER;
            rc = RTSemPing(&pVM->dbgf.s.PingPong);
        }

        /*
         * Process commands until we get a detached command.
         */
        while (RT_SUCCESS(rc) && enmCmd != DBGFCMD_DETACHED_DEBUGGER)
        {
            if (enmCmd != DBGFCMD_NO_COMMAND)
            {
                /* process command */
                bool fResumeExecution;
                DBGFCMDDATA CmdData = pVM->dbgf.s.VMMCmdData;
                rc = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
                enmCmd = DBGFCMD_NO_COMMAND;
            }
            else
            {
                /* wait for new command. */
                rc = RTSemPingWait(&pVM->dbgf.s.PingPong, RT_INDEFINITE_WAIT);
                if (RT_SUCCESS(rc))
                    enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
            }
        }
    }

    /*
     * Terminate the other bits.
     */
    dbgfR3OSTerm(pVM);
    dbgfR3AsTerm(pVM);
    dbgfR3RegTerm(pVM);
    dbgfR3TraceTerm(pVM);
    dbgfR3InfoTerm(pVM);
    return VINF_SUCCESS;
}
Ejemplo n.º 2
0
/**
 * Waits for the debugger to respond.
 *
 * @returns VBox status. (clearify)
 * @param   pVM     Pointer to the VM.
 */
static int dbgfR3VMMWait(PVM pVM)
{
    PVMCPU pVCpu = VMMGetCpu(pVM);

    LogFlow(("dbgfR3VMMWait:\n"));

    /** @todo stupid GDT/LDT sync hack. go away! */
    SELMR3UpdateFromCPUM(pVM, pVCpu);
    int rcRet = VINF_SUCCESS;

    /*
     * Waits for the debugger to reply (i.e. issue an command).
     */
    for (;;)
    {
        /*
         * Wait.
         */
        uint32_t cPollHack = 1; /** @todo this interface is horrible now that we're using lots of VMR3ReqCall stuff all over DBGF. */
        for (;;)
        {
            int rc;
            if (    !VM_FF_ISPENDING(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_REQUEST)
                &&  !VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_REQUEST))
            {
                rc = RTSemPingWait(&pVM->dbgf.s.PingPong, cPollHack);
                if (RT_SUCCESS(rc))
                    break;
                if (rc != VERR_TIMEOUT)
                {
                    LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rc));
                    return rc;
                }
            }

            if (VM_FF_ISPENDING(pVM, VM_FF_EMT_RENDEZVOUS))
            {
                rc = VMMR3EmtRendezvousFF(pVM, pVCpu);
                cPollHack = 1;
            }
            else if (   VM_FF_ISPENDING(pVM, VM_FF_REQUEST)
                     || VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_REQUEST))
            {
                LogFlow(("dbgfR3VMMWait: Processes requests...\n"));
                rc = VMR3ReqProcessU(pVM->pUVM, VMCPUID_ANY, false /*fPriorityOnly*/);
                if (rc == VINF_SUCCESS)
                    rc = VMR3ReqProcessU(pVM->pUVM, pVCpu->idCpu, false /*fPriorityOnly*/);
                LogFlow(("dbgfR3VMMWait: VMR3ReqProcess -> %Rrc rcRet=%Rrc\n", rc, rcRet));
                cPollHack = 1;
            }
            else
            {
                rc = VINF_SUCCESS;
                if (cPollHack < 120)
                    cPollHack++;
            }

            if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
            {
                switch (rc)
                {
                    case VINF_EM_DBG_BREAKPOINT:
                    case VINF_EM_DBG_STEPPED:
                    case VINF_EM_DBG_STEP:
                    case VINF_EM_DBG_STOP:
                        AssertMsgFailed(("rc=%Rrc\n", rc));
                        break;

                    /* return straight away */
                    case VINF_EM_TERMINATE:
                    case VINF_EM_OFF:
                        LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rc));
                        return rc;

                    /* remember return code. */
                    default:
                        AssertReleaseMsgFailed(("rc=%Rrc is not in the switch!\n", rc));
                    case VINF_EM_RESET:
                    case VINF_EM_SUSPEND:
                    case VINF_EM_HALT:
                    case VINF_EM_RESUME:
                    case VINF_EM_RESCHEDULE:
                    case VINF_EM_RESCHEDULE_REM:
                    case VINF_EM_RESCHEDULE_RAW:
                        if (rc < rcRet || rcRet == VINF_SUCCESS)
                            rcRet = rc;
                        break;
                }
            }
            else if (RT_FAILURE(rc))
            {
                LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rc));
                return rc;
            }
        }

        /*
         * Process the command.
         */
        bool            fResumeExecution;
        DBGFCMDDATA     CmdData = pVM->dbgf.s.VMMCmdData;
        DBGFCMD         enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
        int rc = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
        if (fResumeExecution)
        {
            if (RT_FAILURE(rc))
                rcRet = rc;
            else if (    rc >= VINF_EM_FIRST
                     &&  rc <= VINF_EM_LAST
                     &&  (rc < rcRet || rcRet == VINF_SUCCESS))
                rcRet = rc;
            LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rcRet));
            return rcRet;
        }
    }
}
int main()
{
    RTR3Init();

    /*
     * Create a ping pong and kick off a second thread which we'll
     * exchange TSTSEMPINGPONG_ITERATIONS messages with.
     */
    RTPINGPONG PingPong;
    int rc = RTSemPingPongInit(&PingPong);
    if (RT_FAILURE(rc))
    {
        RTPrintf("tstSemPingPong: FATAL ERROR - RTSemPingPongInit -> %Rrc\n", rc);
        return 1;
    }

    RTTHREAD hThread;
    rc = RTThreadCreate(&hThread, tstSemPingPongThread, &PingPong, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "PONG");
    if (RT_FAILURE(rc))
    {
        RTPrintf("tstSemPingPong: FATAL ERROR - RTSemPingPongInit -> %Rrc\n", rc);
        return 1;
    }

    RTPrintf("tstSemPingPong: TESTING - %u iterations...\n", TSTSEMPINGPONG_ITERATIONS);
    for (uint32_t i = 0; i < TSTSEMPINGPONG_ITERATIONS; i++)
    {
        if (!RTSemPingIsSpeaker(&PingPong))
        {
            ASMAtomicIncU32(&g_cErrors);
            RTPrintf("tstSemPingPong: ERROR - RTSemPingIsSpeaker returned false before RTSemPing.\n");
        }

        rc = RTSemPing(&PingPong);
        if (RT_FAILURE(rc))
        {
            ASMAtomicIncU32(&g_cErrors);
            RTPrintf("tstSemPingPong: ERROR - RTSemPing -> %Rrc\n", rc);
            break;
        }

        if (!RTSemPingShouldWait(&PingPong))
        {
            ASMAtomicIncU32(&g_cErrors);
            RTPrintf("tstSemPingPong: ERROR - RTSemPingShouldWait returned false before RTSemPingWait.\n");
        }

        rc = RTSemPingWait(&PingPong, RT_INDEFINITE_WAIT);
        if (RT_FAILURE(rc))
        {
            ASMAtomicIncU32(&g_cErrors);
            RTPrintf("tstSemPingPong: ERROR - RTSemPingWait -> %Rrc\n", rc);
            break;
        }
    }

    int rcThread;
    rc = RTThreadWait(hThread, 5000, &rcThread);
    if (RT_FAILURE(rc))
    {
        ASMAtomicIncU32(&g_cErrors);
        RTPrintf("tstSemPingPong: ERROR - RTSemPingWait -> %Rrc\n", rc);
    }

    rc = RTSemPingPongDelete(&PingPong);
    if (RT_FAILURE(rc))
    {
        ASMAtomicIncU32(&g_cErrors);
        RTPrintf("tstSemPingPong: ERROR - RTSemPingPongDestroy -> %Rrc\n", rc);
    }

    /*
     * Summary.
     */
    uint32_t cErrors = ASMAtomicUoReadU32(&g_cErrors);
    if (cErrors)
        RTPrintf("tstSemPingPong: FAILED - %d errors\n", cErrors);
    else
        RTPrintf("tstSemPingPong: SUCCESS\n");
    return cErrors ? 1 : 0;
}