VirtualBox

Changeset 40806 in vbox for trunk/src/VBox/Runtime/generic


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.

Location:
trunk/src/VBox/Runtime/generic
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/generic/mempool-generic.cpp

    r33540 r40806  
    138138    if (!pMemPool)
    139139        return VERR_NO_MEMORY;
    140     int rc = RTSpinlockCreate(&pMemPool->hSpinLock);
     140    int rc = RTSpinlockCreate(&pMemPool->hSpinLock, RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, "RTMemPoolCreate");
    141141    if (RT_SUCCESS(rc))
    142142    {
     
    203203    if (pMemPool->hSpinLock != NIL_RTSPINLOCK)
    204204    {
    205         RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
    206         RTSpinlockAcquire(pMemPool->hSpinLock, &Tmp);
     205        RTSpinlockAcquire(pMemPool->hSpinLock);
    207206
    208207        PRTMEMPOOLENTRY pHead = pMemPool->pHead;
     
    212211        pMemPool->pHead = pEntry;
    213212
    214         RTSpinlockRelease(pMemPool->hSpinLock, &Tmp);
     213        RTSpinlockRelease(pMemPool->hSpinLock);
    215214    }
    216215
     
    224223    if (pMemPool->hSpinLock != NIL_RTSPINLOCK)
    225224    {
    226         RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
    227         RTSpinlockAcquire(pMemPool->hSpinLock, &Tmp);
     225        RTSpinlockAcquire(pMemPool->hSpinLock);
    228226
    229227        PRTMEMPOOLENTRY pNext = pEntry->pNext;
     
    237235        pEntry->pMemPool = NULL;
    238236
    239         RTSpinlockRelease(pMemPool->hSpinLock, &Tmp);
     237        RTSpinlockRelease(pMemPool->hSpinLock);
    240238    }
    241239    else
  • trunk/src/VBox/Runtime/generic/spinlock-generic.cpp

    r34239 r40806  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    6565    /** Spinlock magic value (RTSPINLOCK_MAGIC). */
    6666    uint32_t            u32Magic;
     67    /** The spinlock creation flags. */
     68    uint32_t            fFlags;
    6769    /** The spinlock. */
    6870    uint32_t volatile   fLocked;
     71    /** The saved CPU interrupt. */
     72    uint32_t volatile   fIntSaved;
    6973} RTSPINLOCKINTERNAL, *PRTSPINLOCKINTERNAL;
    7074
    7175
    72 RTDECL(int)  RTSpinlockCreate(PRTSPINLOCK pSpinlock)
    73 {
     76RTDECL(int)  RTSpinlockCreate(PRTSPINLOCK pSpinlock, uint32_t fFlags, const char *pszName)
     77{
     78    PRTSPINLOCKINTERNAL pThis;
     79    AssertReturn(fFlags == RTSPINLOCK_FLAGS_INTERRUPT_SAFE || fFlags == RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, VERR_INVALID_PARAMETER);
     80
    7481    /*
    7582     * Allocate.
    7683     */
    77     PRTSPINLOCKINTERNAL pSpinlockInt;
    78     pSpinlockInt = (PRTSPINLOCKINTERNAL)RTMemAlloc(sizeof(*pSpinlockInt));
    79     if (!pSpinlockInt)
     84    pThis = (PRTSPINLOCKINTERNAL)RTMemAlloc(sizeof(*pThis));
     85    if (!pThis)
    8086        return VERR_NO_MEMORY;
    8187
     
    8389     * Initialize and return.
    8490     */
    85     pSpinlockInt->u32Magic = RTSPINLOCK_MAGIC;
    86     ASMAtomicXchgU32(&pSpinlockInt->fLocked, 0);
    87 
    88     *pSpinlock = pSpinlockInt;
     91    pThis->u32Magic  = RTSPINLOCK_MAGIC;
     92    pThis->fFlags    = fFlags;
     93    pThis->fIntSaved = 0;
     94    ASMAtomicWriteU32(&pThis->fLocked, 0);
     95
     96    *pSpinlock = pThis;
    8997    return VINF_SUCCESS;
    9098}
     
    97105     * Validate input.
    98106     */
    99     PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
    100     if (!pSpinlockInt)
     107    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
     108    if (!pThis)
    101109        return VERR_INVALID_PARAMETER;
    102     if (pSpinlockInt->u32Magic != RTSPINLOCK_MAGIC)
    103     {
    104         AssertMsgFailed(("Invalid spinlock %p magic=%#x\n", pSpinlockInt, pSpinlockInt->u32Magic));
     110    if (pThis->u32Magic != RTSPINLOCK_MAGIC)
     111    {
     112        AssertMsgFailed(("Invalid spinlock %p magic=%#x\n", pThis, pThis->u32Magic));
    105113        return VERR_INVALID_PARAMETER;
    106114    }
    107115
    108     ASMAtomicIncU32(&pSpinlockInt->u32Magic);
    109     RTMemFree(pSpinlockInt);
     116    ASMAtomicIncU32(&pThis->u32Magic);
     117    RTMemFree(pThis);
    110118    return VINF_SUCCESS;
    111119}
     
    113121
    114122
    115 RTDECL(void) RTSpinlockAcquireNoInts(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
    116 {
    117     PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
    118     AssertMsg(pSpinlockInt && pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC,
    119               ("pSpinlockInt=%p u32Magic=%08x\n", pSpinlockInt, pSpinlockInt ? (int)pSpinlockInt->u32Magic : 0));
    120 
    121 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    122     pTmp->uFlags = ASMGetFlags();
     123RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock)
     124{
     125    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
     126    AssertMsg(pThis && pThis->u32Magic == RTSPINLOCK_MAGIC,
     127              ("pThis=%p u32Magic=%08x\n", pThis, pThis ? (int)pThis->u32Magic : 0));
     128
     129    if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE)
     130    {
     131#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     132        uint32_t fIntSaved = ASMGetFlags();
     133#endif
     134
     135#if RT_CFG_SPINLOCK_GENERIC_DO_SLEEP
     136        for (;;)
     137        {
     138            ASMIntDisable();
     139            for (int c = RT_CFG_SPINLOCK_GENERIC_DO_SLEEP; c > 0; c--)
     140            {
     141                if (ASMAtomicCmpXchgU32(&pThis->fLocked, 1, 0))
     142                {
     143# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     144                    pThis->fIntSaved = fIntSaved;
     145# endif
     146                    return;
     147                }
     148                ASMNopPause();
     149            }
     150            ASMSetFlags(fIntSaved);
     151            RTThreadYield();
     152        }
    123153#else
    124     pTmp->uFlags = 0;
    125 #endif
     154        for (;;)
     155        {
     156            ASMIntDisable();
     157            if (ASMAtomicCmpXchgU32(&pThis->fLocked, 1, 0))
     158            {
     159# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     160                pThis->fIntSaved = fIntSaved;
     161# endif
     162                return;
     163            }
     164            ASMSetFlags(fIntSaved);
     165            ASMNopPause();
     166        }
     167#endif
     168    }
     169    else
     170    {
    126171#if RT_CFG_SPINLOCK_GENERIC_DO_SLEEP
    127     for (;;)
    128     {
    129 # if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    130         ASMIntDisable();
    131 # endif
    132         for (int c = RT_CFG_SPINLOCK_GENERIC_DO_SLEEP; c > 0; c--)
    133             if (ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 1, 0))
    134                 return;
    135         RTThreadYield();
    136     }
     172        for (;;)
     173        {
     174            for (int c = RT_CFG_SPINLOCK_GENERIC_DO_SLEEP; c > 0; c--)
     175            {
     176                if (ASMAtomicCmpXchgU32(&pThis->fLocked, 1, 0))
     177                    return;
     178                ASMNopPause();
     179            }
     180            RTThreadYield();
     181        }
    137182#else
    138 # if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    139     ASMIntDisable();
    140 # endif
    141     while (!ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 1, 0))
    142         /*nothing */;
    143 #endif
    144 }
    145 RT_EXPORT_SYMBOL(RTSpinlockAcquireNoInts);
    146 
    147 
    148 RTDECL(void) RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
    149 {
    150     PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
    151     AssertMsg(pSpinlockInt && pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC,
    152               ("pSpinlockInt=%p u32Magic=%08x\n", pSpinlockInt, pSpinlockInt ? (int)pSpinlockInt->u32Magic : 0));
    153     NOREF(pSpinlockInt);
    154 
    155     if (!ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 0, 1))
    156         AssertMsgFailed(("Spinlock %p was not locked!\n", pSpinlockInt));
    157 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    158     ASMSetFlags(pTmp->uFlags);
    159 #endif
     183        while (!ASMAtomicCmpXchgU32(&pThis->fLocked, 1, 0))
     184            ASMNopPause();
     185#endif
     186    }
     187}
     188RT_EXPORT_SYMBOL(RTSpinlockAcquire);
     189
     190
     191RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock)
     192{
     193    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
     194    AssertMsg(pThis && pThis->u32Magic == RTSPINLOCK_MAGIC,
     195              ("pThis=%p u32Magic=%08x\n", pThis, pThis ? (int)pThis->u32Magic : 0));
     196
     197    if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE)
     198    {
     199#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     200        uint32_t fIntSaved = pThis->fIntSaved;
     201        pThis->fIntSaved   = 0;
     202#endif
     203
     204        if (!ASMAtomicCmpXchgU32(&pThis->fLocked, 0, 1))
     205            AssertMsgFailed(("Spinlock %p was not locked!\n", pThis));
     206
     207#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     208        ASMSetFlags(fIntSaved);
     209#endif
     210    }
     211    else
     212    {
     213        if (!ASMAtomicCmpXchgU32(&pThis->fLocked, 0, 1))
     214            AssertMsgFailed(("Spinlock %p was not locked!\n", pThis));
     215    }
     216}
     217RT_EXPORT_SYMBOL(RTSpinlockRelease);
     218
     219
     220RTDECL(void) RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock)
     221{
     222#if 1
     223    if (RT_UNLIKELY(!(Spinlock->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE)))
     224        RTAssertMsg2("RTSpinlockReleaseNoInts: %p (magic=%#x)\n", Spinlock, Spinlock->u32Magic);
     225#else
     226    AssertRelease(Spinlock->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE);
     227#endif
     228    RTSpinlockRelease(Spinlock);
    160229}
    161230RT_EXPORT_SYMBOL(RTSpinlockReleaseNoInts);
    162231
    163 
    164 RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
    165 {
    166     PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
    167     AssertMsg(pSpinlockInt && pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC,
    168               ("pSpinlockInt=%p u32Magic=%08x\n", pSpinlockInt, pSpinlockInt ? (int)pSpinlockInt->u32Magic : 0));
    169     NOREF(pTmp);
    170 
    171 #if RT_CFG_SPINLOCK_GENERIC_DO_SLEEP
    172     for (;;)
    173     {
    174         for (int c = RT_CFG_SPINLOCK_GENERIC_DO_SLEEP; c > 0; c--)
    175             if (ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 1, 0))
    176                 return;
    177         RTThreadYield();
    178     }
    179 #else
    180     while (!ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 1, 0))
    181         /*nothing */;
    182 #endif
    183 }
    184 RT_EXPORT_SYMBOL(RTSpinlockAcquire);
    185 
    186 
    187 RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
    188 {
    189     PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
    190     AssertMsg(pSpinlockInt && pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC,
    191               ("pSpinlockInt=%p u32Magic=%08x\n", pSpinlockInt, pSpinlockInt ? (int)pSpinlockInt->u32Magic : 0));
    192     NOREF(pTmp);
    193 
    194     if (!ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 0, 1))
    195         AssertMsgFailed(("Spinlock %p was not locked!\n", pSpinlockInt));
    196 }
    197 RT_EXPORT_SYMBOL(RTSpinlockRelease);
    198 
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