VirtualBox

Changeset 22884 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Sep 9, 2009 9:55:47 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
52140
Message:

SSM: Added cancellation support (SSMR3Cancel). Needed by the state machinery as well as main.

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/SSM.cpp

    r22807 r22884  
    260260#define SSM_LOG_BYTES                           16
    261261
     262/** SSMHANDLE::fCancelled value indicating that the operation has been
     263 *  cancelled. */
     264#define SSMHANDLE_CANCELLED                     UINT32_C(0xdeadbeef)
     265/** SSMHANDLE::fCancelled value indicating no cancellation. */
     266#define SSMHANDLE_OK                            UINT32_C(0x77777777)
     267
    262268
    263269/** Macro for checking the u32CRC field of a structure.
     
    296302                    || pSSM->enmOp == SSMSTATE_OPEN_READ,\
    297303                    ("Invalid state %d\n", pSSM->enmOp), VERR_SSM_INVALID_STATE);
     304
     305/** Checks for cancellation and returns if pending.
     306 * Sets SSMHANDLE::rc to VERR_SSM_CANCELLED (if it still indicates success) and
     307 * then returns SSMHANDLE::rc. (Debug logging only.) */
     308#define SSM_CHECK_CANCELLED_RET(pSSM) \
     309    do \
     310    { \
     311        if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED)) \
     312        { \
     313            LogFlow(("%Rfn: Cancelled -> VERR_SSM_CANCELLED\n", __PRETTY_FUNCTION__)); \
     314            if (RT_SUCCESS((pSSM)->rc)) \
     315                (pSSM)->rc = VERR_SSM_CANCELLED; \
     316            return (pSSM)->rc; \
     317        } \
     318    } while (0)
    298319
    299320
     
    403424{
    404425    /** Stream/buffer manager. */
    405     SSMSTRM         Strm;
     426    SSMSTRM                 Strm;
    406427
    407428    /** The VM handle. */
    408     PVM             pVM;
     429    PVM                     pVM;
    409430    /** The current operation. */
    410     SSMSTATE        enmOp;
     431    SSMSTATE                enmOp;
    411432    /** What to do after save completes. (move the enum) */
    412     SSMAFTER        enmAfter;
     433    SSMAFTER                enmAfter;
     434    /** Flag indicating that the operation has been cancelled. */
     435    uint32_t volatile       fCancelled;
    413436    /** The current rc of the save operation. */
    414     int             rc;
     437    int32_t                 rc;
    415438    /** Number of compressed bytes left in the current data unit (V1). */
    416     uint64_t        cbUnitLeftV1;
     439    uint64_t                cbUnitLeftV1;
    417440    /** The current uncompressed offset into the data unit. */
    418     uint64_t        offUnit;
     441    uint64_t                offUnit;
    419442
    420443    /** Pointer to the progress callback function. */
    421     PFNVMPROGRESS   pfnProgress;
     444    PFNVMPROGRESS           pfnProgress;
    422445    /** User specified arguemnt to the callback function. */
    423     void           *pvUser;
     446    void                   *pvUser;
    424447    /** Next completion percentage. (corresponds to offEstProgress) */
    425     unsigned        uPercent;
     448    unsigned                uPercent;
    426449    /** The position of the next progress callback in the estimated file. */
    427     uint64_t        offEstProgress;
     450    uint64_t                offEstProgress;
    428451    /** The estimated total byte count.
    429452     * (Only valid after the prep.) */
    430     uint64_t        cbEstTotal;
     453    uint64_t                cbEstTotal;
    431454    /** Current position in the estimated file. */
    432     uint64_t        offEst;
     455    uint64_t                offEst;
    433456    /** End of current unit in the estimated file. */
    434     uint64_t        offEstUnitEnd;
     457    uint64_t                offEstUnitEnd;
    435458    /** the amount of % we reserve for the 'prepare' phase */
    436     unsigned        uPercentPrepare;
     459    unsigned                uPercentPrepare;
    437460    /** the amount of % we reserve for the 'done' stage */
    438     unsigned        uPercentDone;
     461    unsigned                uPercentDone;
    439462    /** The filename, NULL if remote stream. */
    440     const char     *pszFilename;
     463    const char             *pszFilename;
    441464
    442465    union
     
    801824
    802825/**
     826 * Cleans up resources allocated by SSM on VM termination.
     827 *
     828 * @param   pVM                 The VM handle.
     829 */
     830VMMR3_INT_DECL(void) SSMR3Term(PVM pVM)
     831{
     832    if (pVM->ssm.s.fInitialized)
     833    {
     834        pVM->ssm.s.fInitialized = false;
     835        RTCritSectDelete(&pVM->ssm.s.CancelCritSect);
     836    }
     837}
     838
     839
     840/**
    803841 * Performs lazy initialization of the SSM.
    804842 *
     
    817855                                   NULL /*pfnSavePrep*/, ssmR3SelfSaveExec, NULL /*pfnSaveDone*/,
    818856                                   NULL /*pfnSavePrep*/, ssmR3SelfLoadExec, NULL /*pfnSaveDone*/);
     857
     858    /*
     859     * Initialize the cancellation critsect now.
     860     */
     861    if (RT_SUCCESS(rc))
     862        rc = RTCritSectInit(&pVM->ssm.s.CancelCritSect);
     863
    819864    pVM->ssm.s.fInitialized = RT_SUCCESS(rc);
    820865    return rc;
     
    25742619                             / (100 - pSSM->uPercentDone - pSSM->uPercentPrepare);
    25752620    }
     2621}
     2622
     2623
     2624/**
     2625 * Makes the SSM operation cancellable or not (via SSMR3Cancel).
     2626 *
     2627 * @param   pVM             The VM handle.
     2628 * @param   pSSM            The saved state handle. (SSMHANDLE::rc may be set.)
     2629 * @param   fCancellable    The new state.
     2630 */
     2631static void ssmR3SetCancellable(PVM pVM, PSSMHANDLE pSSM, bool fCancellable)
     2632{
     2633    RTCritSectEnter(&pVM->ssm.s.CancelCritSect);
     2634    if (fCancellable)
     2635    {
     2636        Assert(!pVM->ssm.s.pSSM);
     2637        pVM->ssm.s.pSSM = pSSM;
     2638    }
     2639    else
     2640    {
     2641        if (pVM->ssm.s.pSSM == pSSM)
     2642            pVM->ssm.s.pSSM = NULL;
     2643
     2644        uint32_t fCancelled = ASMAtomicUoReadU32(&pSSM->fCancelled);
     2645        if (    fCancelled == SSMHANDLE_CANCELLED
     2646            &&  RT_SUCCESS(pSSM->rc))
     2647            pSSM->rc = VERR_SSM_CANCELLED;
     2648    }
     2649
     2650    RTCritSectLeave(&pVM->ssm.s.CancelCritSect);
    25762651}
    25772652
     
    29433018{
    29443019    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3020    SSM_CHECK_CANCELLED_RET(pSSM);
    29453021    uint8_t u8 = fBool; /* enforce 1 byte size */
    29463022    return ssmR3DataWrite(pSSM, &u8, sizeof(u8));
     
    29583034{
    29593035    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3036    SSM_CHECK_CANCELLED_RET(pSSM);
    29603037    return ssmR3DataWrite(pSSM, &u8, sizeof(u8));
    29613038}
     
    29723049{
    29733050    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3051    SSM_CHECK_CANCELLED_RET(pSSM);
    29743052    return ssmR3DataWrite(pSSM, &i8, sizeof(i8));
    29753053}
     
    29863064{
    29873065    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3066    SSM_CHECK_CANCELLED_RET(pSSM);
    29883067    return ssmR3DataWrite(pSSM, &u16, sizeof(u16));
    29893068}
     
    30003079{
    30013080    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3081    SSM_CHECK_CANCELLED_RET(pSSM);
    30023082    return ssmR3DataWrite(pSSM, &i16, sizeof(i16));
    30033083}
     
    30143094{
    30153095    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3096    SSM_CHECK_CANCELLED_RET(pSSM);
    30163097    return ssmR3DataWrite(pSSM, &u32, sizeof(u32));
    30173098}
     
    30283109{
    30293110    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3111    SSM_CHECK_CANCELLED_RET(pSSM);
    30303112    return ssmR3DataWrite(pSSM, &i32, sizeof(i32));
    30313113}
     
    30423124{
    30433125    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3126    SSM_CHECK_CANCELLED_RET(pSSM);
    30443127    return ssmR3DataWrite(pSSM, &u64, sizeof(u64));
    30453128}
     
    30563139{
    30573140    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3141    SSM_CHECK_CANCELLED_RET(pSSM);
    30583142    return ssmR3DataWrite(pSSM, &i64, sizeof(i64));
    30593143}
     
    30703154{
    30713155    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3156    SSM_CHECK_CANCELLED_RET(pSSM);
    30723157    return ssmR3DataWrite(pSSM, &u128, sizeof(u128));
    30733158}
     
    30843169{
    30853170    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3171    SSM_CHECK_CANCELLED_RET(pSSM);
    30863172    return ssmR3DataWrite(pSSM, &i128, sizeof(i128));
    30873173}
     
    30983184{
    30993185    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3186    SSM_CHECK_CANCELLED_RET(pSSM);
    31003187    return ssmR3DataWrite(pSSM, &u, sizeof(u));
    31013188}
     
    31123199{
    31133200    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3201    SSM_CHECK_CANCELLED_RET(pSSM);
    31143202    return ssmR3DataWrite(pSSM, &i, sizeof(i));
    31153203}
     
    31283216{
    31293217    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3218    SSM_CHECK_CANCELLED_RET(pSSM);
    31303219    return ssmR3DataWrite(pSSM, &u, sizeof(u));
    31313220}
     
    31423231{
    31433232    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3233    SSM_CHECK_CANCELLED_RET(pSSM);
    31443234    return ssmR3DataWrite(pSSM, &u, sizeof(u));
    31453235}
     
    31563246{
    31573247    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3248    SSM_CHECK_CANCELLED_RET(pSSM);
    31583249    return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
    31593250}
     
    31703261{
    31713262    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3263    SSM_CHECK_CANCELLED_RET(pSSM);
    31723264    return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
    31733265}
     
    31843276{
    31853277    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3278    SSM_CHECK_CANCELLED_RET(pSSM);
    31863279    return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
    31873280}
     
    31983291{
    31993292    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3293    SSM_CHECK_CANCELLED_RET(pSSM);
    32003294    return ssmR3DataWrite(pSSM, &GCPtr, sizeof(GCPtr));
    32013295}
     
    32123306{
    32133307    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3308    SSM_CHECK_CANCELLED_RET(pSSM);
    32143309    return ssmR3DataWrite(pSSM, &RCPtr, sizeof(RCPtr));
    32153310}
     
    32263321{
    32273322    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3323    SSM_CHECK_CANCELLED_RET(pSSM);
    32283324    return ssmR3DataWrite(pSSM, &GCPtr, sizeof(GCPtr));
    32293325}
     
    32403336{
    32413337    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3338    SSM_CHECK_CANCELLED_RET(pSSM);
    32423339    return ssmR3DataWrite(pSSM, &IOPort, sizeof(IOPort));
    32433340}
     
    32543351{
    32553352    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3353    SSM_CHECK_CANCELLED_RET(pSSM);
    32563354    return ssmR3DataWrite(pSSM, &Sel, sizeof(Sel));
    32573355}
     
    32693367{
    32703368    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3369    SSM_CHECK_CANCELLED_RET(pSSM);
    32713370    return ssmR3DataWrite(pSSM, pv, cb);
    32723371}
     
    32833382{
    32843383    SSM_ASSERT_WRITEABLE_RET(pSSM);
     3384    SSM_CHECK_CANCELLED_RET(pSSM);
    32853385
    32863386    size_t cch = strlen(psz);
     
    33113411
    33123412    /*
    3313      * Close the stream and delete the file on failure.
    3314      */
     3413     * Make it non-cancellable, close the stream and delete the file on failure.
     3414     */
     3415    ssmR3SetCancellable(pVM, pSSM, false);
    33153416    int rc = ssmR3StrmClose(&pSSM->Strm);
    33163417    if (RT_SUCCESS(rc))
     
    33433444     * Trash the handle before freeing it.
    33443445     */
     3446    ASMAtomicWriteU32(&pSSM->fCancelled, 0);
    33453447    pSSM->pVM = NULL;
    33463448    pSSM->enmAfter = SSMAFTER_INVALID;
     
    35953697        }
    35963698        pUnit->offStream = ssmR3StrmTell(&pSSM->Strm);
     3699
     3700        /*
     3701         * Check for cancellation.
     3702         */
     3703        if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
     3704        {
     3705            LogRel(("SSM: Cancelled!\n"));
     3706            AssertRC(pSSM->rc);
     3707            return pSSM->rc = VERR_SSM_CANCELLED;
     3708        }
    35973709
    35983710        /*
     
    38884000    pSSM->enmOp                 = SSMSTATE_INVALID;
    38894001    pSSM->enmAfter              = enmAfter;
     4002    pSSM->fCancelled            = SSMHANDLE_OK;
    38904003    pSSM->rc                    = VINF_SUCCESS;
    38914004    pSSM->cbUnitLeftV1          = 0;
     
    39634076    rc = ssmR3WriteHeaderAndClearPerUnitData(pVM, pSSM);
    39644077    if (RT_SUCCESS(rc))
     4078    {
     4079        ssmR3SetCancellable(pVM, pSSM, true);
    39654080        ssmR3SaveDoCommon(pVM, pSSM);
     4081    }
     4082
    39664083    return ssmR3SaveDoClose(pVM, pSSM);
    39674084}
     
    40594176            continue;
    40604177        pUnit->offStream = ssmR3StrmTell(&pSSM->Strm);
     4178
     4179        /*
     4180         * Check for cancellation.
     4181         */
     4182        if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
     4183        {
     4184            LogRel(("SSM: Cancelled!\n"));
     4185            AssertRC(pSSM->rc);
     4186            return pSSM->rc = VERR_SSM_CANCELLED;
     4187        }
    40614188
    40624189        /*
     
    44014528             */
    44024529            pSSM->enmOp = SSMSTATE_LIVE_STEP1;
     4530            ssmR3SetCancellable(pVM, pSSM, true);
    44034531            *ppSSM = pSSM;
    44044532            return VINF_SUCCESS;
     
    51945322{
    51955323    SSM_ASSERT_READABLE_RET(pSSM);
     5324    SSM_CHECK_CANCELLED_RET(pSSM);
    51965325    uint8_t u8; /* see SSMR3PutBool */
    51975326    int rc = ssmR3DataRead(pSSM, &u8, sizeof(u8));
     
    52155344{
    52165345    SSM_ASSERT_READABLE_RET(pSSM);
     5346    SSM_CHECK_CANCELLED_RET(pSSM);
    52175347    return ssmR3DataRead(pSSM, pu8, sizeof(*pu8));
    52185348}
     
    52295359{
    52305360    SSM_ASSERT_READABLE_RET(pSSM);
     5361    SSM_CHECK_CANCELLED_RET(pSSM);
    52315362    return ssmR3DataRead(pSSM, pi8, sizeof(*pi8));
    52325363}
     
    52435374{
    52445375    SSM_ASSERT_READABLE_RET(pSSM);
     5376    SSM_CHECK_CANCELLED_RET(pSSM);
    52455377    return ssmR3DataRead(pSSM, pu16, sizeof(*pu16));
    52465378}
     
    52575389{
    52585390    SSM_ASSERT_READABLE_RET(pSSM);
     5391    SSM_CHECK_CANCELLED_RET(pSSM);
    52595392    return ssmR3DataRead(pSSM, pi16, sizeof(*pi16));
    52605393}
     
    52715404{
    52725405    SSM_ASSERT_READABLE_RET(pSSM);
     5406    SSM_CHECK_CANCELLED_RET(pSSM);
    52735407    return ssmR3DataRead(pSSM, pu32, sizeof(*pu32));
    52745408}
     
    52855419{
    52865420    SSM_ASSERT_READABLE_RET(pSSM);
     5421    SSM_CHECK_CANCELLED_RET(pSSM);
    52875422    return ssmR3DataRead(pSSM, pi32, sizeof(*pi32));
    52885423}
     
    52995434{
    53005435    SSM_ASSERT_READABLE_RET(pSSM);
     5436    SSM_CHECK_CANCELLED_RET(pSSM);
    53015437    return ssmR3DataRead(pSSM, pu64, sizeof(*pu64));
    53025438}
     
    53135449{
    53145450    SSM_ASSERT_READABLE_RET(pSSM);
     5451    SSM_CHECK_CANCELLED_RET(pSSM);
    53155452    return ssmR3DataRead(pSSM, pi64, sizeof(*pi64));
    53165453}
     
    53275464{
    53285465    SSM_ASSERT_READABLE_RET(pSSM);
     5466    SSM_CHECK_CANCELLED_RET(pSSM);
    53295467    return ssmR3DataRead(pSSM, pu128, sizeof(*pu128));
    53305468}
     
    53415479{
    53425480    SSM_ASSERT_READABLE_RET(pSSM);
     5481    SSM_CHECK_CANCELLED_RET(pSSM);
    53435482    return ssmR3DataRead(pSSM, pi128, sizeof(*pi128));
    53445483}
     
    53555494{
    53565495    SSM_ASSERT_READABLE_RET(pSSM);
     5496    SSM_CHECK_CANCELLED_RET(pSSM);
    53575497    return ssmR3DataRead(pSSM, pu, sizeof(*pu));
    53585498}
     
    53695509{
    53705510    SSM_ASSERT_READABLE_RET(pSSM);
     5511    SSM_CHECK_CANCELLED_RET(pSSM);
    53715512    return ssmR3DataRead(pSSM, pi, sizeof(*pi));
    53725513}
     
    54135554{
    54145555    SSM_ASSERT_READABLE_RET(pSSM);
     5556    SSM_CHECK_CANCELLED_RET(pSSM);
    54155557    return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
    54165558}
     
    54275569{
    54285570    SSM_ASSERT_READABLE_RET(pSSM);
     5571    SSM_CHECK_CANCELLED_RET(pSSM);
    54295572    return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
    54305573}
     
    54415584{
    54425585    SSM_ASSERT_READABLE_RET(pSSM);
     5586    SSM_CHECK_CANCELLED_RET(pSSM);
    54435587
    54445588    /*
     
    55185662{
    55195663    SSM_ASSERT_READABLE_RET(pSSM);
     5664    SSM_CHECK_CANCELLED_RET(pSSM);
    55205665
    55215666    /*
     
    55735718{
    55745719    SSM_ASSERT_READABLE_RET(pSSM);
     5720    SSM_CHECK_CANCELLED_RET(pSSM);
    55755721    return ssmR3DataRead(pSSM, pRCPtr, sizeof(*pRCPtr));
    55765722}
     
    55875733{
    55885734    SSM_ASSERT_READABLE_RET(pSSM);
     5735    SSM_CHECK_CANCELLED_RET(pSSM);
    55895736    return ssmR3DataRead(pSSM, pIOPort, sizeof(*pIOPort));
    55905737}
     
    56015748{
    56025749    SSM_ASSERT_READABLE_RET(pSSM);
     5750    SSM_CHECK_CANCELLED_RET(pSSM);
    56035751    return ssmR3DataRead(pSSM, pSel, sizeof(*pSel));
    56045752}
     
    56165764{
    56175765    SSM_ASSERT_READABLE_RET(pSSM);
     5766    SSM_CHECK_CANCELLED_RET(pSSM);
    56185767    return ssmR3DataRead(pSSM, pv, cb);
    56195768}
     
    56465795{
    56475796    SSM_ASSERT_READABLE_RET(pSSM);
     5797    SSM_CHECK_CANCELLED_RET(pSSM);
    56485798
    56495799    /* read size prefix. */
     
    56765826{
    56775827    SSM_ASSERT_READABLE_RET(pSSM);
     5828    SSM_CHECK_CANCELLED_RET(pSSM);
    56785829    while (cb > 0)
    56795830    {
     
    57035854{
    57045855    SSM_ASSERT_READABLE_RET(pSSM);
     5856    SSM_CHECK_CANCELLED_RET(pSSM);
    57055857    if (pSSM->u.Read.uFmtVerMajor >= 2)
    57065858    {
     
    61686320     * Initialize the handle.
    61696321     */
    6170     pSSM->pVM              = pVM;
    6171     pSSM->enmOp            = SSMSTATE_INVALID;
    6172     pSSM->enmAfter         = SSMAFTER_INVALID;
    6173     pSSM->rc               = VINF_SUCCESS;
    6174     pSSM->cbUnitLeftV1     = 0;
    6175     pSSM->offUnit          = UINT64_MAX;
    6176     pSSM->pfnProgress      = NULL;
    6177     pSSM->pvUser           = NULL;
    6178     pSSM->uPercent         = 0;
    6179     pSSM->offEstProgress   = 0;
    6180     pSSM->cbEstTotal       = 0;
    6181     pSSM->offEst           = 0;
    6182     pSSM->offEstUnitEnd    = 0;
    6183     pSSM->uPercentPrepare  = 5;
    6184     pSSM->uPercentDone     = 2;
    6185     pSSM->pszFilename      = pszFilename;
     6322    pSSM->pVM               = pVM;
     6323    pSSM->enmOp             = SSMSTATE_INVALID;
     6324    pSSM->enmAfter          = SSMAFTER_INVALID;
     6325    pSSM->fCancelled        = SSMHANDLE_OK;
     6326    pSSM->rc                = VINF_SUCCESS;
     6327    pSSM->cbUnitLeftV1      = 0;
     6328    pSSM->offUnit           = UINT64_MAX;
     6329    pSSM->pfnProgress       = NULL;
     6330    pSSM->pvUser            = NULL;
     6331    pSSM->uPercent          = 0;
     6332    pSSM->offEstProgress    = 0;
     6333    pSSM->cbEstTotal        = 0;
     6334    pSSM->offEst            = 0;
     6335    pSSM->offEstUnitEnd     = 0;
     6336    pSSM->uPercentPrepare   = 5;
     6337    pSSM->uPercentDone      = 2;
     6338    pSSM->pszFilename       = pszFilename;
    61866339
    61876340    pSSM->u.Read.pZipDecompV1   = NULL;
     
    64156568        {
    64166569            LogRel(("SSM: I/O error. rc=%Rrc\n", rc));
     6570            break;
     6571        }
     6572
     6573        /*
     6574         * Check for cancellation.
     6575         */
     6576        if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
     6577        {
     6578            LogRel(("SSM: Cancelled!n"));
     6579            rc = pSSM->rc;
     6580            if (RT_SUCCESS(pSSM->rc))
     6581                pSSM->rc = rc = VERR_SSM_CANCELLED;
    64176582            break;
    64186583        }
     
    65546719            ssmR3DataReadFinishV2(pSSM);
    65556720        }
     6721
     6722        /*
     6723         * Check for cancellation.
     6724         */
     6725        if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
     6726        {
     6727            LogRel(("SSM: Cancelled!\n"));
     6728            if (RT_SUCCESS(pSSM->rc))
     6729                pSSM->rc = VERR_SSM_CANCELLED;
     6730            return pSSM->rc;
     6731        }
    65566732    }
    65576733    /* won't get here */
     
    65976773    {
    65986774        ssmR3StrmStartIoThread(&Handle.Strm);
     6775        ssmR3SetCancellable(pVM, &Handle, true);
    65996776
    66006777        Handle.enmAfter     = enmAfter;
     
    67146891                    if (RT_SUCCESS(Handle.rc))
    67156892                        Handle.rc = rc;
     6893                    break;
    67166894                }
    67176895            }
     
    67236901            pfnProgress(pVM, 99, pvUser);
    67246902
     6903        ssmR3SetCancellable(pVM, &Handle, false);
    67256904        ssmR3StrmClose(&Handle.Strm);
    67266905    }
     
    68387017    AssertMsgReturn(pSSM->enmAfter == SSMAFTER_OPENED, ("%d\n", pSSM->enmAfter),VERR_INVALID_PARAMETER);
    68397018    AssertMsgReturn(pSSM->enmOp == SSMSTATE_OPEN_READ, ("%d\n", pSSM->enmOp), VERR_INVALID_PARAMETER);
     7019    Assert(pSSM->fCancelled == SSMHANDLE_OK);
    68407020
    68417021    /*
     
    71367316 * to SSM.
    71377317 *
     7318 * @returns VBox status code of the handle, or VERR_INVALID_PARAMETER.
     7319 * @param   pSSM            SSM operation handle.
     7320 * @param   iStatus         Failure status code. This MUST be a VERR_*.
     7321 */
     7322VMMR3DECL(int) SSMR3HandleSetStatus(PSSMHANDLE pSSM, int iStatus)
     7323{
     7324    Assert(pSSM->enmOp != SSMSTATE_LIVE_VOTE);
     7325    if (RT_FAILURE(iStatus))
     7326    {
     7327        int rc = pSSM->rc;
     7328        if (RT_SUCCESS(rc))
     7329            pSSM->rc = rc = iStatus;
     7330        return rc;
     7331    }
     7332    AssertMsgFailed(("iStatus=%d %Rrc\n", iStatus, iStatus));
     7333    return VERR_INVALID_PARAMETER;
     7334}
     7335
     7336
     7337/**
     7338 * Get what to do after this operation.
     7339 *
    71387340 * @returns SSMAFTER enum value.
    71397341 * @param   pSSM            SSM operation handle.
    7140  * @param   iStatus         Failure status code. This MUST be a VERR_*.
    7141  */
    7142 VMMR3DECL(int) SSMR3HandleSetStatus(PSSMHANDLE pSSM, int iStatus)
    7143 {
    7144     Assert(pSSM->enmOp != SSMSTATE_LIVE_VOTE);
    7145     if (RT_FAILURE(iStatus))
    7146     {
    7147         if (RT_SUCCESS(pSSM->rc))
    7148             pSSM->rc = iStatus;
    7149         return pSSM->rc = iStatus;
    7150     }
    7151     AssertMsgFailed(("iStatus=%d %Rrc\n", iStatus, iStatus));
    7152     return VERR_INVALID_PARAMETER;
    7153 }
    7154 
    7155 
    7156 /**
    7157  * Get what to do after this operation.
    7158  *
    7159  * @returns SSMAFTER enum value.
    7160  * @param   pSSM            SSM operation handle.
    71617342 */
    71627343VMMR3DECL(SSMAFTER) SSMR3HandleGetAfter(PSSMHANDLE pSSM)
     
    71787359}
    71797360
     7361
     7362/**
     7363 * Asynchronously cancels the current SSM operation ASAP.
     7364 *
     7365 * @returns VBox status code.
     7366 * @retval  VINF_SUCCESS on success.
     7367 * @retval  VERR_SSM_NO_PENDING_OPERATION if nothing around that can be
     7368 *          cancelled.
     7369 * @retval  VERR_SSM_ALREADY_CANCELLED if the operation as already been
     7370 *          cancelled.
     7371 *
     7372 * @param   pVM                 The VM handle.
     7373 *
     7374 * @thread  Any.
     7375 */
     7376VMMR3DECL(int) SSMR3Cancel(PVM pVM)
     7377{
     7378    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     7379
     7380    int rc = RTCritSectEnter(&pVM->ssm.s.CancelCritSect);
     7381    AssertRCReturn(rc, rc);
     7382
     7383    PSSMHANDLE pSSM = pVM->ssm.s.pSSM;
     7384    if (pSSM)
     7385    {
     7386        uint32_t u32Old;
     7387        if (ASMAtomicCmpXchgExU32(&pSSM->fCancelled, SSMHANDLE_CANCELLED, SSMHANDLE_OK, &u32Old))
     7388        {
     7389            LogRel(("SSM: Cancelled pending operation\n"));
     7390            rc = VINF_SUCCESS;
     7391        }
     7392        else if (u32Old == SSMHANDLE_CANCELLED)
     7393            rc = VERR_SSM_ALREADY_CANCELLED;
     7394        else
     7395        {
     7396            AssertLogRelMsgFailed(("fCancelled=%RX32 enmOp=%d\n", u32Old, pSSM->enmOp));
     7397            rc = VERR_INTERNAL_ERROR_2;
     7398        }
     7399    }
     7400    else
     7401        rc = VERR_SSM_NO_PENDING_OPERATION;
     7402
     7403    RTCritSectLeave(&pVM->ssm.s.CancelCritSect);
     7404    return rc;
     7405}
     7406
  • trunk/src/VBox/VMM/SSMInternal.h

    r22480 r22884  
    2626#include <VBox/types.h>
    2727#include <VBox/ssm.h>
     28#include <iprt/critsect.h>
    2829
    2930RT_C_DECLS_BEGIN
     
    266267    /** For lazy init. */
    267268    bool                    fInitialized;
     269    /** Critical section for serializing cancellation. */
     270    RTCRITSECT              CancelCritSect;
     271    /** The handle of the current save or load operation.
     272     * This is used by SSMR3Cancel.  */
     273    PSSMHANDLE volatile     pSSM;
    268274} SSM;
    269275/** Pointer to SSM VM instance data. */
Note: See TracChangeset for help on using the changeset viewer.

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