VirtualBox

Changeset 6727 in vbox


Ignore:
Timestamp:
Feb 1, 2008 5:06:53 PM (17 years ago)
Author:
vboxsync
Message:

Reimplemented mutex semaphores in sems-linux.cpp (64bit linux has bugs in pthreads lib function pthread_mutex_timedlock causing SEGV). Disabled at the moment as there are performance issues with lwip. The synchronization itself is apparently correct.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/linux/sems-linux.cpp

    r5999 r6727  
    8585
    8686
     87#ifndef VBOX_REWRITTEN_MUTEX
    8788/**
    8889 * Posix internal representation of a Mutex semaphore.
     
    9798    volatile uint32_t   cNesting;
    9899};
     100#else /* VBOX_REWRITTEN_MUTEX */
     101/**
     102 * Linux internal representation of a Mutex semaphore.
     103 */
     104struct RTSEMMUTEXINTERNAL
     105{
     106    /** Magic value. */
     107    intptr_t volatile   iMagic;
     108    /** The futex state variable.
     109     * 0 means unlocked.
     110     * 1 means locked, no waiters.
     111     * 2 means locked, one or more waiters.
     112     */
     113    int32_t volatile    iState;
     114    /** The owner of the mutex. */
     115    volatile pthread_t  Owner;
     116    /** Nesting count. */
     117    volatile uint32_t   cNesting;
     118};
     119#endif /* VBOX_REWRITTEN_MUTEX */
    99120
    100121
     
    281302                return VERR_SEM_DESTROYED;
    282303
    283             /* Did somebody wake us up us from RTSemEventSignal()? */
     304            /* Did somebody wake us up from RTSemEventSignal()? */
    284305            if (rc == 0)
    285306                return VINF_SUCCESS;
     
    535556        return false;
    536557
     558#ifdef VBOX_REWRITTEN_MUTEX
     559    if (pIntMutexSem->iMagic != RTSEMMUTEX_MAGIC)
     560        return false;
     561
     562#endif /* VBOX_REWRITTEN_MUTEX */
    537563    if (pIntMutexSem->cNesting == (uint32_t)~0)
    538564        return false;
     
    542568
    543569
     570#ifndef VBOX_REWRITTEN_MUTEX
    544571RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
    545572{
     
    745772    return VINF_SUCCESS;
    746773}
    747 
     774#else /* VBOX_REWRITTEN_MUTEX */
     775RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
     776{
     777    /*
     778     * Allocate semaphore handle.
     779     */
     780    struct RTSEMMUTEXINTERNAL *pIntMutexSem = (struct RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(struct RTSEMMUTEXINTERNAL));
     781    if (pIntMutexSem)
     782    {
     783        pIntMutexSem->iMagic   = RTSEMMUTEX_MAGIC;
     784        pIntMutexSem->iState   = 0;
     785        pIntMutexSem->Owner    = (pthread_t)~0;
     786        pIntMutexSem->cNesting = 0;
     787
     788        *pMutexSem = pIntMutexSem;
     789        return VINF_SUCCESS;
     790    }
     791
     792    return VERR_NO_MEMORY;
     793}
     794
     795
     796RTDECL(int)  RTSemMutexDestroy(RTSEMMUTEX MutexSem)
     797{
     798    struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
     799    /*
     800     * Validate input.
     801     */
     802    if (!rtsemMutexValid(pIntMutexSem))
     803    {
     804        AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
     805        return VERR_INVALID_HANDLE;
     806    }
     807
     808    /*
     809     * Invalidate the semaphore and wake up anyone waiting on it.
     810     */
     811    ASMAtomicXchgSize(&pIntMutexSem->iMagic, RTSEMMUTEX_MAGIC + 1);
     812    if (ASMAtomicXchgS32(&pIntMutexSem->iState, 0) > 0)
     813    {
     814        sys_futex(&pIntMutexSem->iState, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
     815        usleep(1000);
     816    }
     817    pIntMutexSem->Owner    = (pthread_t)~0;
     818    pIntMutexSem->cNesting = ~0;
     819
     820    /*
     821     * Free the semaphore memory and be gone.
     822     */
     823    RTMemFree(pIntMutexSem);
     824    return VINF_SUCCESS;
     825}
     826
     827
     828static int rtsemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies, bool fAutoResume)
     829{
     830    /*
     831     * Validate input.
     832     */
     833    struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
     834    if (!rtsemMutexValid(pIntMutexSem))
     835    {
     836        AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
     837        return VERR_INVALID_HANDLE;
     838    }
     839
     840    /*
     841     * Check if nested request.
     842     */
     843    pthread_t Self = pthread_self();
     844    if (    pIntMutexSem->Owner == Self
     845        &&  pIntMutexSem->cNesting > 0)
     846    {
     847        pIntMutexSem->cNesting++;
     848        return VINF_SUCCESS;
     849    }
     850
     851    /*
     852     * Convert timeout value.
     853     */
     854    struct timespec ts;
     855    struct timespec *pTimeout = NULL;
     856    if (cMillies != RT_INDEFINITE_WAIT)
     857    {
     858        ts.tv_sec  = cMillies / 1000;
     859        ts.tv_nsec = (cMillies % 1000) * 1000000;
     860        pTimeout = &ts;
     861    }
     862
     863    /*
     864     * Lock the mutex.
     865     */
     866    int32_t iOld;
     867    ASMAtomicCmpXchgExS32(&pIntMutexSem->iState, 1, 0, &iOld);
     868    if (iOld != 0)
     869    {
     870        iOld = ASMAtomicXchgS32(&pIntMutexSem->iState, 2);
     871        while (iOld != 0)
     872        {
     873            /*
     874             * Go to sleep.
     875             */
     876            long rc = sys_futex(&pIntMutexSem->iState, FUTEX_WAIT, 2, pTimeout, NULL, 0);
     877            if (RT_UNLIKELY(pIntMutexSem->iMagic != RTSEMMUTEX_MAGIC))
     878                return VERR_SEM_DESTROYED;
     879
     880            /*
     881             * Act on the wakup code.
     882             */
     883            if (rc == -ETIMEDOUT)
     884            {
     885                Assert(pTimeout);
     886                iOld = ASMAtomicXchgS32(&pIntMutexSem->iState, 2);
     887                return VERR_TIMEOUT;
     888            }
     889            if (rc == 0)
     890                /* we'll leave the loop now unless another thread is faster */;
     891            else if (rc == -EWOULDBLOCK)
     892                /* retry with new value. */;
     893            else if (rc == -EINTR)
     894            {
     895                if (!fAutoResume)
     896                    return VERR_INTERRUPTED;
     897            }
     898            else
     899            {
     900                /* this shouldn't happen! */
     901                AssertMsgFailed(("rc=%ld errno=%d\n", rc, errno));
     902                return RTErrConvertFromErrno(rc);
     903            }
     904
     905            iOld = ASMAtomicXchgS32(&pIntMutexSem->iState, 2);
     906        }
     907    }
     908
     909    /*
     910     * Set the owner and nesting.
     911     */
     912    pIntMutexSem->Owner = Self;
     913    ASMAtomicXchgU32(&pIntMutexSem->cNesting, 1);
     914    return VINF_SUCCESS;
     915}
     916
     917
     918RTDECL(int)  RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
     919{
     920    int rc = rtsemMutexRequest(MutexSem, cMillies, true);
     921    Assert(rc != VERR_INTERRUPTED);
     922    return rc;
     923}
     924
     925
     926RTDECL(int)  RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies)
     927{
     928    return rtsemMutexRequest(MutexSem, cMillies, false);
     929}
     930
     931
     932RTDECL(int)  RTSemMutexRelease(RTSEMMUTEX MutexSem)
     933{
     934    /*
     935     * Validate input.
     936     */
     937    struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
     938    if (!rtsemMutexValid(pIntMutexSem))
     939    {
     940        AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
     941        return VERR_INVALID_HANDLE;
     942    }
     943
     944    /*
     945     * Check if nested.
     946     */
     947    pthread_t Self = pthread_self();
     948    if (    pIntMutexSem->Owner != Self
     949        ||  pIntMutexSem->cNesting == (uint32_t)~0)
     950    {
     951        AssertMsgFailed(("Not owner of mutex %p!! Self=%08x Owner=%08x cNesting=%d\n",
     952                         pIntMutexSem, Self, pIntMutexSem->Owner, pIntMutexSem->cNesting));
     953        return VERR_NOT_OWNER;
     954    }
     955
     956    /*
     957     * If nested we'll just pop a nesting.
     958     */
     959    if (pIntMutexSem->cNesting > 1)
     960    {
     961        pIntMutexSem->cNesting--;
     962        return VINF_SUCCESS;
     963    }
     964
     965    /*
     966     * Clear the state. (cNesting == 1)
     967     */
     968    pIntMutexSem->Owner = (pthread_t)~0;
     969    ASMAtomicXchgU32(&pIntMutexSem->cNesting, 0);
     970
     971    /*
     972     * Release the mutex.
     973     */
     974    int32_t iNew = ASMAtomicDecS32(&pIntMutexSem->iState);
     975    if (iNew != 0)
     976    {
     977        /* somebody is waiting, try wake up one of them. */
     978        pIntMutexSem->iState = 0;
     979        (void)sys_futex(&pIntMutexSem->iState, FUTEX_WAKE, 1, NULL, NULL, 0);
     980    }
     981    return VINF_SUCCESS;
     982}
     983#endif /* VBOX_REWRITTEN_MUTEX */
    748984
    749985
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