VirtualBox

Changeset 46775 in vbox


Ignore:
Timestamp:
Jun 25, 2013 12:37:57 PM (11 years ago)
Author:
vboxsync
Message:

Main/Host(HostPower)+Session+Console: convert HostPower code to signal pause/resume/savestate through internal methods, conveying information why the method was called, preparing for VM/PDM passing this information to devices and drivers

Location:
trunk/src/VBox/Main
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r46667 r46775  
    1684716847  -->
    1684816848
     16849  <enum
     16850    name="Reason"
     16851    uuid="e7e8e097-299d-4e98-8bbc-c31c2d47d0cc"
     16852    >
     16853    <desc>
     16854      Internal event reason type.
     16855    </desc>
     16856
     16857    <const name="Unspecified"       value="0">
     16858      <desc>Null value, means "no known reason".</desc>
     16859    </const>
     16860    <const name="HostSuspend"       value="1">
     16861      <desc>Host is being suspended (power management event).</desc>
     16862    </const>
     16863    <const name="HostResume"        value="2">
     16864      <desc>Host is being resumed (power management event).</desc>
     16865    </const>
     16866    <const name="HostBatteryLow"    value="3">
     16867      <desc>Host is running low on battery (power management event).</desc>
     16868    </const>
     16869  </enum>
     16870
    1684916871  <interface
    1685016872    name="IInternalSessionControl" extends="$unknown"
    16851     uuid="0ba8d8b3-204b-448e-99c2-242eaa666ea8"
     16873    uuid="cddf451c-a006-4c33-8245-63b3c9ae6586"
    1685216874    internal="yes"
    1685316875    wsmap="suppress"
     
    1734517367      <param name="enable" type="boolean" dir="in">
    1734617368        <desc>True enables statistics collection.</desc>
     17369      </param>
     17370    </method>
     17371
     17372    <method name="pauseWithReason">
     17373      <desc>
     17374        Internal method for triggering a VM pause with a specified reason code.
     17375        The reason code can be interpreted by device/drivers and thus it might
     17376        behave slightly differently than a normal VM pause.
     17377
     17378        <result name="VBOX_E_INVALID_VM_STATE">
     17379          Virtual machine not in Running state.
     17380        </result>
     17381        <result name="VBOX_E_VM_ERROR">
     17382          Virtual machine error in suspend operation.
     17383        </result>
     17384        <see><link to="Console::pause"/></see>
     17385      </desc>
     17386
     17387      <param name="reason" type="Reason" dir="in">
     17388        <desc>Specify the best matching reason code please.</desc>
     17389      </param>
     17390    </method>
     17391
     17392    <method name="resumeWithReason">
     17393      <desc>
     17394        Internal method for triggering a VM resume with a specified reason code.
     17395        The reason code can be interpreted by device/drivers and thus it might
     17396        behave slightly differently than a normal VM resume.
     17397
     17398        <result name="VBOX_E_INVALID_VM_STATE">
     17399          Virtual machine not in Paused state.
     17400        </result>
     17401        <result name="VBOX_E_VM_ERROR">
     17402          Virtual machine error in resume operation.
     17403        </result>
     17404        <see><link to="Console::resume"/></see>
     17405      </desc>
     17406
     17407      <param name="reason" type="Reason" dir="in">
     17408        <desc>Specify the best matching reason code please.</desc>
     17409      </param>
     17410    </method>
     17411
     17412    <method name="saveStateWithReason">
     17413      <desc>
     17414        Internal method for triggering a VM save state with a specified reason
     17415        code. The reason code can be interpreted by device/drivers and thus it
     17416        might behave slightly differently than a normal VM save state.
     17417
     17418        <result name="VBOX_E_INVALID_VM_STATE">
     17419          Virtual machine state neither Running nor Paused.
     17420        </result>
     17421        <result name="VBOX_E_FILE_ERROR">
     17422          Failed to create directory for saved state file.
     17423        </result>
     17424        <see><link to="Console::saveState"/></see>
     17425      </desc>
     17426
     17427      <param name="reason" type="Reason" dir="in">
     17428        <desc>Specify the best matching reason code please.</desc>
     17429      </param>
     17430      <param name="progress" type="IProgress" dir="return">
     17431        <desc>Progress object to track the operation completion.</desc>
    1734717432      </param>
    1734817433    </method>
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r46465 r46775  
    258258    }
    259259    void enableVMMStatistics(BOOL aEnable);
     260
     261    HRESULT pause(Reason_T aReason);
     262    HRESULT resume(Reason_T aReason);
     263    HRESULT saveState(Reason_T aReason, IProgress **aProgress);
    260264
    261265    // callback callers (partly; for some events console callbacks are notified
  • trunk/src/VBox/Main/include/Global.h

    r39248 r46775  
    194194
    195195    /**
     196     * Stringify a reason.
     197     *
     198     * @returns Pointer to a read only string.
     199     * @param   aReason     The reason code.
     200     */
     201    static const char *stringifyReason(Reason_T aReason);
     202
     203    /**
    196204     * Try convert a COM status code to a VirtualBox status code (VBox/err.h).
    197205     *
  • trunk/src/VBox/Main/include/HostPower.h

    r44528 r46775  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2020
    2121#include "VirtualBoxBase.h"
    22 #include "MachineImpl.h"
    2322
    2423#include <vector>
     
    2928#endif /* RT_OS_DARWIN */
    3029
    31 typedef enum
    32 {
    33     HostPowerEvent_Suspend,
    34     HostPowerEvent_Resume,
    35     HostPowerEvent_BatteryLow
    36 } HostPowerEvent;
    37 
    3830class HostPowerService
    3931{
    4032public:
    4133
    42     HostPowerService (VirtualBox *aVirtualBox);
     34    HostPowerService(VirtualBox *aVirtualBox);
    4335    virtual ~HostPowerService();
    4436
    45     void    notify (HostPowerEvent aEvent);
     37    void notify(Reason_T aReason);
    4638
    4739protected:
    4840
    49     VirtualBox              *mVirtualBox;
     41    VirtualBox *mVirtualBox;
    5042
    51     std::vector< ComPtr<IConsole> > mConsoles;
     43    std::vector<ComPtr<IInternalSessionControl> > mSessionControls;
    5244};
    5345
     
    6557private:
    6658
    67     static DECLCALLBACK(int) NotificationThread (RTTHREAD ThreadSelf, void *pInstance);
     59    static DECLCALLBACK(int) NotificationThread(RTTHREAD ThreadSelf, void *pInstance);
    6860    static LRESULT CALLBACK  WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    6961
     
    7971public:
    8072
    81     HostPowerServiceDarwin (VirtualBox *aVirtualBox);
     73    HostPowerServiceDarwin(VirtualBox *aVirtualBox);
    8274    virtual ~HostPowerServiceDarwin();
    8375
    8476private:
    8577
    86     static DECLCALLBACK(int) powerChangeNotificationThread (RTTHREAD ThreadSelf, void *pInstance);
    87     static void powerChangeNotificationHandler (void *pvData, io_service_t service, natural_t messageType, void *pMessageArgument);
    88     static void lowPowerHandler (void *pvData);
     78    static DECLCALLBACK(int) powerChangeNotificationThread(RTTHREAD ThreadSelf, void *pInstance);
     79    static void powerChangeNotificationHandler(void *pvData, io_service_t service, natural_t messageType, void *pMessageArgument);
     80    static void lowPowerHandler(void *pvData);
    8981
    90     void checkBatteryCriticalLevel (bool *pfCriticalChanged = NULL);
     82    void checkBatteryCriticalLevel(bool *pfCriticalChanged = NULL);
    9183
    9284    /* Private member vars */
  • trunk/src/VBox/Main/include/SessionImpl.h

    r46465 r46775  
    55
    66/*
    7  * Copyright (C) 2006-2012 Oracle Corporation
     7 * Copyright (C) 2006-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    117117                                 IProgress *aProgress);
    118118    STDMETHOD(EnableVMMStatistics)(BOOL aEnable);
     119    STDMETHOD(PauseWithReason)(Reason_T aReason);
     120    STDMETHOD(ResumeWithReason)(Reason_T aReason);
     121    STDMETHOD(SaveStateWithReason)(Reason_T aReason, IProgress **aProgress);
    119122
    120123private:
  • trunk/src/VBox/Main/src-all/Global.cpp

    r46350 r46775  
    451451}
    452452
     453
     454/*static*/ const char *
     455Global::stringifyReason(Reason_T aReason)
     456{
     457    switch (aReason)
     458    {
     459        case Reason_Unspecified:      return "unspecified";
     460        case Reason_HostSuspend:      return "host suspend";
     461        case Reason_HostResume:       return "host resume";
     462        case Reason_HostBatteryLow:   return "host battery low";
     463        default:
     464        {
     465            AssertMsgFailed(("%d (%#x)\n", aReason, aReason));
     466            static char s_szMsg[48];
     467            RTStrPrintf(s_szMsg, sizeof(s_szMsg), "invalid reason %#010x\n", aReason);
     468            return s_szMsg;
     469        }
     470    }
     471}
     472
    453473/*static*/ int
    454474Global::vboxStatusCodeFromCOM(HRESULT aComStatus)
  • trunk/src/VBox/Main/src-client/ConsoleImpl.cpp

    r46610 r46775  
    263263               const ComPtr<IProgress> &aServerProgress,
    264264               const Utf8Str &aSavedStateFile,
    265                MachineState_T aMachineStateBefore)
     265               MachineState_T aMachineStateBefore,
     266               Reason_T aReason)
    266267        : VMTask(aConsole, NULL /* aProgress */, aServerProgress,
    267268                 true /* aUsesVMPtr */),
    268269          mSavedStateFile(aSavedStateFile),
    269           mMachineStateBefore(aMachineStateBefore)
     270          mMachineStateBefore(aMachineStateBefore),
     271          mReason(aReason)
    270272    {}
    271273
     
    273275    /* The local machine state we had before. Required if something fails */
    274276    MachineState_T mMachineStateBefore;
     277    /* The reason for saving state */
     278    Reason_T mReason;
    275279};
    276280
     
    20742078{
    20752079    LogFlowThisFuncEnter();
    2076     LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
    20772080
    20782081    CheckComArgOutPointerValid(aProgress);
     
    20832086    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    20842087
     2088    LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
    20852089    switch (mMachineState)
    20862090    {
     
    22062210{
    22072211    LogFlowThisFuncEnter();
    2208     LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
    22092212
    22102213    AutoCaller autoCaller(this);
     
    22132216    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    22142217
     2218    LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
    22152219    if (   mMachineState != MachineState_Running
    22162220        && mMachineState != MachineState_Teleporting
     
    22572261
    22582262    LogFlowThisFuncEnter();
    2259     LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
    22602263
    22612264    AutoCaller autoCaller(this);
     
    22642267    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    22652268
     2269    LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
    22662270    AssertReturn(m_pVMMDev, E_FAIL);
    22672271    PPDMIVMMDEVPORT pVmmDevPort = m_pVMMDev->getVMMDevPort();
     
    24012405
    24022406    LogFlowThisFuncEnter();
    2403     LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
    24042407
    24052408    AutoCaller autoCaller(this);
     
    24082411    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    24092412
     2413    LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
    24102414    if (   mMachineState != MachineState_Running
    24112415        && mMachineState != MachineState_Teleporting
     
    24742478    LogFlowThisFuncEnter();
    24752479
    2476     AutoCaller autoCaller(this);
    2477     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    2478 
    2479     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2480 
    2481     switch (mMachineState)
    2482     {
    2483         case MachineState_Running:
    2484         case MachineState_Teleporting:
    2485         case MachineState_LiveSnapshotting:
    2486             break;
    2487 
    2488         case MachineState_Paused:
    2489         case MachineState_TeleportingPausedVM:
    2490         case MachineState_Saving:
    2491             return setError(VBOX_E_INVALID_VM_STATE, tr("Already paused"));
    2492 
    2493         default:
    2494             return setInvalidMachineStateError();
    2495     }
    2496 
    2497     /* get the VM handle. */
    2498     SafeVMPtr ptrVM(this);
    2499     if (!ptrVM.isOk())
    2500         return ptrVM.rc();
    2501 
    2502     LogFlowThisFunc(("Sending PAUSE request...\n"));
    2503 
    2504     /* release the lock before a VMR3* call (EMT will call us back)! */
    2505     alock.release();
    2506 
    2507     int vrc = VMR3Suspend(ptrVM.rawUVM());
    2508 
    2509     HRESULT hrc = S_OK;
    2510     if (RT_FAILURE(vrc))
    2511         hrc = setError(VBOX_E_VM_ERROR, tr("Could not suspend the machine execution (%Rrc)"), vrc);
    2512 
    2513     LogFlowThisFunc(("hrc=%Rhrc\n", hrc));
     2480    HRESULT rc = pause(Reason_Unspecified);
     2481
     2482    LogFlowThisFunc(("rc=%Rhrc\n", rc));
    25142483    LogFlowThisFuncLeave();
    2515     return hrc;
     2484    return rc;
    25162485}
    25172486
     
    25202489    LogFlowThisFuncEnter();
    25212490
    2522     AutoCaller autoCaller(this);
    2523     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    2524 
    2525     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2526 
    2527     if (mMachineState != MachineState_Paused)
    2528         return setError(VBOX_E_INVALID_VM_STATE,
    2529                         tr("Cannot resume the machine as it is not paused (machine state: %s)"),
    2530                         Global::stringifyMachineState(mMachineState));
    2531 
    2532     /* get the VM handle. */
    2533     SafeVMPtr ptrVM(this);
    2534     if (!ptrVM.isOk())
    2535         return ptrVM.rc();
    2536 
    2537     LogFlowThisFunc(("Sending RESUME request...\n"));
    2538 
    2539     /* release the lock before a VMR3* call (EMT will call us back)! */
    2540     alock.release();
    2541 
    2542 #ifdef VBOX_WITH_EXTPACK
    2543     int vrc = mptrExtPackManager->callAllVmPowerOnHooks(this, VMR3GetVM(ptrVM.rawUVM())); /** @todo called a few times too many... */
    2544 #else
    2545     int vrc = VINF_SUCCESS;
    2546 #endif
    2547     if (RT_SUCCESS(vrc))
    2548     {
    2549         if (VMR3GetStateU(ptrVM.rawUVM()) == VMSTATE_CREATED)
    2550             vrc = VMR3PowerOn(ptrVM.rawUVM()); /* (PowerUpPaused) */
    2551         else
    2552             vrc = VMR3Resume(ptrVM.rawUVM());
    2553     }
    2554 
    2555     HRESULT rc = RT_SUCCESS(vrc) ? S_OK :
    2556         setError(VBOX_E_VM_ERROR,
    2557                  tr("Could not resume the machine execution (%Rrc)"),
    2558                  vrc);
     2491    HRESULT rc = resume(Reason_Unspecified);
    25592492
    25602493    LogFlowThisFunc(("rc=%Rhrc\n", rc));
     
    27572690{
    27582691    LogFlowThisFuncEnter();
    2759     LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
    2760 
    2761     CheckComArgOutPointerValid(aProgress);
    2762 
    2763     AutoCaller autoCaller(this);
    2764     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    2765 
    2766     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2767 
    2768     if (   mMachineState != MachineState_Running
    2769         && mMachineState != MachineState_Paused)
    2770     {
    2771         return setError(VBOX_E_INVALID_VM_STATE,
    2772             tr("Cannot save the execution state as the machine is not running or paused (machine state: %s)"),
    2773             Global::stringifyMachineState(mMachineState));
    2774     }
    2775 
    2776     /* memorize the current machine state */
    2777     MachineState_T lastMachineState = mMachineState;
    2778 
    2779     if (mMachineState == MachineState_Running)
    2780     {
    2781         /* get the VM handle. */
    2782         SafeVMPtr ptrVM(this);
    2783         if (!ptrVM.isOk())
    2784             return ptrVM.rc();
    2785 
    2786         /* release the lock before a VMR3* call (EMT will call us back)! */
    2787         alock.release();
    2788         int vrc = VMR3Suspend(ptrVM.rawUVM());
    2789         alock.acquire();
    2790 
    2791         HRESULT hrc = S_OK;
    2792         if (RT_FAILURE(vrc))
    2793             hrc = setError(VBOX_E_VM_ERROR, tr("Could not suspend the machine execution (%Rrc)"), vrc);
    2794         if (FAILED(hrc))
    2795             return hrc;
    2796     }
    2797 
    2798     HRESULT rc = S_OK;
    2799     bool fBeganSavingState = false;
    2800     bool fTaskCreationFailed = false;
    2801 
    2802     do
    2803     {
    2804         ComPtr<IProgress> pProgress;
    2805         Bstr stateFilePath;
    2806 
    2807         /*
    2808          * request a saved state file path from the server
    2809          * (this will set the machine state to Saving on the server to block
    2810          * others from accessing this machine)
    2811          */
    2812         rc = mControl->BeginSavingState(pProgress.asOutParam(),
    2813                                         stateFilePath.asOutParam());
    2814         if (FAILED(rc))
    2815             break;
    2816 
    2817         fBeganSavingState = true;
    2818 
    2819         /* sync the state with the server */
    2820         setMachineStateLocally(MachineState_Saving);
    2821 
    2822         /* ensure the directory for the saved state file exists */
    2823         {
    2824             Utf8Str dir = stateFilePath;
    2825             dir.stripFilename();
    2826             if (!RTDirExists(dir.c_str()))
    2827             {
    2828                 int vrc = RTDirCreateFullPath(dir.c_str(), 0700);
    2829                 if (RT_FAILURE(vrc))
    2830                 {
    2831                     rc = setError(VBOX_E_FILE_ERROR,
    2832                         tr("Could not create a directory '%s' to save the state to (%Rrc)"),
    2833                         dir.c_str(), vrc);
    2834                     break;
    2835                 }
    2836             }
    2837         }
    2838 
    2839         /* Create a task object early to ensure mpUVM protection is successful. */
    2840         std::auto_ptr<VMSaveTask> task(new VMSaveTask(this, pProgress,
    2841                                                       stateFilePath,
    2842                                                       lastMachineState));
    2843         rc = task->rc();
    2844         /*
    2845          * If we fail here it means a PowerDown() call happened on another
    2846          * thread while we were doing Pause() (which releases the Console lock).
    2847          * We assign PowerDown() a higher precedence than SaveState(),
    2848          * therefore just return the error to the caller.
    2849          */
    2850         if (FAILED(rc))
    2851         {
    2852             fTaskCreationFailed = true;
    2853             break;
    2854         }
    2855 
    2856         /* create a thread to wait until the VM state is saved */
    2857         int vrc = RTThreadCreate(NULL, Console::saveStateThread, (void *)task.get(),
    2858                                  0, RTTHREADTYPE_MAIN_WORKER, 0, "VMSave");
    2859         if (RT_FAILURE(vrc))
    2860         {
    2861             rc = setError(E_FAIL, "Could not create VMSave thread (%Rrc)", vrc);
    2862             break;
    2863         }
    2864 
    2865         /* task is now owned by saveStateThread(), so release it */
    2866         task.release();
    2867 
    2868         /* return the progress to the caller */
    2869         pProgress.queryInterfaceTo(aProgress);
    2870     } while (0);
    2871 
    2872     if (FAILED(rc) && !fTaskCreationFailed)
    2873     {
    2874         /* preserve existing error info */
    2875         ErrorInfoKeeper eik;
    2876 
    2877         if (fBeganSavingState)
    2878         {
    2879             /*
    2880              * cancel the requested save state procedure.
    2881              * This will reset the machine state to the state it had right
    2882              * before calling mControl->BeginSavingState().
    2883              */
    2884             mControl->EndSavingState(eik.getResultCode(), eik.getText().raw());
    2885         }
    2886 
    2887         if (lastMachineState == MachineState_Running)
    2888         {
    2889             /* restore the paused state if appropriate */
    2890             setMachineStateLocally(MachineState_Paused);
    2891             /* restore the running state if appropriate */
    2892             SafeVMPtr ptrVM(this);
    2893             if (ptrVM.isOk())
    2894             {
    2895                 alock.release();
    2896                 VMR3Resume(ptrVM.rawUVM());
    2897                 alock.acquire();
    2898             }
    2899         }
    2900         else
    2901             setMachineStateLocally(lastMachineState);
    2902     }
     2692
     2693    HRESULT rc = saveState(Reason_Unspecified, aProgress);
    29032694
    29042695    LogFlowThisFunc(("rc=%Rhrc\n", rc));
     
    33613152{
    33623153    LogFlowThisFuncEnter();
    3363     LogFlowThisFunc(("aName='%ls' mMachineState=%d\n", aName, mMachineState));
    33643154
    33653155    CheckComArgStrNotEmptyOrNull(aName);
     
    33703160
    33713161    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     3162    LogFlowThisFunc(("aName='%ls' mMachineState=%d\n", aName, mMachineState));
    33723163
    33733164    if (Global::IsTransient(mMachineState))
     
    59215712
    59225713/**
     5714 * Worker for Console::Pause and internal entry point for pausing a VM for
     5715 * a specific reason.
     5716 */
     5717HRESULT Console::pause(Reason_T aReason)
     5718{
     5719    LogFlowThisFuncEnter();
     5720
     5721    AutoCaller autoCaller(this);
     5722    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     5723
     5724    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     5725
     5726    switch (mMachineState)
     5727    {
     5728        case MachineState_Running:
     5729        case MachineState_Teleporting:
     5730        case MachineState_LiveSnapshotting:
     5731            break;
     5732
     5733        case MachineState_Paused:
     5734        case MachineState_TeleportingPausedVM:
     5735        case MachineState_Saving:
     5736            return setError(VBOX_E_INVALID_VM_STATE, tr("Already paused"));
     5737
     5738        default:
     5739            return setInvalidMachineStateError();
     5740    }
     5741
     5742    /* get the VM handle. */
     5743    SafeVMPtr ptrVM(this);
     5744    if (!ptrVM.isOk())
     5745        return ptrVM.rc();
     5746
     5747    /* release the lock before a VMR3* call (EMT will call us back)! */
     5748    alock.release();
     5749
     5750    LogFlowThisFunc(("Sending PAUSE request...\n"));
     5751    if (aReason != Reason_Unspecified)
     5752        LogRel(("Pausing VM execution, reason \"%s\"\n", Global::stringifyReason(aReason)));
     5753
     5754    /** @todo r=klaus make use of aReason */
     5755    int vrc = VMR3Suspend(ptrVM.rawUVM());
     5756
     5757    HRESULT hrc = S_OK;
     5758    if (RT_FAILURE(vrc))
     5759        hrc = setError(VBOX_E_VM_ERROR, tr("Could not suspend the machine execution (%Rrc)"), vrc);
     5760
     5761    LogFlowThisFunc(("hrc=%Rhrc\n", hrc));
     5762    LogFlowThisFuncLeave();
     5763    return hrc;
     5764}
     5765
     5766/**
     5767 * Worker for Console::Resume and internal entry point for resuming a VM for
     5768 * a specific reason.
     5769 */
     5770HRESULT Console::resume(Reason_T aReason)
     5771{
     5772    LogFlowThisFuncEnter();
     5773
     5774    AutoCaller autoCaller(this);
     5775    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     5776
     5777    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     5778
     5779    if (mMachineState != MachineState_Paused)
     5780        return setError(VBOX_E_INVALID_VM_STATE,
     5781                        tr("Cannot resume the machine as it is not paused (machine state: %s)"),
     5782                        Global::stringifyMachineState(mMachineState));
     5783
     5784    /* get the VM handle. */
     5785    SafeVMPtr ptrVM(this);
     5786    if (!ptrVM.isOk())
     5787        return ptrVM.rc();
     5788
     5789    /* release the lock before a VMR3* call (EMT will call us back)! */
     5790    alock.release();
     5791
     5792    LogFlowThisFunc(("Sending RESUME request...\n"));
     5793    if (aReason != Reason_Unspecified)
     5794        LogRel(("Resuming VM execution, reason \"%s\"\n", Global::stringifyReason(aReason)));
     5795
     5796    /** @todo r=klaus make use of aReason */
     5797    int vrc;
     5798    if (VMR3GetStateU(ptrVM.rawUVM()) == VMSTATE_CREATED)
     5799    {
     5800#ifdef VBOX_WITH_EXTPACK
     5801        vrc = mptrExtPackManager->callAllVmPowerOnHooks(this, VMR3GetVM(ptrVM.rawUVM()));
     5802#else
     5803        vrc = VINF_SUCCESS;
     5804#endif
     5805        if (RT_SUCCESS(vrc))
     5806            vrc = VMR3PowerOn(ptrVM.rawUVM()); /* (PowerUpPaused) */
     5807    }
     5808    else
     5809        vrc = VMR3Resume(ptrVM.rawUVM());
     5810
     5811    HRESULT rc = RT_SUCCESS(vrc) ? S_OK :
     5812        setError(VBOX_E_VM_ERROR,
     5813                 tr("Could not resume the machine execution (%Rrc)"),
     5814                 vrc);
     5815
     5816    LogFlowThisFunc(("rc=%Rhrc\n", rc));
     5817    LogFlowThisFuncLeave();
     5818    return rc;
     5819}
     5820
     5821/**
     5822 * Worker for Console::SaveState and internal entry point for saving state of
     5823 * a VM for a specific reason.
     5824 */
     5825HRESULT Console::saveState(Reason_T aReason, IProgress **aProgress)
     5826{
     5827    LogFlowThisFuncEnter();
     5828
     5829    CheckComArgOutPointerValid(aProgress);
     5830
     5831    AutoCaller autoCaller(this);
     5832    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     5833
     5834    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     5835
     5836    LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
     5837    if (   mMachineState != MachineState_Running
     5838        && mMachineState != MachineState_Paused)
     5839    {
     5840        return setError(VBOX_E_INVALID_VM_STATE,
     5841            tr("Cannot save the execution state as the machine is not running or paused (machine state: %s)"),
     5842            Global::stringifyMachineState(mMachineState));
     5843    }
     5844
     5845    if (aReason != Reason_Unspecified)
     5846        LogRel(("Saving state of VM, reason \"%s\"\n", Global::stringifyReason(aReason)));
     5847
     5848    /* memorize the current machine state */
     5849    MachineState_T lastMachineState = mMachineState;
     5850
     5851    if (mMachineState == MachineState_Running)
     5852    {
     5853        /* get the VM handle. */
     5854        SafeVMPtr ptrVM(this);
     5855        if (!ptrVM.isOk())
     5856            return ptrVM.rc();
     5857
     5858        /* release the lock before a VMR3* call (EMT will call us back)! */
     5859        alock.release();
     5860        int vrc = VMR3Suspend(ptrVM.rawUVM());
     5861        alock.acquire();
     5862
     5863        HRESULT hrc = S_OK;
     5864        if (RT_FAILURE(vrc))
     5865            hrc = setError(VBOX_E_VM_ERROR, tr("Could not suspend the machine execution (%Rrc)"), vrc);
     5866        if (FAILED(hrc))
     5867            return hrc;
     5868    }
     5869
     5870    HRESULT rc = S_OK;
     5871    bool fBeganSavingState = false;
     5872    bool fTaskCreationFailed = false;
     5873
     5874    do
     5875    {
     5876        ComPtr<IProgress> pProgress;
     5877        Bstr stateFilePath;
     5878
     5879        /*
     5880         * request a saved state file path from the server
     5881         * (this will set the machine state to Saving on the server to block
     5882         * others from accessing this machine)
     5883         */
     5884        rc = mControl->BeginSavingState(pProgress.asOutParam(),
     5885                                        stateFilePath.asOutParam());
     5886        if (FAILED(rc))
     5887            break;
     5888
     5889        fBeganSavingState = true;
     5890
     5891        /* sync the state with the server */
     5892        setMachineStateLocally(MachineState_Saving);
     5893
     5894        /* ensure the directory for the saved state file exists */
     5895        {
     5896            Utf8Str dir = stateFilePath;
     5897            dir.stripFilename();
     5898            if (!RTDirExists(dir.c_str()))
     5899            {
     5900                int vrc = RTDirCreateFullPath(dir.c_str(), 0700);
     5901                if (RT_FAILURE(vrc))
     5902                {
     5903                    rc = setError(VBOX_E_FILE_ERROR,
     5904                        tr("Could not create a directory '%s' to save the state to (%Rrc)"),
     5905                        dir.c_str(), vrc);
     5906                    break;
     5907                }
     5908            }
     5909        }
     5910
     5911        /* Create a task object early to ensure mpUVM protection is successful. */
     5912        std::auto_ptr<VMSaveTask> task(new VMSaveTask(this, pProgress,
     5913                                                      stateFilePath,
     5914                                                      lastMachineState,
     5915                                                      aReason));
     5916        rc = task->rc();
     5917        /*
     5918         * If we fail here it means a PowerDown() call happened on another
     5919         * thread while we were doing Pause() (which releases the Console lock).
     5920         * We assign PowerDown() a higher precedence than SaveState(),
     5921         * therefore just return the error to the caller.
     5922         */
     5923        if (FAILED(rc))
     5924        {
     5925            fTaskCreationFailed = true;
     5926            break;
     5927        }
     5928
     5929        /* create a thread to wait until the VM state is saved */
     5930        int vrc = RTThreadCreate(NULL, Console::saveStateThread, (void *)task.get(),
     5931                                 0, RTTHREADTYPE_MAIN_WORKER, 0, "VMSave");
     5932        if (RT_FAILURE(vrc))
     5933        {
     5934            rc = setError(E_FAIL, "Could not create VMSave thread (%Rrc)", vrc);
     5935            break;
     5936        }
     5937
     5938        /* task is now owned by saveStateThread(), so release it */
     5939        task.release();
     5940
     5941        /* return the progress to the caller */
     5942        pProgress.queryInterfaceTo(aProgress);
     5943    } while (0);
     5944
     5945    if (FAILED(rc) && !fTaskCreationFailed)
     5946    {
     5947        /* preserve existing error info */
     5948        ErrorInfoKeeper eik;
     5949
     5950        if (fBeganSavingState)
     5951        {
     5952            /*
     5953             * cancel the requested save state procedure.
     5954             * This will reset the machine state to the state it had right
     5955             * before calling mControl->BeginSavingState().
     5956             */
     5957            mControl->EndSavingState(eik.getResultCode(), eik.getText().raw());
     5958        }
     5959
     5960        if (lastMachineState == MachineState_Running)
     5961        {
     5962            /* restore the paused state if appropriate */
     5963            setMachineStateLocally(MachineState_Paused);
     5964            /* restore the running state if appropriate */
     5965            SafeVMPtr ptrVM(this);
     5966            if (ptrVM.isOk())
     5967            {
     5968                alock.release();
     5969                VMR3Resume(ptrVM.rawUVM());
     5970                alock.acquire();
     5971            }
     5972        }
     5973        else
     5974            setMachineStateLocally(lastMachineState);
     5975    }
     5976
     5977    LogFlowThisFunc(("rc=%Rhrc\n", rc));
     5978    LogFlowThisFuncLeave();
     5979    return rc;
     5980}
     5981
     5982/**
    59235983 * Gets called by Session::UpdateMachineState()
    59245984 * (IInternalSessionControl::updateMachineState()).
     
    63916451
    63926452    LogFlowThisFuncEnter();
    6393     LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
    63946453
    63956454    CheckComArgOutPointerValid(aProgress);
     
    64006459    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    64016460
     6461    LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
    64026462    HRESULT rc = S_OK;
    64036463    ComObjPtr<Progress> pPowerupProgress;
     
    96879747    LogFlowFunc(("Saving the state to '%s'...\n", task->mSavedStateFile.c_str()));
    96889748
     9749    /** @todo r=klaus make use of task->mReason */
    96899750    bool fSuspenededBySave;
    96909751    int vrc = VMR3Save(task->mpUVM,
  • trunk/src/VBox/Main/src-client/SessionImpl.cpp

    r46465 r46775  
    926926
    927927    return S_OK;
     928}
     929
     930STDMETHODIMP Session::PauseWithReason(Reason_T aReason)
     931{
     932    AutoCaller autoCaller(this);
     933    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
     934
     935    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     936    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
     937    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     938    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
     939
     940    return mConsole->pause(aReason);
     941}
     942
     943STDMETHODIMP Session::ResumeWithReason(Reason_T aReason)
     944{
     945    AutoCaller autoCaller(this);
     946    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
     947
     948    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     949    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
     950    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     951    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
     952
     953    return mConsole->resume(aReason);
     954}
     955
     956STDMETHODIMP Session::SaveStateWithReason(Reason_T aReason, IProgress **aProgress)
     957{
     958    AutoCaller autoCaller(this);
     959    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
     960
     961    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     962    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
     963    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     964    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
     965
     966    return mConsole->saveState(aReason, aProgress);
    928967}
    929968
  • trunk/src/VBox/Main/src-server/HostPower.cpp

    r44528 r46775  
    55
    66/*
    7  * Copyright (C) 2006-2011 Oracle Corporation
     7 * Copyright (C) 2006-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2727
    2828#include "VirtualBoxImpl.h"
     29#include "MachineImpl.h"
    2930
    3031#include <iprt/mem.h>
    3132
    32 HostPowerService::HostPowerService (VirtualBox *aVirtualBox)
     33HostPowerService::HostPowerService(VirtualBox *aVirtualBox)
    3334{
    3435    Assert(aVirtualBox != NULL);
     
    4041}
    4142
    42 void HostPowerService::notify(HostPowerEvent aEvent)
     43void HostPowerService::notify(Reason_T aReason)
    4344{
    4445    SessionMachinesList machines;
     
    4748    HRESULT rc = S_OK;
    4849
    49     switch (aEvent)
     50    switch (aReason)
    5051    {
    51         case HostPowerEvent_Suspend:
     52        case Reason_HostSuspend:
    5253        {
    53             LogFunc (("SUSPEND\n"));
     54            LogFunc(("SUSPEND\n"));
    5455
    5556#ifdef VBOX_WITH_RESOURCE_USAGE_API
     
    6970                ComPtr<IInternalSessionControl> pControl = *it;
    7071
    71                 /* get the remote console */
    72                 ComPtr<IConsole> console;
    73                 rc = pControl->GetRemoteConsole(console.asOutParam());
    74                 /* the VM could have been powered down and closed or whatever */
    75                 if (FAILED(rc))
    76                     continue;
    77 
    78                 /* note that Pause() will simply return a failure if the VM is
    79                  * in an inappropriate state */
    80                 rc = console->Pause();
     72                /* PauseWithReason() will simply return a failure if
     73                 * the VM is in an inappropriate state */
     74                rc = pControl->PauseWithReason(Reason_HostSuspend);
    8175                if (FAILED(rc))
    8276                    continue;
    8377
    8478                /* save the control to un-pause the VM later */
    85                 mConsoles.push_back(console);
     79                mSessionControls.push_back(pControl);
    8680            }
    8781
    88             LogFunc (("Suspended %d VMs\n", mConsoles.size()));
     82            LogFunc(("Suspended %d VMs\n", mSessionControls.size()));
    8983
    9084            break;
    9185        }
    9286
    93         case HostPowerEvent_Resume:
     87        case Reason_HostResume:
    9488        {
    95             LogFunc (("RESUME\n"));
     89            LogFunc(("RESUME\n"));
    9690
    9791            size_t resumed = 0;
    9892
    9993            /* go through VMs we paused on Suspend */
    100             for (size_t i = 0; i < mConsoles.size(); ++i)
     94            for (size_t i = 0; i < mSessionControls.size(); ++i)
    10195            {
    10296                /* note that Resume() will simply return a failure if the VM is
     
    10498                 * been somehow closed by this time already so that the
    10599                 * console reference we have is dead) */
    106                 rc = mConsoles[i]->Resume();
     100                rc = mSessionControls[i]->ResumeWithReason(Reason_HostResume);
    107101                if (FAILED(rc))
    108102                    continue;
    109103
    110                 ++ resumed;
     104                ++resumed;
    111105            }
    112106
    113             LogFunc (("Resumed %d VMs\n", resumed));
     107            LogFunc(("Resumed %d VMs\n", resumed));
    114108
    115109#ifdef VBOX_WITH_RESOURCE_USAGE_API
     
    121115#endif
    122116
    123             mConsoles.clear();
     117            mSessionControls.clear();
    124118
    125119            break;
    126120        }
    127121
    128         case HostPowerEvent_BatteryLow:
     122        case Reason_HostBatteryLow:
    129123        {
    130             LogFunc (("BATTERY LOW\n"));
     124            LogFunc(("BATTERY LOW\n"));
    131125
    132126            mVirtualBox->getOpenedMachines(machines, &controls);
     
    140134            {
    141135                ComPtr<IInternalSessionControl> pControl = *it;
    142                 /* get the remote console */
    143                 ComPtr<IConsole> console;
    144                 rc = pControl->GetRemoteConsole (console.asOutParam());
    145                 /* the VM could have been powered down and closed or whatever */
    146                 if (FAILED(rc))
    147                     continue;
    148136
    149137                ComPtr<IProgress> progress;
    150138
    151                 /* note that SaveState() will simply return a failure if the VM
    152                  * is in an inappropriate state */
    153                 rc = console->SaveState (progress.asOutParam());
     139                /* note that SaveStateWithReason() will simply return a failure
     140                 * if the VM is in an inappropriate state */
     141                rc = pControl->SaveStateWithReason(Reason_HostBatteryLow, progress.asOutParam());
    154142                if (FAILED(rc))
    155143                    continue;
     
    164152                }
    165153
    166                 AssertMsg (SUCCEEDED(rc), ("SaveState WaitForCompletion "
    167                                             "failed with %Rhrc (%#08X)\n", rc, rc));
     154                AssertMsg(SUCCEEDED(rc), ("SaveState WaitForCompletion failed with %Rhrc (%#08X)\n", rc, rc));
    168155
    169156                if (SUCCEEDED(rc))
    170                     ++ saved;
     157                    ++saved;
    171158            }
    172159
    173             LogFunc (("Saved %d VMs\n", saved));
     160            LogFunc(("Saved %d VMs\n", saved));
    174161
    175162            break;
    176163        }
     164
     165        default:
     166            /* nothing */;
    177167    }
    178168}
  • trunk/src/VBox/Main/src-server/darwin/HostPowerDarwin.cpp

    r44529 r46775  
    55
    66/*
    7  * Copyright (C) 2008-2010 Oracle Corporation
     7 * Copyright (C) 2008-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2626#define POWER_SOURCE_BATTERY 2
    2727
    28 HostPowerServiceDarwin::HostPowerServiceDarwin (VirtualBox *aVirtualBox)
    29   : HostPowerService (aVirtualBox)
    30   , mThread (NULL)
    31   , mRootPort (MACH_PORT_NULL)
    32   , mNotifyPort (nil)
    33   , mRunLoop (nil)
    34   , mCritical (false)
     28HostPowerServiceDarwin::HostPowerServiceDarwin(VirtualBox *aVirtualBox)
     29  : HostPowerService(aVirtualBox)
     30  , mThread(NULL)
     31  , mRootPort(MACH_PORT_NULL)
     32  , mNotifyPort(nil)
     33  , mRunLoop(nil)
     34  , mCritical(false)
    3535{
    3636    /* Create the new worker thread. */
    37     int rc = RTThreadCreate (&mThread, HostPowerServiceDarwin::powerChangeNotificationThread, this, 65536,
    38                              RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "MainPower");
     37    int rc = RTThreadCreate(&mThread, HostPowerServiceDarwin::powerChangeNotificationThread, this, 65536,
     38                            RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "MainPower");
    3939
    4040    if (RT_FAILURE(rc))
    41         LogFlow (("RTThreadCreate failed with %Rrc\n", rc));
     41        LogFlow(("RTThreadCreate failed with %Rrc\n", rc));
    4242}
    4343
     
    4545{
    4646    /* Jump out of the run loop. */
    47     CFRunLoopStop (mRunLoop);
     47    CFRunLoopStop(mRunLoop);
    4848    /* Remove the sleep notification port from the application runloop. */
    49     CFRunLoopRemoveSource (CFRunLoopGetCurrent(),
    50                            IONotificationPortGetRunLoopSource (mNotifyPort),
    51                            kCFRunLoopCommonModes);
     49    CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
     50                          IONotificationPortGetRunLoopSource(mNotifyPort),
     51                          kCFRunLoopCommonModes);
    5252    /* Deregister for system sleep notifications. */
    53     IODeregisterForSystemPower (&mNotifierObject);
     53    IODeregisterForSystemPower(&mNotifierObject);
    5454    /* IORegisterForSystemPower implicitly opens the Root Power Domain
    5555     * IOService so we close it here. */
    56     IOServiceClose (mRootPort);
     56    IOServiceClose(mRootPort);
    5757    /* Destroy the notification port allocated by IORegisterForSystemPower */
    58     IONotificationPortDestroy (mNotifyPort);
    59 }
    60 
    61 
    62 DECLCALLBACK(int) HostPowerServiceDarwin::powerChangeNotificationThread (RTTHREAD /* ThreadSelf */, void *pInstance)
    63 {
    64     HostPowerServiceDarwin *pPowerObj = static_cast<HostPowerServiceDarwin *> (pInstance);
     58    IONotificationPortDestroy(mNotifyPort);
     59}
     60
     61
     62DECLCALLBACK(int) HostPowerServiceDarwin::powerChangeNotificationThread(RTTHREAD /* ThreadSelf */, void *pInstance)
     63{
     64    HostPowerServiceDarwin *pPowerObj = static_cast<HostPowerServiceDarwin *>(pInstance);
    6565
    6666    /* We have to initial set the critical state of the battery, cause we want
     
    7070
    7171    /* Register to receive system sleep notifications */
    72     pPowerObj->mRootPort = IORegisterForSystemPower (pPowerObj, &pPowerObj->mNotifyPort,
    73                                                      HostPowerServiceDarwin::powerChangeNotificationHandler,
    74                                                      &pPowerObj->mNotifierObject);
     72    pPowerObj->mRootPort = IORegisterForSystemPower(pPowerObj, &pPowerObj->mNotifyPort,
     73                                                    HostPowerServiceDarwin::powerChangeNotificationHandler,
     74                                                    &pPowerObj->mNotifierObject);
    7575    if (pPowerObj->mRootPort == MACH_PORT_NULL)
    7676    {
    77         LogFlow (("IORegisterForSystemPower failed\n"));
     77        LogFlow(("IORegisterForSystemPower failed\n"));
    7878        return VERR_NOT_SUPPORTED;
    7979    }
    8080    pPowerObj->mRunLoop = CFRunLoopGetCurrent();
    8181    /* Add the notification port to the application runloop */
    82     CFRunLoopAddSource (pPowerObj->mRunLoop,
    83                         IONotificationPortGetRunLoopSource (pPowerObj->mNotifyPort),
    84                         kCFRunLoopCommonModes);
     82    CFRunLoopAddSource(pPowerObj->mRunLoop,
     83                       IONotificationPortGetRunLoopSource(pPowerObj->mNotifyPort),
     84                       kCFRunLoopCommonModes);
    8585
    8686    /* Register for all battery change events. The handler will check for low
     
    9797}
    9898
    99 void HostPowerServiceDarwin::powerChangeNotificationHandler (void *pvData, io_service_t /* service */, natural_t messageType, void *pMessageArgument)
    100 {
    101     HostPowerServiceDarwin *pPowerObj = static_cast<HostPowerServiceDarwin *> (pvData);
    102     Log (( "powerChangeNotificationHandler: messageType %08lx, arg %08lx\n", (long unsigned int)messageType, (long unsigned int)pMessageArgument));
     99void HostPowerServiceDarwin::powerChangeNotificationHandler(void *pvData, io_service_t /* service */, natural_t messageType, void *pMessageArgument)
     100{
     101    HostPowerServiceDarwin *pPowerObj = static_cast<HostPowerServiceDarwin *>(pvData);
     102    Log(( "powerChangeNotificationHandler: messageType %08lx, arg %08lx\n", (long unsigned int)messageType, (long unsigned int)pMessageArgument));
    103103
    104104    switch (messageType)
     
    114114                 * IOAllowPowerChange or IOCancelPowerChange, the system will
    115115                 * wait 30 seconds then go to sleep. */
    116                 IOAllowPowerChange (pPowerObj->mRootPort, reinterpret_cast<long> (pMessageArgument));
     116                IOAllowPowerChange(pPowerObj->mRootPort, reinterpret_cast<long>(pMessageArgument));
    117117                break;
    118118            }
     
    120120            {
    121121                /* The system will go for sleep. */
    122                 pPowerObj->notify (HostPowerEvent_Suspend);
     122                pPowerObj->notify(Reason_HostSuspend);
    123123                /* If you do not call IOAllowPowerChange or IOCancelPowerChange to
    124124                 * acknowledge this message, sleep will be delayed by 30 seconds.
    125125                 * NOTE: If you call IOCancelPowerChange to deny sleep it returns
    126126                 * kIOReturnSuccess, however the system WILL still go to sleep. */
    127                 IOAllowPowerChange (pPowerObj->mRootPort, reinterpret_cast<long> (pMessageArgument));
     127                IOAllowPowerChange(pPowerObj->mRootPort, reinterpret_cast<long>(pMessageArgument));
    128128                break;
    129129            }
     
    136136            {
    137137                /* System has finished the wake up process. */
    138                 pPowerObj->notify (HostPowerEvent_Resume);
     138                pPowerObj->notify(Reason_HostResume);
    139139                break;
    140140            }
     
    144144}
    145145
    146 void HostPowerServiceDarwin::lowPowerHandler (void *pvData)
    147 {
    148     HostPowerServiceDarwin *pPowerObj = static_cast<HostPowerServiceDarwin *> (pvData);
    149 
    150     /* Following role for sending the BatteryLow event (5% is critical):
     146void HostPowerServiceDarwin::lowPowerHandler(void *pvData)
     147{
     148    HostPowerServiceDarwin *pPowerObj = static_cast<HostPowerServiceDarwin *>(pvData);
     149
     150    /* Following role for sending the BatteryLow event(5% is critical):
    151151     * - Not at VM start even if the battery is in an critical state already.
    152152     * - When the power cord is removed so the power supply change from AC to
     
    157157     *   normal triggers nothing. */
    158158    bool fCriticalStateChanged = false;
    159     pPowerObj->checkBatteryCriticalLevel (&fCriticalStateChanged);
     159    pPowerObj->checkBatteryCriticalLevel(&fCriticalStateChanged);
    160160    if (fCriticalStateChanged)
    161         pPowerObj->notify (HostPowerEvent_BatteryLow);
    162 }
    163 
    164 void HostPowerServiceDarwin::checkBatteryCriticalLevel (bool *pfCriticalChanged)
     161        pPowerObj->notify(Reason_HostBatteryLow);
     162}
     163
     164void HostPowerServiceDarwin::checkBatteryCriticalLevel(bool *pfCriticalChanged)
    165165{
    166166    CFTypeRef pBlob = IOPSCopyPowerSourcesInfo();
    167     CFArrayRef pSources = IOPSCopyPowerSourcesList (pBlob);
     167    CFArrayRef pSources = IOPSCopyPowerSourcesList(pBlob);
    168168
    169169    CFDictionaryRef pSource = NULL;
     
    173173    bool critical = false;
    174174
    175     if (CFArrayGetCount (pSources) > 0)
     175    if (CFArrayGetCount(pSources) > 0)
    176176    {
    177         for (int i = 0; i < CFArrayGetCount (pSources); ++i)
     177        for (int i = 0; i < CFArrayGetCount(pSources); ++i)
    178178        {
    179             pSource = IOPSGetPowerSourceDescription (pBlob, CFArrayGetValueAtIndex (pSources, i));
     179            pSource = IOPSGetPowerSourceDescription(pBlob, CFArrayGetValueAtIndex(pSources, i));
    180180            /* If the source is empty skip over to the next one. */
    181181            if (!pSource)
     
    183183            /* Skip all power sources which are currently not present like a
    184184             * second battery. */
    185             if (CFDictionaryGetValue (pSource, CFSTR (kIOPSIsPresentKey)) == kCFBooleanFalse)
     185            if (CFDictionaryGetValue(pSource, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse)
    186186                continue;
    187187            /* Only internal power types are of interest. */
    188             result = CFDictionaryGetValueIfPresent (pSource, CFSTR (kIOPSTransportTypeKey), &psValue);
     188            result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTransportTypeKey), &psValue);
    189189            if (result &&
    190                 CFStringCompare ((CFStringRef)psValue, CFSTR (kIOPSInternalType), 0) == kCFCompareEqualTo)
     190                CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSInternalType), 0) == kCFCompareEqualTo)
    191191            {
    192192                /* First check which power source we are connect on. */
    193                 result = CFDictionaryGetValueIfPresent (pSource, CFSTR (kIOPSPowerSourceStateKey), &psValue);
     193                result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSPowerSourceStateKey), &psValue);
    194194                if (result &&
    195                     CFStringCompare ((CFStringRef)psValue, CFSTR (kIOPSACPowerValue), 0) == kCFCompareEqualTo)
     195                    CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo)
    196196                    powerSource = POWER_SOURCE_OUTLET;
    197197                else if (result &&
    198                          CFStringCompare ((CFStringRef)psValue, CFSTR (kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo)
     198                         CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo)
    199199                    powerSource = POWER_SOURCE_BATTERY;
    200200
     
    204204
    205205                /* Fetch the current capacity value of the power source */
    206                 result = CFDictionaryGetValueIfPresent (pSource, CFSTR (kIOPSCurrentCapacityKey), &psValue);
     206                result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSCurrentCapacityKey), &psValue);
    207207                if (result)
    208                     CFNumberGetValue ((CFNumberRef)psValue, kCFNumberSInt32Type, &curCapacity);
     208                    CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &curCapacity);
    209209                /* Fetch the maximum capacity value of the power source */
    210                 result = CFDictionaryGetValueIfPresent (pSource, CFSTR (kIOPSMaxCapacityKey), &psValue);
     210                result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSMaxCapacityKey), &psValue);
    211211                if (result)
    212                     CFNumberGetValue ((CFNumberRef)psValue, kCFNumberSInt32Type, &maxCapacity);
     212                    CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &maxCapacity);
    213213
    214214                /* Calculate the remaining capacity in percent */
     
    217217                /* Check for critical. 5 percent is default. */
    218218                int criticalValue = 5;
    219                 result = CFDictionaryGetValueIfPresent (pSource, CFSTR (kIOPSDeadWarnLevelKey), &psValue);
     219                result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSDeadWarnLevelKey), &psValue);
    220220                if (result)
    221                     CFNumberGetValue ((CFNumberRef)psValue, kCFNumberSInt32Type, &criticalValue);
     221                    CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &criticalValue);
    222222                critical = (remCapacity < criticalValue);
    223223                /* We have to take action only if we are on battery, the
     
    229229                    pfCriticalChanged)
    230230                    *pfCriticalChanged = true;
    231                 Log (("checkBatteryCriticalLevel: Remains: %d.%d%% Critical: %d Critical State Changed: %d\n", (int)remCapacity, (int)(remCapacity * 10) % 10, critical, pfCriticalChanged?*pfCriticalChanged:-1));
     231                Log(("checkBatteryCriticalLevel: Remains: %d.%d%% Critical: %d Critical State Changed: %d\n", (int)remCapacity, (int)(remCapacity * 10) % 10, critical, pfCriticalChanged?*pfCriticalChanged:-1));
    232232            }
    233233        }
     
    236236    mCritical = critical;
    237237
    238     CFRelease (pBlob);
    239     CFRelease (pSources);
    240 }
    241 
     238    CFRelease(pBlob);
     239    CFRelease(pSources);
     240}
     241
  • trunk/src/VBox/Main/src-server/win/HostPowerWin.cpp

    r46722 r46775  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3636    mHwnd = 0;
    3737
    38     int rc = RTThreadCreate (&mThread, HostPowerServiceWin::NotificationThread, this, 65536,
    39                              RTTHREADTYPE_GUI, RTTHREADFLAGS_WAITABLE, "MainPower");
     38    int rc = RTThreadCreate(&mThread, HostPowerServiceWin::NotificationThread, this, 65536,
     39                            RTTHREADTYPE_GUI, RTTHREADFLAGS_WAITABLE, "MainPower");
    4040
    4141    if (RT_FAILURE(rc))
     
    6363
    6464
    65 DECLCALLBACK(int) HostPowerServiceWin::NotificationThread (RTTHREAD ThreadSelf, void *pInstance)
     65DECLCALLBACK(int) HostPowerServiceWin::NotificationThread(RTTHREAD ThreadSelf, void *pInstance)
    6666{
    6767    HostPowerServiceWin *pPowerObj = (HostPowerServiceWin *)pInstance;
     
    7171    int rc = VINF_SUCCESS;
    7272
    73     HINSTANCE hInstance = (HINSTANCE)GetModuleHandle (NULL);
     73    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
    7474
    7575    /* Register the Window Class. */
     
    9797    {
    9898        /* Create the window. */
    99         hwnd = pPowerObj->mHwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
    100                                                   gachWindowClassName, gachWindowClassName,
    101                                                   WS_POPUPWINDOW,
    102                                                  -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
     99        hwnd = pPowerObj->mHwnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
     100                                                 gachWindowClassName, gachWindowClassName,
     101                                                 WS_POPUPWINDOW,
     102                                                -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
    103103
    104104        if (hwnd == NULL)
     
    124124    Log(("HostPowerServiceWin::NotificationThread: exit thread\n"));
    125125    if (hwnd)
    126         DestroyWindow (hwnd);
     126        DestroyWindow(hwnd);
    127127
    128128    if (atomWindowClass != 0)
    129129    {
    130         UnregisterClass (gachWindowClassName, hInstance);
     130        UnregisterClass(gachWindowClassName, hInstance);
    131131        atomWindowClass = 0;
    132132    }
     
    149149                {
    150150                case PBT_APMSUSPEND:
    151                     pPowerObj->notify(HostPowerEvent_Suspend);
     151                    pPowerObj->notify(Reason_HostSuspend);
    152152                    break;
    153153
    154154                case PBT_APMRESUMEAUTOMATIC:
    155                     pPowerObj->notify(HostPowerEvent_Resume);
     155                    pPowerObj->notify(Reason_HostResume);
    156156                    break;
    157157
     
    180180                                    &&  BatteryState.EstimatedTime < 60*5)
    181181                                {
    182                                     pPowerObj->notify(HostPowerEvent_BatteryLow);
     182                                    pPowerObj->notify(Reason_HostBatteryLow);
    183183                                }
    184184                            }
     
    187187                            if (SystemPowerStatus.BatteryFlag == 4      /* critical battery status; less than 5% */)
    188188                            {
    189                                 pPowerObj->notify(HostPowerEvent_BatteryLow);
     189                                pPowerObj->notify(Reason_HostBatteryLow);
    190190                            }
    191191                        }
     
    194194                }
    195195                default:
    196                     return DefWindowProc (hwnd, msg, wParam, lParam);
     196                    return DefWindowProc(hwnd, msg, wParam, lParam);
    197197                }
    198198            }
     
    201201
    202202        default:
    203             return DefWindowProc (hwnd, msg, wParam, lParam);
    204     }
    205 }
     203            return DefWindowProc(hwnd, msg, wParam, lParam);
     204    }
     205}
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