VirtualBox

Changeset 40257 in vbox


Ignore:
Timestamp:
Feb 27, 2012 9:25:12 AM (13 years ago)
Author:
vboxsync
Message:

Main/Medium: rework locking scheme to solve lock order violations and long GUI start up time caused by too much locking
Main/all: Remove the enter and leave methods from write locks, they cause hard to find locking problems. Better solve them explicitly.

Location:
trunk
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/com/AutoLock.h

    r38773 r40257  
    55
    66/*
    7  * Copyright (C) 2006-2011 Oracle Corporation
     7 * Copyright (C) 2006-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    401401 * which derive from this.
    402402 *
    403  * In addition to utility methods for subclasses, this implements the public
    404  * leave/enter methods, which are common to all
    405  * write locks.
     403 * It has some utility methods for subclasses.
    406404 */
    407405class AutoWriteLockBase : public AutoLockBase
     
    427425    virtual void callLockImpl(LockHandle &l);
    428426    virtual void callUnlockImpl(LockHandle &l);
    429 
    430 public:
    431     void leave();
    432     void enter();
    433427};
    434428
  • trunk/src/VBox/Main/glue/AutoLock.cpp

    r38773 r40257  
    55
    66/*
    7  * Copyright (C) 2006-2011 Oracle Corporation
     7 * Copyright (C) 2006-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    7171        { LOCKCLASS_MACHINEOBJECT,      "5-MACHINEOBJECT" },
    7272        { LOCKCLASS_SNAPSHOTOBJECT,     "6-SNAPSHOTOBJECT" },
    73         { LOCKCLASS_LISTOFMEDIA,        "7-LISTOFMEDIA" },
    74         { LOCKCLASS_LISTOFOTHEROBJECTS, "8-LISTOFOTHEROBJECTS" },
    75         { LOCKCLASS_MEDIUMQUERY,        "9-MEDIUMQUERY" },
     73        { LOCKCLASS_MEDIUMQUERY,        "7-MEDIUMQUERY" },
     74        { LOCKCLASS_LISTOFMEDIA,        "8-LISTOFMEDIA" },
     75        { LOCKCLASS_LISTOFOTHEROBJECTS, "9-LISTOFOTHEROBJECTS" },
    7676        { LOCKCLASS_OTHEROBJECT,        "10-OTHEROBJECT" },
    7777        { LOCKCLASS_USBLIST,            "11-USBLIST" },
     
    303303
    304304typedef std::vector<LockHandle*> HandlesVector;
    305 typedef std::vector<uint32_t> CountsVector;
    306305
    307306struct AutoLockBase::Data
     
    315314        )
    316315        : fIsLocked(false),
    317           aHandles(cHandles),       // size of array
    318           acUnlockedInLeave(cHandles)
     316          aHandles(cHandles)        // size of array
    319317#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
    320318          , pcszFile(pcszFile_),
     
    324322    {
    325323        for (uint32_t i = 0; i < cHandles; ++i)
    326         {
    327             acUnlockedInLeave[i] = 0;
    328324            aHandles[i] = NULL;
    329         }
    330325    }
    331326
     
    335330                                        // and AutoReadLock, there will only be one item on the list; with the
    336331                                        // AutoMulti* derivatives, there will be multiple
    337     CountsVector    acUnlockedInLeave;  // for each lock handle, how many times the handle was unlocked in leave(); otherwise 0
    338332
    339333#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
     
    415409 * Destructor implementation that can also be called explicitly, if required.
    416410 * Restores the exact state before the AutoLock was created; that is, unlocks
    417  * all contained semaphores and might actually lock them again if leave()
    418  * was called during the AutoLock's lifetime.
     411 * all contained semaphores.
    419412 */
    420413void AutoLockBase::cleanup()
    421414{
    422     bool fAnyUnlockedInLeave = false;
    423 
    424     uint32_t i = 0;
    425     for (HandlesVector::iterator it = m->aHandles.begin();
    426          it != m->aHandles.end();
    427          ++it)
    428     {
    429         LockHandle *pHandle = *it;
    430         if (pHandle)
    431         {
    432             if (m->acUnlockedInLeave[i])
    433             {
    434                 // there was a leave() before the destruction: then restore the
    435                 // lock level that might have been set by locks other than our own
    436                 if (m->fIsLocked)
    437                 {
    438                     --m->acUnlockedInLeave[i];
    439                     fAnyUnlockedInLeave = true;
    440                 }
    441                 for (; m->acUnlockedInLeave[i]; --m->acUnlockedInLeave[i])
    442                     callLockImpl(*pHandle);
    443             }
    444         }
    445         ++i;
    446     }
    447 
    448     if (m->fIsLocked && !fAnyUnlockedInLeave)
     415    if (m->fIsLocked)
    449416        callUnlockOnAllHandles();
    450417}
     
    553520{
    554521    l.unlockWrite();
    555 }
    556 
    557 /**
    558  * Causes the current thread to completely release the write lock to make
    559  * the managed semaphore immediately available for locking by other threads.
    560  *
    561  * This implies that all nested write locks on the semaphore will be
    562  * released, even those that were acquired through the calls to #lock()
    563  * methods of all other AutoWriteLock/AutoReadLock instances managing the
    564  * <b>same</b> read/write semaphore.
    565  *
    566  * After calling this method, the only method you are allowed to call is
    567  * #enter(). It will acquire the write lock again and restore the same
    568  * level of nesting as it had before calling #leave().
    569  *
    570  * If this instance is destroyed without calling #enter(), the destructor
    571  * will try to restore the write lock level that existed when #leave() was
    572  * called minus the number of nested #lock() calls made on this instance
    573  * itself. This is done to preserve lock levels of other
    574  * AutoWriteLock/AutoReadLock instances managing the same semaphore (if
    575  * any). Tiis also means that the destructor may indefinitely block if a
    576  * write or a read lock is owned by some other thread by that time.
    577  */
    578 void AutoWriteLockBase::leave()
    579 {
    580     AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot leave()!"));
    581 
    582     // unlock in reverse order!
    583     uint32_t i = m->aHandles.size();
    584     for (HandlesVector::reverse_iterator it = m->aHandles.rbegin();
    585          it != m->aHandles.rend();
    586          ++it)
    587     {
    588         --i;            // array index is zero based, decrement with every loop since we iterate backwards
    589         LockHandle *pHandle = *it;
    590         if (pHandle)
    591         {
    592             AssertMsg(m->acUnlockedInLeave[i] == 0, ("m->cUnlockedInLeave[%d] is %d, must be 0! Called leave() twice?", i, m->acUnlockedInLeave[i]));
    593             m->acUnlockedInLeave[i] = pHandle->writeLockLevel();
    594             AssertMsg(m->acUnlockedInLeave[i] >= 1, ("m->cUnlockedInLeave[%d] is %d, must be >=1!", i, m->acUnlockedInLeave[i]));
    595 
    596             for (uint32_t left = m->acUnlockedInLeave[i];
    597                  left;
    598                  --left)
    599                 callUnlockImpl(*pHandle);
    600         }
    601     }
    602 }
    603 
    604 /**
    605  * Causes the current thread to restore the write lock level after the
    606  * #leave() call. This call will indefinitely block if another thread has
    607  * successfully acquired a write or a read lock on the same semaphore in
    608  * between.
    609  */
    610 void AutoWriteLockBase::enter()
    611 {
    612     AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot enter()!"));
    613 
    614     uint32_t i = 0;
    615     for (HandlesVector::iterator it = m->aHandles.begin();
    616          it != m->aHandles.end();
    617          ++it)
    618     {
    619         LockHandle *pHandle = *it;
    620         if (pHandle)
    621         {
    622             AssertMsg(m->acUnlockedInLeave[i] != 0, ("m->cUnlockedInLeave[%d] is 0! enter() without leave()?", i));
    623 
    624             for (; m->acUnlockedInLeave[i]; --m->acUnlockedInLeave[i])
    625                 callLockImpl(*pHandle);
    626         }
    627         ++i;
    628     }
    629522}
    630523
  • trunk/src/VBox/Main/include/MediumImpl.h

    r38499 r40257  
    269269
    270270    HRESULT queryInfo(bool fSetImageId, bool fSetParentId);
     271    HRESULT lockRead(MediumState_T *aState, bool fWithinQueryInfo);
     272    HRESULT lockWrite(MediumState_T *aState, bool fWithinQueryInfo);
    271273
    272274    HRESULT canClose();
  • trunk/src/VBox/Main/include/VirtualBoxImpl.h

    r38818 r40257  
    55
    66/*
    7  * Copyright (C) 2006-2011 Oracle Corporation
     7 * Copyright (C) 2006-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    260260    void copyPathRelativeToConfig(const Utf8Str &strSource, Utf8Str &strTarget);
    261261
    262     HRESULT registerHardDisk(Medium *aHardDisk, GuidList *pllRegistriesThatNeedSaving);
    263     HRESULT unregisterHardDisk(Medium *aHardDisk, GuidList *pllRegistriesThatNeedSaving);
    264 
    265     HRESULT registerImage(Medium *aImage, DeviceType_T argType, GuidList *pllRegistriesThatNeedSaving);
    266     HRESULT unregisterImage(Medium *aImage, DeviceType_T argType, GuidList *pllRegistriesThatNeedSaving);
     262    HRESULT registerMedium(Medium *pMedium, ComObjPtr<Medium> *ppMedium, DeviceType_T argType, GuidList *pllRegistriesThatNeedSaving);
     263    HRESULT unregisterMedium(Medium *pMedium, GuidList *pllRegistriesThatNeedSaving);
    267264
    268265    void pushMediumToListWithChildren(MediaList &llMedia, Medium *pMedium);
     
    301298                                   const Utf8Str &aLocation,
    302299                                   Utf8Str &aConflictType,
    303                                    bool &fIdentical);
     300                                   ComObjPtr<Medium> *pDupMedium);
    304301
    305302    HRESULT registerMachine(Machine *aMachine);
  • trunk/src/VBox/Main/src-all/ProgressImpl.cpp

    r38181 r40257  
    66
    77/*
    8  * Copyright (C) 2006-2010 Oracle Corporation
     8 * Copyright (C) 2006-2012 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    820820        {
    821821            mWaitersCount++;
    822             alock.leave();
     822            alock.release();
    823823            vrc = RTSemEventMultiWait(mCompletedSem,
    824824                                      fForever ? RT_INDEFINITE_WAIT : (RTMSINTERVAL)timeLeft);
    825             alock.enter();
     825            alock.acquire();
    826826            mWaitersCount--;
    827827
     
    884884        {
    885885            mWaitersCount ++;
    886             alock.leave();
     886            alock.release();
    887887            vrc = RTSemEventMultiWait(mCompletedSem,
    888888                                      fForever ? RT_INDEFINITE_WAIT : (unsigned) timeLeft);
    889             alock.enter();
     889            alock.acquire();
    890890            mWaitersCount--;
    891891
     
    16641664        while (!mCompleted && (forever || timeLeft > 0))
    16651665        {
    1666             alock.leave();
     1666            alock.release();
    16671667            rc = mProgresses.back()->WaitForCompletion(forever ? -1 : (LONG) timeLeft);
    1668             alock.enter();
     1668            alock.acquire();
    16691669
    16701670            if (SUCCEEDED(rc))
     
    17481748               (forever || timeLeft > 0))
    17491749        {
    1750             alock.leave();
     1750            alock.release();
    17511751            /* wait for the appropriate progress operation completion */
    17521752            rc = mProgresses[progress]-> WaitForOperationCompletion(operation,
    17531753                                                                    forever ? -1 : (LONG) timeLeft);
    1754             alock.enter();
     1754            alock.acquire();
    17551755
    17561756            if (SUCCEEDED(rc))
  • trunk/src/VBox/Main/src-all/VirtualBoxBase.cpp

    r38533 r40257  
    77
    88/*
    9  * Copyright (C) 2006-2010 Oracle Corporation
     9 * Copyright (C) 2006-2012 Oracle Corporation
    1010 *
    1111 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    209209            LogFlowThisFunc(("Waiting for AutoInitSpan/AutoReinitSpan to finish...\n"));
    210210
    211             stateLock.leave();
     211            stateLock.release();
    212212            RTSemEventMultiWait (mInitUninitSem, RT_INDEFINITE_WAIT);
    213             stateLock.enter();
     213            stateLock.acquire();
    214214
    215215            if (-- mInitUninitWaiters == 0)
     
    776776    {
    777777        mObj->setState(VirtualBoxBase::InitFailed);
    778         /* leave the lock to prevent nesting when uninit() is called */
    779         stateLock.leave();
     778        /* release the lock to prevent nesting when uninit() is called */
     779        stateLock.acquire();
    780780        /* call uninit() to let the object uninit itself after failed init() */
    781781        mObj->uninit();
     
    906906                         mObj));
    907907
    908             stateLock.leave();
     908            stateLock.release();
    909909            RTSemEventMultiWait(mObj->mInitUninitSem, RT_INDEFINITE_WAIT);
    910             stateLock.enter();
     910            stateLock.acquire();
    911911
    912912            if (--mObj->mInitUninitWaiters == 0)
     
    935935                     mObj, mObj->mCallers));
    936936
    937         stateLock.leave();
     937        stateLock.release();
    938938        RTSemEventWait(mObj->mZeroCallersSem, RT_INDEFINITE_WAIT);
    939939    }
  • trunk/src/VBox/Main/src-client/ConsoleImpl.cpp

    r40084 r40257  
    20772077        return ptrVM.rc();
    20782078
    2079     /* leave the lock before a VMR3* call (EMT will call us back)! */
    2080     alock.leave();
     2079    /* release the lock before a VMR3* call (EMT will call us back)! */
     2080    alock.release();
    20812081
    20822082    int vrc = VMR3Reset(ptrVM);
     
    22902290                          this, pVM, aCpu);
    22912291
    2292     /* leave the lock before a VMR3* call (EMT will call us back)! */
     2292    /* release the lock before a VMR3* call (EMT will call us back)! */
    22932293    alock.release();
    22942294
     
    23542354    LogFlowThisFunc(("Sending PAUSE request...\n"));
    23552355
    2356     /* leave the lock before a VMR3* call (EMT will call us back)! */
    2357     alock.leave();
     2356    /* release the lock before a VMR3* call (EMT will call us back)! */
     2357    alock.release();
    23582358
    23592359    int vrc = VMR3Suspend(ptrVM);
     
    23892389    LogFlowThisFunc(("Sending RESUME request...\n"));
    23902390
    2391     /* leave the lock before a VMR3* call (EMT will call us back)! */
    2392     alock.leave();
     2391    /* release the lock before a VMR3* call (EMT will call us back)! */
     2392    alock.release();
    23932393
    23942394#ifdef VBOX_WITH_EXTPACK
     
    24342434    if (!ptrVM.isOk())
    24352435        return ptrVM.rc();
    2436 /** @todo leave the console lock? */
     2436
     2437/** @todo release the console lock? */
    24372438
    24382439    /* get the acpi device interface and press the button. */
     
    24812482    if (!ptrVM.isOk())
    24822483        return ptrVM.rc();
    2483 /** @todo leave the console lock? */
     2484
     2485/** @todo release the console lock? */
    24842486
    24852487    /* get the acpi device interface and check if the button press was handled. */
     
    25362538        return ptrVM.rc();
    25372539
    2538 /** @todo leave the console lock? */
     2540/** @todo release the console lock? */
    25392541
    25402542    /* get the acpi device interface and query the information. */
     
    25772579        return ptrVM.rc();
    25782580
    2579 /** @todo leave the console lock? */
     2581/** @todo release the console lock? */
    25802582
    25812583    /* get the acpi device interface and press the sleep button. */
     
    26792681        /*
    26802682         * If we fail here it means a PowerDown() call happened on another
    2681          * thread while we were doing Pause() (which leaves the Console lock).
     2683         * thread while we were doing Pause() (which releases the Console lock).
    26822684         * We assign PowerDown() a higher precedence than SaveState(),
    26832685         * therefore just return the error to the caller.
     
    28872889            tr("The virtual machine does not have a USB controller"));
    28882890
    2889     /* leave the lock because the USB Proxy service may call us back
     2891    /* release the lock because the USB Proxy service may call us back
    28902892     * (via onUSBDeviceAttach()) */
    2891     alock.leave();
     2893    alock.release();
    28922894
    28932895    /* Request the device capture */
     
    29322934     * Inform the USB device and USB proxy about what's cooking.
    29332935     */
    2934     alock.leave();
     2936    alock.release();
    29352937    HRESULT rc2 = mControl->DetachUSBDevice(aId, false /* aDone */);
    29362938    if (FAILED(rc2))
    29372939        return rc2;
    2938     alock.enter();
     2940    alock.acquire();
    29392941
    29402942    /* Request the PDM to detach the USB device. */
     
    29432945    if (SUCCEEDED(rc))
    29442946    {
    2945         /* leave the lock since we don't need it any more (note though that
     2947        /* release the lock since we don't need it any more (note though that
    29462948         * the USB Proxy service must not call us back here) */
    2947         alock.leave();
     2949        alock.release();
    29482950
    29492951        /* Request the device release. Even if it fails, the device will
     
    32693271        /*
    32703272         * If we fail here it means a PowerDown() call happened on another
    3271          * thread while we were doing Pause() (which leaves the Console lock).
     3273         * thread while we were doing Pause() (which releases the Console lock).
    32723274         * We assign PowerDown() a higher precedence than TakeSnapshot(),
    32733275         * therefore just return the error to the caller.
     
    35953597                          fForce);
    35963598
    3597     /* leave the lock before waiting for a result (EMT will call us back!) */
    3598     alock.leave();
     3599    /* release the lock before waiting for a result (EMT will call us back!) */
     3600    alock.release();
    35993601
    36003602    if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
     
    38483850                          aMediumAttachment);
    38493851
    3850     /* leave the lock before waiting for a result (EMT will call us back!) */
    3851     alock.leave();
     3852    /* release the lock before waiting for a result (EMT will call us back!) */
     3853    alock.release();
    38523854
    38533855    if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
     
    40894091                          aMediumAttachment);
    40904092
    4091     /* leave the lock before waiting for a result (EMT will call us back!) */
    4092     alock.leave();
     4093    /* release the lock before waiting for a result (EMT will call us back!) */
     4094    alock.release();
    40934095
    40944096    if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
     
    44984500                          this, ptrVM.raw(), pszDevice, uInstance, uLun, aNetworkAdapter);
    44994501
    4500     /* leave the lock before waiting for a result (EMT will call us back!) */
    4501     alock.leave();
     4502    /* release the lock before waiting for a result (EMT will call us back!) */
     4503    alock.release();
    45024504
    45034505    if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
     
    48334835        {
    48344836            /* VRDP server may call this Console object back from other threads (VRDP INPUT or OUTPUT). */
    4835             alock.leave();
     4837            alock.release();
    48364838
    48374839            if (vrdpEnabled)
     
    48524854            }
    48534855
    4854             alock.enter();
     4856            alock.acquire();
    48554857        }
    48564858    }
     
    66886690    /* ----------------------------------------------------------------------
    66896691     * DONE with necessary state changes, perform the power down actions (it's
    6690      * safe to leave the object lock now if needed)
     6692     * safe to release the object lock now if needed)
    66916693     * ---------------------------------------------------------------------- */
    66926694
     
    66996701        /* Leave the lock since EMT will call us back as addVMCaller()
    67006702         * in updateDisplayData(). */
    6701         alock.leave();
     6703        alock.release();
    67026704
    67036705        mConsoleVRDPServer->Stop();
    67046706
    6705         alock.enter();
     6707        alock.acquire();
    67066708    }
    67076709
     
    67296731                          mVMCallers));
    67306732
    6731         alock.leave();
     6733        alock.release();
    67326734
    67336735        RTSemEventWait(mVMZeroCallersSem, RT_INDEFINITE_WAIT);
    67346736
    6735         alock.enter();
     6737        alock.acquire();
    67366738    }
    67376739
     
    67536755    {
    67546756        LogFlowThisFunc(("Powering off the VM...\n"));
    6755         alock.leave();
     6757        alock.release();
    67566758        vrc = VMR3PowerOff(VMR3GetVM(pUVM));
    67576759#ifdef VBOX_WITH_EXTPACK
    67586760        mptrExtPackManager->callAllVmPowerOffHooks(this, VMR3GetVM(pUVM));
    67596761#endif
    6760         alock.enter();
     6762        alock.acquire();
    67616763    }
    67626764
     
    67726774
    67736775        /* Leave the lock since EMT will call us back as addVMCaller() */
    6774         alock.leave();
     6776        alock.release();
    67756777
    67766778        m_pVMMDev->hgcmShutdown();
    67776779
    6778         alock.enter();
     6780        alock.acquire();
    67796781    }
    67806782
     
    68056807
    68066808        /* Now we've got to destroy the VM as well. (mpVM is not valid beyond
    6807          * this point). We leave the lock before calling VMR3Destroy() because
     6809         * this point). We release the lock before calling VMR3Destroy() because
    68086810         * it will result into calling destructors of drivers associated with
    68096811         * Console children which may in turn try to lock Console (e.g. by
     
    68186820        LogFlowThisFunc(("Destroying the VM...\n"));
    68196821
    6820         alock.leave();
     6822        alock.release();
    68216823
    68226824        vrc = VMR3Destroy(VMR3GetVM(pUVM));
    68236825
    68246826        /* take the lock again */
    6825         alock.enter();
     6827        alock.acquire();
    68266828
    68276829        /* advance percent count */
     
    69306932             * UpdateState we will require Machine and SessionMachine locks
    69316933             * (remember that here we're holding the Console lock here, and also
    6932              * all locks that have been entered by the thread before calling
     6934             * all locks that have been acquire by the thread before calling
    69336935             * this method).
    69346936             */
     
    76487650    AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
    76497651
    7650     /* still want a lock object because we need to leave it */
     7652    /* still want a lock object because we need to release it */
    76517653    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    76527654
     
    76807682                      Address.c_str(), uuid.raw()));
    76817683
    7682     /* leave the lock before a VMR3* call (EMT will call us back)! */
    7683     alock.leave();
     7684    /* release the lock before a VMR3* call (EMT will call us back)! */
     7685    alock.release();
    76847686
    76857687/** @todo just do everything here and only wrap the PDMR3Usb call. That'll offload some notification stuff from the EMT thread. */
     
    76897691
    76907692    /* restore the lock */
    7691     alock.enter();
     7693    alock.acquire();
    76927694
    76937695    /* hrc is S_OK here */
     
    77907792    AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
    77917793
    7792     /* still want a lock object because we need to leave it */
     7794    /* still want a lock object because we need to release it */
    77937795    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    77947796
     
    78047806                     (*aIt)->id().raw()));
    78057807
    7806     /* leave the lock before a VMR3* call (EMT will call us back)! */
    7807     alock.leave();
     7808    /* release the lock before a VMR3* call (EMT will call us back)! */
     7809    alock.release();
    78087810
    78097811/** @todo just do everything here and only wrap the PDMR3Usb call. That'll offload some notification stuff from the EMT thread. */
     
    82668268    if (RT_SUCCESS(vrc))
    82678269    {
    8268         /* leave the lock before calling Host in VBoxSVC since Host may call
     8270        /* release the lock before calling Host in VBoxSVC since Host may call
    82698271         * us back from under its lock (e.g. onUSBDeviceAttach()) which would
    82708272         * produce an inter-process dead-lock otherwise. */
    82718273        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    8272         alock.leave();
     8274        alock.release();
    82738275
    82748276        HRESULT hrc = mControl->AutoCaptureUSBDevices();
     
    83008302    mUSBDevices.clear();
    83018303
    8302     /* leave the lock before calling Host in VBoxSVC since Host may call
     8304    /* release the lock before calling Host in VBoxSVC since Host may call
    83038305     * us back from under its lock (e.g. onUSBDeviceAttach()) which would
    83048306     * produce an inter-process dead-lock otherwise. */
    83058307    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    8306     alock.leave();
     8308    alock.release();
    83078309
    83088310    mControl->DetachAllUSBDevices(aDone);
     
    85758577
    85768578        /* Does VRDP server call Console from the other thread?
    8577          * Not sure (and can change), so leave the lock just in case.
     8579         * Not sure (and can change), so release the lock just in case.
    85788580         */
    8579         alock.leave();
     8581        alock.release();
    85808582        vrc = server->Launch();
    8581         alock.enter();
     8583        alock.acquire();
    85828584
    85838585        if (vrc == VERR_NET_ADDRESS_IN_USE)
     
    86278629        PVM pVM;
    86288630        /*
    8629          * leave the lock since EMT will call Console. It's safe because
     8631         * release the lock since EMT will call Console. It's safe because
    86308632         * mMachineState is either Starting or Restoring state here.
    86318633         */
    8632         alock.leave();
     8634        alock.release();
    86338635
    86348636        vrc = VMR3Create(cCpus,
     
    86408642                         &pVM);
    86418643
    8642         alock.enter();
     8644        alock.acquire();
    86438645
    86448646        /* Enable client connections to the server. */
     
    86778679                {
    86788680                    /* Does the code below call Console from the other thread?
    8679                      * Not sure, so leave the lock just in case. */
    8680                     alock.leave();
     8681                     * Not sure, so release the lock just in case. */
     8682                    alock.release();
    86818683
    86828684                    for (SharedFolderDataMap::const_iterator it = task->mSharedFolders.begin();
     
    86988700                        rc = S_OK;          // do not fail with broken shared folders
    86998701
    8700                     /* enter the lock again */
    8701                     alock.enter();
     8702                    /* acquire the lock again */
     8703                    alock.acquire();
    87028704                }
    87038705
     
    87088710                if (FAILED(rc)) break;
    87098711
    8710                 /* leave the lock before a lengthy operation */
    8711                 alock.leave();
     8712                /* release the lock before a lengthy operation */
     8713                alock.release();
    87128714
    87138715                /* Load saved state? */
     
    88228824                }
    88238825
    8824                 /* enter the lock again */
    8825                 alock.enter();
     8826                /* acquire the lock again */
     8827                alock.acquire();
    88268828            }
    88278829            while (0);
     
    88358837                /* powerDown() will call VMR3Destroy() and do all necessary
    88368838                 * cleanup (VRDP, USB devices) */
     8839                alock.release();
    88378840                HRESULT rc2 = pConsole->powerDown();
     8841                alock.acquire();
    88388842                AssertComRC(rc2);
    88398843            }
     
    88458849                 * be sticky but our error callback isn't.
    88468850                 */
    8847                 alock.leave();
     8851                alock.release();
    88488852                VMR3AtErrorDeregister(pVM, Console::genericVMSetErrorCallback, &task->mErrorMsg);
    88498853                /** @todo register another VMSetError callback? */
    8850                 alock.enter();
     8854                alock.acquire();
    88518855            }
    88528856        }
     
    89148918     */
    89158919
    8916     /* leave the lock, don't need it any more */
    8917     alock.leave();
     8920    /* release the lock, don't need it any more */
     8921    alock.release();
    89188922
    89198923    if (SUCCEEDED(rc))
     
    91149118            pTask->mProgress->setCancelCallback(takesnapshotProgressCancelCallback, ptrVM.rawUVM());
    91159119
    9116             alock.leave();
     9120            alock.release();
    91179121            LogFlowFunc(("VMR3Save...\n"));
    91189122            int vrc = VMR3Save(ptrVM,
     
    91229126                               static_cast<IProgress *>(pTask->mProgress),
    91239127                               &fSuspenededBySave);
    9124             alock.enter();
     9128            alock.acquire();
    91259129            if (RT_FAILURE(vrc))
    91269130                throw setErrorStatic(E_FAIL,
     
    91909194
    91919195                /*
    9192                  * don't leave the lock since reconfigureMediumAttachment
     9196                 * don't release the lock since reconfigureMediumAttachment
    91939197                 * isn't going to need the Console lock.
    91949198                 */
     
    92659269                LogFlowFunc(("VMR3Resume...\n"));
    92669270                SafeVMPtr ptrVM(that);
    9267                 alock.leave();
     9271                alock.release();
    92689272                int vrc = VMR3Resume(ptrVM);
    9269                 alock.enter();
     9273                alock.acquire();
    92709274                if (RT_FAILURE(vrc))
    92719275                {
     
    93239327                        LogFlowFunc(("VMR3Resume (on failure)...\n"));
    93249328                        SafeVMPtr ptrVM(that);
    9325                         alock.leave();
     9329                        alock.release();
    93269330                        int vrc = VMR3Resume(ptrVM); AssertLogRelRC(vrc);
    9327                         alock.enter();
     9331                        alock.acquire();
    93289332                        if (RT_FAILURE(vrc))
    93299333                            that->setMachineState(MachineState_Paused);
     
    94119415         */
    94129416        task->releaseVMCaller();
     9417        thatLock.release();
    94139418        rc = that->powerDown();
     9419        thatLock.acquire();
    94149420    }
    94159421
     
    94589464    /* release VM caller to avoid the powerDown() deadlock */
    94599465    task->releaseVMCaller();
     9466
     9467    thatLock.release();
    94609468
    94619469    that->powerDown(task->mServerProgress);
  • trunk/src/VBox/Main/src-client/ConsoleImplTeleporter.cpp

    r40066 r40257  
    55
    66/*
    7  * Copyright (C) 2010 Oracle Corporation
     7 * Copyright (C) 2010-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    886886                        if (pState->mfSuspendedByUs)
    887887                        {
    888                             autoLock.leave();
     888                            autoLock.release();
    889889                            int rc = VMR3Resume(VMR3GetVM(pState->mpUVM));
    890890                            AssertLogRelMsgRC(rc, ("VMR3Resume -> %Rrc\n", rc));
    891                             autoLock.enter();
     891                            autoLock.acquire();
    892892                        }
    893893                    }
     
    901901        }
    902902    }
    903     autoLock.leave();
     903    autoLock.release();
    904904
    905905    /*
  • trunk/src/VBox/Main/src-client/DisplayImpl.cpp

    r39603 r40257  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    20382038    if (pVM.isOk())
    20392039    {
    2040         /* Must leave the lock here because the changeFramebuffer will
     2040        /* Must release the lock here because the changeFramebuffer will
    20412041         * also obtain it. */
    2042         alock.leave ();
     2042        alock.release();
    20432043
    20442044        /* send request to the EMT thread */
     
    20462046                                   (PFNRT) changeFramebuffer, 3, this, aFramebuffer, aScreenId);
    20472047
    2048         alock.enter ();
     2048        alock.acquire();
    20492049
    20502050        ComAssertRCRet (vrc, E_FAIL);
     
    20642064                VMMDev *pVMMDev = mParent->getVMMDev();
    20652065
    2066                 alock.leave ();
     2066                alock.release();
    20672067
    20682068                if (pVMMDev)
     
    20702070                /*ComAssertRCRet (vrc, E_FAIL);*/
    20712071
    2072                 alock.enter ();
     2072                alock.acquire();
    20732073            }
    20742074        }
     
    21552155//        return setError(E_FAIL, tr("Not enough VRAM for the selected video mode"));
    21562156
    2157     /* Have to leave the lock because the pfnRequestDisplayChange
     2157    /* Have to release the lock because the pfnRequestDisplayChange
    21582158     * will call EMT.  */
    2159     alock.leave ();
     2159    alock.release();
    21602160
    21612161    VMMDev *pVMMDev = mParent->getVMMDev();
     
    21762176    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    21772177
    2178     /* Have to leave the lock because the pfnRequestSeamlessChange will call EMT.  */
    2179     alock.leave ();
     2178    /* Have to release the lock because the pfnRequestSeamlessChange will call EMT.  */
     2179    alock.release();
    21802180
    21812181    VMMDev *pVMMDev = mParent->getVMMDev();
     
    23772377    LogRelFlowFunc (("Sending SCREENSHOT request\n"));
    23782378
    2379     /* Leave lock because other thread (EMT) is called and it may initiate a resize
     2379    /* Release lock because other thread (EMT) is called and it may initiate a resize
    23802380     * which also needs lock.
    23812381     *
    23822382     * This method does not need the lock anymore.
    23832383     */
    2384     alock.leave();
     2384    alock.release();
    23852385
    23862386    int vrc = displayTakeScreenshot(pVM, this, mpDrv, aScreenId, address, width, height);
     
    24302430    LogRelFlowFunc (("Sending SCREENSHOT request\n"));
    24312431
    2432     /* Leave lock because other thread (EMT) is called and it may initiate a resize
     2432    /* Release lock because other thread (EMT) is called and it may initiate a resize
    24332433     * which also needs lock.
    24342434     *
    24352435     * This method does not need the lock anymore.
    24362436     */
    2437     alock.leave();
     2437    alock.release();
    24382438
    24392439    size_t cbData = width * 4 * height;
     
    25072507    LogRelFlowFunc (("Sending SCREENSHOT request\n"));
    25082508
    2509     /* Leave lock because other thread (EMT) is called and it may initiate a resize
     2509    /* Release lock because other thread (EMT) is called and it may initiate a resize
    25102510     * which also needs lock.
    25112511     *
    25122512     * This method does not need the lock anymore.
    25132513     */
    2514     alock.leave();
     2514    alock.release();
    25152515
    25162516    size_t cbData = width * 4 * height;
     
    26762676    if (FAILED(pVM.rc())) return pVM.rc();
    26772677
    2678     /* Leave lock because the call scheduled on EMT may also try to take it. */
    2679     alock.leave();
     2678    /* Release lock because the call scheduled on EMT may also try to take it. */
     2679    alock.release();
    26802680
    26812681    /*
     
    28002800    LogRelFlowFunc (("Sending DPYUPDATE request\n"));
    28012801
    2802     /* Have to leave the lock when calling EMT.  */
    2803     alock.leave ();
     2802    /* Have to release the lock when calling EMT.  */
     2803    alock.release();
    28042804
    28052805    /* pdm.h says that this has to be called from the EMT thread */
    28062806    int rcVBox = VMR3ReqCallVoidWait(pVM, VMCPUID_ANY, (PFNRT)Display::InvalidateAndUpdateEMT,
    28072807                                     1, this);
    2808     alock.enter ();
     2808    alock.acquire();
    28092809
    28102810    if (RT_FAILURE(rcVBox))
     
    30033003
    30043004#if defined(VBOX_WITH_CROGL)
    3005         /* Leave the lock, because SHCRGL_HOST_FN_SCREEN_CHANGED will read current framebuffer */
     3005        /* Release the lock, because SHCRGL_HOST_FN_SCREEN_CHANGED will read current framebuffer */
    30063006        {
    30073007            BOOL is3denabled;
     
    30103010            if (is3denabled)
    30113011            {
    3012                 alock.leave ();
     3012                alock.release();
    30133013            }
    30143014        }
  • trunk/src/VBox/Main/src-client/SessionImpl.cpp

    r40177 r40257  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    936936         *  SessionState_Closing here, so it's safe.
    937937         */
    938         alock.leave();
     938        alock.release();
    939939
    940940        LogFlowThisFunc(("Calling mControl->OnSessionEnd()...\n"));
     
    942942        LogFlowThisFunc(("mControl->OnSessionEnd()=%08X\n", rc));
    943943
    944         alock.enter();
     944        alock.acquire();
    945945
    946946        /*
  • trunk/src/VBox/Main/src-server/BandwidthControlImpl.cpp

    r35638 r40257  
    55
    66/*
    7  * Copyright (C) 2006-2009 Oracle Corporation
     7 * Copyright (C) 2006-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    472472
    473473    /* inform the direct session if any */
    474     alock.leave();
     474    alock.release();
    475475    //onStorageControllerChange(); @todo
    476476
  • trunk/src/VBox/Main/src-server/BandwidthGroupImpl.cpp

    r35638 r40257  
    55
    66/*
    7  * Copyright (C) 2006-2009 Oracle Corporation
     7 * Copyright (C) 2006-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    294294    /* inform direct session if any. */
    295295    ComObjPtr<Machine> pMachine = m->pParent->getMachine();
    296     alock.leave();
     296    alock.release();
    297297    pMachine->onBandwidthGroupChange(this);
    298298
  • trunk/src/VBox/Main/src-server/HostUSBDeviceImpl.cpp

    r38213 r40257  
    55
    66/*
    7  * Copyright (C) 2006-2007 Oracle Corporation
     7 * Copyright (C) 2006-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    355355 * As a convenience, this method will operate like attachToVM() if the device
    356356 * is already held by the proxy. Note that it will then perform IPC to the VM
    357  * process, which means it will temporarily leave all locks. (Is this a good idea?)
     357 * process, which means it will temporarily release all locks. (Is this a good idea?)
    358358 *
    359359 * @param   aMachine    Machine this device should be attach to.
     
    483483
    484484    /*
    485      * The VM process will query the object, so grab a reference to ourselves and leave the locks.
     485     * The VM process will query the object, so grab a reference to ourselves and release the locks.
    486486     */
    487487    ComPtr<IUSBDevice> d = this;
    488488
    489489    AutoWriteLock alockSelf(this COMMA_LOCKVAL_SRC_POS);
    490     alockSelf.leave();
     490    alockSelf.release();
    491491    AutoWriteLock alockProxy(mUSBProxyService COMMA_LOCKVAL_SRC_POS);
    492     alockProxy.leave();
     492    alockProxy.release();
    493493
    494494    /*
     
    504504
    505505    /*
    506      * As we re-enter the lock, we'll have to check if the device was
     506     * As we re-acquire the lock, we'll have to check if the device was
    507507     * physically detached while we were busy.
    508508     */
    509     alockProxy.enter();
    510     alockSelf.enter();
     509    alockProxy.acquire();
     510    alockSelf.acquire();
    511511
    512512    if (SUCCEEDED(hrc))
     
    561561
    562562    /*
    563      * Change the state and abandond the locks. The VM may query
     563     * Change the state and abandon the locks. The VM may query
    564564     * data and we don't want to deadlock - the state protects us,
    565565     * so, it's not a bit issue here.
     
    567567    setState(kHostUSBDeviceState_PhysDetachingFromVM, kHostUSBDeviceState_PhysDetached);
    568568    AutoWriteLock alockSelf(this COMMA_LOCKVAL_SRC_POS);
    569     alockSelf.leave();
     569    alockSelf.release();
    570570    AutoWriteLock alockProxy(mUSBProxyService COMMA_LOCKVAL_SRC_POS);
    571     alockProxy.leave();
     571    alockProxy.release();
    572572
    573573    /*
     
    584584
    585585    /*
    586      * Re-enter the locks and complete the transition.
    587      */
    588     alockProxy.enter();
    589     alockSelf.enter();
     586     * Re-acquire the locks and complete the transition.
     587     */
     588    alockProxy.acquire();
     589    alockSelf.acquire();
    590590    advanceTransition();
    591591}
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r40084 r40257  
    827827
    828828    /* the lock is no more necessary (SessionMachine is uninitialized) */
    829     alock.leave();
     829    alock.release();
    830830
    831831    // has machine been modified?
     
    30643064
    30653065        /*
    3066          *  Leave the lock before calling the client process. It's safe here
     3066         *  Release the lock before calling the client process. It's safe here
    30673067         *  since the only thing to do after we get the lock again is to add
    30683068         *  the remote control to the list (which doesn't directly influence
    30693069         *  anything).
    30703070         */
    3071         alock.leave();
     3071        alock.release();
    30723072
    30733073        // get the console of the session holding the write lock (this is a remote call)
     
    30923092            return setError(VBOX_E_VM_ERROR,
    30933093                            tr("Failed to assign the machine to the session (%Rrc)"), rc);
    3094         alock.enter();
    3095 
    3096         // need to revalidate the state after entering the lock again
     3094        alock.acquire();
     3095
     3096        // need to revalidate the state after acquiring the lock again
    30973097        if (mData->mSession.mState != SessionState_Locked)
    30983098        {
     
    31633163             *  Set the session state to Spawning to protect against subsequent
    31643164             *  attempts to open a session and to unregister the machine after
    3165              *  we leave the lock.
     3165             *  we release the lock.
    31663166             */
    31673167            SessionState_T origState = mData->mSession.mState;
     
    31693169
    31703170            /*
    3171              *  Leave the lock before calling the client process -- it will call
    3172              *  Machine/SessionMachine methods. Leaving the lock here is quite safe
     3171             *  Release the lock before calling the client process -- it will call
     3172             *  Machine/SessionMachine methods. Releasing the lock here is quite safe
    31733173             *  because the state is Spawning, so that LaunchVMProcess() and
    31743174             *  LockMachine() calls will fail. This method, called before we
    3175              *  enter the lock again, will fail because of the wrong PID.
     3175             *  acquire the lock again, will fail because of the wrong PID.
    31763176             *
    31773177             *  Note that mData->mSession.mRemoteControls accessed outside
    31783178             *  the lock may not be modified when state is Spawning, so it's safe.
    31793179             */
    3180             alock.leave();
     3180            alock.release();
    31813181
    31823182            LogFlowThisFunc(("Calling AssignMachine()...\n"));
     
    32273227            }
    32283228
    3229             /* enter the lock again */
    3230             alock.enter();
     3229            /* acquire the lock again */
     3230            alock.acquire();
    32313231
    32323232            /* Restore the session state */
     
    32833283        }
    32843284
    3285         /* Leave the lock since SessionMachine::uninit() locks VirtualBox which
     3285        /* Release the lock since SessionMachine::uninit() locks VirtualBox which
    32863286         * would break the lock order */
    3287         alock.leave();
     3287        alock.release();
    32883288
    32893289        /* uninitialize the created session machine on failure */
     
    38043804        /* Apply the normal locking logic to the entire chain. */
    38053805        MediumLockList *pMediumLockList(new MediumLockList());
     3806        mediumLock.release();
     3807        treeLock.release();
    38063808        rc = diff->createMediumLockList(true /* fFailIfInaccessible */,
    38073809                                        true /* fMediumLockWrite */,
    38083810                                        medium,
    38093811                                        *pMediumLockList);
     3812        treeLock.acquire();
     3813        mediumLock.acquire();
    38103814        if (SUCCEEDED(rc))
    38113815        {
     3816            mediumLock.release();
     3817            treeLock.release();
    38123818            rc = pMediumLockList->Lock();
     3819            treeLock.acquire();
     3820            mediumLock.acquire();
    38133821            if (FAILED(rc))
    38143822                setError(rc,
     
    38173825            else
    38183826            {
    3819                 /* will leave the lock before the potentially lengthy operation, so
    3820                  * protect with the special state */
     3827                /* will release the lock before the potentially lengthy
     3828                 * operation, so protect with the special state */
    38213829                MachineState_T oldState = mData->mMachineState;
    38223830                setMachineState(MachineState_SettingUp);
    38233831
    3824                 mediumLock.leave();
    3825                 treeLock.leave();
    3826                 alock.leave();
     3832                mediumLock.release();
     3833                treeLock.release();
     3834                alock.release();
    38273835
    38283836                rc = medium->createDiffStorage(diff,
     
    38333841                                               &llRegistriesThatNeedSaving);
    38343842
    3835                 alock.enter();
    3836                 treeLock.enter();
    3837                 mediumLock.enter();
     3843                alock.acquire();
     3844                treeLock.acquire();
     3845                mediumLock.acquire();
    38383846
    38393847                setMachineState(oldState);
     
    38903898
    38913899    mediumLock.release();
    3892     treeLock.leave();
     3900    treeLock.release();
    38933901    alock.release();
    38943902
     
    39583966    if (fHotplug)
    39593967    {
    3960         alock.leave();
     3968        alock.release();
    39613969        rc = onStorageDeviceChange(pAttach, TRUE /* aRemove */);
    3962         alock.enter();
     3970        alock.acquire();
    39633971    }
    39643972    if (FAILED(rc)) return rc;
     
    46324640        // (this state combination is not supported). Note releasing the caller and
    46334641        // leaving the lock before calling uninit()
    4634         alock.leave();
     4642        alock.release();
    46354643        autoCaller.release();
    46364644
     
    50645072
    50655073    /* inform the direct session if any */
    5066     alock.leave();
     5074    alock.release();
    50675075    onSharedFolderChange();
    50685076
     
    50915099
    50925100    /* inform the direct session if any */
    5093     alock.leave();
     5101    alock.release();
    50945102    onSharedFolderChange();
    50955103
     
    56505658
    56515659    /* inform the direct session if any */
    5652     alock.leave();
     5660    alock.release();
    56535661    onStorageControllerChange();
    56545662
     
    57445752    {
    57455753        /* inform the direct session if any */
    5746         alock.leave();
     5754        alock.release();
    57475755        onStorageControllerChange();
    57485756    }
     
    57885796
    57895797    /* inform the direct session if any */
    5790     alock.leave();
     5798    alock.release();
    57915799    onStorageControllerChange();
    57925800
     
    67976805
    67986806    /*
    6799      *  Note that we don't leave the lock here before calling the client,
     6807     *  Note that we don't release the lock here before calling the client,
    68006808     *  because it doesn't need to call us back if called with a NULL argument.
    6801      *  Leaving the lock here is dangerous because we didn't prepare the
     6809     *  Releasing the lock here is dangerous because we didn't prepare the
    68026810     *  launch data yet, but the client we've just started may happen to be
    68036811     *  too fast and call openSession() that will fail (because of PID, etc.),
     
    75157523        RTSemEventMultiReset(mData->mMachineStateDepsSem);
    75167524
    7517         alock.leave();
     7525        alock.release();
    75187526
    75197527        RTSemEventMultiWait(mData->mMachineStateDepsSem, RT_INDEFINITE_WAIT);
    75207528
    7521         alock.enter();
     7529        alock.acquire();
    75227530
    75237531        -- mData->mMachineStateChangePending;
     
    94579465                              &mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
    94589466
    9459     /* must be in a protective state because we leave the lock below */
     9467    /* must be in a protective state because we release the lock below */
    94609468    AssertReturn(   mData->mMachineState == MachineState_Saving
    94619469                 || mData->mMachineState == MachineState_LiveSnapshotting
     
    94909498
    94919499                    MediumLockList *pMediumLockList(new MediumLockList());
     9500                    alock.release();
    94929501                    rc = pMedium->createMediumLockList(true /* fFailIfInaccessible */,
    94939502                                                       false /* fMediumLockWrite */,
    94949503                                                       NULL,
    94959504                                                       *pMediumLockList);
     9505                    alock.acquire();
    94969506                    if (FAILED(rc))
    94979507                    {
     
    95099519
    95109520            /* Now lock all media. If this fails, nothing is locked. */
     9521            alock.release();
    95119522            rc = lockedMediaMap->Lock();
     9523            alock.acquire();
    95129524            if (FAILED(rc))
    95139525            {
     
    95839595
    95849596            /** @todo r=bird: How is the locking and diff image cleaned up if we fail before
    9585              *        the push_back?  Looks like we're going to leave medium with the
     9597             *        the push_back?  Looks like we're going to release medium with the
    95869598             *        wrong kind of lock (general issue with if we fail anywhere at all)
    95879599             *        and an orphaned VDI in the snapshots folder. */
     
    95939605            if (aOnline)
    95949606            {
     9607                alock.release();
    95959608                rc = pMediumLockList->Update(pMedium, false);
     9609                alock.acquire();
    95969610                AssertComRCThrowRC(rc);
    95979611            }
    95989612
    9599             /* leave the locks before the potentially lengthy operation */
     9613            /* release the locks before the potentially lengthy operation */
    96009614            alock.release();
    96019615            rc = pMedium->createDiffStorage(diff, MediumVariant_Standard,
     
    96099623            rc = lockedMediaMap->Unlock();
    96109624            AssertComRCThrowRC(rc);
     9625            alock.release();
    96119626            rc = pMediumLockList->Append(diff, true);
     9627            alock.acquire();
    96129628            AssertComRCThrowRC(rc);
     9629            alock.release();
    96139630            rc = lockedMediaMap->Lock();
     9631            alock.acquire();
    96149632            AssertComRCThrowRC(rc);
    96159633
     
    96549672        MultiResult mrc = rc;
    96559673
     9674        alock.release();
    96569675        mrc = deleteImplicitDiffs(pllRegistriesThatNeedSaving);
    96579676    }
     
    97269745    if (implicitAtts.size() != 0)
    97279746    {
    9728         /* will leave the lock before the potentially lengthy
     9747        /* will release the lock before the potentially lengthy
    97299748         * operation, so protect with the special state (unless already
    97309749         * protected) */
     
    97399758            setMachineState(MachineState_SettingUp);
    97409759
    9741         alock.leave();
     9760        alock.release();
    97429761
    97439762        for (MediaData::AttachmentList::const_iterator it = implicitAtts.begin();
     
    97549773        }
    97559774
    9756         alock.enter();
     9775        alock.acquire();
    97579776
    97589777        if (mData->mMachineState == MachineState_SettingUp)
     
    98699888        /* attempt to implicitly delete the implicitly created diff */
    98709889
    9871             /// @todo move the implicit flag from MediumAttachment to Medium
    9872             /// and forbid any hard disk operation when it is implicit. Or maybe
    9873             /// a special media state for it to make it even more simple.
     9890        /// @todo move the implicit flag from MediumAttachment to Medium
     9891        /// and forbid any hard disk operation when it is implicit. Or maybe
     9892        /// a special media state for it to make it even more simple.
    98749893
    98759894        Assert(mMediaData.isBackedUp());
    98769895
    9877             /* will leave the lock before the potentially lengthy operation, so
    9878             * protect with the special state */
     9896        /* will release the lock before the potentially lengthy operation, so
     9897         * protect with the special state */
    98799898        MachineState_T oldState = mData->mMachineState;
    98809899        setMachineState(MachineState_SettingUp);
     
    1039010409        ComObjPtr<Machine> that = this;
    1039110410        uint32_t flModifications = mData->flModifications;
    10392         alock.leave();
     10411        alock.release();
    1039310412
    1039410413        if (flModifications & IsModified_SharedFolders)
     
    1125811277    mData.free();
    1125911278
    11260 #if 1 /** @todo Please review this change! (bird) */
    11261     /* drop the exclusive lock before setting the below two to NULL */
     11279    /* release the exclusive lock before setting the below two to NULL */
    1126211280    multilock.release();
    11263 #else
    11264     /* leave the exclusive lock before setting the below two to NULL */
    11265     multilock.leave();
    11266 #endif
    1126711281
    1126811282    unconst(mParent) = NULL;
     
    1199012004           )
    1199112005        {
    11992             alock.leave();
     12006            alock.release();
    1199312007
    1199412008            mParent->onGuestPropertyChange(mData->mUuid,
     
    1272712741            bool fIsVitalImage = (devType == DeviceType_HardDisk);
    1272812742
     12743            alock.release();
    1272912744            mrc = pMedium->createMediumLockList(fIsVitalImage /* fFailIfInaccessible */,
    1273012745                                                !fIsReadOnlyLock /* fMediumLockWrite */,
    1273112746                                                NULL,
    1273212747                                                *pMediumLockList);
     12748            alock.acquire();
    1273312749            if (FAILED(mrc))
    1273412750            {
     
    1275212768    {
    1275312769        /* Now lock all media. If this fails, nothing is locked. */
     12770        alock.release();
    1275412771        HRESULT rc = mData->mSession.mLockedMedia.Lock();
     12772        alock.acquire();
    1275512773        if (FAILED(rc))
    1275612774        {
  • trunk/src/VBox/Main/src-server/MachineImplCloneVM.cpp

    r39926 r40257  
    55
    66/*
    7  * Copyright (C) 2011 Oracle Corporation
     7 * Copyright (C) 2011-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    649649    try
    650650    {
    651         Bstr bstrSrcId;
    652         rc = pParent->COMGETTER(Id)(bstrSrcId.asOutParam());
    653         if (FAILED(rc)) throw rc;
     651        // check validity of parent object
     652        {
     653            AutoReadLock alock(pParent COMMA_LOCKVAL_SRC_POS);
     654            Bstr bstrSrcId;
     655            rc = pParent->COMGETTER(Id)(bstrSrcId.asOutParam());
     656            if (FAILED(rc)) throw rc;
     657        }
    654658        ComObjPtr<Medium> diff;
    655659        diff.createObject();
     
    661665        if (FAILED(rc)) throw rc;
    662666
    663         // need tree lock for createMediumLockList
    664         AutoWriteLock treeLock(p->getVirtualBox()->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
    665 
    666667        MediumLockList *pMediumLockList(new MediumLockList());
    667668        rc = diff->createMediumLockList(true /* fFailIfInaccessible */,
     
    672673        rc = pMediumLockList->Lock();
    673674        if (FAILED(rc)) throw rc;
    674 
    675         treeLock.release();
    676675
    677676        /* this already registers the new diff image */
     
    12021201                        {
    12031202                            AutoWriteLock tlock(p->mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
    1204                             rc = p->mParent->registerHardDisk(pTarget, NULL /* pllRegistriesThatNeedSaving */);
     1203                            rc = p->mParent->registerMedium(pTarget, &pTarget,
     1204                                                            DeviceType_HardDisk,
     1205                                                            NULL /* pllRegistriesThatNeedSaving */);
    12051206                            if (FAILED(rc)) throw rc;
    12061207                        }
  • trunk/src/VBox/Main/src-server/MediumImpl.cpp

    r39799 r40257  
    55
    66/*
    7  * Copyright (C) 2008-2011 Oracle Corporation
     7 * Copyright (C) 2008-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    125125    MediumState_T preLockState;
    126126
    127     /** Special synchronization for operations which must wait for queryInfo()
    128      * in another thread to complete. Using a SemRW is not quite ideal, but at
    129      * least it is subject to the lock validator, unlike the SemEventMulti
    130      * which we had here for many years. Catching possible deadlocks is more
    131      * important than a tiny bit of efficiency. */
     127    /** Special synchronization for operations which must wait for
     128     * Medium::queryInfo in another thread to complete. Using a SemRW is
     129     * not quite ideal, but at least it is subject to the lock validator,
     130     * unlike the SemEventMulti which we had here for many years. Catching
     131     * possible deadlocks is more important than a tiny bit of efficiency. */
    132132    RWLockHandle queryInfoSem;
    133133    bool queryInfoRunning : 1;
     
    144144    bool autoReset : 1;
    145145
    146     /** New UUID to be set on the next queryInfo() call. */
     146    /** New UUID to be set on the next Medium::queryInfo call. */
    147147    const Guid uuidImage;
    148     /** New parent UUID to be set on the next queryInfo() call. */
     148    /** New parent UUID to be set on the next Medium::queryInfo call. */
    149149    const Guid uuidParentImage;
    150150
     
    956956    m->hostDrive = false;
    957957
    958     /* No storage unit is created yet, no need to queryInfo() */
     958    /* No storage unit is created yet, no need to call Medium::queryInfo */
    959959
    960960    rc = setFormat(aFormat);
     
    978978
    979979        AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
    980         rc = m->pVirtualBox->registerHardDisk(this, pllRegistriesThatNeedSaving);
     980        ComObjPtr<Medium> pMedium;
     981        rc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk,
     982                                            pllRegistriesThatNeedSaving);
     983        Assert(this == pMedium);
    981984    }
    982985
     
    10541057        unconst(m->uuidImage).create();
    10551058
    1056     {
    1057         // Medium::queryInfo needs write lock
    1058         AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
    1059         rc = queryInfo(fForceNewUuid /* fSetImageId */, false /* fSetParentId */);
    1060     }
     1059    rc = queryInfo(fForceNewUuid /* fSetImageId */, false /* fSetParentId */);
    10611060
    10621061    if (SUCCEEDED(rc))
     
    10731072            AssertReturn(!m->id.isEmpty(), E_FAIL);
    10741073
    1075             /* storage format must be detected by queryInfo() if the medium is accessible */
     1074            /* storage format must be detected by Medium::queryInfo if the
     1075             * medium is accessible */
    10761076            AssertReturn(!m->strFormat.isEmpty(), E_FAIL);
    10771077        }
     
    11341134    }
    11351135
    1136     /* see below why we don't call queryInfo() (and therefore treat the medium
    1137      * as inaccessible for now */
     1136    /* see below why we don't call Medium::queryInfo (and therefore treat
     1137     * the medium as inaccessible for now */
    11381138    m->state = MediumState_Inaccessible;
    11391139    m->strLastAccessError = tr("Accessibility check was not yet performed");
     
    12301230                     m->strLocationFull.c_str(), m->strFormat.c_str(), m->id.raw()));
    12311231
    1232     /* Don't call queryInfo() for registered media to prevent the calling
     1232    /* Don't call Medium::queryInfo for registered media to prevent the calling
    12331233     * thread (i.e. the VirtualBox server startup thread) from an unexpected
    12341234     * freeze but mark it as initially inaccessible instead. The vital UUID,
     
    12561256        if (FAILED(rc)) break;
    12571257
    1258         rc = m->pVirtualBox->registerHardDisk(pHD, NULL /* pllRegistriesThatNeedSaving */ );
     1258        rc = m->pVirtualBox->registerMedium(pHD, &pHD, DeviceType_HardDisk,
     1259                                            NULL /* pllRegistriesThatNeedSaving */ );
    12591260        if (FAILED(rc)) break;
    12601261    }
     
    13351336 * @note All children of this medium get uninitialized by calling their
    13361337 *       uninit() methods.
    1337  *
    1338  * @note Caller must hold the tree lock of the medium tree this medium is on.
    13391338 */
    13401339void Medium::uninit()
     
    16321631
    16331632    // we access mParent and members
    1634     AutoMultiWriteLock2 mlock(&m->pVirtualBox->getMediaTreeLockHandle(),
    1635                               this->lockHandle() COMMA_LOCKVAL_SRC_POS);
     1633    AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
     1634    AutoWriteLock mlock(this COMMA_LOCKVAL_SRC_POS);
    16361635
    16371636    switch (m->state)
     
    17071706            if (aType == MediumType_Shareable)
    17081707            {
    1709                 if (m->state == MediumState_Inaccessible)
    1710                 {
    1711                     HRESULT rc = queryInfo(false /* fSetImageId */, false /* fSetParentId */);
    1712                     if (FAILED(rc))
    1713                         return setError(rc,
    1714                                         tr("Cannot change type for medium '%s' to 'Shareable' because the medium is inaccessible"),
    1715                                         m->strLocationFull.c_str());
    1716                 }
    1717 
    17181708                MediumVariant_T variant = getVariant();
    17191709                if (!(variant & MediumVariant_Fixed))
     
    17621752    addToRegistryIDList(llRegistriesThatNeedSaving);
    17631753    mlock.release();
     1754    treeLock.release();
    17641755    HRESULT rc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
    17651756
     
    19641955    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    19651956
    1966     AutoMultiWriteLock2 alock(&m->pVirtualBox->getMediaTreeLockHandle(),
    1967                               this->lockHandle() COMMA_LOCKVAL_SRC_POS);
     1957    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    19681958
    19691959    switch (m->state)
     
    19981988    unconst(m->uuidParentImage) = parentId;
    19991989
     1990    // must not hold any locks before calling Medium::queryInfo
     1991    alock.release();
     1992
    20001993    HRESULT rc = queryInfo(!!aSetImageId /* fSetImageId */,
    20011994                           !!aSetParentId /* fSetParentId */);
     
    20112004    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    20122005
    2013     /* queryInfo() locks this for writing. */
    2014     AutoMultiWriteLock2 alock(&m->pVirtualBox->getMediaTreeLockHandle(),
    2015                               this->lockHandle() COMMA_LOCKVAL_SRC_POS);
     2006    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    20162007
    20172008    HRESULT rc = S_OK;
     
    20232014        case MediumState_LockedRead:
    20242015        {
     2016            // must not hold any locks before calling Medium::queryInfo
     2017            alock.release();
     2018
    20252019            rc = queryInfo(false /* fSetImageId */, false /* fSetParentId */);
     2020
     2021            alock.acquire();
    20262022            break;
    20272023        }
     
    20952091    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    20962092
    2097     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2098 
    2099     /* Wait for a concurrently running queryInfo() to complete */
    2100     while (m->queryInfoRunning)
    2101     {
    2102         alock.leave();
    2103         {
    2104             AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS);
    2105         }
    2106         alock.enter();
    2107     }
    2108 
    2109     /* return the current state before */
    2110     if (aState)
    2111         *aState = m->state;
    2112 
    2113     HRESULT rc = S_OK;
    2114 
    2115     switch (m->state)
    2116     {
    2117         case MediumState_Created:
    2118         case MediumState_Inaccessible:
    2119         case MediumState_LockedRead:
    2120         {
    2121             ++m->readers;
    2122 
    2123             ComAssertMsgBreak(m->readers != 0, ("Counter overflow"), rc = E_FAIL);
    2124 
    2125             /* Remember pre-lock state */
    2126             if (m->state != MediumState_LockedRead)
    2127                 m->preLockState = m->state;
    2128 
    2129             LogFlowThisFunc(("Okay - prev state=%d readers=%d\n", m->state, m->readers));
    2130             m->state = MediumState_LockedRead;
    2131 
    2132             break;
    2133         }
    2134         default:
    2135         {
    2136             LogFlowThisFunc(("Failing - state=%d\n", m->state));
    2137             rc = setStateError();
    2138             break;
    2139         }
    2140     }
    2141 
    2142     return rc;
     2093    return lockRead(aState, false /* fWithinQueryInfo */);
    21432094}
    21442095
     
    21602111        case MediumState_LockedRead:
    21612112        {
    2162             Assert(m->readers != 0);
     2113            ComAssertMsgBreak(m->readers != 0, ("Counter underflow"), rc = E_FAIL);
    21632114            --m->readers;
    21642115
     
    22032154    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    22042155
    2205     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2206 
    2207     /* Wait for a concurrently running queryInfo() to complete */
    2208     while (m->queryInfoRunning)
    2209     {
    2210         alock.leave();
    2211         {
    2212             AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS);
    2213         }
    2214         alock.enter();
    2215     }
    2216 
    2217     /* return the current state before */
    2218     if (aState)
    2219         *aState = m->state;
    2220 
    2221     HRESULT rc = S_OK;
    2222 
    2223     switch (m->state)
    2224     {
    2225         case MediumState_Created:
    2226         case MediumState_Inaccessible:
    2227         {
    2228             m->preLockState = m->state;
    2229 
    2230             LogFlowThisFunc(("Okay - prev state=%d locationFull=%s\n", m->state, getLocationFull().c_str()));
    2231             m->state = MediumState_LockedWrite;
    2232             break;
    2233         }
    2234         default:
    2235         {
    2236             LogFlowThisFunc(("Failing - state=%d locationFull=%s\n", m->state, getLocationFull().c_str()));
    2237             rc = setStateError();
    2238             break;
    2239         }
    2240     }
    2241 
    2242     return rc;
     2156    return lockWrite(aState, false /* fWithinQueryInfo */);
    22432157}
    22442158
     
    25572471    /* Apply the normal locking logic to the entire chain. */
    25582472    MediumLockList *pMediumLockList(new MediumLockList());
     2473    alock.release();
    25592474    HRESULT rc = diff->createMediumLockList(true /* fFailIfInaccessible */,
    25602475                                            true /* fMediumLockWrite */,
    25612476                                            this,
    25622477                                            *pMediumLockList);
     2478    alock.acquire();
    25632479    if (FAILED(rc))
    25642480    {
     
    25672483    }
    25682484
     2485    alock.release();
    25692486    rc = pMediumLockList->Lock();
     2487    alock.acquire();
    25702488    if (FAILED(rc))
    25712489    {
     
    26752593        /* Build the source lock list. */
    26762594        MediumLockList *pSourceMediumLockList(new MediumLockList());
     2595        alock.release();
    26772596        rc = createMediumLockList(true /* fFailIfInaccessible */,
    26782597                                  false /* fMediumLockWrite */,
    26792598                                  NULL,
    26802599                                  *pSourceMediumLockList);
     2600        alock.acquire();
    26812601        if (FAILED(rc))
    26822602        {
     
    26872607        /* Build the target lock list (including the to-be parent chain). */
    26882608        MediumLockList *pTargetMediumLockList(new MediumLockList());
     2609        alock.release();
    26892610        rc = pTarget->createMediumLockList(true /* fFailIfInaccessible */,
    26902611                                           true /* fMediumLockWrite */,
    26912612                                           pParent,
    26922613                                           *pTargetMediumLockList);
     2614        alock.acquire();
    26932615        if (FAILED(rc))
    26942616        {
     
    26982620        }
    26992621
     2622        alock.release();
    27002623        rc = pSourceMediumLockList->Lock();
     2624        alock.acquire();
    27012625        if (FAILED(rc))
    27022626        {
     
    27072631                           getLocationFull().c_str());
    27082632        }
     2633        alock.release();
    27092634        rc = pTargetMediumLockList->Lock();
     2635        alock.acquire();
    27102636        if (FAILED(rc))
    27112637        {
     
    27702696    try
    27712697    {
    2772         /* We need to lock both the current object, and the tree lock (would
    2773          * cause a lock order violation otherwise) for createMediumLockList. */
    2774         AutoMultiWriteLock2 multilock(&m->pVirtualBox->getMediaTreeLockHandle(),
    2775                                       this->lockHandle()
    2776                                       COMMA_LOCKVAL_SRC_POS);
     2698        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    27772699
    27782700        /* Build the medium lock list. */
    27792701        MediumLockList *pMediumLockList(new MediumLockList());
     2702        alock.release();
    27802703        rc = createMediumLockList(true /* fFailIfInaccessible */ ,
    27812704                                  true /* fMediumLockWrite */,
    27822705                                  NULL,
    27832706                                  *pMediumLockList);
     2707        alock.acquire();
    27842708        if (FAILED(rc))
    27852709        {
     
    27882712        }
    27892713
     2714        alock.release();
    27902715        rc = pMediumLockList->Lock();
     2716        alock.acquire();
    27912717        if (FAILED(rc))
    27922718        {
     
    28432769    try
    28442770    {
    2845         /* We need to lock both the current object, and the tree lock (would
    2846          * cause a lock order violation otherwise) for createMediumLockList. */
    2847         AutoMultiWriteLock2 multilock(&m->pVirtualBox->getMediaTreeLockHandle(),
    2848                                       this->lockHandle()
    2849                                       COMMA_LOCKVAL_SRC_POS);
     2771        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    28502772
    28512773        /* Build the medium lock list. */
    28522774        MediumLockList *pMediumLockList(new MediumLockList());
     2775        alock.release();
    28532776        rc = createMediumLockList(true /* fFailIfInaccessible */ ,
    28542777                                  true /* fMediumLockWrite */,
    28552778                                  NULL,
    28562779                                  *pMediumLockList);
     2780        alock.acquire();
    28572781        if (FAILED(rc))
    28582782        {
     
    28612785        }
    28622786
     2787        alock.release();
    28632788        rc = pMediumLockList->Lock();
     2789        alock.acquire();
    28642790        if (FAILED(rc))
    28652791        {
     
    29342860        /* Build the medium lock list. */
    29352861        MediumLockList *pMediumLockList(new MediumLockList());
     2862        multilock.release();
    29362863        rc = createMediumLockList(true /* fFailIfInaccessible */,
    29372864                                  true /* fMediumLockWrite */,
    29382865                                  NULL,
    29392866                                  *pMediumLockList);
     2867        multilock.acquire();
    29402868        if (FAILED(rc))
    29412869        {
     
    29442872        }
    29452873
    2946         /* Temporary leave this lock, cause IMedium::LockWrite, will wait for
    2947          * an running IMedium::queryInfo. If there is one running it might be
    2948          * it tries to acquire a MediaTreeLock as well -> dead-lock. */
    2949         multilock.leave();
     2874        multilock.release();
    29502875        rc = pMediumLockList->Lock();
    2951         multilock.enter();
     2876        multilock.acquire();
    29522877        if (FAILED(rc))
    29532878        {
     
    37753700 * Constructs a medium lock list for this medium. The lock is not taken.
    37763701 *
    3777  * @note Caller must lock the medium tree for writing.
     3702 * @note Caller MUST NOT hold the media tree or medium lock.
    37783703 *
    37793704 * @param fFailIfInaccessible If true, this fails with an error if a medium is inaccessible. If false,
     
    37893714                                     MediumLockList &mediumLockList)
    37903715{
    3791     // Medium::queryInfo needs write lock
    3792     Assert(m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
     3716    Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
     3717    Assert(!isWriteLockOnCurrentThread());
    37933718
    37943719    AutoCaller autoCaller(this);
     
    38113736    while (!pMedium.isNull())
    38123737    {
    3813         // need write lock for queryInfo if medium is inaccessible
    3814         AutoWriteLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
     3738        AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
    38153739
    38163740        /* Accessibility check must be first, otherwise locking interferes
     
    38203744        if (mediumState == MediumState_Inaccessible)
    38213745        {
     3746            alock.release();
    38223747            rc = pMedium->queryInfo(false /* fSetImageId */, false /* fSetParentId */);
     3748            alock.acquire();
    38233749            if (FAILED(rc)) return rc;
    38243750
     
    40814007    }
    40824008
    4083     // leave the AutoCaller, as otherwise uninit() will simply hang
     4009    // release the AutoCaller, as otherwise uninit() will simply hang
    40844010    autoCaller.release();
    40854011
     
    42004126        /* Build the medium lock list. */
    42014127        MediumLockList *pMediumLockList(new MediumLockList());
     4128        multilock.release();
    42024129        rc = createMediumLockList(true /* fFailIfInaccessible */,
    42034130                                  true /* fMediumLockWrite */,
    42044131                                  NULL,
    42054132                                  *pMediumLockList);
     4133        multilock.acquire();
    42064134        if (FAILED(rc))
    42074135        {
     
    42104138        }
    42114139
     4140        multilock.release();
    42124141        rc = pMediumLockList->Lock();
     4142        multilock.acquire();
    42134143        if (FAILED(rc))
    42144144        {
     
    42924222HRESULT Medium::markForDeletion()
    42934223{
    4294     ComAssertRet(this->lockHandle()->isWriteLockOnCurrentThread(), E_FAIL);
     4224    ComAssertRet(isWriteLockOnCurrentThread(), E_FAIL);
    42954225    switch (m->state)
    42964226    {
     
    43124242HRESULT Medium::unmarkForDeletion()
    43134243{
    4314     ComAssertRet(this->lockHandle()->isWriteLockOnCurrentThread(), E_FAIL);
     4244    ComAssertRet(isWriteLockOnCurrentThread(), E_FAIL);
    43154245    switch (m->state)
    43164246    {
     
    43304260HRESULT Medium::markLockedForDeletion()
    43314261{
    4332     ComAssertRet(this->lockHandle()->isWriteLockOnCurrentThread(), E_FAIL);
     4262    ComAssertRet(isWriteLockOnCurrentThread(), E_FAIL);
    43334263    if (   (   m->state == MediumState_LockedRead
    43344264            || m->state == MediumState_LockedWrite)
     
    43494279HRESULT Medium::unmarkLockedForDeletion()
    43504280{
    4351     ComAssertRet(this->lockHandle()->isWriteLockOnCurrentThread(), E_FAIL);
     4281    ComAssertRet(isWriteLockOnCurrentThread(), E_FAIL);
    43524282    if (   (   m->state == MediumState_LockedRead
    43534283            || m->state == MediumState_LockedWrite)
     
    44484378        /* Build the lock list. */
    44494379        aMediumLockList = new MediumLockList();
     4380        treeLock.release();
    44504381        if (fMergeForward)
    44514382            rc = pTarget->createMediumLockList(true /* fFailIfInaccessible */,
     
    44584389                                      NULL,
    44594390                                      *aMediumLockList);
     4391        treeLock.acquire();
    44604392        if (FAILED(rc))
    44614393            throw rc;
     
    45544486
    45554487        /* Update medium states appropriately */
    4556         if (m->state == MediumState_Created)
    4557         {
    4558             rc = markForDeletion();
    4559             if (FAILED(rc))
    4560                 throw rc;
    4561         }
    4562         else
    4563         {
    4564             if (fLockMedia)
    4565                 throw setStateError();
    4566             else if (   m->state == MediumState_LockedWrite
    4567                      || m->state == MediumState_LockedRead)
     4488        {
     4489            AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     4490
     4491            if (m->state == MediumState_Created)
    45684492            {
    4569                 /* Either mark it for deletion in locked state or allow
    4570                  * others to have done so. */
    4571                 if (m->preLockState == MediumState_Created)
    4572                     markLockedForDeletion();
    4573                 else if (m->preLockState != MediumState_Deleting)
     4493                rc = markForDeletion();
     4494                if (FAILED(rc))
     4495                    throw rc;
     4496            }
     4497            else
     4498            {
     4499                if (fLockMedia)
     4500                    throw setStateError();
     4501                else if (   m->state == MediumState_LockedWrite
     4502                         || m->state == MediumState_LockedRead)
     4503                {
     4504                    /* Either mark it for deletion in locked state or allow
     4505                     * others to have done so. */
     4506                    if (m->preLockState == MediumState_Created)
     4507                        markLockedForDeletion();
     4508                    else if (m->preLockState != MediumState_Deleting)
     4509                        throw setStateError();
     4510                }
     4511                else
    45744512                    throw setStateError();
    45754513            }
    4576             else
    4577                 throw setStateError();
    45784514        }
    45794515
     
    45814517        {
    45824518            /* we will need parent to reparent target */
    4583             pParentForTarget = m->pParent;
     4519            pParentForTarget = getParent();
    45844520        }
    45854521        else
     
    46414577        if (fLockMedia)
    46424578        {
     4579            treeLock.release();
    46434580            rc = aMediumLockList->Lock();
     4581            treeLock.acquire();
    46444582            if (FAILED(rc))
    46454583            {
     
    48854823HRESULT Medium::fixParentUuidOfChildren(const MediaList &childrenToReparent)
    48864824{
     4825    Assert(!isWriteLockOnCurrentThread());
     4826    Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
    48874827    MediumLockList mediumLockList;
    48884828    HRESULT rc = createMediumLockList(true /* fFailIfInaccessible */,
     
    49944934    try
    49954935    {
    4996         // locking: we need the tree lock first because we access parent pointers
    4997         // and we need to write-lock the media involved
    4998         AutoMultiWriteLock2 alock(&m->pVirtualBox->getMediaTreeLockHandle(),
    4999                                   this->lockHandle() COMMA_LOCKVAL_SRC_POS);
     4936        // This needs no extra locks besides what is done in the called methods.
    50004937
    50014938        /* Build the source lock list. */
     
    50915028        /* Build the target lock list. */
    50925029        MediumLockList *pTargetMediumLockList(new MediumLockList());
     5030        alock.release();
    50935031        rc = createMediumLockList(true /* fFailIfInaccessible */,
    50945032                                  true /* fMediumLockWrite */,
    50955033                                  aParent,
    50965034                                  *pTargetMediumLockList);
     5035        alock.acquire();
    50975036        if (FAILED(rc))
    50985037        {
     
    51015040        }
    51025041
     5042        alock.release();
    51035043        rc = pTargetMediumLockList->Lock();
     5044        alock.acquire();
    51045045        if (FAILED(rc))
    51055046        {
     
    51865127        /* Build the source lock list. */
    51875128        MediumLockList *pSourceMediumLockList(new MediumLockList());
     5129        alock.release();
    51885130        rc = createMediumLockList(true /* fFailIfInaccessible */,
    51895131                                  false /* fMediumLockWrite */,
    51905132                                  NULL,
    51915133                                  *pSourceMediumLockList);
     5134        alock.acquire();
    51925135        if (FAILED(rc))
    51935136        {
     
    51985141        /* Build the target lock list (including the to-be parent chain). */
    51995142        MediumLockList *pTargetMediumLockList(new MediumLockList());
     5143        alock.release();
    52005144        rc = aTarget->createMediumLockList(true /* fFailIfInaccessible */,
    52015145                                           true /* fMediumLockWrite */,
    52025146                                           aParent,
    52035147                                           *pTargetMediumLockList);
     5148        alock.acquire();
    52045149        if (FAILED(rc))
    52055150        {
     
    52095154        }
    52105155
     5156        alock.release();
    52115157        rc = pSourceMediumLockList->Lock();
     5158        alock.acquire();
    52125159        if (FAILED(rc))
    52135160        {
     
    52185165                           getLocationFull().c_str());
    52195166        }
     5167        alock.release();
    52205168        rc = pTargetMediumLockList->Lock();
     5169        alock.acquire();
    52215170        if (FAILED(rc))
    52225171        {
     
    52765225
    52775226/**
     5227 * @note @a aState may be NULL if the state value is not needed (only for
     5228 *       in-process calls).
     5229 */
     5230HRESULT Medium::lockRead(MediumState_T *aState, bool fWithinQueryInfo)
     5231{
     5232    /* Must not hold the object lock, as we need control over it below. */
     5233    Assert(!isWriteLockOnCurrentThread());
     5234    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     5235
     5236    /* Wait for a concurrently running Medium::queryInfo to complete. */
     5237    if (m->queryInfoRunning)
     5238    {
     5239        /* Must not hold the media tree lock, as Medium::queryInfo needs this
     5240         * lock and thus we would run into a deadlock here. */
     5241        if (!fWithinQueryInfo)
     5242            Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
     5243        while (m->queryInfoRunning)
     5244        {
     5245            alock.release();
     5246            {
     5247                AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS);
     5248            }
     5249            alock.acquire();
     5250        }
     5251    }
     5252
     5253    /* return the current state before */
     5254    if (aState)
     5255        *aState = m->state;
     5256
     5257    HRESULT rc = S_OK;
     5258
     5259    switch (m->state)
     5260    {
     5261        case MediumState_Created:
     5262        case MediumState_Inaccessible:
     5263        case MediumState_LockedRead:
     5264        {
     5265            ++m->readers;
     5266
     5267            ComAssertMsgBreak(m->readers != 0, ("Counter overflow"), rc = E_FAIL);
     5268
     5269            /* Remember pre-lock state */
     5270            if (m->state != MediumState_LockedRead)
     5271                m->preLockState = m->state;
     5272
     5273            LogFlowThisFunc(("Okay - prev state=%d readers=%d\n", m->state, m->readers));
     5274            m->state = MediumState_LockedRead;
     5275
     5276            break;
     5277        }
     5278        default:
     5279        {
     5280            LogFlowThisFunc(("Failing - state=%d\n", m->state));
     5281            rc = setStateError();
     5282            break;
     5283        }
     5284    }
     5285
     5286    return rc;
     5287}
     5288
     5289/**
     5290 * @note @a aState may be NULL if the state value is not needed (only for
     5291 *       in-process calls).
     5292 */
     5293HRESULT Medium::lockWrite(MediumState_T *aState, bool fWithinQueryInfo)
     5294{
     5295    /* Must not hold the object lock, as we need control over it below. */
     5296    Assert(!isWriteLockOnCurrentThread());
     5297    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     5298
     5299    /* Wait for a concurrently running Medium::queryInfo to complete. */
     5300    if (m->queryInfoRunning)
     5301    {
     5302        /* Must not hold the media tree lock, as Medium::queryInfo needs this
     5303         * lock and thus we would run into a deadlock here. */
     5304        if (!fWithinQueryInfo)
     5305            Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
     5306        while (m->queryInfoRunning)
     5307        {
     5308            alock.release();
     5309            {
     5310                AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS);
     5311            }
     5312            alock.acquire();
     5313        }
     5314    }
     5315
     5316    /* return the current state before */
     5317    if (aState)
     5318        *aState = m->state;
     5319
     5320    HRESULT rc = S_OK;
     5321
     5322    switch (m->state)
     5323    {
     5324        case MediumState_Created:
     5325        case MediumState_Inaccessible:
     5326        {
     5327            m->preLockState = m->state;
     5328
     5329            LogFlowThisFunc(("Okay - prev state=%d locationFull=%s\n", m->state, getLocationFull().c_str()));
     5330            m->state = MediumState_LockedWrite;
     5331            break;
     5332        }
     5333        default:
     5334        {
     5335            LogFlowThisFunc(("Failing - state=%d locationFull=%s\n", m->state, getLocationFull().c_str()));
     5336            rc = setStateError();
     5337            break;
     5338        }
     5339    }
     5340
     5341    return rc;
     5342}
     5343
     5344/**
    52785345 * Queries information from the medium.
    52795346 *
     
    52845351 *       accessibility.
    52855352 *
    5286  * @note Caller must hold medium tree for writing.
     5353 * @note Caller MUST NOT hold the media tree or medium lock.
    52875354 *
    52885355 * @note Locks mParent for reading. Locks this object for writing.
     
    52945361HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
    52955362{
    5296     Assert(m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
     5363    Assert(!isWriteLockOnCurrentThread());
    52975364    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    52985365
     
    53155382        while (m->queryInfoRunning)
    53165383        {
    5317             alock.leave();
     5384            alock.release();
    53185385            {
    53195386                AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS);
    53205387            }
    5321             alock.enter();
     5388            alock.acquire();
    53225389        }
    53235390
    53245391        return S_OK;
    53255392    }
     5393
     5394    alock.release();
     5395    Assert(!isWriteLockOnCurrentThread());
     5396    Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
     5397    AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
     5398    alock.acquire();
    53265399
    53275400    bool success = false;
     
    53495422
    53505423    /* Lock the medium, which makes the behavior much more consistent */
     5424    alock.release();
    53515425    if (uOpenFlags & (VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_SHAREABLE))
    5352         rc = LockRead(NULL);
     5426        rc = lockRead(NULL, true /* fWithinQueryInfo */);
    53535427    else
    5354         rc = LockWrite(NULL);
     5428        rc = lockWrite(NULL, true /* fWithinQueryInfo */);
    53555429    if (FAILED(rc)) return rc;
     5430    alock.acquire();
    53565431
    53575432    /* Copies of the input state fields which are not read-only,
     
    53735448    bool fRepairImageZeroParentUuid = false;
    53745449
    5375     /* leave the object lock before a lengthy operation */
     5450    /* release the object lock before a lengthy operation */
    53765451    m->queryInfoRunning = true;
    5377     alock.leave();
     5452    alock.release();
     5453    treeLock.release();
     5454    Assert(!isWriteLockOnCurrentThread());
     5455    Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
     5456
    53785457    /* Note that taking the queryInfoSem after leaving the object lock above
    53795458     * can lead to short spinning of the loops waiting for queryInfo() to
     
    55205599
    55215600                    /* we set mParent & children() */
    5522                     AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
     5601                    treeLock.acquire();
    55235602
    55245603                    Assert(m->pParent.isNull());
    55255604                    m->pParent = pParent;
    55265605                    m->pParent->m->llChildren.push_back(this);
     5606
     5607                    treeLock.release();
    55275608                }
    55285609                else
    55295610                {
    55305611                    /* we access mParent */
    5531                     AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
     5612                    treeLock.acquire();
    55325613
    55335614                    /* check that parent UUIDs match. Note that there's no need
     
    55735654                    /// accessible while the diff is? Probably nothing. The
    55745655                    /// real code will detect the mismatch anyway.
     5656
     5657                    treeLock.release();
    55755658                }
    55765659            }
     
    55935676    }
    55945677
    5595     alock.enter();
     5678    treeLock.acquire();
     5679    alock.acquire();
    55965680
    55975681    if (isImport || fSetImageId)
     
    56425726        if (FAILED(rc)) return rc;
    56435727
    5644         alock.leave();
     5728        alock.release();
    56455729
    56465730        try
     
    56775761        }
    56785762
    5679         alock.enter();
     5763        alock.acquire();
    56805764
    56815765        rc = UnlockWrite(NULL);
     
    57125796 * Unregisters this medium with mVirtualBox. Called by close() under the medium tree lock.
    57135797 *
    5714  * This calls either VirtualBox::unregisterImage or VirtualBox::unregisterHardDisk depending
    5715  * on the device type of this medium.
    5716  *
    57175798 * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs that will receive the registry IDs that need saving.
    57185799 *
     
    57325813        deparent();
    57335814
    5734     HRESULT rc = E_FAIL;
    5735     switch (m->devType)
    5736     {
    5737         case DeviceType_DVD:
    5738         case DeviceType_Floppy:
    5739             rc = m->pVirtualBox->unregisterImage(this,
    5740                                                  m->devType,
    5741                                                  pllRegistriesThatNeedSaving);
    5742         break;
    5743 
    5744         case DeviceType_HardDisk:
    5745             rc = m->pVirtualBox->unregisterHardDisk(this, pllRegistriesThatNeedSaving);
    5746         break;
    5747 
    5748         default:
    5749         break;
    5750     }
    5751 
     5815    HRESULT rc = m->pVirtualBox->unregisterMedium(this, pllRegistriesThatNeedSaving);
    57525816    if (FAILED(rc))
    57535817    {
     
    64296493        {
    64306494            id.create();
    6431             /* VirtualBox::registerHardDisk() will need UUID */
     6495            /* VirtualBox::registerMedium() will need UUID */
    64326496            unconst(m->id) = id;
    64336497        }
     
    64956559         * better than breaking media registry consistency) */
    64966560        AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
    6497         rc = m->pVirtualBox->registerHardDisk(this, NULL /* pllRegistriesThatNeedSaving */);
    6498     }
    6499 
    6500     // reenter the lock before changing state
     6561        ComObjPtr<Medium> pMedium;
     6562        rc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk,
     6563                                            NULL /* pllRegistriesThatNeedSaving */);
     6564        Assert(this == pMedium);
     6565    }
     6566
     6567    // re-acquire the lock before changing state
    65016568    AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
    65026569
     
    65586625        {
    65596626            targetId.create();
    6560             /* VirtualBox::registerHardDisk() will need UUID */
     6627            /* VirtualBox::registerMedium() will need UUID */
    65616628            unconst(pTarget->m->id) = targetId;
    65626629        }
     
    66726739         * Created state only on success (leaving an orphan file is
    66736740         * better than breaking media registry consistency) */
    6674         mrc = m->pVirtualBox->registerHardDisk(pTarget, &llRegistriesThatNeedSaving);
     6741        ComObjPtr<Medium> pMedium;
     6742        mrc = m->pVirtualBox->registerMedium(pTarget, &pMedium, DeviceType_HardDisk,
     6743                                             &llRegistriesThatNeedSaving);
     6744        Assert(pTarget == pMedium);
    66756745
    66766746        if (FAILED(mrc))
     
    68916961            /* first, unregister the target since it may become a base
    68926962             * medium which needs re-registration */
    6893             rc2 = m->pVirtualBox->unregisterHardDisk(pTarget, NULL /*&fNeedsGlobalSaveSettings*/);
     6963            rc2 = m->pVirtualBox->unregisterMedium(pTarget, NULL /*pfNeedsGlobalSaveSettings*/);
    68946964            AssertComRC(rc2);
    68956965
     
    69056975
    69066976            /* then, register again */
    6907             rc2 = m->pVirtualBox->registerHardDisk(pTarget, NULL /* pllRegistriesThatNeedSaving */ );
     6977            ComObjPtr<Medium> pMedium;
     6978            rc2 = m->pVirtualBox->registerMedium(pTarget, &pMedium,
     6979                                                 DeviceType_HardDisk,
     6980                                                 NULL /* pllRegistriesThatNeedSaving */ );
    69086981            AssertComRC(rc2);
    69096982        }
     
    69587031            }
    69597032
    6960             rc2 = pMedium->m->pVirtualBox->unregisterHardDisk(pMedium,
    6961                                                               NULL /*pfNeedsGlobalSaveSettings*/);
     7033            rc2 = pMedium->m->pVirtualBox->unregisterMedium(pMedium,
     7034                                                            NULL /*pfNeedsGlobalSaveSettings*/);
    69627035            AssertComRC(rc2);
    69637036
     
    72547327             * better than breaking media registry consistency) */
    72557328            eik.restore();
    7256             mrc = pParent->m->pVirtualBox->registerHardDisk(pTarget, NULL /* pllRegistriesThatNeedSaving */);
     7329            ComObjPtr<Medium> pMedium;
     7330            mrc = pParent->m->pVirtualBox->registerMedium(pTarget, &pMedium,
     7331                                                          DeviceType_HardDisk,
     7332                                                          NULL /* pllRegistriesThatNeedSaving */);
     7333            Assert(pTarget == pMedium);
    72577334            eik.fetch();
    72587335
     
    72657342            /* just register  */
    72667343            eik.restore();
    7267             mrc = m->pVirtualBox->registerHardDisk(pTarget, NULL /* pllRegistriesThatNeedSaving */);
     7344            ComObjPtr<Medium> pMedium;
     7345            mrc = m->pVirtualBox->registerMedium(pTarget, &pMedium,
     7346                                                 DeviceType_HardDisk,
     7347                                                 NULL /* pllRegistriesThatNeedSaving */);
     7348            Assert(pTarget == pMedium);
    72687349            eik.fetch();
    72697350        }
     
    80298110             * better than breaking media registry consistency) */
    80308111            eik.restore();
    8031             mrc = pParent->m->pVirtualBox->registerHardDisk(this, NULL /* llRegistriesThatNeedSaving */);
     8112            ComObjPtr<Medium> pMedium;
     8113            mrc = pParent->m->pVirtualBox->registerMedium(this, &pMedium,
     8114                                                          DeviceType_HardDisk,
     8115                                                          NULL /* llRegistriesThatNeedSaving */);
     8116            Assert(this == pMedium);
    80328117            eik.fetch();
    80338118
     
    80408125            /* just register  */
    80418126            eik.restore();
    8042             mrc = m->pVirtualBox->registerHardDisk(this, NULL /* pllRegistriesThatNeedSaving */);
     8127            ComObjPtr<Medium> pMedium;
     8128            mrc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk,
     8129                                                 NULL /* pllRegistriesThatNeedSaving */);
     8130            Assert(this == pMedium);
    80438131            eik.fetch();
    80448132        }
  • trunk/src/VBox/Main/src-server/SnapshotImpl.cpp

    r39248 r40257  
    66
    77/*
    8  * Copyright (C) 2006-2011 Oracle Corporation
     8 * Copyright (C) 2006-2012 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    341341    {
    342342        m->strName = strName;
    343         alock.leave(); /* Important! (child->parent locks are forbidden) */
     343        alock.release(); /* Important! (child->parent locks are forbidden) */
    344344        rc = m->pMachine->onSnapshotChange(this);
    345345    }
     
    374374    {
    375375        m->strDescription = strDescription;
    376         alock.leave(); /* Important! (child->parent locks are forbidden) */
     376        alock.release(); /* Important! (child->parent locks are forbidden) */
    377377        rc = m->pMachine->onSnapshotChange(this);
    378378    }
     
    12321232    HRESULT rc = mPeer->saveSettings(&fNeedsGlobalSaveSettings,
    12331233                                     SaveS_Force);        // we know we need saving, no need to check
    1234     mlock.leave();
     1234    mlock.release();
    12351235
    12361236    if (SUCCEEDED(rc) && fNeedsGlobalSaveSettings)
     
    18341834            }
    18351835
    1836             /* leave the locks before the potentially lengthy operation */
     1836            /* release the locks before the potentially lengthy operation */
    18371837            snapshotLock.release();
    1838             alock.leave();
     1838            alock.release();
    18391839
    18401840            rc = createImplicitDiffs(aTask.pProgress,
     
    18451845                throw rc;
    18461846
    1847             alock.enter();
     1847            alock.acquire();
    18481848            snapshotLock.acquire();
    18491849
     
    19511951
    19521952        // let go of the locks while we're deleting image files below
    1953         alock.leave();
     1953        alock.release();
    19541954        // from here on we cannot roll back on failure any more
    19551955
     
    23022302    {
    23032303        /* Locking order:  */
    2304         AutoMultiWriteLock3 multiLock(this->lockHandle(),                   // machine
    2305                                       aTask.pSnapshot->lockHandle(),        // snapshot
    2306                                       &mParent->getMediaTreeLockHandle()    // media tree
     2304        AutoMultiWriteLock2 multiLock(this->lockHandle(),                   // machine
     2305                                      aTask.pSnapshot->lockHandle()         // snapshot
    23072306                                      COMMA_LOCKVAL_SRC_POS);
    2308             // once we have this lock, we know that SessionMachine::DeleteSnapshot()
    2309             // has exited after setting the machine state to MachineState_DeletingSnapshot
     2307        // once we have this lock, we know that SessionMachine::DeleteSnapshot()
     2308        // has exited after setting the machine state to MachineState_DeletingSnapshot
     2309
     2310        AutoWriteLock treeLock(mParent->getMediaTreeLockHandle()
     2311                                      COMMA_LOCKVAL_SRC_POS);
    23102312
    23112313        ComObjPtr<SnapshotMachine> pSnapMachine = aTask.pSnapshot->getSnapshotMachine();
     
    23842386                    fOnlineMergePossible = false;
    23852387            }
     2388
     2389            // no need to hold the lock any longer
     2390            attachLock.release();
     2391
     2392            treeLock.release();
    23862393            rc = prepareDeleteSnapshotMedium(pHD, machineId, snapshotId,
    23872394                                             fOnlineMergePossible,
     
    23912398                                             fNeedsOnlineMerge,
    23922399                                             pMediumLockList);
     2400            treeLock.acquire();
    23932401            if (FAILED(rc))
    23942402                throw rc;
    2395 
    2396             // no need to hold the lock any longer
    2397             attachLock.release();
    23982403
    23992404            // For simplicity, prepareDeleteSnapshotMedium selects the merge
     
    24652470        }
    24662471
    2467         // we can release the lock now since the machine state is MachineState_DeletingSnapshot
     2472        // we can release the locks now since the machine state is MachineState_DeletingSnapshot
     2473        treeLock.release();
    24682474        multiLock.release();
    24692475
     
    27862792                                                    MediumLockList * &aMediumLockList)
    27872793{
    2788     Assert(mParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
     2794    Assert(!mParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
    27892795    Assert(!fOnlineMergePossible || VALID_PTR(aVMMALockList));
    27902796
     
    28122818            /* lock only, to prevent any usage until the snapshot deletion
    28132819             * is completed */
     2820            alock.release();
    28142821            return aHD->LockWrite(NULL);
    28152822        }
     
    28292836    ComObjPtr<Medium> pChild = aHD->getChildren().front();
    28302837
    2831     /* we keep this locked, so lock the affected child to make sure the lock
    2832      * order is correct when calling prepareMergeTo() */
    28332838    AutoWriteLock childLock(pChild COMMA_LOCKVAL_SRC_POS);
    28342839
     
    28432848            /* backward merge is too tricky, we'll just detach on snapshot
    28442849             * deletion, so lock only, to prevent any usage */
     2850            childLock.release();
     2851            alock.release();
    28452852            return aHD->LockWrite(NULL);
    28462853        }
     
    28572864
    28582865    HRESULT rc;
     2866    childLock.release();
     2867    alock.release();
    28592868    rc = aSource->prepareMergeTo(aTarget, &aMachineId, &aSnapshotId,
    28602869                                 !fOnlineMergePossible /* fLockMedia */,
    28612870                                 aMergeForward, aParentForTarget,
    28622871                                 aChildrenToReparent, aMediumLockList);
     2872    alock.acquire();
     2873    childLock.acquire();
    28632874    if (SUCCEEDED(rc) && fOnlineMergePossible)
    28642875    {
     
    28672878         * asking the VM to do the merging. Only continue with the online
    28682879         * merging preparation if applicable. */
     2880        childLock.release();
     2881        alock.release();
    28692882        rc = aMediumLockList->Lock();
     2883        alock.acquire();
     2884        childLock.acquire();
    28702885        if (FAILED(rc) && fOnlineMergePossible)
    28712886        {
     
    28952910                }
    28962911                bool fLockReq = (it2->GetLockRequest() || it->GetLockRequest());
     2912                childLock.release();
     2913                alock.release();
    28972914                rc = it->UpdateLock(fLockReq);
     2915                alock.acquire();
     2916                childLock.acquire();
    28982917                if (FAILED(rc))
    28992918                {
     
    29122931                {
    29132932                    ComObjPtr<Medium> pMedium = *it;
     2933                    AutoReadLock mediumLock(pMedium COMMA_LOCKVAL_SRC_POS);
    29142934                    if (pMedium->getState() == MediumState_Created)
    29152935                    {
     2936                        mediumLock.release();
     2937                        childLock.release();
     2938                        alock.release();
    29162939                        rc = pMedium->LockWrite(NULL);
     2940                        alock.acquire();
     2941                        childLock.acquire();
     2942                        mediumLock.acquire();
    29172943                        if (FAILED(rc))
    29182944                            throw rc;
     
    29202946                    else
    29212947                    {
     2948                        mediumLock.release();
     2949                        childLock.release();
     2950                        alock.release();
    29222951                        rc = aVMMALockList->Update(pMedium, true);
     2952                        alock.acquire();
     2953                        childLock.acquire();
     2954                        mediumLock.acquire();
    29232955                        if (FAILED(rc))
    29242956                        {
     2957                            mediumLock.release();
     2958                            childLock.release();
     2959                            alock.release();
    29252960                            rc = pMedium->LockWrite(NULL);
     2961                            alock.acquire();
     2962                            childLock.acquire();
     2963                            mediumLock.acquire();
    29262964                            if (FAILED(rc))
    2927                             throw rc;
     2965                                throw rc;
    29282966                        }
    29292967                    }
     
    29332971            if (fOnlineMergePossible)
    29342972            {
     2973                childLock.release();
     2974                alock.release();
    29352975                rc = aVMMALockList->Lock();
     2976                alock.acquire();
     2977                childLock.acquire();
    29362978                if (FAILED(rc))
    29372979                {
     
    29673009                     ++it)
    29683010                {
     3011                    childLock.release();
     3012                    alock.release();
    29693013                    it->UpdateLock(it == lockListLast);
     3014                    alock.acquire();
     3015                    childLock.acquire();
    29703016                    ComObjPtr<Medium> pMedium = it->GetMedium();
    29713017                    AutoWriteLock mediumLock(pMedium COMMA_LOCKVAL_SRC_POS);
     
    30583104                    pMedium->unmarkLockedForDeletion();
    30593105                }
     3106                mediumLock.release();
    30603107                it->UpdateLock(it == lockListLast);
     3108                mediumLock.acquire();
    30613109            }
    30623110        }
     
    32223270        // first, unregister the target since it may become a base
    32233271        // hard disk which needs re-registration
    3224         rc = mParent->unregisterHardDisk(pTarget, NULL /*&fNeedsGlobalSaveSettings*/);
     3272        rc = mParent->unregisterMedium(pTarget, NULL /*&fNeedsGlobalSaveSettings*/);
    32253273        AssertComRC(rc);
    32263274
     
    32333281
    32343282        // then, register again
    3235         rc = mParent->registerHardDisk(pTarget, NULL /* pllRegistriesThatNeedSaving */);
     3283        rc = mParent->registerMedium(pTarget, &pTarget, DeviceType_HardDisk,
     3284                                     NULL /* pllRegistriesThatNeedSaving */);
    32363285        AssertComRC(rc);
    32373286    }
     
    32613310                toReparent.push_back(pMedium);
    32623311            }
     3312            treeLock.release();
    32633313            pTarget->fixParentUuidOfChildren(toReparent);
     3314            treeLock.acquire();
    32643315
    32653316            // obey {parent,child} lock order
     
    33043355        else
    33053356        {
    3306             rc = mParent->unregisterHardDisk(pMedium,
    3307                                              NULL /*pfNeedsGlobalSaveSettings*/);
     3357            rc = mParent->unregisterMedium(pMedium, NULL /*pfNeedsGlobalSaveSettings*/);
    33083358            AssertComRC(rc);
    33093359
  • trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp

    r40205 r40257  
    628628        if (FAILED(rc)) return rc;
    629629
    630         rc = registerHardDisk(pHardDisk, NULL /* pllRegistriesThatNeedSaving */);
     630        rc = registerMedium(pHardDisk, &pHardDisk, DeviceType_HardDisk,
     631                            NULL /* pllRegistriesThatNeedSaving */);
    631632        if (FAILED(rc)) return rc;
    632633    }
     
    648649        if (FAILED(rc)) return rc;
    649650
    650         rc = registerImage(pImage,
    651                            DeviceType_DVD,
    652                            NULL /* pllRegistriesThatNeedSaving */);
     651        rc = registerMedium(pImage, &pImage, DeviceType_DVD,
     652                            NULL /* pllRegistriesThatNeedSaving */);
    653653        if (FAILED(rc)) return rc;
    654654    }
     
    670670        if (FAILED(rc)) return rc;
    671671
    672         rc = registerImage(pImage,
    673                            DeviceType_Floppy,
    674                            NULL /* pllRegistriesThatNeedSaving */);
     672        rc = registerMedium(pImage, &pImage, DeviceType_Floppy,
     673                            NULL /* pllRegistriesThatNeedSaving */);
    675674        if (FAILED(rc)) return rc;
    676675    }
     
    17131712    {
    17141713        pMedium.createObject();
     1714        treeLock.release();
    17151715        rc = pMedium->init(this,
    17161716                           aLocation,
     
    17181718                           fForceNewUuid,
    17191719                           deviceType);
     1720        treeLock.acquire();
    17201721
    17211722        if (SUCCEEDED(rc))
    17221723        {
    1723             switch (deviceType)
    1724             {
    1725                 case DeviceType_HardDisk:
    1726                     rc = registerHardDisk(pMedium, NULL /* pllRegistriesThatNeedSaving */);
    1727                 break;
    1728 
    1729                 case DeviceType_DVD:
    1730                 case DeviceType_Floppy:
    1731                     rc = registerImage(pMedium,
    1732                                        deviceType,
    1733                                        NULL /* pllRegistriesThatNeedSaving */);
    1734                 break;
    1735             }
     1724            rc = registerMedium(pMedium, &pMedium, deviceType,
     1725                                NULL /* pllRegistriesThatNeedSaving */);
    17361726
    17371727            treeLock.release();
     
    32003190 * @param aLocation     Location to check.
    32013191 * @param aConflict     Where to return parameters of the conflicting medium.
     3192 * @param ppMedium      Medium reference in case this is simply a duplicate.
    32023193 *
    32033194 * @note Locks the media tree and media objects for reading.
     
    32063197                                           const Utf8Str &aLocation,
    32073198                                           Utf8Str &aConflict,
    3208                                            bool &fIdentical)
    3209 {
     3199                                           ComObjPtr<Medium> *ppMedium)
     3200{
     3201    AssertReturn(!aId.isEmpty() && !aLocation.isEmpty(), E_FAIL);
     3202    AssertReturn(!ppMedium, E_INVALIDARG);
     3203
    32103204    aConflict.setNull();
    3211 
    3212     AssertReturn(!aId.isEmpty() && !aLocation.isEmpty(), E_FAIL);
     3205    ppMedium->setNull();
    32133206
    32143207    AutoReadLock alock(getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
    32153208
    32163209    HRESULT rc = S_OK;
    3217 
    3218     aConflict.setNull();
    3219     fIdentical = false;
    32203210
    32213211    ComObjPtr<Medium> pMediumFound;
     
    32543244             && (idFound == aId)
    32553245           )
    3256             fIdentical = true;
     3246            *ppMedium = pMediumFound;
    32573247
    32583248        aConflict = Utf8StrFmt(tr("%s '%s' with UUID {%RTuuid}"),
     
    35423532
    35433533/**
    3544  * Remembers the given hard disk by storing it in either the global hard disk registry
    3545  * or a machine one.
    3546  *
    3547  * @note Caller must hold the media tree lock for writing; in addition, this locks @a aHardDisk for reading
    3548  *
    3549  * @param aHardDisk Hard disk object to remember.
    3550  * @param uuidMachineRegistry UUID of machine whose registry should be used, or a NULL UUID for the global registry.
     3534 * Remembers the given medium object by storing it in either the global
     3535 * medium registry or a machine one.
     3536 *
     3537 * @note Caller must hold the media tree lock for writing; in addition, this
     3538 * locks @a pMedium for reading
     3539 *
     3540 * @param pMedium   Hard disk object to remember.
     3541 * @param ppMedium  Actually stored hard disk object. Can be different if due
     3542 *                  to an unavoidable race there was a duplicate Medium object
     3543 *                  created.
     3544 * @param argType   Either DeviceType_DVD or DeviceType_Floppy.
    35513545 * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs of media registries that need saving.
    35523546 * @return
    35533547 */
    3554 HRESULT VirtualBox::registerHardDisk(Medium *pMedium,
    3555                                      GuidList *pllRegistriesThatNeedSaving)
     3548HRESULT VirtualBox::registerMedium(Medium *pMedium,
     3549                                   ComObjPtr<Medium> *ppMedium,
     3550                                   DeviceType_T argType,
     3551                                   GuidList *pllRegistriesThatNeedSaving)
    35563552{
    35573553    AssertReturn(pMedium != NULL, E_INVALIDARG);
     3554    AssertReturn(ppMedium != NULL, E_INVALIDARG);
    35583555
    35593556    AutoCaller autoCaller(this);
    35603557    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    35613558
    3562     AutoCaller hardDiskCaller(pMedium);
    3563     AssertComRCReturn(hardDiskCaller.rc(), hardDiskCaller.rc());
     3559    AutoCaller mediumCaller(pMedium);
     3560    AssertComRCReturn(mediumCaller.rc(), mediumCaller.rc());
     3561
     3562    const char *pszDevType = NULL;
     3563    ObjectsList<Medium> *pall = NULL;
     3564    switch (argType)
     3565    {
     3566        case DeviceType_HardDisk:
     3567            pall = &m->allHardDisks;
     3568            pszDevType = tr("hard disk");
     3569            break;
     3570        case DeviceType_DVD:
     3571            pszDevType = tr("DVD image");
     3572            pall = &m->allDVDImages;
     3573            break;
     3574        case DeviceType_Floppy:
     3575            pszDevType = tr("floppy image");
     3576            pall = &m->allFloppyImages;
     3577            break;
     3578        default:
     3579            AssertMsgFailedReturn(("invalid device type %d", argType), E_INVALIDARG);
     3580    }
    35643581
    35653582    // caller must hold the media tree write lock
     
    35703587    ComObjPtr<Medium> pParent;
    35713588    {
    3572         AutoReadLock hardDiskLock(pMedium COMMA_LOCKVAL_SRC_POS);
     3589        AutoReadLock mediumLock(pMedium COMMA_LOCKVAL_SRC_POS);
    35733590        id = pMedium->getId();
    35743591        strLocationFull = pMedium->getLocationFull();
     
    35793596
    35803597    Utf8Str strConflict;
    3581     bool fIdentical;
     3598    ComObjPtr<Medium> pDupMedium;
    35823599    rc = checkMediaForConflicts(id,
    35833600                                strLocationFull,
    35843601                                strConflict,
    3585                                 fIdentical);
     3602                                &pDupMedium);
    35863603    if (FAILED(rc)) return rc;
    35873604
    3588     if (!fIdentical)
     3605    if (pDupMedium.isNull())
    35893606    {
    35903607        if (strConflict.length())
    35913608            return setError(E_INVALIDARG,
    3592                             tr("Cannot register the hard disk '%s' {%RTuuid} because a %s already exists"),
     3609                            tr("Cannot register the %s '%s' {%RTuuid} because a %s already exists"),
     3610                            pszDevType,
    35933611                            strLocationFull.c_str(),
    35943612                            id.raw(),
     
    35963614                            m->strSettingsFilePath.c_str());
    35973615
    3598         // store base (root) hard disks in the list
     3616        // add to the collection if it is a base medium
    35993617        if (pParent.isNull())
    3600             m->allHardDisks.getList().push_back(pMedium);
    3601                     // access the list directly because we already locked the list above
     3618            pall->getList().push_back(pMedium);
    36023619
    36033620        // store all hard disks (even differencing images) in the map
    3604         m->mapHardDisks[id] = pMedium;
     3621        if (argType == DeviceType_HardDisk)
     3622            m->mapHardDisks[id] = pMedium;
    36053623
    36063624        if (pllRegistriesThatNeedSaving)
    36073625            pMedium->addToRegistryIDList(*pllRegistriesThatNeedSaving);
    36083626    }
     3627    else
     3628        pMedium = pDupMedium;
     3629
     3630    *ppMedium = pMedium;
    36093631
    36103632    return rc;
     
    36123634
    36133635/**
    3614  * Removes the given hard disk from the hard disk registry.
    3615  *
    3616  * @param aHardDisk     Hard disk object to remove.
     3636 * Removes the given medium from the respective registry.
     3637 *
     3638 * @param pMedium    Hard disk object to remove.
    36173639 * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
    36183640 *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
    36193641 *
    3620  * @note Caller must hold the media tree lock for writing; in addition, this locks @a aHardDisk for reading
    3621  */
    3622 HRESULT VirtualBox::unregisterHardDisk(Medium *aHardDisk,
    3623                                        GuidList *pllRegistriesThatNeedSaving)
    3624 {
    3625     AssertReturn(aHardDisk != NULL, E_INVALIDARG);
     3642 * @note Caller must hold the media tree lock for writing; in addition, this locks @a pMedium for reading
     3643 */
     3644HRESULT VirtualBox::unregisterMedium(Medium *pMedium,
     3645                                     GuidList *pllRegistriesThatNeedSaving)
     3646{
     3647    AssertReturn(pMedium != NULL, E_INVALIDARG);
    36263648
    36273649    AutoCaller autoCaller(this);
    36283650    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    36293651
    3630     AutoCaller hardDiskCaller(aHardDisk);
    3631     AssertComRCReturn(hardDiskCaller.rc(), hardDiskCaller.rc());
     3652    AutoCaller mediumCaller(pMedium);
     3653    AssertComRCReturn(mediumCaller.rc(), mediumCaller.rc());
    36323654
    36333655    // caller must hold the media tree write lock
     
    36363658    Guid id;
    36373659    ComObjPtr<Medium> pParent;
    3638     {
    3639         AutoReadLock hardDiskLock(aHardDisk COMMA_LOCKVAL_SRC_POS);
    3640         id = aHardDisk->getId();
    3641         pParent = aHardDisk->getParent();
    3642     }
    3643 
    3644     // remove base (root) hard disks from the list
     3660    DeviceType_T devType;
     3661    {
     3662        AutoReadLock mediumLock(pMedium COMMA_LOCKVAL_SRC_POS);
     3663        id = pMedium->getId();
     3664        pParent = pMedium->getParent();
     3665        devType = pMedium->getDeviceType();
     3666    }
     3667
     3668    ObjectsList<Medium> *pall = NULL;
     3669    switch (devType)
     3670    {
     3671        case DeviceType_HardDisk:
     3672            pall = &m->allHardDisks;
     3673            break;
     3674        case DeviceType_DVD:
     3675            pall = &m->allDVDImages;
     3676            break;
     3677        case DeviceType_Floppy:
     3678            pall = &m->allFloppyImages;
     3679            break;
     3680        default:
     3681            AssertMsgFailedReturn(("invalid device type %d", devType), E_INVALIDARG);
     3682    }
     3683
     3684    // remove from the collection if it is a base medium
    36453685    if (pParent.isNull())
    3646         m->allHardDisks.getList().remove(aHardDisk);
    3647                 // access the list directly because caller must have locked the list
     3686        pall->getList().remove(pMedium);
    36483687
    36493688    // remove all hard disks (even differencing images) from map
    3650     size_t cnt = m->mapHardDisks.erase(id);
    3651     Assert(cnt == 1);
    3652     NOREF(cnt);
     3689    if (devType == DeviceType_HardDisk)
     3690    {
     3691        size_t cnt = m->mapHardDisks.erase(id);
     3692        Assert(cnt == 1);
     3693        NOREF(cnt);
     3694    }
    36533695
    36543696    if (pllRegistriesThatNeedSaving)
    3655         aHardDisk->addToRegistryIDList(*pllRegistriesThatNeedSaving);
     3697        pMedium->addToRegistryIDList(*pllRegistriesThatNeedSaving);
    36563698
    36573699    return S_OK;
    3658 }
    3659 
    3660 /**
    3661  * Remembers the given image by storing it in the CD/DVD or floppy image registry.
    3662  *
    3663  * @param argImage      Image object to remember.
    3664  * @param argType       Either DeviceType_DVD or DeviceType_Floppy.
    3665  * @param uuidMachineRegistry UUID of machine whose registry should be used, or a NULL UUID for the global registry.
    3666  *
    3667  * @note Caller must hold the media tree lock for writing; in addition, this locks @a argImage for reading
    3668  */
    3669 HRESULT VirtualBox::registerImage(Medium *pMedium,
    3670                                   DeviceType_T argType,
    3671                                   GuidList *pllRegistriesThatNeedSaving)
    3672 {
    3673     AssertReturn(pMedium != NULL, E_INVALIDARG);
    3674 
    3675     AutoCaller autoCaller(this);
    3676     AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    3677 
    3678     AutoCaller imageCaller(pMedium);
    3679     AssertComRCReturn(imageCaller.rc(), imageCaller.rc());
    3680 
    3681     // caller must hold the media tree write lock
    3682     Assert(getMediaTreeLockHandle().isWriteLockOnCurrentThread());
    3683 
    3684     Guid id;
    3685     Utf8Str strLocationFull;
    3686     ComObjPtr<Medium> pParent;
    3687     {
    3688         AutoReadLock al(pMedium COMMA_LOCKVAL_SRC_POS);
    3689         id = pMedium->getId();
    3690         strLocationFull = pMedium->getLocationFull();
    3691         pParent = pMedium->getParent();
    3692     }
    3693 
    3694     // work on DVDs or floppies list?
    3695     ObjectsList<Medium> &all = (argType == DeviceType_DVD) ? m->allDVDImages : m->allFloppyImages;
    3696 
    3697     HRESULT rc;
    3698     // lock the images lists (list + map) while checking for conflicts
    3699     AutoWriteLock al(all.getLockHandle() COMMA_LOCKVAL_SRC_POS);
    3700 
    3701     Utf8Str strConflict;
    3702     bool fIdentical;
    3703     rc = checkMediaForConflicts(id,
    3704                                 strLocationFull,
    3705                                 strConflict,
    3706                                 fIdentical);
    3707     if (FAILED(rc)) return rc;
    3708 
    3709     if (!fIdentical)
    3710     {
    3711         if (strConflict.length())
    3712             return setError(VBOX_E_INVALID_OBJECT_STATE,
    3713                             tr("Cannot register the image '%s' with UUID {%RTuuid} because a %s already exists"),
    3714                             strLocationFull.c_str(),
    3715                             id.raw(),
    3716                             strConflict.c_str());
    3717 
    3718         // add to the collection
    3719         all.getList().push_back(pMedium);
    3720                 // access the list directly because we already locked the list above
    3721 
    3722         if (pllRegistriesThatNeedSaving)
    3723             pMedium->addToRegistryIDList(*pllRegistriesThatNeedSaving);
    3724     }
    3725 
    3726     return rc;
    3727 }
    3728 
    3729 /**
    3730  * Removes the given image from the CD/DVD or floppy image registry.
    3731  *
    3732  * @param argImage        Image object to remove.
    3733  * @param argType         Either DeviceType_DVD or DeviceType_Floppy.
    3734  * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
    3735  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
    3736  *
    3737  * @note Caller must hold the media tree lock for writing; in addition, this locks @a argImage for reading
    3738  */
    3739 HRESULT VirtualBox::unregisterImage(Medium *argImage,
    3740                                     DeviceType_T argType,
    3741                                     GuidList *pllRegistriesThatNeedSaving)
    3742 {
    3743     AssertReturn(argImage != NULL, E_INVALIDARG);
    3744 
    3745     AutoCaller autoCaller(this);
    3746     AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    3747 
    3748     AutoCaller imageCaller(argImage);
    3749     AssertComRCReturn(imageCaller.rc(), imageCaller.rc());
    3750 
    3751     // caller must hold the media tree write lock
    3752     Assert(getMediaTreeLockHandle().isWriteLockOnCurrentThread());
    3753 
    3754     Guid id;
    3755     ComObjPtr<Medium> pParent;
    3756     {
    3757         AutoReadLock al(argImage COMMA_LOCKVAL_SRC_POS);
    3758         id = argImage->getId();
    3759         pParent = argImage->getParent();
    3760     }
    3761 
    3762     // work on DVDs or floppies list?
    3763     ObjectsList<Medium> &all = (argType == DeviceType_DVD) ? m->allDVDImages : m->allFloppyImages;
    3764 
    3765     // access the list directly because the caller must have requested the lock
    3766     all.getList().remove(argImage);
    3767 
    3768     HRESULT rc = S_OK;
    3769 
    3770     if (pllRegistriesThatNeedSaving)
    3771         argImage->addToRegistryIDList(*pllRegistriesThatNeedSaving);
    3772 
    3773     return rc;
    37743700}
    37753701
     
    47424668
    47434669/**
    4744  * Remembers the given dhcp server by storing it in the hard disk registry.
    4745  *
    4746  * @param aDHCPServer     Dhcp Server object to remember.
    4747  * @param aSaveRegistry @c true to save hard disk registry to disk (default).
    4748  *
    4749  * When @a aSaveRegistry is @c true, this operation may fail because of the
     4670 * Remembers the given DHCP server in the settings.
     4671 *
     4672 * @param aDHCPServer   DHCP server object to remember.
     4673 * @param aSaveSettings @c true to save settings to disk (default).
     4674 *
     4675 * When @a aSaveSettings is @c true, this operation may fail because of the
    47504676 * failed #saveSettings() method it calls. In this case, the dhcp server object
    47514677 * will not be remembered. It is therefore the responsibility of the caller to
     
    47574683 */
    47584684HRESULT VirtualBox::registerDHCPServer(DHCPServer *aDHCPServer,
    4759                                        bool aSaveRegistry /*= true*/)
     4685                                       bool aSaveSettings /*= true*/)
    47604686{
    47614687    AssertReturn(aDHCPServer != NULL, E_INVALIDARG);
     
    47814707    m->allDHCPServers.addChild(aDHCPServer);
    47824708
    4783     if (aSaveRegistry)
     4709    if (aSaveSettings)
    47844710    {
    47854711        AutoWriteLock vboxLock(this COMMA_LOCKVAL_SRC_POS);
     
    47884714
    47894715        if (FAILED(rc))
    4790             unregisterDHCPServer(aDHCPServer, false /* aSaveRegistry */);
     4716            unregisterDHCPServer(aDHCPServer, false /* aSaveSettings */);
    47914717    }
    47924718
     
    47954721
    47964722/**
    4797  * Removes the given hard disk from the hard disk registry.
    4798  *
    4799  * @param aHardDisk     Hard disk object to remove.
    4800  * @param aSaveRegistry @c true to save hard disk registry to disk (default).
    4801  *
    4802  * When @a aSaveRegistry is @c true, this operation may fail because of the
    4803  * failed #saveSettings() method it calls. In this case, the hard disk object
    4804  * will NOT be removed from the registry when this method returns. It is
    4805  * therefore the responsibility of the caller to call this method as the first
    4806  * step of some action that requires unregistration, before calling uninit() on
    4807  * @a aHardDisk.
    4808  *
    4809  * @note Locks this object for writing and @a aHardDisk for reading.
     4723 * Removes the given DHCP server from the settings.
     4724 *
     4725 * @param aDHCPServer   DHCP server object to remove.
     4726 * @param aSaveSettings @c true to save settings to disk (default).
     4727 *
     4728 * When @a aSaveSettings is @c true, this operation may fail because of the
     4729 * failed #saveSettings() method it calls. In this case, the DHCP server
     4730 * will NOT be removed from the settingsi when this method returns.
     4731 *
     4732 * @note Locks this object for writing.
    48104733 */
    48114734HRESULT VirtualBox::unregisterDHCPServer(DHCPServer *aDHCPServer,
    4812                                          bool aSaveRegistry /*= true*/)
     4735                                         bool aSaveSettings /*= true*/)
    48134736{
    48144737    AssertReturn(aDHCPServer != NULL, E_INVALIDARG);
     
    48244747    HRESULT rc = S_OK;
    48254748
    4826     if (aSaveRegistry)
     4749    if (aSaveSettings)
    48274750    {
    48284751        AutoWriteLock vboxLock(this COMMA_LOCKVAL_SRC_POS);
     
    48314754
    48324755        if (FAILED(rc))
    4833             registerDHCPServer(aDHCPServer, false /* aSaveRegistry */);
     4756            registerDHCPServer(aDHCPServer, false /* aSaveSettings */);
    48344757    }
    48354758
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