VirtualBox

Changeset 30111 in vbox for trunk/include


Ignore:
Timestamp:
Jun 9, 2010 12:14:59 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
62505
Message:

iprt/asm.h,*: Revised the ASMAtomic*Ptr functions and macros. The new saves lots of unsafe (void * volatile *) casts as well as adding some type safety when using GCC (typeof rulez).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/asm.h

    r29286 r30111  
    470470#endif
    471471}
     472
     473
     474/**
     475 * Convenience macro for avoiding the annoying casting with ASMAtomicXchgPtr.
     476 *
     477 * @returns Current *pv value
     478 * @param   ppv     Pointer to the pointer variable to update.
     479 * @param   pv      The pointer value to assign to *ppv.
     480 * @param   Type    The type of *ppv, sans volatile.
     481 */
     482#ifdef __GNUC__
     483# define ASMAtomicXchgPtrT(ppv, pv, Type) \
     484    __extension__ \
     485    ({\
     486        __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \
     487        Type                          const pvTypeChecked  = (pv); \
     488        Type pvTypeCheckedRet = (__typeof__(*(ppv))) ASMAtomicXchgPtr((void * volatile *)ppvTypeChecked, (void *)pvTypeChecked); \
     489        pvTypeCheckedRet; \
     490     })
     491#else
     492# define ASMAtomicXchgPtrT(ppv, pv, Type) \
     493    (Type)ASMAtomicXchgPtr((void * volatile *)(ppv), (void *)(pv))
     494#endif
    472495
    473496
     
    849872 * @param   pvOld       The old value to *ppv compare with.
    850873 */
    851 DECLINLINE(bool) ASMAtomicCmpXchgPtr(void * volatile *ppv, const void *pvNew, const void *pvOld)
     874DECLINLINE(bool) ASMAtomicCmpXchgPtrVoid(void * volatile *ppv, const void *pvNew, const void *pvOld)
    852875{
    853876#if ARCH_BITS == 32
     
    859882#endif
    860883}
     884
     885
     886/**
     887 * Atomically Compare and Exchange a pointer value, ordered.
     888 *
     889 * @returns true if xchg was done.
     890 * @returns false if xchg wasn't done.
     891 *
     892 * @param   ppv         Pointer to the value to update.
     893 * @param   pvNew       The new value to assigned to *ppv.
     894 * @param   pvOld       The old value to *ppv compare with.
     895 *
     896 * @remarks This is relatively type safe on GCC platforms.
     897 */
     898#ifdef __GNUC__
     899# define ASMAtomicCmpXchgPtr(ppv, pvNew, pvOld) \
     900    __extension__ \
     901    ({\
     902        __typeof__(*(ppv)) volatile * const ppvTypeChecked   = (ppv); \
     903        __typeof__(*(ppv))            const pvNewTypeChecked = (pvNew); \
     904        __typeof__(*(ppv))            const pvOldTypeChecked = (pvOld); \
     905        bool fMacroRet = ASMAtomicCmpXchgPtrVoid((void * volatile *)ppvTypeChecked, \
     906                                                 (void *)pvNewTypeChecked, (void *)pvOldTypeChecked); \
     907        fMacroRet; \
     908     })
     909#else
     910# define ASMAtomicCmpXchgPtr(ppv, pvNew, pvOld) \
     911    ASMAtomicCmpXchgPtrVoid((void * volatile *)(ppv), (void *)(pvNew), (void *)(pvOld))
     912#endif
    861913
    862914
     
    11761228 * @param   ppvOld      Pointer store the old value at.
    11771229 */
    1178 DECLINLINE(bool) ASMAtomicCmpXchgExPtr(void * volatile *ppv, const void *pvNew, const void *pvOld, void **ppvOld)
     1230DECLINLINE(bool) ASMAtomicCmpXchgExPtrVoid(void * volatile *ppv, const void *pvNew, const void *pvOld, void **ppvOld)
    11791231{
    11801232#if ARCH_BITS == 32
     
    11861238#endif
    11871239}
     1240
     1241
     1242/**
     1243 * Atomically Compare and Exchange a pointer value, additionally
     1244 * passing back old value, ordered.
     1245 *
     1246 * @returns true if xchg was done.
     1247 * @returns false if xchg wasn't done.
     1248 *
     1249 * @param   ppv         Pointer to the value to update.
     1250 * @param   pvNew       The new value to assigned to *ppv.
     1251 * @param   pvOld       The old value to *ppv compare with.
     1252 * @param   ppvOld      Pointer store the old value at.
     1253 *
     1254 * @remarks This is relatively type safe on GCC platforms.
     1255 */
     1256#ifdef __GNUC__
     1257# define ASMAtomicCmpXchgExPtr(ppv, pvNew, pvOld, ppvOld) \
     1258    __extension__ \
     1259    ({\
     1260        __typeof__(*(ppv)) volatile * const ppvTypeChecked    = (ppv); \
     1261        __typeof__(*(ppv))            const pvNewTypeChecked  = (pvNew); \
     1262        __typeof__(*(ppv))            const pvOldTypeChecked  = (pvOld); \
     1263        __typeof__(*(ppv)) *          const ppvOldTypeChecked = (ppvOld); \
     1264        bool fMacroRet = ASMAtomicCmpXchgExPtrVoid((void * volatile *)ppvTypeChecked, \
     1265                                                   (void *)pvNewTypeChecked, (void *)pvOldTypeChecked, \
     1266                                                   (void **)ppvOld); \
     1267        fMacroRet; \
     1268     })
     1269#else
     1270# define ASMAtomicCmpXchgExPtr(ppv, pvNew, pvOld, ppvOld) \
     1271    ASMAtomicCmpXchgExPtrVoid((void * volatile *)(ppv), (void *)(pvNew), (void *)pvOld, (void **)ppvOld)
     1272#endif
    11881273
    11891274
     
    19031988 * @returns Current *pv value
    19041989 * @param   ppv     Pointer to the pointer variable to read.
     1990 *
     1991 * @remarks Please use ASMAtomicReadPtrT, it provides better type safety and
     1992 *          requires less typing (no casts).
    19051993 */
    19061994DECLINLINE(void *) ASMAtomicReadPtr(void * volatile *ppv)
     
    19152003}
    19162004
    1917 
    1918 /**
    1919  * Atomically reads a pointer value, unordered.
     2005/**
     2006 * Convenience macro for avoiding the annoying casting with ASMAtomicReadPtr.
    19202007 *
    19212008 * @returns Current *pv value
    19222009 * @param   ppv     Pointer to the pointer variable to read.
     2010 * @param   Type    The type of *ppv, sans volatile.
     2011 */
     2012#ifdef __GNUC__
     2013# define ASMAtomicReadPtrT(ppv, Type) \
     2014    __extension__ \
     2015    ({\
     2016        __typeof__(*(ppv)) volatile *ppvTypeChecked = (ppv); \
     2017        Type pvTypeChecked = (__typeof__(*(ppv))) ASMAtomicReadPtr((void * volatile *)ppvTypeChecked); \
     2018        pvTypeChecked; \
     2019     })
     2020#else
     2021# define ASMAtomicReadPtrT(ppv, Type) \
     2022    (Type)ASMAtomicReadPtr((void * volatile *)(ppv))
     2023#endif
     2024
     2025
     2026/**
     2027 * Atomically reads a pointer value, unordered.
     2028 *
     2029 * @returns Current *pv value
     2030 * @param   ppv     Pointer to the pointer variable to read.
     2031 *
     2032 * @remarks Please use ASMAtomicUoReadPtrT, it provides better type safety and
     2033 *          requires less typing (no casts).
    19232034 */
    19242035DECLINLINE(void *) ASMAtomicUoReadPtr(void * volatile *ppv)
     
    19322043#endif
    19332044}
     2045
     2046
     2047/**
     2048 * Convenience macro for avoiding the annoying casting with ASMAtomicUoReadPtr.
     2049 *
     2050 * @returns Current *pv value
     2051 * @param   ppv     Pointer to the pointer variable to read.
     2052 * @param   Type    The type of *ppv, sans volatile.
     2053 */
     2054#ifdef __GNUC__
     2055# define ASMAtomicUoReadPtrT(ppv, Type) \
     2056    __extension__ \
     2057    ({\
     2058        __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \
     2059        Type pvTypeChecked = (__typeof__(*(ppv))) ASMAtomicUoReadPtr((void * volatile *)ppvTypeChecked); \
     2060        pvTypeChecked; \
     2061     })
     2062#else
     2063# define ASMAtomicUoReadPtrT(ppv, Type) \
     2064    (Type)ASMAtomicUoReadPtr((void * volatile *)(ppv))
     2065#endif
    19342066
    19352067
     
    22862418 * @returns Current *pv value
    22872419 * @param   ppv     Pointer to the pointer variable.
    2288  * @param   pv      The pointer value to assigne to *ppv.
    2289  */
    2290 DECLINLINE(void) ASMAtomicWritePtr(void * volatile *ppv, const void *pv)
     2420 * @param   pv      The pointer value to assign to *ppv.
     2421 */
     2422DECLINLINE(void) ASMAtomicWritePtrVoid(void * volatile *ppv, const void *pv)
    22912423{
    22922424#if ARCH_BITS == 32
     
    23012433
    23022434/**
    2303  * Atomically writes a pointer value, unordered.
     2435 * Convenience macro for avoiding the annoying casting with ASMAtomicWritePtr.
    23042436 *
    23052437 * @returns Current *pv value
    23062438 * @param   ppv     Pointer to the pointer variable.
    2307  * @param   pv      The pointer value to assigne to *ppv.
    2308  */
    2309 DECLINLINE(void) ASMAtomicUoWritePtr(void * volatile *ppv, const void *pv)
    2310 {
    2311 #if ARCH_BITS == 32
    2312     ASMAtomicUoWriteU32((volatile uint32_t *)(void *)ppv, (uint32_t)pv);
    2313 #elif ARCH_BITS == 64
    2314     ASMAtomicUoWriteU64((volatile uint64_t *)(void *)ppv, (uint64_t)pv);
    2315 #else
    2316 # error "ARCH_BITS is bogus"
    2317 #endif
    2318 }
     2439 * @param   pv      The pointer value to assign to *ppv. If NULL, you may have
     2440 *                  to cast it to the right pointer type for GCC to be happy.
     2441 *
     2442 * @remarks This is relatively type safe on GCC platforms when @a pv isn't
     2443 *          NULL.
     2444 */
     2445#ifdef __GNUC__
     2446# define ASMAtomicWritePtr(ppv, pv) \
     2447    do \
     2448    { \
     2449        __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \
     2450        __typeof__(*(ppv))            const pvTypeChecked  = (pv); \
     2451        \
     2452        AssertCompile(sizeof(*ppv) == sizeof(void *)); \
     2453        AssertCompile(sizeof(pv) == sizeof(void *)); \
     2454        Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
     2455        \
     2456        ASMAtomicWritePtrVoid((void * volatile *)(ppvTypeChecked), (void *)(pvTypeChecked)); \
     2457    } while (0)
     2458#else
     2459# define ASMAtomicWritePtr(ppv, pv) \
     2460    do \
     2461    { \
     2462        AssertCompile(sizeof(*ppv) == sizeof(void *)); \
     2463        AssertCompile(sizeof(pv) == sizeof(void *)); \
     2464        Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
     2465        \
     2466        ASMAtomicWritePtrVoid((void * volatile *)(ppv), (void *)(pv)); \
     2467    } while (0)
     2468#endif
     2469
     2470
     2471/**
     2472 * Convenience macro for avoiding the annoying casting involved when using
     2473 * ASMAtomicWritePtr.
     2474 *
     2475 * @returns Current *pv value
     2476 * @param   ppv     Pointer to the pointer variable.
     2477 * @param   pv      The pointer value to assign to *ppv.
     2478 *
     2479 * @remarks This is relatively type safe on GCC platforms when @a pv isn't
     2480 *          NULL.
     2481 */
     2482#ifdef __GNUC__
     2483# define ASMAtomicUoWritePtr(ppv, pv) \
     2484    do \
     2485    { \
     2486        __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \
     2487        __typeof__(*(ppv))            const pvTypeChecked  = (pv); \
     2488        \
     2489        AssertCompile(sizeof(*ppv) == sizeof(void *)); \
     2490        AssertCompile(sizeof(pv) == sizeof(void *)); \
     2491        Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
     2492        \
     2493        *(ppvTypeChecked) = pvTypeChecked; \
     2494    } while (0)
     2495#else
     2496# define ASMAtomicUoWritePtr(ppv, pv) \
     2497    do \
     2498    { \
     2499        AssertCompile(sizeof(*ppv) == sizeof(void *)); \
     2500        AssertCompile(sizeof(pv) == sizeof(void *)); \
     2501        Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
     2502        *(ppv) = pv; \
     2503    } while (0)
     2504#endif
    23192505
    23202506
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