VirtualBox

Ignore:
Timestamp:
Apr 6, 2012 9:05:19 PM (13 years ago)
Author:
vboxsync
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/solaris/spinlock-r0drv-solaris.c

    r40149 r40806  
    5555    /** Spinlock magic value (RTSPINLOCK_MAGIC). */
    5656    uint32_t volatile   u32Magic;
     57    /** Spinlock creation flags.  */
     58    uint32_t            fFlags;
     59    /** Saved interrupt flag. */
     60    uint32_t volatile   fIntSaved;
    5761    /** A Solaris spinlock. */
    5862    kmutex_t            Mtx;
     
    6771
    6872
    69 
    70 RTDECL(int)  RTSpinlockCreate(PRTSPINLOCK pSpinlock)
    71 {
     73This code has changed and need testing!;
     74
     75
     76RTDECL(int)  RTSpinlockCreate(PRTSPINLOCK pSpinlock, uint32_t fFlags, const char *pszName)
     77{
     78    RT_ASSERT_PREEMPTIBLE();
     79    AssertReturn(fFlags == RTSPINLOCK_FLAGS_INTERRUPT_SAFE || fFlags == RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, VERR_INVALID_PARAMETER);
     80
    7281    /*
    7382     * Allocate.
    7483     */
    75     RT_ASSERT_PREEMPTIBLE();
    7684    AssertCompile(sizeof(RTSPINLOCKINTERNAL) > sizeof(void *));
    7785    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)RTMemAlloc(sizeof(*pThis));
     
    8290     * Initialize & return.
    8391     */
    84     pThis->u32Magic = RTSPINLOCK_MAGIC;
     92    pThis->u32Magic  = RTSPINLOCK_MAGIC;
     93    pThis->fFlags    = fFlags;
     94    pThis->fIntSaved = 0;
     95    /** @todo Consider different PIL when not interrupt safe requirement. */
    8596    mutex_init(&pThis->Mtx, "IPRT Spinlock", MUTEX_SPIN, (void *)ipltospl(PIL_MAX));
    8697    *pSpinlock = pThis;
     
    112123
    113124
    114 RTDECL(void) RTSpinlockAcquireNoInts(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
    115 {
    116     PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
    117     RT_ASSERT_PREEMPT_CPUID_VAR();
    118 
    119     AssertPtr(pThis);
    120     Assert(pThis->u32Magic == RTSPINLOCK_MAGIC);
    121 
    122 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    123     pTmp->uFlags = ASMIntDisableFlags();
    124 #else
    125     pTmp->uFlags = 0;
    126 #endif
    127     mutex_enter(&pThis->Mtx);
    128 
    129     /*
    130      * Solaris 10 doesn't preserve the interrupt flag, but since we're at PIL_MAX we should be
    131      * fine and not get interrupts while lock is held. Re-disable interrupts to not upset
    132      * assertions & assumptions callers might have.
    133      */
    134 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    135     ASMIntDisable();
    136 #endif
    137 
    138 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    139     Assert(!ASMIntAreEnabled());
    140 #endif
    141     RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pThis);
    142 }
    143 
    144 
    145 RTDECL(void) RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
    146 {
    147     PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
    148     RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE_VARS();
    149 
    150     AssertPtr(pThis);
    151     Assert(pThis->u32Magic == RTSPINLOCK_MAGIC);
    152     RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE(pThis);
    153     NOREF(pTmp);
    154 
    155     mutex_exit(&pThis->Mtx);
    156 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    157     ASMSetFlags(pTmp->uFlags);
    158 #endif
    159 
    160     RT_ASSERT_PREEMPT_CPUID();
    161 }
    162 
    163 
    164 RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
     125RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock)
    165126{
    166127    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
     
    168129    AssertPtr(pThis);
    169130    Assert(pThis->u32Magic == RTSPINLOCK_MAGIC);
    170     NOREF(pTmp);
     131
     132    if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE)
     133    {
     134#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     135        uint32_t fIntSaved = ASMIntDisableFlags();
     136#endif
     137        mutex_enter(&pThis->Mtx);
     138
     139        /*
     140         * Solaris 10 doesn't preserve the interrupt flag, but since we're at PIL_MAX we should be
     141         * fine and not get interrupts while lock is held. Re-disable interrupts to not upset
     142         * assertions & assumptions callers might have.
     143         */
     144#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     145        ASMIntDisable();
     146#endif
     147
     148#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     149        Assert(!ASMIntAreEnabled());
     150#endif
     151        pThis->fIntSaved = fIntSaved;
     152    }
     153    else
     154    {
    171155#if defined(RT_STRICT) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
    172     bool fIntsOn = ASMIntAreEnabled();
    173 #endif
    174 
    175     mutex_enter(&pThis->Mtx);
    176 
    177 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    178     AssertMsg(fIntsOn == ASMIntAreEnabled(), ("fIntsOn=%RTbool\n", fIntsOn));
    179 #endif
     156        bool fIntsOn = ASMIntAreEnabled();
     157#endif
     158
     159        mutex_enter(&pThis->Mtx);
     160
     161#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     162        AssertMsg(fIntsOn == ASMIntAreEnabled(), ("fIntsOn=%RTbool\n", fIntsOn));
     163#endif
     164    }
    180165
    181166    RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pThis);
     
    183168
    184169
    185 RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
     170RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock)
    186171{
    187172    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
     
    191176    Assert(pThis->u32Magic == RTSPINLOCK_MAGIC);
    192177    RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE(pThis);
    193     NOREF(pTmp);
     178
     179    if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE)
     180    {
     181#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     182        uint32_t fIntSaved = pThis->fIntSaved;
     183        pThis->fIntSaved = 0;
     184#endif
     185        mutex_exit(&pThis->Mtx);
     186
     187#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     188        ASMSetFlags(fIntSaved);
     189#endif
     190    }
     191    else
     192    {
    194193#if defined(RT_STRICT) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
    195     bool fIntsOn = ASMIntAreEnabled();
    196 #endif
    197 
    198     mutex_exit(&pThis->Mtx);
    199 
    200 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    201     AssertMsg(fIntsOn == ASMIntAreEnabled(), ("fIntsOn=%RTbool\n", fIntsOn));
    202 #endif
     194        bool fIntsOn = ASMIntAreEnabled();
     195#endif
     196
     197        mutex_exit(&pThis->Mtx);
     198
     199#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     200        AssertMsg(fIntsOn == ASMIntAreEnabled(), ("fIntsOn=%RTbool\n", fIntsOn));
     201#endif
     202    }
     203
    203204    RT_ASSERT_PREEMPT_CPUID();
    204205}
    205206
     207
     208RTDECL(void) RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock)
     209{
     210#if 1
     211    if (RT_UNLIKELY(!(Spinlock->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE)))
     212        RTAssertMsg2("RTSpinlockReleaseNoInts: %p (magic=%#x)\n", Spinlock, Spinlock->u32Magic);
     213#else
     214    AssertRelease(Spinlock->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE);
     215#endif
     216    RTSpinlockRelease(Spinlock);
     217}
     218
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