/** * Detaches a debugger from the specified VM. * * Caller must be attached to the VM. * * @returns VBox status code. * @param pVM Pointer to the VM. */ VMMR3DECL(int) DBGFR3Detach(PVM pVM) { LogFlow(("DBGFR3Detach:\n")); int rc; /* * Check if attached. */ AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED); /* * Try send the detach command. * Keep in mind that we might be racing EMT, so, be extra careful. */ DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_DETACH_DEBUGGER); if (RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong)) { rc = RTSemPong(&pVM->dbgf.s.PingPong); AssertMsgRCReturn(rc, ("Failed to signal emulation thread. rc=%Rrc\n", rc), rc); LogRel(("DBGFR3Detach: enmCmd=%d (pong -> ping)\n", enmCmd)); } /* * Wait for the OK event. */ rc = RTSemPongWait(&pVM->dbgf.s.PingPong, RT_INDEFINITE_WAIT); AssertLogRelMsgRCReturn(rc, ("Wait on detach command failed, rc=%Rrc\n", rc), rc); /* * Send the notification command indicating that we're really done. */ enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_DETACHED_DEBUGGER); rc = RTSemPong(&pVM->dbgf.s.PingPong); AssertMsgRCReturn(rc, ("Failed to signal emulation thread. rc=%Rrc\n", rc), rc); LogFlowFunc(("returns VINF_SUCCESS\n")); return VINF_SUCCESS; }
/** * Resumes VM execution. * * There is no receipt event on this command. * * @returns VBox status. * @param pVM Pointer to the VM. */ VMMR3DECL(int) DBGFR3Resume(PVM pVM) { /* * Check state. */ AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED); AssertReturn(RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong), VERR_SEM_OUT_OF_TURN); /* * Send the ping back to the emulation thread telling it to run. */ dbgfR3SetCmd(pVM, DBGFCMD_GO); int rc = RTSemPong(&pVM->dbgf.s.PingPong); AssertRC(rc); return rc; }
/** * Step Into. * * A single step event is generated from this command. * The current implementation is not reliable, so don't rely on the event coming. * * @returns VBox status. * @param pVM Pointer to the VM. * @param idCpu The ID of the CPU to single step on. */ VMMR3DECL(int) DBGFR3Step(PVM pVM, VMCPUID idCpu) { /* * Check state. */ AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED); AssertReturn(RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong), VERR_SEM_OUT_OF_TURN); AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_PARAMETER); /* * Send the ping back to the emulation thread telling it to run. */ /** @todo SMP (idCpu) */ dbgfR3SetCmd(pVM, DBGFCMD_SINGLE_STEP); int rc = RTSemPong(&pVM->dbgf.s.PingPong); AssertRC(rc); return rc; }
static DECLCALLBACK(int) tstSemPingPongThread(RTTHREAD hThread, void *pvPP) { int rc; PRTPINGPONG pPP = (PRTPINGPONG)pvPP; for (uint32_t i = 0; i < TSTSEMPINGPONG_ITERATIONS; i++) { if (!RTSemPongShouldWait(pPP)) { ASMAtomicIncU32(&g_cErrors); RTPrintf("tstSemPingPong: ERROR - RTSemPongShouldWait returned false before RTSemPongWait.\n"); } rc = RTSemPongWait(pPP, RT_INDEFINITE_WAIT); if (RT_FAILURE(rc)) { ASMAtomicIncU32(&g_cErrors); RTPrintf("tstSemPingPong: ERROR - RTSemPongWait -> %Rrc\n", rc); break; } if (!RTSemPongIsSpeaker(pPP)) { ASMAtomicIncU32(&g_cErrors); RTPrintf("tstSemPingPong: ERROR - RTSemPongIsSpeaker returned false before RTSemPong.\n"); } rc = RTSemPong(pPP); if (RT_FAILURE(rc)) { ASMAtomicIncU32(&g_cErrors); RTPrintf("tstSemPingPong: ERROR - RTSemPong -> %Rrc\n", rc); break; } } return rc; }