VirtualBox

Changeset 22580 in vbox


Ignore:
Timestamp:
Aug 30, 2009 8:38:49 PM (15 years ago)
Author:
vboxsync
Message:

Runtime/spinlock-r0drv-freebsd:

Replace spin mutexes with our own implementation.
Spin mutexes are always disabling interrupts which
is not what we always want here

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/freebsd/spinlock-r0drv-freebsd.c

    r19565 r22580  
    3333*******************************************************************************/
    3434#include "the-freebsd-kernel.h"
     35#include "internal/iprt.h"
    3536
    3637#include <iprt/spinlock.h>
     
    3940#include <iprt/assert.h>
    4041#include <iprt/asm.h>
     42#include <iprt/thread.h>
     43#include <iprt/mp.h>
    4144
    4245#include "internal/magics.h"
     
    5356    /** Spinlock magic value (RTSPINLOCK_MAGIC). */
    5457    uint32_t volatile   u32Magic;
    55     /** A FreeBSD spinlock. (mtx can be both sleep and spin lock.) */
    56     struct mtx          Mtx;
     58    /** The spinlock. */
     59    uint32_t volatile   fLocked;
     60    /** Reserved to satisfy compile assertion below. */
     61    uint32_t            uReserved;
     62#ifdef RT_MORE_STRICT
     63    /** The idAssertCpu variable before acquring the lock for asserting after
     64     *  releasing the spinlock. */
     65    RTCPUID volatile    idAssertCpu;
     66    /** The CPU that owns the lock. */
     67    RTCPUID volatile    idCpuOwner;
     68#endif
    5769} RTSPINLOCKINTERNAL, *PRTSPINLOCKINTERNAL;
    5870
     
    6375     * Allocate.
    6476     */
     77    RT_ASSERT_PREEMPTIBLE();
    6578    AssertCompile(sizeof(RTSPINLOCKINTERNAL) > sizeof(void *));
    6679    PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)RTMemAllocZ(sizeof(*pSpinlockInt));
     
    7285     */
    7386    pSpinlockInt->u32Magic = RTSPINLOCK_MAGIC;
    74     mtx_init(&pSpinlockInt->Mtx, "IPRT Spinlock", NULL, MTX_SPIN);
     87    pSpinlockInt->fLocked  = 0;
    7588    *pSpinlock = pSpinlockInt;
    7689    return VINF_SUCCESS;
     
    8396     * Validate input.
    8497     */
     98    RT_ASSERT_INTS_ON();
    8599    PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
    86100    if (!pSpinlockInt)
     
    94108     */
    95109    ASMAtomicIncU32(&pSpinlockInt->u32Magic);
    96     mtx_destroy(&pSpinlockInt->Mtx);
    97110    RTMemFree(pSpinlockInt);
    98111    return VINF_SUCCESS;
     
    105118    AssertPtr(pSpinlockInt);
    106119    Assert(pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC);
     120    RT_ASSERT_PREEMPT_CPUID_VAR();
     121
     122    for (;;)
     123    {
     124        pTmp->uFlags = ASMGetFlags();
     125        ASMIntDisable();
     126        critical_enter();
     127
     128        for (int c = 50; c > 0; c--)
     129            if (ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 1, 0))
     130            {
     131                RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pSpinlockInt);
     132                return;
     133            }
     134            else
     135                cpu_spinwait();
     136
     137        /* Enable interrupts while we sleep. */
     138        ASMSetFlags(pTmp->uFlags);
     139        critical_exit();
     140        DELAY(1);
     141    }
     142}
     143
     144
     145RTDECL(void) RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
     146{
     147    PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
     148    RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE_VARS();
     149
     150    AssertPtr(pSpinlockInt);
     151    Assert(pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC);
     152    RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE(pSpinlockInt);
    107153    NOREF(pTmp);
    108154
    109     mtx_lock_spin(&pSpinlockInt->Mtx);
    110 }
    111 
    112 
    113 RTDECL(void) RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
    114 {
    115     PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
    116     AssertPtr(pSpinlockInt);
    117     Assert(pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC);
     155    if (!ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 0, 1))
     156        AssertMsgFailed(("Spinlock %p was not locked!\n", pSpinlockInt));
     157    ASMSetFlags(pTmp->uFlags);
     158
     159    critical_exit();
     160}
     161
     162
     163RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
     164{
     165    PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
     166    RT_ASSERT_PREEMPT_CPUID_VAR();
     167    AssertPtr(pSpinlockInt);
     168    Assert(pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC);
     169
    118170    NOREF(pTmp);
    119171
    120     mtx_unlock_spin(&pSpinlockInt->Mtx);
    121 }
    122 
    123 
    124 RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
    125 {
    126     PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
    127     AssertPtr(pSpinlockInt);
    128     Assert(pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC);
     172    for (;;)
     173    {
     174        critical_enter();
     175        for (int c = 50; c > 0; c--)
     176            if (ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 1, 0))
     177            {
     178                RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pSpinlockInt);
     179                return;
     180            }
     181            else
     182                cpu_spinwait();
     183
     184        critical_exit();
     185        DELAY(1);
     186    }
     187}
     188
     189
     190RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
     191{
     192    PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
     193    RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE_VARS();
     194
     195    AssertPtr(pSpinlockInt);
     196    Assert(pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC);
     197    RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE(pSpinlockInt);
     198
    129199    NOREF(pTmp);
    130200
    131     mtx_lock_spin(&pSpinlockInt->Mtx);
    132 }
    133 
    134 
    135 RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
    136 {
    137     PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
    138     AssertPtr(pSpinlockInt);
    139     Assert(pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC);
    140     NOREF(pTmp);
    141 
    142     mtx_unlock_spin(&pSpinlockInt->Mtx);
    143 }
    144 
     201    if (!ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 0, 1))
     202        AssertMsgFailed(("Spinlock %p was not locked!\n", pSpinlockInt));
     203
     204    critical_exit();
     205}
     206
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