VirtualBox

Ignore:
Timestamp:
Apr 6, 2012 9:05:19 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
77321
Message:

RTSpinlock: Redid the interface, eliminating NoInts and Tmp. Whether a spinlock is interrupt safe or not is now defined at creation time, preventing stupid bugs arrising from calling the wrong acquire and/or release methods somewhere. The saved flags are stored in the spinlock strucutre, eliminating the annoying Tmp variable. Needs testing on each platform before fixing the build burn.

File:
1 edited

Legend:

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

    r29500 r40806  
    5959    /** The spinlock. */
    6060    uint32_t volatile   fLocked;
    61     /** Reserved to satisfy compile assertion below. */
    62     uint32_t            uReserved;
     61    /** Saved interrupt flag. */
     62    uint32_t volatile   fIntSaved;
     63    /** The spinlock creation flags. */
     64    uint32_t            fFlags;
    6365#ifdef RT_MORE_STRICT
    6466    /** The idAssertCpu variable before acquring the lock for asserting after
     
    7173
    7274
    73 RTDECL(int)  RTSpinlockCreate(PRTSPINLOCK pSpinlock)
    74 {
     75RTDECL(int)  RTSpinlockCreate(PRTSPINLOCK pSpinlock, uint32_t fFlags, const char *pszName)
     76{
     77    RT_ASSERT_PREEMPTIBLE();
     78    AssertReturn(fFlags == RTSPINLOCK_FLAGS_INTERRUPT_SAFE || fFlags == RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, VERR_INVALID_PARAMETER);
     79
    7580    /*
    7681     * Allocate.
    7782     */
    78     RT_ASSERT_PREEMPTIBLE();
    7983    AssertCompile(sizeof(RTSPINLOCKINTERNAL) > sizeof(void *));
    8084    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)RTMemAllocZ(sizeof(*pThis));
     
    8589     * Initialize & return.
    8690     */
    87     pThis->u32Magic = RTSPINLOCK_MAGIC;
    88     pThis->fLocked  = 0;
     91    pThis->u32Magic  = RTSPINLOCK_MAGIC;
     92    pThis->fLocked   = 0;
     93    pThis->fFlags    = fFlags;
     94    pThis->fIntSaved = 0;
     95
    8996    *pSpinlock = pThis;
    9097    return VINF_SUCCESS;
     
    114121
    115122
    116 RTDECL(void) RTSpinlockAcquireNoInts(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
    117 {
    118     PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
    119     AssertPtr(pThis);
    120     Assert(pThis->u32Magic == RTSPINLOCK_MAGIC);
    121     RT_ASSERT_PREEMPT_CPUID_VAR();
    122     Assert(pTmp->uFlags == 0);
    123 
    124     for (;;)
    125     {
    126         pTmp->uFlags = ASMIntDisableFlags();
    127         critical_enter();
    128 
    129         int c = 50;
    130         for (;;)
    131         {
    132             if (ASMAtomicCmpXchgU32(&pThis->fLocked, 1, 0))
    133             {
    134                 RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pThis);
    135                 return;
    136             }
    137             if (--c <= 0)
    138                 break;
    139             cpu_spinwait();
    140         }
    141 
    142         /* Enable interrupts while we sleep. */
    143         ASMSetFlags(pTmp->uFlags);
    144         critical_exit();
    145         DELAY(1);
    146     }
    147 }
    148 
    149 
    150 RTDECL(void) RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
    151 {
    152     PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
    153     RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE_VARS();
    154 
    155     AssertPtr(pThis);
    156     Assert(pThis->u32Magic == RTSPINLOCK_MAGIC);
    157     RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE(pThis);
    158 
    159     if (!ASMAtomicCmpXchgU32(&pThis->fLocked, 0, 1))
    160         AssertMsgFailed(("Spinlock %p was not locked!\n", pThis));
    161 
    162     ASMSetFlags(pTmp->uFlags);
    163     critical_exit();
    164     pTmp->uFlags = 0;
    165 }
    166 
    167 
    168 RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
     123RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock)
    169124{
    170125    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
     
    172127    AssertPtr(pThis);
    173128    Assert(pThis->u32Magic == RTSPINLOCK_MAGIC);
    174 #ifdef RT_STRICT
    175     Assert(pTmp->uFlags == 0);
    176     pTmp->uFlags = 42;
    177 #endif
    178 
    179     NOREF(pTmp);
    180 
    181     for (;;)
    182     {
    183         critical_enter();
    184 
    185         int c = 50;
     129
     130    if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE)
     131    {
    186132        for (;;)
    187133        {
    188             if (ASMAtomicCmpXchgU32(&pThis->fLocked, 1, 0))
     134            uint32_t fIntSaved = ASMIntDisableFlags();
     135            critical_enter();
     136
     137            int c = 50;
     138            for (;;)
    189139            {
    190                 RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pThis);
    191                 return;
     140                if (ASMAtomicCmpXchgU32(&pThis->fLocked, 1, 0))
     141                {
     142                    RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pThis);
     143                    pThis->fIntSaved = fIntSaved;
     144                    return;
     145                }
     146                if (--c <= 0)
     147                    break;
     148                cpu_spinwait();
    192149            }
    193             if (--c <= 0)
    194                 break;
    195             cpu_spinwait();
     150
     151            /* Enable interrupts while we sleep. */
     152            critical_exit();
     153            ASMSetFlags(fIntSaved);
     154            DELAY(1);
    196155        }
    197 
    198         critical_exit();
    199         DELAY(1);
    200     }
    201 }
    202 
    203 
    204 RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
     156    }
     157    else
     158    {
     159        for (;;)
     160        {
     161            critical_enter();
     162
     163            int c = 50;
     164            for (;;)
     165            {
     166                if (ASMAtomicCmpXchgU32(&pThis->fLocked, 1, 0))
     167                {
     168                    RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pThis);
     169                    return;
     170                }
     171                if (--c <= 0)
     172                    break;
     173                cpu_spinwait();
     174            }
     175
     176            critical_exit();
     177            DELAY(1);
     178        }
     179    }
     180}
     181
     182
     183RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock)
    205184{
    206185    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
     
    210189    Assert(pThis->u32Magic == RTSPINLOCK_MAGIC);
    211190    RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE(pThis);
    212 #ifdef RT_STRICT
    213     Assert(pTmp->uFlags == 42);
    214     pTmp->uFlags = 0;
     191
     192    if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE)
     193    {
     194        uint32_t fIntSaved = pThis->fIntSaved;
     195        pThis->fIntSaved = 0;
     196        if (ASMAtomicCmpXchgU32(&pThis->fLocked, 0, 1))
     197            ASMSetFlags(pThis->fIntSaved);
     198        else
     199            AssertMsgFailed(("Spinlock %p was not locked!\n", pThis));
     200    }
     201    else
     202    {
     203        if (!ASMAtomicCmpXchgU32(&pThis->fLocked, 0, 1))
     204            AssertMsgFailed(("Spinlock %p was not locked!\n", pThis));
     205    }
     206
     207    critical_exit();
     208}
     209
     210
     211RTDECL(void) RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock)
     212{
     213#if 1
     214    if (RT_UNLIKELY(!(Spinlock->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE)))
     215        RTAssertMsg2("RTSpinlockReleaseNoInts: %p (magic=%#x)\n", Spinlock, Spinlock->u32Magic);
     216#else
     217    AssertRelease(Spinlock->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE);
    215218#endif
    216     NOREF(pTmp);
    217 
    218     if (!ASMAtomicCmpXchgU32(&pThis->fLocked, 0, 1))
    219         AssertMsgFailed(("Spinlock %p was not locked!\n", pThis));
    220 
    221     critical_exit();
    222 }
    223 
     219    RTSpinlockRelease(Spinlock);
     220}
     221
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette