Пример #1
0
/**
 * Lazy initialization of the m_pWorkLoop member.
 *
 * @returns m_pWorkLoop.
 */
IOWorkLoop *org_virtualbox_VBoxGuest::getWorkLoop()
{
/** @todo r=bird: This is actually a classic RTOnce scenario, except it's
 *        tied to a org_virtualbox_VBoxGuest instance.  */
    /*
     * Handle the case when work loop was not created yet.
     */
    if (ASMAtomicCmpXchgU8(&g_fWorkLoopCreated, VBOXGUEST_OBJECT_INITIALIZING, VBOXGUEST_OBJECT_UNINITIALIZED))
    {
        m_pWorkLoop = IOWorkLoop::workLoop();
        if (m_pWorkLoop)
        {
            /* Notify the rest of threads about the fact that work
             * loop was successully allocated and can be safely used */
            Log(("VBoxGuest: created new work loop\n"));
            ASMAtomicWriteU8(&g_fWorkLoopCreated, VBOXGUEST_OBJECT_INITIALIZED);
        }
        else
        {
            /* Notify the rest of threads about the fact that there was
             * an error during allocation of a work loop */
            Log(("VBoxGuest: failed to create new work loop!\n"));
            ASMAtomicWriteU8(&g_fWorkLoopCreated, VBOXGUEST_OBJECT_UNINITIALIZED);
        }
    }
    /*
     * Handle the case when work loop is already create or
     * in the process of being.
     */
    else
    {
        uint8_t fWorkLoopCreated = ASMAtomicReadU8(&g_fWorkLoopCreated);
        while (fWorkLoopCreated == VBOXGUEST_OBJECT_INITIALIZING)
        {
            thread_block(0);
            fWorkLoopCreated = ASMAtomicReadU8(&g_fWorkLoopCreated);
        }
        if (fWorkLoopCreated != VBOXGUEST_OBJECT_INITIALIZED)
            Log(("VBoxGuest: No work loop!\n"));
    }

    return m_pWorkLoop;
}
Пример #2
0
IOWorkLoop *
org_virtualbox_VBoxGuest::getWorkLoop()
{
    /* Handle the case when work loop was not created yet */
    if(ASMAtomicCmpXchgU8(&g_fWorkLoopCreated, VBOXGUEST_OBJECT_INITIALIZING, VBOXGUEST_OBJECT_UNINITIALIZED))
    {
        m_pWorkLoop = IOWorkLoop::workLoop();
        if (m_pWorkLoop)
        {
            /* Notify the rest of threads about the fact that work
             * loop was successully allocated and can be safely used */
            PDEBUG("created new work loop\n");
            ASMAtomicWriteU8(&g_fWorkLoopCreated, VBOXGUEST_OBJECT_INITIALIZED);
        }
        else
        {
            /* Notify the rest of threads about the fact that there was
             * an error during allocation of a work loop */
            PDEBUG("unable new work loop\n");
            ASMAtomicWriteU8(&g_fWorkLoopCreated, VBOXGUEST_OBJECT_UNINITIALIZED);
        }
    }
    else
    {
        /* Handle the case when work loop is currently being
         * created or it was previously failed to create */
        uint8_t fWorkLoopCreated = VBOXGUEST_OBJECT_INVALID;
        while (fWorkLoopCreated != VBOXGUEST_OBJECT_INITIALIZED
            && fWorkLoopCreated != VBOXGUEST_OBJECT_UNINITIALIZED)
        {
            fWorkLoopCreated = ASMAtomicReadU8(&g_fWorkLoopCreated);
            thread_block(0);
        }
        if (fWorkLoopCreated == VBOXGUEST_OBJECT_INITIALIZED)
            PDEBUG("returned existing work loop");
        else
            PDEBUG("work loop was not allocated correctly");
    }

    return m_pWorkLoop;
}
Пример #3
0
/**
 * Get VBoxVFS root vnode.
 *
 * Handle three cases here:
 *  - vnode does not exist yet: create a new one
 *  - currently creating vnode: wait till the end, increment usage count and return existing one
 *  - vnode already created: increment usage count and return existing one
 *  - vnode was failed to create: give a chance to try to re-create it later
 *
 * @param mp        Mount data provided by VFS layer.
 * @param ppVnode   vnode to return.
 * @param pContext  kAuth context needed in order to authentificate mount operation.
 *
 * @return 0 on success or BSD error code otherwise.
 */
static int
vboxvfs_root(struct mount *mp, struct vnode **ppVnode, vfs_context_t pContext)
{
    NOREF(pContext);

    vboxvfs_mount_t *pMount;
    int rc = 0;
    uint32_t vid;

    PDEBUG("Getting root vnode...");

    AssertReturn(mp,      EINVAL);
    AssertReturn(ppVnode, EINVAL);

    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp);
    AssertReturn(pMount, EINVAL);

    /* Check case when vnode does not exist yet */
    if (ASMAtomicCmpXchgU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_INITIALIZING, VBOXVFS_OBJECT_UNINITIALIZED))
    {
        PDEBUG("Create new root vnode");

        /* Allocate empty SHFLSTRING to indicate path to root vnode within Shared Folder */
        char        szEmpty[1];
        SHFLSTRING *pSFVnodePath;

        pSFVnodePath = vboxvfs_construct_shflstring((char *)szEmpty, 0);
        if (pSFVnodePath)
        {
            int rc2;
            rc2 = vboxvfs_create_vnode_internal(mp, VDIR, NULL, TRUE, pSFVnodePath, &pMount->pRootVnode);
            if (rc2 != 0)
            {
                RTMemFree(pSFVnodePath);
                rc = ENOTSUP;
            }
        }
        else
            rc = ENOMEM;

        /* Notify other threads about result */
        if (rc == 0)
            ASMAtomicWriteU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_INITIALIZED);
        else
            ASMAtomicWriteU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_INVALID);
    }
    else
    {
        /* Check case if we are currently creating vnode. Wait while other thread to finish allocation. */
        uint8_t fRootVnodeState = VBOXVFS_OBJECT_UNINITIALIZED;
        while (fRootVnodeState != VBOXVFS_OBJECT_INITIALIZED
            && fRootVnodeState != VBOXVFS_OBJECT_INVALID)
        {
            /* @todo: Currently, we are burning CPU cycles while waiting. This is for a short
             * time but we should relax here! */
            fRootVnodeState = ASMAtomicReadU8(&pMount->fRootVnodeState);

        }

        /* Check if the other thread initialized root vnode and it is ready to be returned */
        if (fRootVnodeState == VBOXVFS_OBJECT_INITIALIZED)
        {
            /* Take care about iocount */
            vid = vnode_vid(pMount->pRootVnode);
            rc = vnode_getwithvid(pMount->pRootVnode, vid);
        }
        else
        {
            /* Other thread reported initialization failure.
             * Set vnode state VBOXVFS_OBJECT_UNINITIALIZED in order to try recreate root
             * vnode in other attempt */
            ASMAtomicWriteU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_UNINITIALIZED);
        }

    }

    /* Only return vnode if we got success */
    if (rc == 0)
    {
        PDEBUG("Root vnode can be returned");
        *ppVnode = pMount->pRootVnode;
    }
    else
        PDEBUG("Root vnode cannot be returned: 0x%X", rc);

    return rc;
}