VirtualBox

Changeset 75861 in vbox


Ignore:
Timestamp:
Dec 2, 2018 12:26:36 AM (6 years ago)
Author:
vboxsync
Message:

Main/Guest: Added a few codereview comments, mainly in the guest base class area. Replaced the object ID management in GuestSession with a classic allocation bitmap approach as that's much less memory intensive than 16 byte structs in a insert-only std::map and an additional map tracking free 32-bit IDs after we run out. bugref:9313

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h

    r74734 r75861  
    10781078    int                              GetGuestError(void) const { return mGuestRc; }
    10791079    int                              SignalExternal(IEvent *pEvent);
    1080     const GuestEventTypes            Types(void) { return mEventTypes; }
     1080    const GuestEventTypes           &Types(void) { return mEventTypes; }
    10811081    size_t                           TypeCount(void) { return mEventTypes.size(); }
    10821082
     
    11401140     *  for HGCM (VMMDev) communication. */
    11411141    Console                 *mConsole;
    1142     /** The next upcoming context ID for this object. */
     1142    /**  The next context ID counter component for this object. */
    11431143    uint32_t                 mNextContextID;
    11441144    /** Local listener for handling the waiting events
  • trunk/src/VBox/Main/include/GuestSessionImpl.h

    r75798 r75861  
    2929#include "GuestSessionImplTasks.h"
    3030
     31#include <iprt/asm.h> /** @todo r=bird: Needed for ASMBitSet() in GuestSession::Data constructor.  Removed when
     32                       *        that is moved into the class implementation file as it should be. */
    3133#include <deque>
    3234
     
    3638 * Guest session implementation.
    3739 */
    38 class ATL_NO_VTABLE GuestSession :
    39     public GuestSessionWrap,
    40     public GuestBase
     40class ATL_NO_VTABLE GuestSession
     41    : public GuestSessionWrap
     42    , public GuestBase
    4143{
    4244public:
     
    245247    struct SessionObject
    246248    {
    247         /** Creation timestamp (in ms). */
    248         uint64_t          tsCreatedMs;
     249        /** Creation timestamp (in ms).
     250         * @note not used by anyone at the moment.  */
     251        uint64_t          msBirth;
    249252        /** The object type. */
    250253        SESSIONOBJECTTYPE enmType;
     
    305308    Guest                  *i_getParent(void) { return mParent; }
    306309    uint32_t                i_getProtocolVersion(void) { return mData.mProtocolVersion; }
    307     int                     i_objectRegister(SESSIONOBJECTTYPE enmType, uint32_t *puObjectID);
    308     int                     i_objectRegisterEx(SESSIONOBJECTTYPE enmType, uint32_t fFlags, uint32_t *puObjectID);
     310    int                     i_objectRegister(SESSIONOBJECTTYPE enmType, uint32_t *pidObject);
    309311    int                     i_objectUnregister(uint32_t uObjectID);
    310312    int                     i_pathRename(const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags, int *pGuestRc);
     
    341343    const ComObjPtr<EventSource>    mEventSource;
    342344
     345    /** @todo r=bird: One of the core points of the DATA sub-structures in Main is
     346     * hinding implementation details and stuff that requires including iprt/asm.h.
     347     * The way it's used here totally defeats that purpose.  You need to make it
     348     * a pointer to a anynmous Data struct and define that structure in
     349     * GuestSessionImpl.cpp and allocate it in the Init() function.
     350     */
    343351    struct Data
    344352    {
     
    367375        /** Map of registered session objects (files, directories, ...). */
    368376        SessionObjects              mObjects;
    369         /** Queue of object IDs which are not used anymore (free list).
    370          *  Acts as a "free list" for the mObjects map. */
    371         SessionObjectsFree          mObjectsFree;
    372377        /** Guest control protocol version to be used.
    373378         *  Guest Additions < VBox 4.3 have version 1,
     
    379384         *  returned from the guest side. */
    380385        int                         mRC;
     386        /** Object ID allocation bitmap; clear bits are free, set bits are busy. */
     387        uint64_t                    bmObjectIds[VBOX_GUESTCTRL_MAX_OBJECTS / sizeof(uint64_t) / 8];
    381388
    382389        Data(void)
    383390            : mpBaseEnvironment(NULL)
    384         { }
     391        {
     392            RT_ZERO(bmObjectIds);
     393            ASMBitSet(&bmObjectIds, VBOX_GUESTCTRL_MAX_OBJECTS - 1);    /* Reserved for the session itself? */
     394            ASMBitSet(&bmObjectIds, 0);                                 /* Let's reserve this too. */
     395        }
    385396        Data(const Data &rThat)
    386397            : mCredentials(rThat.mCredentials)
     
    393404            , mProcesses(rThat.mProcesses)
    394405            , mObjects(rThat.mObjects)
    395             , mObjectsFree(rThat.mObjectsFree)
    396406            , mProtocolVersion(rThat.mProtocolVersion)
    397407            , mTimeout(rThat.mTimeout)
    398408            , mRC(rThat.mRC)
    399         { }
     409        {
     410            memcpy(&bmObjectIds, &rThat.bmObjectIds, sizeof(bmObjectIds));
     411        }
    400412        ~Data(void)
    401413        {
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r75854 r75861  
    160160        alock.release();
    161161
     162#ifdef DEBUG
    162163        bool fDispatch = true;
    163 #ifdef DEBUG
    164164        /*
    165165         * Pre-check: If we got a status message with an error and VERR_TOO_MUCH_DATA
     
    188188            }
    189189        }
     190        if (fDispatch)
    190191#endif
    191         if (fDispatch)
    192192        {
    193193            switch (pCtxCb->uFunction)
  • trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp

    r75801 r75861  
    3737#endif /* DEBUG */
    3838#include <iprt/fs.h>
     39#include <iprt/rand.h>
    3940#include <iprt/time.h>
    4041
     
    648649
    649650GuestBase::GuestBase(void)
    650     : mConsole(NULL),
    651       mNextContextID(0)
     651    : mConsole(NULL)
     652    , mNextContextID(RTRandU32() % VBOX_GUESTCTRL_MAX_CONTEXTS)
    652653{
    653654}
     
    791792
    792793    uint32_t uCount = ASMAtomicIncU32(&mNextContextID);
    793     if (uCount == VBOX_GUESTCTRL_MAX_CONTEXTS)
     794    if (uCount >= VBOX_GUESTCTRL_MAX_CONTEXTS)
    794795        uCount = 0;
    795796
    796     uint32_t uNewContextID =
    797         VBOX_GUESTCTRL_CONTEXTID_MAKE(uSessionID, uObjectID, uCount);
     797    uint32_t uNewContextID = VBOX_GUESTCTRL_CONTEXTID_MAKE(uSessionID, uObjectID, uCount);
    798798
    799799    *puContextID = uNewContextID;
     
    812812 * around once at a time.
    813813 *
    814  * @returns IPRT status code. VERR_ALREADY_EXISTS if an event with the given session
    815  *          and object ID already has been registered.
     814 * @returns IPRT status code.
     815 * @retval  VERR_ALREADY_EXISTS if an event with the given session and object ID
     816 *          already has been registered.  r=bird: Incorrect, see explanation in
     817 *          registerWaitEventEx().
    816818 *
    817819 * @param   uSessionID              Session ID to register wait event for.
     
    827829
    828830/**
    829  * Registers (creates) a new wait event based on a given session, object ID
    830  * and a list of event types to wait for.
    831  *
    832  * From those IDs an unique context ID (CID) will be built, which only can be
    833  * around once at a time.
    834  *
    835  * @returns IPRT status code. VERR_ALREADY_EXISTS if an event with the given session
    836  *          and object ID already has been registered.
     831 * Creates and registers a new wait event object that waits on a set of events
     832 * related to a given object within the session.
     833 *
     834 * From the session ID and object ID a one-time unique context ID (CID) is built
     835 * for this wait object.  Normally the CID is then passed to the guest along
     836 * with a request, and the guest passed the CID back with the reply.  The
     837 * handler for the reply then emits a signal on the event type associated with
     838 * the reply, which includes signalling the object returned by this method and
     839 * the waking up the thread waiting on it.
     840 *
     841 * @returns VBox status code.
     842 * @retval  VERR_ALREADY_EXISTS if an event with the given session and object ID
     843 *          already has been registered.  r=bird: No, this isn't when this is
     844 *          returned, it is returned when generateContextID() generates a
     845 *          duplicate.  The duplicate being in the count part (bits 15:0) of the
     846 *          session ID.  So, VERR_DUPLICATE would be more appropraite.
    837847 *
    838848 * @param   uSessionID              Session ID to register wait event for.
     
    845855                                   GuestWaitEvent **ppEvent)
    846856{
     857    AssertReturn(!lstEvents.empty(), VERR_INVALID_PARAMETER);
    847858    AssertPtrReturn(ppEvent, VERR_INVALID_POINTER);
    848859
    849     uint32_t uContextID;
    850     int rc = generateContextID(uSessionID, uObjectID, &uContextID);
    851     if (RT_FAILURE(rc))
    852         return rc;
    853 
     860    uint32_t idContext;
     861    int rc = generateContextID(uSessionID, uObjectID, &idContext);
     862    AssertRCReturn(rc, rc);
     863
     864#if 1 /** @todo r=bird: Incorrect exception and memory handling, no strategy for dealing with duplicate IDs: */
    854865    rc = RTCritSectEnter(&mWaitEventCritSect);
    855866    if (RT_SUCCESS(rc))
     
    857868        try
    858869        {
    859             GuestWaitEvent *pEvent = new GuestWaitEvent(uContextID, lstEvents);
     870            GuestWaitEvent *pEvent = new GuestWaitEvent(idContext, lstEvents);
    860871            AssertPtr(pEvent);
    861872
    862             LogFlowThisFunc(("New event=%p, CID=%RU32\n", pEvent, uContextID));
     873            LogFlowThisFunc(("New event=%p, CID=%RU32\n", pEvent, idContext));
    863874
    864875            /* Insert event into matching event group. This is for faster per-group
     
    869880                /* Check if the event group already has an event with the same
    870881                 * context ID in it (collision). */
    871                 GuestWaitEvents eventGroup = mWaitEventGroups[(*itEvents)];
    872                 if (eventGroup.find(uContextID) == eventGroup.end())
     882                GuestWaitEvents eventGroup = mWaitEventGroups[(*itEvents)]; /** @todo r=bird: Why copy it? */
     883                if (eventGroup.find(idContext) == eventGroup.end())
    873884                {
    874885                    /* No, insert. */
    875                     mWaitEventGroups[(*itEvents)].insert(std::pair<uint32_t, GuestWaitEvent *>(uContextID, pEvent));
     886                    mWaitEventGroups[(*itEvents)].insert(std::pair<uint32_t, GuestWaitEvent *>(idContext, pEvent));
    876887                }
    877888                else
     
    885896            {
    886897                /* Register event in regular event list. */
    887                 if (mWaitEvents.find(uContextID) == mWaitEvents.end())
     898                if (mWaitEvents.find(idContext) == mWaitEvents.end())
    888899                {
    889                     mWaitEvents[uContextID] = pEvent;
     900                    mWaitEvents[idContext] = pEvent;
    890901                }
    891902                else
     
    905916            rc = rc2;
    906917    }
    907 
    908918    return rc;
     919
     920#else /** @todo r=bird: Version with proper exception handling, no leaks and limited duplicate CID handling:  */
     921
     922    GuestWaitEvent *pEvent = new GuestWaitEvent(idContext, lstEvents);
     923    AssertReturn(pEvent, VERR_NO_MEMORY);
     924    LogFlowThisFunc(("New event=%p, CID=%RU32\n", pEvent, idContext));
     925
     926    rc = RTCritSectEnter(&mWaitEventCritSect);
     927    if (RT_SUCCESS(rc))
     928    {
     929        /*
     930         * Check that we don't have any context ID collisions (should be very unlikely).
     931         *
     932         * The ASSUMPTION here is that mWaitEvents has all the same events as
     933         * mWaitEventGroups, so it suffices to check one of the two.
     934         */
     935        if (mWaitEvents.find(idContext) != mWaitEvents.end())
     936        {
     937            uint32_t cTries = 0;
     938            do
     939            {
     940                rc = generateContextID(uSessionID, uObjectID, &idContext);
     941                AssertRCBreak(rc);
     942                Log(("Duplicate! Trying a different context ID: %#x\n", idContext));
     943                if (mWaitEvents.find(idContext) != mWaitEvents.end())
     944                    rc = VERR_ALREADY_EXISTS;
     945            } while (RT_FAILURE_NP(rc) && cTries++ < 10);
     946        }
     947        if (RT_SUCCESS(rc))
     948        {
     949            /*
     950             * Insert event into matching event group. This is for faster per-group lookup of all events later.
     951             */
     952            uint32_t cInserts = 0;
     953            for (GuestEventTypes::const_iterator ItType = lstEvents.begin(); ItType != lstEvents.end(); ++ItType)
     954            {
     955                GuestWaitEvents &eventGroup = mWaitEventGroups[*ItType];
     956                if (eventGroup.find(idContext) == eventGroup.end())
     957                {
     958                    try
     959                    {
     960                        eventGroup.insert(std::pair<uint32_t, GuestWaitEvent *>(idContext, pEvent));
     961                        cInserts++;
     962                    }
     963                    catch (std::bad_alloc &)
     964                    {
     965                        while (ItType != lstEvents.begin())
     966                        {
     967                            --ItType;
     968                            mWaitEventGroups[*ItType].erase(idContext);
     969                        }
     970                        rc = VERR_NO_MEMORY;
     971                        break;
     972                    }
     973                }
     974                else
     975                    Assert(cInserts > 0); /* else: lstEvents has duplicate entries. */
     976            }
     977            if (RT_SUCCESS(rc))
     978            {
     979                Assert(cInserts > 0);
     980                NOREF(cInserts);
     981
     982                /*
     983                 * Register event in the regular event list.
     984                 */
     985                try
     986                {
     987                    mWaitEvents[idContext] = pEvent;
     988                }
     989                catch (std::bad_alloc &)
     990                {
     991                    for (GuestEventTypes::const_iterator ItType = lstEvents.begin(); ItType != lstEvents.end(); ++ItType)
     992                        mWaitEventGroups[*ItType].erase(idContext);
     993                    rc = VERR_NO_MEMORY;
     994                }
     995            }
     996        }
     997
     998        RTCritSectLeave(&mWaitEventCritSect);
     999    }
     1000    if (RT_SUCCESS(rc))
     1001        return rc;
     1002
     1003    delete pEvent;
     1004    return rc;
     1005#endif
    9091006}
    9101007
     
    9201017        if (itGroup != mWaitEventGroups.end())
    9211018        {
     1019#if 1 /** @todo r=bird: consider the other variant. */
    9221020            GuestWaitEvents::iterator itEvents = itGroup->second.begin();
    9231021            while (itEvents != itGroup->second.end())
     
    9301028                                 VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(itEvents->first)));
    9311029#endif
    932                 ComPtr<IEvent> pThisEvent = aEvent;
     1030                ComPtr<IEvent> pThisEvent = aEvent; /** @todo r=bird: This means addref/release for each iteration. Isn't that silly? */
    9331031                Assert(!pThisEvent.isNull());
    9341032                int rc2 = itEvents->second->SignalExternal(aEvent);
    9351033                if (RT_SUCCESS(rc))
    936                     rc = rc2;
     1034                    rc = rc2; /** @todo r=bird: This doesn't make much sense since it will only fail if not
     1035                               * properly initialized or major memory corruption.  And if it's broken, why
     1036                               * don't you just remove it instead of leaving it in the group???  It would
     1037                               * make life so much easier here as you could just change the while condition
     1038                               * to while ((itEvents = itGroup->second.begin() != itGroup->second.end())
     1039                               * and skip all this two step removal below.  I'll put this in a #if 0 and show what I mean... */
    9371040
    9381041                if (RT_SUCCESS(rc2))
    9391042                {
     1043                    /** @todo r=bird: I don't follow the logic here.  Why don't you just remove
     1044                     *        it from all groups, including this one?  You just have move the  */
     1045
    9401046                    /* Remove the event from all other event groups (except the
    9411047                     * original one!) because it was signalled. */
     
    9751081#endif
    9761082            }
     1083#else
     1084            /* Signal all events in the group, leaving the group empty afterwards. */
     1085            GuestWaitEvents::iterator ItWaitEvt;
     1086            while ((ItWaitEvt = itGroup->second.begin()) != itGroup->second.end())
     1087            {
     1088                LogFlowThisFunc(("Signalling event=%p, type=%ld (CID %#x: Session=%RU32, Object=%RU32, Count=%RU32) ...\n",
     1089                                 ItWaitEvt->second, aType, ItWaitEvt->first, VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(ItWaitEvt->first),
     1090                                 VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(ItWaitEvt->first), VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(ItWaitEvt->first)));
     1091
     1092                int rc2 = ItWaitEvt->second->SignalExternal(aEvent);
     1093                AssertRC(rc2);
     1094
     1095                /* Take down the wait event object details before we erase it from this list and invalid ItGrpEvt. */
     1096                const GuestEventTypes &EvtTypes  = ItWaitEvt->second->Types();
     1097                uint32_t               idContext = ItWaitEvt->first;
     1098                itGroup->second.erase(ItWaitEvt);
     1099
     1100                for (GuestEventTypes::const_iterator ItType = EvtTypes.begin(); ItType != EvtTypes.end(); ++ItType)
     1101                {
     1102                    GuestEventGroup::iterator EvtTypeGrp = mWaitEventGroups.find(*ItType);
     1103                    if (EvtTypeGrp != mWaitEventGroups.end())
     1104                    {
     1105                        ItWaitEvt = EvtTypeGrp->second.find(idContext);
     1106                        if (ItWaitEvt != EvtTypeGrp->second.end())
     1107                        {
     1108                            LogFlowThisFunc(("Removing event %p (CID %#x) from type %d group\n", ItWaitEvt->second, idContext, *ItType));
     1109                            EvtTypeGrp->second.erase(ItWaitEvt);
     1110                            LogFlowThisFunc(("%zu events left for type %d\n", EvtTypeGrp->second.size(), *ItType));
     1111                            Assert(EvtTypeGrp->second.find(idContext) == EvtTypeGrp->second.end()); /* no duplicates */
     1112                        }
     1113                    }
     1114                }
     1115            }
     1116#endif
    9771117        }
    9781118
     
    10351175 *
    10361176 * @returns IPRT status code.
    1037  * @param   pEvent                  Event to unregister (delete).
    1038  */
    1039 int GuestBase::unregisterWaitEvent(GuestWaitEvent *pEvent)
    1040 {
    1041     if (!pEvent) /* Nothing to unregister. */
     1177 * @param   pWaitEvt        Wait event to unregister (delete).
     1178 */
     1179int GuestBase::unregisterWaitEvent(GuestWaitEvent *pWaitEvt)
     1180{
     1181    if (!pWaitEvt) /* Nothing to unregister. */
    10421182        return VINF_SUCCESS;
    10431183
     
    10451185    if (RT_SUCCESS(rc))
    10461186    {
    1047         LogFlowThisFunc(("pEvent=%p\n", pEvent));
    1048 
     1187        LogFlowThisFunc(("pWaitEvt=%p\n", pWaitEvt));
     1188
     1189/** @todo r=bird: One way of optimizing this would be to use the pointer
     1190 * instead of the context ID as index into the groups, i.e. revert the value
     1191 * pair for the GuestWaitEvents type.
     1192 *
     1193 * An even more efficent way, would be to not use sexy std::xxx containers for
     1194 * the types, but iprt/list.h, as that would just be a RTListNodeRemove call for
     1195 * each type w/o needing to iterate much at all.  I.e. add a struct {
     1196 * RTLISTNODE, GuestWaitEvent *pSelf} array to GuestWaitEvent, and change
     1197 * GuestEventGroup to std::map<VBoxEventType_T, RTListAnchorClass>
     1198 * (RTListAnchorClass == RTLISTANCHOR wrapper with a constructor)).
     1199 *
     1200 * P.S. the try/catch is now longer needed after I changed pWaitEvt->Types() to
     1201 * return a const reference rather than a copy of the type list (and it think it
     1202 * is safe to assume iterators are not hitting the heap).  Copy vs reference is
     1203 * an easy mistake to make in C++.
     1204 *
     1205 * P.P.S. The mWaitEventGroups optimization is probably just a lot of extra work
     1206 * with little payoff.
     1207 */
    10491208        try
    10501209        {
    10511210            /* Remove the event from all event type groups. */
    1052             const GuestEventTypes lstTypes = pEvent->Types();
     1211            const GuestEventTypes &lstTypes = pWaitEvt->Types();
    10531212            for (GuestEventTypes::const_iterator itType = lstTypes.begin();
    10541213                 itType != lstTypes.end(); ++itType)
     
    10581217                while (itCurEvent != mWaitEventGroups[(*itType)].end())
    10591218                {
    1060                     if (itCurEvent->second == pEvent)
     1219                    if (itCurEvent->second == pWaitEvt)
    10611220                    {
    10621221                        mWaitEventGroups[(*itType)].erase(itCurEvent);
    10631222                        break;
    10641223                    }
    1065                     else
    1066                         ++itCurEvent;
     1224                    ++itCurEvent;
    10671225                }
    10681226            }
    10691227
    10701228            /* Remove the event from the general event list as well. */
    1071             GuestWaitEvents::iterator itEvent = mWaitEvents.find(pEvent->ContextID());
     1229            GuestWaitEvents::iterator itEvent = mWaitEvents.find(pWaitEvt->ContextID());
    10721230
    10731231            Assert(itEvent != mWaitEvents.end());
    1074             Assert(itEvent->second == pEvent);
     1232            Assert(itEvent->second == pWaitEvt);
    10751233
    10761234            mWaitEvents.erase(itEvent);
    10771235
    1078             delete pEvent;
    1079             pEvent = NULL;
     1236            delete pWaitEvt;
     1237            pWaitEvt = NULL;
    10801238        }
    10811239        catch (const std::exception &ex)
     
    10941252
    10951253/**
    1096  * Waits for a formerly registered guest event.
     1254 * Waits for an already registered guest wait event.
    10971255 *
    10981256 * @return  IPRT status code.
    1099  * @param   pEvent                  Pointer to event to wait for.
    1100  * @param   uTimeoutMS              Timeout (in ms) for waiting.
     1257 * @param   pWaitEvt                Pointer to event to wait for.
     1258 * @param   msTimeout               Timeout (in ms) for waiting.
    11011259 * @param   pType                   Event type of following IEvent.
    11021260 *                                  Optional.
     
    11041262 *                                  for this event. Optional.
    11051263 */
    1106 int GuestBase::waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
    1107                             VBoxEventType_T *pType, IEvent **ppEvent)
     1264int GuestBase::waitForEvent(GuestWaitEvent *pEvent, uint32_t msTimeout, VBoxEventType_T *pType, IEvent **ppEvent)
    11081265{
    11091266    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
     
    11111268    /* ppEvent is optional. */
    11121269
    1113     int vrc = pEvent->Wait(uTimeoutMS);
     1270    int vrc = pEvent->Wait(msTimeout);
    11141271    if (RT_SUCCESS(vrc))
    11151272    {
    11161273        const ComPtr<IEvent> pThisEvent = pEvent->Event();
    1117         if (!pThisEvent.isNull()) /* Having a VBoxEventType_ event is optional. */
     1274        if (pThisEvent.isNotNull()) /* Having a VBoxEventType_ event is optional. */ /** @todo r=bird: misplaced comment? */
    11181275        {
    11191276            if (pType)
     
    12691426}
    12701427
    1271 int GuestWaitEventBase::Wait(RTMSINTERVAL uTimeoutMS)
     1428int GuestWaitEventBase::Wait(RTMSINTERVAL msTimeout)
    12721429{
    12731430    int rc = VINF_SUCCESS;
     
    12801437        AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED);
    12811438
    1282         RTMSINTERVAL msInterval = uTimeoutMS;
    1283         if (!uTimeoutMS)
    1284             msInterval = RT_INDEFINITE_WAIT;
    1285         rc = RTSemEventWait(mEventSem, msInterval);
     1439        rc = RTSemEventWait(mEventSem, msTimeout ? msTimeout : RT_INDEFINITE_WAIT);
    12861440        if (ASMAtomicReadBool(&mfAborted))
    12871441            rc = VERR_CANCELLED;
     
    13011455{
    13021456    int rc2 = Init(uCID);
    1303     AssertRC(rc2); /** @todo Throw exception here. */
     1457    AssertRC(rc2); /** @todo Throw exception here. */ /** @todo r=bird: add+use Init() instead. Will cause weird VERR_CANCELLED errors in GuestBase::signalWaitEvent. */
    13041458
    13051459    mEventTypes = lstEvents;
     
    13091463{
    13101464    int rc2 = Init(uCID);
    1311     AssertRC(rc2); /** @todo Throw exception here. */
     1465    AssertRC(rc2); /** @todo Throw exception here. */ /** @todo r=bird: add+use Init() instead. Will cause weird VERR_CANCELLED errors in GuestBase::signalWaitEvent. */
    13121466}
    13131467
     
    13451499int GuestWaitEvent::SignalExternal(IEvent *pEvent)
    13461500{
     1501    /** @todo r=bird: VERR_CANCELLED is misleading. mEventSem can only be NIL if
     1502     *        not successfully initialized! */
    13471503    AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED);
    13481504
  • trunk/src/VBox/Main/src-client/GuestFileImpl.cpp

    r75737 r75861  
    295295    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    296296
     297/** @todo r=bird: Why do you have both a offset and a tell() function?
     298 * After a ReadAt or WriteAt with a non-current offset, the tell() result will
     299 * differ from this value, because mOffCurrent is only ever incremented with
     300 * data read or written.  */
    297301    *aOffset = mData.mOffCurrent;
    298302
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r75801 r75861  
    4646#include <iprt/file.h> /* For CopyTo/From. */
    4747#include <iprt/path.h>
     48#include <iprt/rand.h>
    4849
    4950#include <VBox/com/array.h>
     
    341342
    342343    mData.mObjects.clear();
    343     mData.mObjectsFree.clear();
    344344
    345345    mData.mEnvironmentChanges.reset();
     
    10171017    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    10181018
    1019     const uint32_t uObjectID = pDirectory->getObjectID();
    1020 
    1021     LogFlowFunc(("Removing directory (objectID=%RU32) ...\n", uObjectID));
    1022 
    1023     int rc = i_objectUnregister(uObjectID);
     1019    const uint32_t idObject = pDirectory->getObjectID();
     1020
     1021    LogFlowFunc(("Removing directory (objectID=%RU32) ...\n", idObject));
     1022
     1023    int rc = i_objectUnregister(idObject);
    10241024    if (RT_FAILURE(rc))
    10251025        return rc;
    10261026
    1027     SessionDirectories::iterator itDirs = mData.mDirectories.find(uObjectID);
     1027    SessionDirectories::iterator itDirs = mData.mDirectories.find(idObject);
    10281028    AssertReturn(itDirs != mData.mDirectories.end(), VERR_NOT_FOUND);
    10291029
     
    10321032
    10331033    LogFlowFunc(("Removing directory ID=%RU32 (session %RU32, now total %zu directories)\n",
    1034                  uObjectID, mData.mSession.mID, mData.mDirectories.size()));
     1034                 idObject, mData.mSession.mID, mData.mDirectories.size()));
    10351035
    10361036    rc = pDirConsumed->i_onRemove();
     
    11621162
    11631163    /* Register a new object ID. */
    1164     uint32_t uObjectID;
    1165     int rc = i_objectRegister(SESSIONOBJECTTYPE_DIRECTORY, &uObjectID);
     1164    uint32_t idObject;
     1165    int rc = i_objectRegister(SESSIONOBJECTTYPE_DIRECTORY, &idObject);
    11661166    if (RT_FAILURE(rc))
    11671167        return rc;
     
    11751175    AssertPtr(pConsole);
    11761176
    1177     int vrc = pDirectory->init(pConsole, this /* Parent */, uObjectID, openInfo);
     1177    int vrc = pDirectory->init(pConsole, this /* Parent */, idObject, openInfo);
    11781178    if (RT_FAILURE(vrc))
    11791179        return vrc;
     
    11891189    {
    11901190        /* Add the created directory to our map. */
    1191         mData.mDirectories[uObjectID] = pDirectory;
     1191        mData.mDirectories[idObject] = pDirectory;
    11921192
    11931193        LogFlowFunc(("Added new guest directory \"%s\" (Session: %RU32) (now total %zu directories)\n",
     
    14161416    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    14171417
    1418     const uint32_t uObjectID = pFile->getObjectID();
    1419 
    1420     LogFlowFunc(("Removing file (objectID=%RU32) ...\n", uObjectID));
    1421 
    1422     int rc = i_objectUnregister(uObjectID);
     1418    const uint32_t idObject = pFile->getObjectID();
     1419
     1420    LogFlowFunc(("Removing file (objectID=%RU32) ...\n", idObject));
     1421
     1422    int rc = i_objectUnregister(idObject);
    14231423    if (RT_FAILURE(rc))
    14241424        return rc;
    14251425
    1426     SessionFiles::iterator itFiles = mData.mFiles.find(uObjectID);
     1426    SessionFiles::iterator itFiles = mData.mFiles.find(idObject);
    14271427    AssertReturn(itFiles != mData.mFiles.end(), VERR_NOT_FOUND);
    14281428
     
    15201520
    15211521    /* Register a new object ID. */
    1522     uint32_t uObjectID;
    1523     int rc = i_objectRegister(SESSIONOBJECTTYPE_FILE, &uObjectID);
     1522    uint32_t idObject;
     1523    int rc = i_objectRegister(SESSIONOBJECTTYPE_FILE, &idObject);
    15241524    if (RT_FAILURE(rc))
    15251525        return rc;
     
    15331533    AssertPtr(pConsole);
    15341534
    1535     rc = pFile->init(pConsole, this /* GuestSession */, uObjectID, openInfo);
     1535    rc = pFile->init(pConsole, this /* GuestSession */, idObject, openInfo);
    15361536    if (RT_FAILURE(rc))
    15371537        return rc;
     
    15471547    {
    15481548        /* Add the created file to our vector. */
    1549         mData.mFiles[uObjectID] = pFile;
     1549        mData.mFiles[idObject] = pFile;
    15501550
    15511551        LogFlowFunc(("Added new guest file \"%s\" (Session: %RU32) (now total %zu files)\n",
     
    20352035
    20362036/**
    2037  * Registers an object to a session.
     2037 * Registers an object with the session, i.e. allocates an object ID.
    20382038 *
    2039  * @return VBox status code.
    2040  * @param  enmType              Session object type to register.
    2041  * @param  puObjectID           Returns registered object ID on success. Optional.
     2039 * @return  VBox status code.
     2040 * @retval  VERR_GSTCTL_MAX_OBJECTS_REACHED if the maximum of concurrent objects
     2041 *          is reached.
     2042 * @param   enmType     Session object type to register.
     2043 * @param   pidObject   Where to return the object ID on success.
    20422044 */
    2043 int GuestSession::i_objectRegister(SESSIONOBJECTTYPE enmType, uint32_t *puObjectID)
    2044 {
    2045     return i_objectRegisterEx(enmType, 0 /* fFlags */, puObjectID);
     2045int GuestSession::i_objectRegister(SESSIONOBJECTTYPE enmType, uint32_t *pidObject)
     2046{
     2047    /*
     2048     * Pick a random bit as starting point.  If it's in use, search forward
     2049     * for a free one, wrapping around.  We've reserved both the zero'th and
     2050     * max-1 IDs (see Data constructor).
     2051     */
     2052    uint32_t idObject = RTRandU32Ex(1, VBOX_GUESTCTRL_MAX_OBJECTS - 2);
     2053    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     2054    if (!ASMBitTestAndSet(&mData.bmObjectIds[0], idObject))
     2055    { /* likely */ }
     2056    else if (mData.mObjects.size() < VBOX_GUESTCTRL_MAX_OBJECTS - 2 /* First and last are not used */)
     2057    {
     2058        /* Forward search. */
     2059        int iHit = ASMBitNextClear(&mData.bmObjectIds[0], VBOX_GUESTCTRL_MAX_OBJECTS, idObject);
     2060        if (iHit < 0)
     2061            iHit = ASMBitFirstClear(&mData.bmObjectIds[0], VBOX_GUESTCTRL_MAX_OBJECTS);
     2062        AssertLogRelMsgReturn(iHit >= 0, ("object count: %#zu\n", mData.mObjects.size()), VERR_GSTCTL_MAX_OBJECTS_REACHED);
     2063        idObject = iHit;
     2064        AssertLogRelMsgReturn(!ASMBitTestAndSet(&mData.bmObjectIds[0], idObject), ("idObject=%#x\n", idObject), VERR_INTERNAL_ERROR_2);
     2065    }
     2066    else
     2067    {
     2068        LogFunc(("enmType=%RU32 -> VERR_GSTCTL_MAX_OBJECTS_REACHED!! (%zu objects)\n", enmType, mData.mObjects.size()));
     2069        return VERR_GSTCTL_MAX_OBJECTS_REACHED;
     2070    }
     2071
     2072    Log2Func(("enmType=%RU32 -> idObject=%RU32 (%zu objects)\n", enmType, idObject, mData.mObjects.size()));
     2073
     2074    try
     2075    {
     2076        mData.mObjects[idObject].enmType = enmType;
     2077        mData.mObjects[idObject].msBirth = RTTimeMilliTS();
     2078    }
     2079    catch (std::bad_alloc &)
     2080    {
     2081        ASMBitClear(&mData.bmObjectIds[0], idObject);
     2082        return VERR_NO_MEMORY;
     2083    }
     2084
     2085    alock.release();
     2086
     2087    *pidObject = idObject;
     2088    return VINF_SUCCESS;
    20462089}
    20472090
    20482091/**
    2049  * Registers an object to a session, extended version.
     2092 * Unregisters an object from a session.
    20502093 *
    2051  * @return VBox status code. VERR_GSTCTL_MAX_OBJECTS_REACHED if the maximum of concurrent objects is reached.
    2052  * @param  enmType              Session object type to register.
    2053  * @param  fFlags               Registration flags. Not used yet and must be 0.
    2054  * @param  puObjectID           Returns registered object ID on success. Optional.
     2094 * @retval  VINF_SUCCESS on success.
     2095 * @retval  VERR_NOT_FOUND if the object ID was not found.
     2096 * @param   idObject        Object ID to unregister.
    20552097 */
    2056 int GuestSession::i_objectRegisterEx(SESSIONOBJECTTYPE enmType, uint32_t fFlags, uint32_t *puObjectID)
    2057 {
    2058     RT_NOREF(fFlags);
    2059     AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER);
    2060 
     2098int GuestSession::i_objectUnregister(uint32_t idObject)
     2099{
    20612100    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    20622101
    20632102    int rc = VINF_SUCCESS;
    2064 
    2065     uint32_t uObjectID = 0; /* Shut up MSVC. */
    2066 
    2067     if (mData.mObjects.size() < VBOX_GUESTCTRL_MAX_OBJECTS - 1 /* Minus 1 for the session itself */)
    2068     {
    2069         SessionObjects::reverse_iterator itRend = mData.mObjects.rbegin();
    2070         if (itRend != mData.mObjects.rend())
    2071             uObjectID = itRend->first + 1; /* Last key plus 1. */
    2072         else
    2073             uObjectID = 0;
    2074     }
    2075     else
    2076     {
    2077         /* Utilize our "free list" to get the next free object ID in the map. */
    2078         if (mData.mObjectsFree.size())
    2079         {
    2080             /* Always re-use the oldest object ID to avoid trouble. */
    2081             uObjectID = mData.mObjectsFree.front();
    2082             mData.mObjectsFree.pop_front();
    2083         }
    2084         else
    2085             rc = VERR_GSTCTL_MAX_OBJECTS_REACHED;
    2086     }
    2087 
    2088     Log2Func(("enmType=%RU32, fFlags=%RU32 -> uObjectID=%RU32 (%zu objects, %zu on free list), rc=%Rrc\n",
    2089               enmType, fFlags, uObjectID, mData.mObjects.size(), mData.mObjectsFree.size(), rc));
    2090 
    2091     if (RT_SUCCESS(rc))
    2092     {
    2093         mData.mObjects[uObjectID].enmType     = enmType;
    2094         mData.mObjects[uObjectID].tsCreatedMs = RTTimeMilliTS();
    2095 
    2096         if (puObjectID)
    2097             *puObjectID = uObjectID;
    2098     }
     2103    AssertMsgStmt(ASMBitTestAndClear(&mData.bmObjectIds, idObject), ("idObject=%#x\n", idObject), rc = VERR_NOT_FOUND);
     2104
     2105    SessionObjects::const_iterator ItObj = mData.mObjects.find(idObject);
     2106    AssertMsgReturn(ItObj != mData.mObjects.end(), ("idObject=%#x\n", idObject), VERR_NOT_FOUND);
     2107    mData.mObjects.erase(ItObj);
    20992108
    21002109    return rc;
    2101 }
    2102 
    2103 /**
    2104  * Unregisters a formerly registered object from a session.
    2105  *
    2106  * @return VBox status code. VERR_NOT_FOUND if object to unregister was not found.
    2107  * @param  uObjectID            Object ID to unregister.
    2108  */
    2109 int GuestSession::i_objectUnregister(uint32_t uObjectID)
    2110 {
    2111     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2112 
    2113     SessionObjects::const_iterator itObj = mData.mObjects.find(uObjectID);
    2114     if (itObj != mData.mObjects.end())
    2115     {
    2116         Log2Func(("uObjectID=%RU32 (now %zu objects in free list)\n", uObjectID, mData.mObjectsFree.size()));
    2117 
    2118         /* Note: Do not remove object from object list (mData.mObjects) here, as we continue operating
    2119          *       on the free list (mData.mObjectsFree) if we reached the object list's maximum. */
    2120 
    2121         mData.mObjectsFree.push_back(uObjectID);
    2122         Assert(mData.mObjectsFree.size() <= VBOX_GUESTCTRL_MAX_OBJECTS);
    2123         return VINF_SUCCESS;
    2124     }
    2125 
    2126     AssertFailed();
    2127     return VERR_NOT_FOUND;
    21282110}
    21292111
     
    22832265    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    22842266
    2285     const uint32_t uObjectID = pProcess->getObjectID();
    2286 
    2287     LogFlowFunc(("Removing process (objectID=%RU32) ...\n", uObjectID));
    2288 
    2289     int rc = i_objectUnregister(uObjectID);
     2267    const uint32_t idObject = pProcess->getObjectID();
     2268
     2269    LogFlowFunc(("Removing process (objectID=%RU32) ...\n", idObject));
     2270
     2271    int rc = i_objectUnregister(idObject);
    22902272    if (RT_FAILURE(rc))
    22912273        return rc;
    22922274
    2293     SessionProcesses::iterator itProcs = mData.mProcesses.find(uObjectID);
     2275    SessionProcesses::iterator itProcs = mData.mProcesses.find(idObject);
    22942276    AssertReturn(itProcs != mData.mProcesses.end(), VERR_NOT_FOUND);
    22952277
     
    23022284
    23032285    LogFlowFunc(("Removing process ID=%RU32 (session %RU32, guest PID %RU32, now total %zu processes)\n",
    2304                  uObjectID, mData.mSession.mID, uPID, mData.mProcesses.size()));
     2286                 idObject, mData.mSession.mID, uPID, mData.mProcesses.size()));
    23052287
    23062288    rc = pProcess->i_onRemove();
     
    23802362
    23812363    /* Register a new object ID. */
    2382     uint32_t uObjectID;
    2383     int rc = i_objectRegister(SESSIONOBJECTTYPE_PROCESS, &uObjectID);
     2364    uint32_t idObject;
     2365    int rc = i_objectRegister(SESSIONOBJECTTYPE_PROCESS, &idObject);
    23842366    if (RT_FAILURE(rc))
    23852367        return rc;
     
    23902372        return VERR_COM_UNEXPECTED;
    23912373
    2392     rc = pProcess->init(mParent->i_getConsole() /* Console */, this /* Session */, uObjectID,
     2374    rc = pProcess->init(mParent->i_getConsole() /* Console */, this /* Session */, idObject,
    23932375                        procInfo, mData.mpBaseEnvironment);
    23942376    if (RT_FAILURE(rc))
     
    23982380    try
    23992381    {
    2400         mData.mProcesses[uObjectID] = pProcess;
     2382        mData.mProcesses[idObject] = pProcess;
    24012383
    24022384        LogFlowFunc(("Added new process (Session: %RU32) with process ID=%RU32 (now total %zu processes)\n",
    2403                      mData.mSession.mID, uObjectID, mData.mProcesses.size()));
     2385                     mData.mSession.mID, idObject, mData.mProcesses.size()));
    24042386
    24052387        alock.release(); /* Release lock before firing off event. */
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