VirtualBox

Changeset 45006 in vbox


Ignore:
Timestamp:
Mar 12, 2013 2:58:51 PM (12 years ago)
Author:
vboxsync
Message:

DBGF/DBGC: Fixing power off problems.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/dbgf.h

    r44896 r45006  
    180180     */
    181181    DBGFEVENT_DEV_STOP,
    182     /** The VM is terminating.
     182    /** The VM is powering off.
    183183     * When this notification is received, the debugger thread should detach ASAP.
    184184     */
    185     DBGFEVENT_TERMINATING,
     185    DBGFEVENT_POWERING_OFF,
    186186
    187187    /** The usual 32-bit hack. */
     
    284284VMMR3_INT_DECL(int)     DBGFR3Init(PVM pVM);
    285285VMMR3_INT_DECL(int)     DBGFR3Term(PVM pVM);
     286VMMR3_INT_DECL(void)    DBGFR3PowerOff(PVM pVM);
    286287VMMR3_INT_DECL(void)    DBGFR3Relocate(PVM pVM, RTGCINTPTR offDelta);
    287288VMMR3_INT_DECL(int)     DBGFR3VMMForcedAction(PVM pVM);
     
    300301VMMR3DECL(int)          DBGFR3Halt(PUVM pUVM);
    301302VMMR3DECL(bool)         DBGFR3IsHalted(PUVM pUVM);
    302 VMMR3DECL(bool)         DBGFR3CanWait(PUVM pUVM);
     303VMMR3DECL(int)          DBGFR3QueryWaitable(PUVM pUVM);
    303304VMMR3DECL(int)          DBGFR3Resume(PUVM pUVM);
    304305VMMR3DECL(int)          DBGFR3Step(PUVM pUVM, VMCPUID idCpu);
  • trunk/src/VBox/Debugger/DBGConsole.cpp

    r44399 r45006  
    738738        }
    739739
    740         case DBGFEVENT_TERMINATING:
     740        case DBGFEVENT_POWERING_OFF:
    741741        {
    742742            pDbgc->fReady = false;
    743743            pDbgc->pBack->pfnSetReady(pDbgc->pBack, false);
    744             pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\nVM is terminating!\n");
     744            pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\nVM is powering off!\n");
    745745            fPrintPrompt = false;
    746746            rc = VERR_GENERAL_FAILURE;
     
    808808     * before we must flush the log.
    809809     */
    810     int rc = VINF_SUCCESS;
     810    int rc;
    811811    for (;;)
    812812    {
    813         if (    pDbgc->pUVM
    814             &&  DBGFR3CanWait(pDbgc->pUVM))
     813        rc = VERR_SEM_OUT_OF_TURN;
     814        if (pDbgc->pUVM)
     815            rc = DBGFR3QueryWaitable(pDbgc->pUVM);
     816
     817        if (RT_SUCCESS(rc))
    815818        {
    816819            /*
     
    838841            }
    839842        }
    840         else
     843        else if (rc == VERR_SEM_OUT_OF_TURN)
    841844        {
    842845            /*
     
    850853            }
    851854        }
     855        else
     856            break;
    852857
    853858        /*
  • trunk/src/VBox/Debugger/testcase/tstDBGCStubs.cpp

    r44528 r45006  
    8181    return VERR_INTERNAL_ERROR;
    8282}
    83 VMMR3DECL(bool) DBGFR3CanWait(PUVM pUVM)
    84 {
    85     return true;
     83VMMR3DECL(int) DBGFR3QueryWaitable(PUVM pUVM)
     84{
     85    return VINF_SUCCESS;
    8686}
    8787VMMR3DECL(int) DBGFR3Detach(PUVM pUVM)
  • trunk/src/VBox/VMM/VMMR3/DBGF.cpp

    r44528 r45006  
    165165{
    166166    PUVM pUVM = pVM->pUVM;
    167     int rc;
    168 
    169     /*
    170      * Send a termination event to any attached debugger.
    171      */
    172     /* wait to become the speaker (we should already be that). */
    173     if (    pVM->dbgf.s.fAttached
    174         &&  RTSemPingShouldWait(&pVM->dbgf.s.PingPong))
    175         RTSemPingWait(&pVM->dbgf.s.PingPong, 5000);
    176 
    177     /* now, send the event if we're the speaker. */
    178     if (    pVM->dbgf.s.fAttached
    179         &&  RTSemPingIsSpeaker(&pVM->dbgf.s.PingPong))
    180     {
    181         DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
    182         if (enmCmd == DBGFCMD_DETACH_DEBUGGER)
    183             /* the debugger beat us to initiating the detaching. */
    184             rc = VINF_SUCCESS;
    185         else
    186         {
    187             /* ignore the command (if any). */
    188             enmCmd = DBGFCMD_NO_COMMAND;
    189             pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_TERMINATING;
    190             pVM->dbgf.s.DbgEvent.enmCtx  = DBGFEVENTCTX_OTHER;
    191             rc = RTSemPing(&pVM->dbgf.s.PingPong);
    192         }
    193 
    194         /*
    195          * Process commands until we get a detached command.
    196          */
    197         while (RT_SUCCESS(rc) && enmCmd != DBGFCMD_DETACHED_DEBUGGER)
    198         {
    199             if (enmCmd != DBGFCMD_NO_COMMAND)
    200             {
    201                 /* process command */
    202                 bool fResumeExecution;
    203                 DBGFCMDDATA CmdData = pVM->dbgf.s.VMMCmdData;
    204                 rc = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
    205                 enmCmd = DBGFCMD_NO_COMMAND;
    206             }
    207             else
    208             {
    209                 /* wait for new command. */
    210                 rc = RTSemPingWait(&pVM->dbgf.s.PingPong, RT_INDEFINITE_WAIT);
    211                 if (RT_SUCCESS(rc))
    212                     enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
    213             }
    214         }
    215     }
    216 
    217     /*
    218      * Terminate the other bits.
    219      */
     167
    220168    dbgfR3OSTerm(pUVM);
    221169    dbgfR3AsTerm(pUVM);
     
    223171    dbgfR3TraceTerm(pVM);
    224172    dbgfR3InfoTerm(pUVM);
     173
    225174    return VINF_SUCCESS;
     175}
     176
     177
     178/**
     179 * Called when the VM is powered off to detach debuggers.
     180 *
     181 * @param   pVM     The VM handle.
     182 */
     183VMMR3_INT_DECL(void) DBGFR3PowerOff(PVM pVM)
     184{
     185
     186    /*
     187     * Send a termination event to any attached debugger.
     188     */
     189    /* wait to become the speaker (we should already be that). */
     190    if (    pVM->dbgf.s.fAttached
     191        &&  RTSemPingShouldWait(&pVM->dbgf.s.PingPong))
     192        RTSemPingWait(&pVM->dbgf.s.PingPong, 5000);
     193
     194    if (pVM->dbgf.s.fAttached)
     195    {
     196        /* Just mark it as detached if we're not in a position to send a power
     197           off event.  It should fail later on. */
     198        if (!RTSemPingIsSpeaker(&pVM->dbgf.s.PingPong))
     199        {
     200            ASMAtomicWriteBool(&pVM->dbgf.s.fAttached, false);
     201            if (RTSemPingIsSpeaker(&pVM->dbgf.s.PingPong))
     202                ASMAtomicWriteBool(&pVM->dbgf.s.fAttached, true);
     203        }
     204
     205        if (RTSemPingIsSpeaker(&pVM->dbgf.s.PingPong))
     206        {
     207            /* Try send the power off event. */
     208            int rc;
     209            DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
     210            if (enmCmd == DBGFCMD_DETACH_DEBUGGER)
     211                /* the debugger beat us to initiating the detaching. */
     212                rc = VINF_SUCCESS;
     213            else
     214            {
     215                /* ignore the command (if any). */
     216                enmCmd = DBGFCMD_NO_COMMAND;
     217                pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_POWERING_OFF;
     218                pVM->dbgf.s.DbgEvent.enmCtx  = DBGFEVENTCTX_OTHER;
     219                rc = RTSemPing(&pVM->dbgf.s.PingPong);
     220            }
     221
     222            /*
     223             * Process commands and priority requests until we get a command
     224             * indicating that the debugger has detached.
     225             */
     226            uint32_t cPollHack = 1;
     227            PVMCPU   pVCpu     = VMMGetCpu(pVM);
     228            while (RT_SUCCESS(rc))
     229            {
     230                if (enmCmd != DBGFCMD_NO_COMMAND)
     231                {
     232                    /* process command */
     233                    bool fResumeExecution;
     234                    DBGFCMDDATA CmdData = pVM->dbgf.s.VMMCmdData;
     235                    rc = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
     236                    if (enmCmd == DBGFCMD_DETACHED_DEBUGGER)
     237                        break;
     238                    enmCmd = DBGFCMD_NO_COMMAND;
     239                }
     240                else
     241                {
     242                    /* Wait for new command, processing pending priority requests
     243                       first.  The request processing is a bit crazy, but
     244                       unfortunately required by plugin unloading. */
     245                    if (   VM_FF_ISPENDING(pVM, VM_FF_REQUEST)
     246                        || VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_REQUEST))
     247                    {
     248                        LogFlow(("DBGFR3PowerOff: Processes priority requests...\n"));
     249                        rc = VMR3ReqProcessU(pVM->pUVM, VMCPUID_ANY, true /*fPriorityOnly*/);
     250                        if (rc == VINF_SUCCESS)
     251                            rc = VMR3ReqProcessU(pVM->pUVM, pVCpu->idCpu, true /*fPriorityOnly*/);
     252                        LogFlow(("DBGFR3PowerOff: VMR3ReqProcess -> %Rrc\n", rc));
     253                        cPollHack = 1;
     254                    }
     255                    else if (cPollHack < 120)
     256                        cPollHack++;
     257
     258                    rc = RTSemPingWait(&pVM->dbgf.s.PingPong, cPollHack);
     259                    if (RT_SUCCESS(rc))
     260                        enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
     261                    else if (rc == VERR_TIMEOUT)
     262                        rc = VINF_SUCCESS;
     263                }
     264            }
     265
     266            /*
     267             * Clear the FF so we won't get confused later on.
     268             */
     269            VM_FF_CLEAR(pVM, VM_FF_DBGF);
     270        }
     271    }
    226272}
    227273
     
    869915VMMR3DECL(int) DBGFR3Attach(PUVM pUVM)
    870916{
    871     UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
     917    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
    872918    PVM pVM = pUVM->pVM;
    873     VM_ASSERT_VALID_EXT_RETURN(pVM, false);
     919    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    874920
    875921    /*
     
    925971     * Check if attached.
    926972     */
    927     UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
     973    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
    928974    PVM pVM = pUVM->pVM;
    929     VM_ASSERT_VALID_EXT_RETURN(pVM, false);
     975    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    930976    AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
    931977
     
    9731019     * Check state.
    9741020     */
    975     UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
     1021    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
    9761022    PVM pVM = pUVM->pVM;
    977     VM_ASSERT_VALID_EXT_RETURN(pVM, false);
     1023    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    9781024    AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
    9791025    *ppEvent = NULL;
     
    10081054     * Check state.
    10091055     */
    1010     UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
     1056    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
    10111057    PVM pVM = pUVM->pVM;
    1012     VM_ASSERT_VALID_EXT_RETURN(pVM, false);
     1058    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    10131059    AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
    10141060    RTPINGPONGSPEAKER enmSpeaker = pVM->dbgf.s.PingPong.enmSpeaker;
     
    10511097 * This function is only used by lazy, multiplexing debuggers. :-)
    10521098 *
    1053  * @returns True if waitable.
    1054  * @returns False if not waitable.
     1099 * @returns VBox status code.
     1100 * @retval  VINF_SUCCESS if waitable.
     1101 * @retval  VERR_SEM_OUT_OF_TURN if not waitable.
     1102 * @retval  VERR_INVALID_VM_HANDLE if the VM is being (/ has been) destroyed
     1103 *          (not asserted) or if the handle is invalid (asserted).
     1104 * @retval  VERR_DBGF_NOT_ATTACHED if not attached.
     1105 *
    10551106 * @param   pUVM        The user mode VM handle.
    10561107 */
    1057 VMMR3DECL(bool) DBGFR3CanWait(PUVM pUVM)
    1058 {
    1059     UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
     1108VMMR3DECL(int) DBGFR3QueryWaitable(PUVM pUVM)
     1109{
     1110    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
     1111
     1112    /* Note! There is a slight race here, unfortunately. */
    10601113    PVM pVM = pUVM->pVM;
    1061     VM_ASSERT_VALID_EXT_RETURN(pVM, false);
    1062     AssertReturn(pVM->dbgf.s.fAttached, false);
    1063 
    1064     return RTSemPongShouldWait(&pVM->dbgf.s.PingPong);
     1114    if (!RT_VALID_PTR(pVM))
     1115        return VERR_INVALID_VM_HANDLE;
     1116    if (pVM->enmVMState >= VMSTATE_DESTROYING)
     1117        return VERR_INVALID_VM_HANDLE;
     1118    AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
     1119
     1120    if (!RTSemPongShouldWait(&pVM->dbgf.s.PingPong))
     1121        return VERR_SEM_OUT_OF_TURN;
     1122
     1123    return VINF_SUCCESS;
    10651124}
    10661125
  • trunk/src/VBox/VMM/VMMR3/VM.cpp

    r44730 r45006  
    22572257         */
    22582258        PDMR3PowerOff(pVM);
     2259        DBGFR3PowerOff(pVM);
    22592260
    22602261        PUVM pUVM = pVM->pUVM;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette