VirtualBox

Changeset 6782 in vbox for trunk/include


Ignore:
Timestamp:
Feb 4, 2008 12:42:58 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
27875
Message:

Added a bunch of ASMAtomic*Read/Write functions and ASM[Memory|Read|Write]Fence (not fully realized).

File:
1 edited

Legend:

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

    r6653 r6782  
    2929#include <iprt/cdefs.h>
    3030#include <iprt/types.h>
     31#include <iprt/assert.h>
    3132/** @todo #include <iprt/param.h> for PAGE_SIZE. */
    3233/** @def RT_INLINE_ASM_USES_INTRIN
     
    9899/** @defgroup grp_asm       ASM - Assembly Routines
    99100 * @ingroup grp_rt
     101 *
     102 * @remarks The difference between ordered and unordered atomic operations are that
     103 *          the former will complete outstanding reads and writes before continuing
     104 *          while the latter doesn't make any promisses about the order. Ordered
     105 *          operations doesn't, it seems, make any 100% promise wrt to whether
     106 *          the operation will complete before any subsequent memory access.
     107 *          (please, correct if wrong.)
     108 *
     109 *          ASMAtomicSomething operations are all ordered, while ASMAtomicUoSomething
     110 *          are unordered (note the Uo).
     111 *
    100112 * @{
    101113 */
     
    16141626
    16151627/**
    1616  * Writes a 8-bit unsigned integer to an I/O port.
     1628 * Writes a 8-bit unsigned integer to an I/O port, ordered.
    16171629 *
    16181630 * @param   Port    I/O port to read from.
     
    16451657
    16461658/**
    1647  * Gets a 8-bit unsigned integer from an I/O port.
     1659 * Gets a 8-bit unsigned integer from an I/O port, ordered.
    16481660 *
    16491661 * @returns 8-bit integer.
     
    16781690
    16791691/**
    1680  * Writes a 16-bit unsigned integer to an I/O port.
     1692 * Writes a 16-bit unsigned integer to an I/O port, ordered.
    16811693 *
    16821694 * @param   Port    I/O port to read from.
     
    17091721
    17101722/**
    1711  * Gets a 16-bit unsigned integer from an I/O port.
     1723 * Gets a 16-bit unsigned integer from an I/O port, ordered.
    17121724 *
    17131725 * @returns 16-bit integer.
     
    17421754
    17431755/**
    1744  * Writes a 32-bit unsigned integer to an I/O port.
     1756 * Writes a 32-bit unsigned integer to an I/O port, ordered.
    17451757 *
    17461758 * @param   Port    I/O port to read from.
     
    17731785
    17741786/**
    1775  * Gets a 32-bit unsigned integer from an I/O port.
     1787 * Gets a 32-bit unsigned integer from an I/O port, ordered.
    17761788 *
    17771789 * @returns 32-bit integer.
     
    18041816#endif
    18051817
    1806 
    1807 /**
    1808  * Atomically Exchange an unsigned 8-bit value.
     1818/** @todo string i/o */
     1819
     1820
     1821/**
     1822 * Atomically Exchange an unsigned 8-bit value, ordered.
    18091823 *
    18101824 * @returns Current *pu8 value
     
    18441858
    18451859/**
    1846  * Atomically Exchange a signed 8-bit value.
     1860 * Atomically Exchange a signed 8-bit value, ordered.
    18471861 *
    18481862 * @returns Current *pu8 value
     
    18571871
    18581872/**
    1859  * Atomically Exchange a bool value.
     1873 * Atomically Exchange a bool value, ordered.
    18601874 *
    18611875 * @returns Current *pf value
     
    18741888
    18751889/**
    1876  * Atomically Exchange an unsigned 16-bit value.
     1890 * Atomically Exchange an unsigned 16-bit value, ordered.
    18771891 *
    18781892 * @returns Current *pu16 value
     
    19121926
    19131927/**
    1914  * Atomically Exchange a signed 16-bit value.
     1928 * Atomically Exchange a signed 16-bit value, ordered.
    19151929 *
    19161930 * @returns Current *pu16 value
     
    19251939
    19261940/**
    1927  * Atomically Exchange an unsigned 32-bit value.
     1941 * Atomically Exchange an unsigned 32-bit value, ordered.
    19281942 *
    19291943 * @returns Current *pu32 value
     
    19671981
    19681982/**
    1969  * Atomically Exchange a signed 32-bit value.
     1983 * Atomically Exchange a signed 32-bit value, ordered.
    19701984 *
    19711985 * @returns Current *pu32 value
     
    19801994
    19811995/**
    1982  * Atomically Exchange an unsigned 64-bit value.
     1996 * Atomically Exchange an unsigned 64-bit value, ordered.
    19831997 *
    19841998 * @returns Current *pu64 value
     
    20582072
    20592073/**
    2060  * Atomically Exchange an signed 64-bit value.
     2074 * Atomically Exchange an signed 64-bit value, ordered.
    20612075 *
    20622076 * @returns Current *pi64 value
     
    20722086#ifdef RT_ARCH_AMD64
    20732087/**
    2074  * Atomically Exchange an unsigned 128-bit value.
     2088 * Atomically Exchange an unsigned 128-bit value, ordered.
    20752089 *
    20762090 * @returns Current *pu128.
     
    21322146
    21332147/**
    2134  * Atomically Reads a unsigned 64-bit value.
    2135  *
    2136  * @returns Current *pu64 value
    2137  * @param   pu64    Pointer to the 64-bit variable to read.
    2138  *                  The memory pointed to must be writable.
    2139  * @remark  This will fault if the memory is read-only!
    2140  */
    2141 #if RT_INLINE_ASM_EXTERNAL
    2142 DECLASM(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64);
    2143 #else
    2144 DECLINLINE(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64)
    2145 {
    2146     uint64_t u64;
    2147 # ifdef RT_ARCH_AMD64
    2148 #  if RT_INLINE_ASM_GNU_STYLE
    2149     __asm__ __volatile__("movq %1, %0\n\t"
    2150                          : "=r" (u64)
    2151                          : "m" (*pu64));
    2152 #  else
    2153     __asm
    2154     {
    2155         mov     rdx, [pu64]
    2156         mov     rax, [rdx]
    2157         mov     [u64], rax
    2158     }
    2159 #  endif
    2160 # else /* !RT_ARCH_AMD64 */
    2161 #  if RT_INLINE_ASM_GNU_STYLE
    2162 #   if defined(PIC) || defined(RT_OS_DARWIN) /* darwin: 4.0.1 compiler option / bug? */
    2163     uint32_t u32EBX = 0;
    2164     __asm__ __volatile__("xchgl %%ebx, %3\n\t"
    2165                          "lock; cmpxchg8b (%5)\n\t"
    2166                          "xchgl %%ebx, %3\n\t"
    2167                          : "=A" (u64),
    2168                            "=m" (*pu64)
    2169                          : "0" (0),
    2170                            "m" (u32EBX),
    2171                            "c" (0),
    2172                            "S" (pu64));
    2173 #   else /* !PIC */
    2174     __asm__ __volatile__("lock; cmpxchg8b %1\n\t"
    2175                          : "=A" (u64),
    2176                            "=m" (*pu64)
    2177                          : "0" (0),
    2178                            "b" (0),
    2179                            "c" (0));
    2180 #   endif
    2181 #  else
    2182     __asm
    2183     {
    2184         xor     eax, eax
    2185         xor     edx, edx
    2186         mov     edi, pu64
    2187         xor     ecx, ecx
    2188         xor     ebx, ebx
    2189         lock cmpxchg8b [edi]
    2190         mov     dword ptr [u64], eax
    2191         mov     dword ptr [u64 + 4], edx
    2192     }
    2193 #  endif
    2194 # endif /* !RT_ARCH_AMD64 */
    2195     return u64;
    2196 }
    2197 #endif
    2198 
    2199 
    2200 /**
    2201  * Atomically Reads a signed 64-bit value.
    2202  *
    2203  * @returns Current *pi64 value
    2204  * @param   pi64    Pointer to the 64-bit variable to read.
    2205  *                  The memory pointed to must be writable.
    2206  * @remark  This will fault if the memory is read-only!
    2207  */
    2208 DECLINLINE(int64_t) ASMAtomicReadS64(volatile int64_t *pi64)
    2209 {
    2210     return (int64_t)ASMAtomicReadU64((volatile uint64_t *)pi64);
    2211 }
    2212 
    2213 
    2214 /**
    22152148 * Atomically Exchange a value which size might differ
    2216  * between platforms or compilers.
     2149 * between platforms or compilers, ordered.
    22172150 *
    22182151 * @param   pu      Pointer to the variable to update.
     
    22322165
    22332166/**
    2234  * Atomically Exchange a pointer value.
     2167 * Atomically Exchange a pointer value, ordered.
    22352168 *
    22362169 * @returns Current *ppv value
     
    22512184
    22522185/**
    2253  * Atomically Compare and Exchange an unsigned 32-bit value.
     2186 * Atomically Compare and Exchange an unsigned 32-bit value, ordered.
    22542187 *
    22552188 * @returns true if xchg was done.
     
    23052238
    23062239/**
    2307  * Atomically Compare and Exchange a signed 32-bit value.
     2240 * Atomically Compare and Exchange a signed 32-bit value, ordered.
    23082241 *
    23092242 * @returns true if xchg was done.
     
    23212254
    23222255/**
    2323  * Atomically Compare and exchange an unsigned 64-bit value.
     2256 * Atomically Compare and exchange an unsigned 64-bit value, ordered.
    23242257 *
    23252258 * @returns true if xchg was done.
     
    24132346
    24142347/**
    2415  * Atomically Compare and exchange a signed 64-bit value.
     2348 * Atomically Compare and exchange a signed 64-bit value, ordered.
    24162349 *
    24172350 * @returns true if xchg was done.
     
    24302363/** @def ASMAtomicCmpXchgSize
    24312364 * Atomically Compare and Exchange a value which size might differ
    2432  * between platforms or compilers.
     2365 * between platforms or compilers, ordered.
    24332366 *
    24342367 * @param   pu          Pointer to the value to update.
     
    24522385
    24532386/**
    2454  * Atomically Compare and Exchange a pointer value.
     2387 * Atomically Compare and Exchange a pointer value, ordered.
    24552388 *
    24562389 * @returns true if xchg was done.
     
    24752408/**
    24762409 * Atomically Compare and Exchange an unsigned 32-bit value, additionally
    2477  * passes back old value.
     2410 * passes back old value, ordered.
    24782411 *
    24792412 * @returns true if xchg was done.
     
    25362469/**
    25372470 * Atomically Compare and Exchange a signed 32-bit value, additionally
    2538  * passes back old value.
     2471 * passes back old value, ordered.
    25392472 *
    25402473 * @returns true if xchg was done.
     
    25542487/**
    25552488 * Atomically Compare and exchange an unsigned 64-bit value, additionally
    2556  * passing back old value.
     2489 * passing back old value, ordered.
    25572490 *
    25582491 * @returns true if xchg was done.
     
    26532586/**
    26542587 * Atomically Compare and exchange a signed 64-bit value, additionally
    2655  * passing back old value.
     2588 * passing back old value, ordered.
    26562589 *
    26572590 * @returns true if xchg was done.
     
    26962629/**
    26972630 * Atomically Compare and Exchange a pointer value, additionally
    2698  * passing back old value.
     2631 * passing back old value, ordered.
    26992632 *
    27002633 * @returns true if xchg was done.
     
    27192652
    27202653/**
    2721  * Atomically increment a 32-bit value.
     2654 * Atomically increment a 32-bit value, ordered.
    27222655 *
    27232656 * @returns The new value.
     
    27612694
    27622695/**
    2763  * Atomically increment a signed 32-bit value.
     2696 * Atomically increment a signed 32-bit value, ordered.
    27642697 *
    27652698 * @returns The new value.
     
    27732706
    27742707/**
    2775  * Atomically decrement an unsigned 32-bit value.
     2708 * Atomically decrement an unsigned 32-bit value, ordered.
    27762709 *
    27772710 * @returns The new value.
     
    28152748
    28162749/**
    2817  * Atomically decrement a signed 32-bit value.
     2750 * Atomically decrement a signed 32-bit value, ordered.
    28182751 *
    28192752 * @returns The new value.
     
    28272760
    28282761/**
    2829  * Atomically Or an unsigned 32-bit value.
     2762 * Atomically Or an unsigned 32-bit value, ordered.
    28302763 *
    28312764 * @param   pu32   Pointer to the pointer variable to OR u32 with.
     
    28622795
    28632796/**
    2864  * Atomically Or a signed 32-bit value.
     2797 * Atomically Or a signed 32-bit value, ordered.
    28652798 *
    28662799 * @param   pi32   Pointer to the pointer variable to OR u32 with.
     
    28742807
    28752808/**
    2876  * Atomically And an unsigned 32-bit value.
     2809 * Atomically And an unsigned 32-bit value, ordered.
    28772810 *
    28782811 * @param   pu32   Pointer to the pointer variable to AND u32 with.
     
    29092842
    29102843/**
    2911  * Atomically And a signed 32-bit value.
     2844 * Atomically And a signed 32-bit value, ordered.
    29122845 *
    29132846 * @param   pi32   Pointer to the pointer variable to AND i32 with.
     
    29182851    ASMAtomicAndU32((uint32_t volatile *)pi32, (uint32_t)i32);
    29192852}
     2853
     2854
     2855/**
     2856 * Memory fence, waits for any pending writes and reads to complete.
     2857 */
     2858DECLINLINE(void) ASMMemoryFence(void)
     2859{
     2860    /** @todo use mfence? check if all cpus we care for support it. */
     2861    uint32_t volatile u32;
     2862    ASMAtomicXchgU32(&u32, 0);
     2863}
     2864
     2865
     2866/**
     2867 * Write fence, waits for any pending writes to complete.
     2868 */
     2869DECLINLINE(void) ASMWriteFence(void)
     2870{
     2871    /** @todo use sfence? check if all cpus we care for support it. */
     2872    ASMMemoryFence();
     2873}
     2874
     2875
     2876/**
     2877 * Read fence, waits for any pending reads to complete.
     2878 */
     2879DECLINLINE(void) ASMReadFence(void)
     2880{
     2881    /** @todo use lfence? check if all cpus we care for support it. */
     2882    ASMMemoryFence();
     2883}
     2884
     2885
     2886/**
     2887 * Atomically reads an unsigned 8-bit value, ordered.
     2888 *
     2889 * @returns Current *pu8 value
     2890 * @param   pu8    Pointer to the 8-bit variable to read.
     2891 */
     2892DECLINLINE(uint8_t) ASMAtomicReadU8(volatile uint8_t *pu8)
     2893{
     2894    ASMMemoryFence();
     2895    return *pu8;    /* byte reads are atomic on x86 */
     2896}
     2897
     2898
     2899/**
     2900 * Atomically reads an unsigned 8-bit value, unordered.
     2901 *
     2902 * @returns Current *pu8 value
     2903 * @param   pu8    Pointer to the 8-bit variable to read.
     2904 */
     2905DECLINLINE(uint8_t) ASMAtomicUoReadU8(volatile uint8_t *pu8)
     2906{
     2907    return *pu8;    /* byte reads are atomic on x86 */
     2908}
     2909
     2910
     2911/**
     2912 * Atomically reads a signed 8-bit value, ordered.
     2913 *
     2914 * @returns Current *pi8 value
     2915 * @param   pi8    Pointer to the 8-bit variable to read.
     2916 */
     2917DECLINLINE(int8_t) ASMAtomicReadS8(volatile int8_t *pi8)
     2918{
     2919    ASMMemoryFence();
     2920    return *pi8;    /* byte reads are atomic on x86 */
     2921}
     2922
     2923
     2924/**
     2925 * Atomically reads a signed 8-bit value, unordered.
     2926 *
     2927 * @returns Current *pi8 value
     2928 * @param   pi8    Pointer to the 8-bit variable to read.
     2929 */
     2930DECLINLINE(int8_t) ASMAtomicUoReadS8(volatile int8_t *pi8)
     2931{
     2932    return *pi8;    /* byte reads are atomic on x86 */
     2933}
     2934
     2935
     2936/**
     2937 * Atomically reads an unsigned 16-bit value, ordered.
     2938 *
     2939 * @returns Current *pu16 value
     2940 * @param   pu16    Pointer to the 16-bit variable to read.
     2941 */
     2942DECLINLINE(uint16_t) ASMAtomicReadU16(volatile uint16_t *pu16)
     2943{
     2944    ASMMemoryFence();
     2945    Assert(!((uintptr_t)pu16 & 1));
     2946    return *pu16;
     2947}
     2948
     2949
     2950/**
     2951 * Atomically reads an unsigned 16-bit value, unordered.
     2952 *
     2953 * @returns Current *pu16 value
     2954 * @param   pu16    Pointer to the 16-bit variable to read.
     2955 */
     2956DECLINLINE(uint16_t) ASMAtomicUoReadU16(volatile uint16_t *pu16)
     2957{
     2958    Assert(!((uintptr_t)pu16 & 1));
     2959    return *pu16;
     2960}
     2961
     2962
     2963/**
     2964 * Atomically reads a signed 16-bit value, ordered.
     2965 *
     2966 * @returns Current *pi16 value
     2967 * @param   pi16    Pointer to the 16-bit variable to read.
     2968 */
     2969DECLINLINE(int16_t) ASMAtomicReadS16(volatile int16_t *pi16)
     2970{
     2971    ASMMemoryFence();
     2972    Assert(!((uintptr_t)pi16 & 1));
     2973    return *pi16;
     2974}
     2975
     2976
     2977/**
     2978 * Atomically reads a signed 16-bit value, unordered.
     2979 *
     2980 * @returns Current *pi16 value
     2981 * @param   pi16    Pointer to the 16-bit variable to read.
     2982 */
     2983DECLINLINE(int16_t) ASMAtomicUoReadS16(volatile int16_t *pi16)
     2984{
     2985    Assert(!((uintptr_t)pi16 & 1));
     2986    return *pi16;
     2987}
     2988
     2989
     2990/**
     2991 * Atomically reads an unsigned 32-bit value, ordered.
     2992 *
     2993 * @returns Current *pu32 value
     2994 * @param   pu32    Pointer to the 32-bit variable to read.
     2995 */
     2996DECLINLINE(uint32_t) ASMAtomicReadU32(volatile uint32_t *pu32)
     2997{
     2998    ASMMemoryFence();
     2999    Assert(!((uintptr_t)pu32 & 3));
     3000    return *pu32;
     3001}
     3002
     3003
     3004/**
     3005 * Atomically reads an unsigned 32-bit value, unordered.
     3006 *
     3007 * @returns Current *pu32 value
     3008 * @param   pu32    Pointer to the 32-bit variable to read.
     3009 */
     3010DECLINLINE(uint32_t) ASMAtomicUoReadU32(volatile uint32_t *pu32)
     3011{
     3012    Assert(!((uintptr_t)pu32 & 3));
     3013    return *pu32;
     3014}
     3015
     3016
     3017/**
     3018 * Atomically reads a signed 32-bit value, ordered.
     3019 *
     3020 * @returns Current *pi32 value
     3021 * @param   pi32    Pointer to the 32-bit variable to read.
     3022 */
     3023DECLINLINE(int32_t) ASMAtomicReadS32(volatile int32_t *pi32)
     3024{
     3025    ASMMemoryFence();
     3026    Assert(!((uintptr_t)pi32 & 3));
     3027    return *pi32;
     3028}
     3029
     3030
     3031/**
     3032 * Atomically reads a signed 32-bit value, unordered.
     3033 *
     3034 * @returns Current *pi32 value
     3035 * @param   pi32    Pointer to the 32-bit variable to read.
     3036 */
     3037DECLINLINE(int32_t) ASMAtomicUoReadS32(volatile int32_t *pi32)
     3038{
     3039    Assert(!((uintptr_t)pi32 & 3));
     3040    return *pi32;
     3041}
     3042
     3043
     3044/**
     3045 * Atomically reads an unsigned 64-bit value, ordered.
     3046 *
     3047 * @returns Current *pu64 value
     3048 * @param   pu64    Pointer to the 64-bit variable to read.
     3049 *                  The memory pointed to must be writable.
     3050 * @remark  This will fault if the memory is read-only!
     3051 */
     3052#if RT_INLINE_ASM_EXTERNAL
     3053DECLASM(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64);
     3054#else
     3055DECLINLINE(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64)
     3056{
     3057    uint64_t u64;
     3058# ifdef RT_ARCH_AMD64
     3059#  if RT_INLINE_ASM_GNU_STYLE
     3060    Assert(!((uintptr_t)pu64 & 7));
     3061    __asm__ __volatile__(  "mfence\n\t"
     3062                           "movq %1, %0\n\t"
     3063                         : "=r" (u64)
     3064                         : "m" (*pu64));
     3065#  else
     3066    __asm
     3067    {
     3068        mfence
     3069        mov     rdx, [pu64]
     3070        mov     rax, [rdx]
     3071        mov     [u64], rax
     3072    }
     3073#  endif
     3074# else /* !RT_ARCH_AMD64 */
     3075#  if RT_INLINE_ASM_GNU_STYLE
     3076#   if defined(PIC) || defined(RT_OS_DARWIN) /* darwin: 4.0.1 compiler option / bug? */
     3077    uint32_t u32EBX = 0;
     3078    Assert(!((uintptr_t)pu64 & 7));
     3079    __asm__ __volatile__("xchgl %%ebx, %3\n\t"
     3080                         "lock; cmpxchg8b (%5)\n\t"
     3081                         "xchgl %%ebx, %3\n\t"
     3082                         : "=A" (u64),
     3083                           "=m" (*pu64)
     3084                         : "0" (0),
     3085                           "m" (u32EBX),
     3086                           "c" (0),
     3087                           "S" (pu64));
     3088#   else /* !PIC */
     3089    __asm__ __volatile__("lock; cmpxchg8b %1\n\t"
     3090                         : "=A" (u64),
     3091                           "=m" (*pu64)
     3092                         : "0" (0),
     3093                           "b" (0),
     3094                           "c" (0));
     3095#   endif
     3096#  else
     3097    Assert(!((uintptr_t)pu64 & 7));
     3098    __asm
     3099    {
     3100        xor     eax, eax
     3101        xor     edx, edx
     3102        mov     edi, pu64
     3103        xor     ecx, ecx
     3104        xor     ebx, ebx
     3105        lock cmpxchg8b [edi]
     3106        mov     dword ptr [u64], eax
     3107        mov     dword ptr [u64 + 4], edx
     3108    }
     3109#  endif
     3110# endif /* !RT_ARCH_AMD64 */
     3111    return u64;
     3112}
     3113#endif
     3114
     3115
     3116/**
     3117 * Atomically reads an unsigned 64-bit value, unordered.
     3118 *
     3119 * @returns Current *pu64 value
     3120 * @param   pu64    Pointer to the 64-bit variable to read.
     3121 *                  The memory pointed to must be writable.
     3122 * @remark  This will fault if the memory is read-only!
     3123 */
     3124#if RT_INLINE_ASM_EXTERNAL
     3125DECLASM(uint64_t) ASMAtomicUoReadU64(volatile uint64_t *pu64);
     3126#else
     3127DECLINLINE(uint64_t) ASMAtomicUoReadU64(volatile uint64_t *pu64)
     3128{
     3129    uint64_t u64;
     3130# ifdef RT_ARCH_AMD64
     3131#  if RT_INLINE_ASM_GNU_STYLE
     3132    Assert(!((uintptr_t)pu64 & 7));
     3133    __asm__ __volatile__("movq %1, %0\n\t"
     3134                         : "=r" (u64)
     3135                         : "m" (*pu64));
     3136#  else
     3137    __asm
     3138    {
     3139        mov     rdx, [pu64]
     3140        mov     rax, [rdx]
     3141        mov     [u64], rax
     3142    }
     3143#  endif
     3144# else /* !RT_ARCH_AMD64 */
     3145#  if RT_INLINE_ASM_GNU_STYLE
     3146#   if defined(PIC) || defined(RT_OS_DARWIN) /* darwin: 4.0.1 compiler option / bug? */
     3147    uint32_t u32EBX = 0;
     3148    Assert(!((uintptr_t)pu64 & 7));
     3149    __asm__ __volatile__("xchgl %%ebx, %3\n\t"
     3150                         "lock; cmpxchg8b (%5)\n\t"
     3151                         "xchgl %%ebx, %3\n\t"
     3152                         : "=A" (u64),
     3153                           "=m" (*pu64)
     3154                         : "0" (0),
     3155                           "m" (u32EBX),
     3156                           "c" (0),
     3157                           "S" (pu64));
     3158#   else /* !PIC */
     3159    __asm__ __volatile__("cmpxchg8b %1\n\t"
     3160                         : "=A" (u64),
     3161                           "=m" (*pu64)
     3162                         : "0" (0),
     3163                           "b" (0),
     3164                           "c" (0));
     3165#   endif
     3166#  else
     3167    Assert(!((uintptr_t)pu64 & 7));
     3168    __asm
     3169    {
     3170        xor     eax, eax
     3171        xor     edx, edx
     3172        mov     edi, pu64
     3173        xor     ecx, ecx
     3174        xor     ebx, ebx
     3175        lock cmpxchg8b [edi]
     3176        mov     dword ptr [u64], eax
     3177        mov     dword ptr [u64 + 4], edx
     3178    }
     3179#  endif
     3180# endif /* !RT_ARCH_AMD64 */
     3181    return u64;
     3182}
     3183#endif
     3184
     3185
     3186/**
     3187 * Atomically reads a signed 64-bit value, ordered.
     3188 *
     3189 * @returns Current *pi64 value
     3190 * @param   pi64    Pointer to the 64-bit variable to read.
     3191 *                  The memory pointed to must be writable.
     3192 * @remark  This will fault if the memory is read-only!
     3193 */
     3194DECLINLINE(int64_t) ASMAtomicReadS64(volatile int64_t *pi64)
     3195{
     3196    return (int64_t)ASMAtomicReadU64((volatile uint64_t *)pi64);
     3197}
     3198
     3199
     3200/**
     3201 * Atomically reads a signed 64-bit value, unordered.
     3202 *
     3203 * @returns Current *pi64 value
     3204 * @param   pi64    Pointer to the 64-bit variable to read.
     3205 *                  The memory pointed to must be writable.
     3206 * @remark  This will fault if the memory is read-only!
     3207 */
     3208DECLINLINE(int64_t) ASMAtomicUoReadS64(volatile int64_t *pi64)
     3209{
     3210    return (int64_t)ASMAtomicUoReadU64((volatile uint64_t *)pi64);
     3211}
     3212
     3213
     3214/**
     3215 * Atomically reads a pointer value, ordered.
     3216 *
     3217 * @returns Current *pv value
     3218 * @param   ppv     Pointer to the pointer variable to read.
     3219 */
     3220DECLINLINE(void *) ASMAtomicReadPtr(void * volatile *ppv)
     3221{
     3222#if ARCH_BITS == 32
     3223    return (void *)ASMAtomicReadU32((volatile uint32_t *)(void *)ppv);
     3224#elif ARCH_BITS == 64
     3225    return (void *)ASMAtomicReadU64((volatile uint64_t *)(void *)ppv);
     3226#else
     3227# error "ARCH_BITS is bogus"
     3228#endif
     3229}
     3230
     3231
     3232/**
     3233 * Atomically reads a pointer value, unordered.
     3234 *
     3235 * @returns Current *pv value
     3236 * @param   ppv     Pointer to the pointer variable to read.
     3237 */
     3238DECLINLINE(void *) ASMAtomicUoReadPtr(void * volatile *ppv)
     3239{
     3240#if ARCH_BITS == 32
     3241    return (void *)ASMAtomicUoReadU32((volatile uint32_t *)(void *)ppv);
     3242#elif ARCH_BITS == 64
     3243    return (void *)ASMAtomicUoReadU64((volatile uint64_t *)(void *)ppv);
     3244#else
     3245# error "ARCH_BITS is bogus"
     3246#endif
     3247}
     3248
     3249
     3250/**
     3251 * Atomically reads a boolean value, ordered.
     3252 *
     3253 * @returns Current *pf value
     3254 * @param   pf      Pointer to the boolean variable to read.
     3255 */
     3256DECLINLINE(bool) ASMAtomicReadBool(volatile bool *pf)
     3257{
     3258    ASMMemoryFence();
     3259    return *pf;     /* byte reads are atomic on x86 */
     3260}
     3261
     3262
     3263/**
     3264 * Atomically reads a boolean value, unordered.
     3265 *
     3266 * @returns Current *pf value
     3267 * @param   pf      Pointer to the boolean variable to read.
     3268 */
     3269DECLINLINE(bool) ASMAtomicUoReadBool(volatile bool *pf)
     3270{
     3271    return *pf;     /* byte reads are atomic on x86 */
     3272}
     3273
     3274
     3275/**
     3276 * Atomically read a value which size might differ
     3277 * between platforms or compilers, ordered.
     3278 *
     3279 * @param   pu      Pointer to the variable to update.
     3280 * @param   puRes   Where to store the result.
     3281 */
     3282#define ASMAtomicReadSize(pu, puRes) \
     3283    do { \
     3284        switch (sizeof(*(pu))) { \
     3285            case 1: *(uint8_t  *)(puRes) = ASMAtomicReadU8( (volatile uint8_t  *)(void *)(pu)); break; \
     3286            case 2: *(uint16_t *)(puRes) = ASMAtomicReadU16((volatile uint16_t *)(void *)(pu)); break; \
     3287            case 4: *(uint32_t *)(puRes) = ASMAtomicReadU32((volatile uint32_t *)(void *)(pu)); break; \
     3288            case 8: *(uint64_t *)(puRes) = ASMAtomicReadU64((volatile uint64_t *)(void *)(pu)); break; \
     3289            default: AssertMsgFailed(("ASMAtomicReadSize: size %d is not supported\n", sizeof(*(pu)))); \
     3290        } \
     3291    } while (0)
     3292
     3293
     3294/**
     3295 * Atomically read a value which size might differ
     3296 * between platforms or compilers, unordered.
     3297 *
     3298 * @param   pu      Pointer to the variable to update.
     3299 * @param   puRes   Where to store the result.
     3300 */
     3301#define ASMAtomicUoReadSize(pu, puRes) \
     3302    do { \
     3303        switch (sizeof(*(pu))) { \
     3304            case 1: *(uint8_t  *)(puRes) = ASMAtomicUoReadU8( (volatile uint8_t  *)(void *)(pu)); break; \
     3305            case 2: *(uint16_t *)(puRes) = ASMAtomicUoReadU16((volatile uint16_t *)(void *)(pu)); break; \
     3306            case 4: *(uint32_t *)(puRes) = ASMAtomicUoReadU32((volatile uint32_t *)(void *)(pu)); break; \
     3307            case 8: *(uint64_t *)(puRes) = ASMAtomicUoReadU64((volatile uint64_t *)(void *)(pu)); break; \
     3308            default: AssertMsgFailed(("ASMAtomicReadSize: size %d is not supported\n", sizeof(*(pu)))); \
     3309        } \
     3310    } while (0)
     3311
     3312
     3313/**
     3314 * Atomically writes an unsigned 8-bit value, ordered.
     3315 *
     3316 * @param   pu8     Pointer to the 8-bit variable.
     3317 * @param   u8      The 8-bit value to assign to *pu8.
     3318 */
     3319DECLINLINE(void) ASMAtomicWriteU8(volatile uint8_t *pu8, uint8_t u8)
     3320{
     3321    ASMAtomicXchgU8(pu8, u8);
     3322}
     3323
     3324
     3325/**
     3326 * Atomically writes an unsigned 8-bit value, unordered.
     3327 *
     3328 * @param   pu8     Pointer to the 8-bit variable.
     3329 * @param   u8      The 8-bit value to assign to *pu8.
     3330 */
     3331DECLINLINE(void) ASMAtomicUoWriteU8(volatile uint8_t *pu8, uint8_t u8)
     3332{
     3333    *pu8 = u8;      /* byte writes are atomic on x86 */
     3334}
     3335
     3336
     3337/**
     3338 * Atomically writes a signed 8-bit value, ordered.
     3339 *
     3340 * @param   pi8     Pointer to the 8-bit variable to read.
     3341 * @param   u8      The 8-bit value to assign to *pu8.
     3342 */
     3343DECLINLINE(void) ASMAtomicWriteS8(volatile int8_t *pi8, int8_t i8)
     3344{
     3345    ASMAtomicXchgS8(pi8, i8);
     3346}
     3347
     3348
     3349/**
     3350 * Atomically writes a signed 8-bit value, unordered.
     3351 *
     3352 * @param   pi8     Pointer to the 8-bit variable to read.
     3353 * @param   u8      The 8-bit value to assign to *pu8.
     3354 */
     3355DECLINLINE(void) ASMAtomicUoWriteS8(volatile int8_t *pi8, int8_t i8)
     3356{
     3357    *pi8 = i8;      /* byte writes are atomic on x86 */
     3358}
     3359
     3360
     3361/**
     3362 * Atomically writes an unsigned 16-bit value, ordered.
     3363 *
     3364 * @param   pu16    Pointer to the 16-bit variable.
     3365 * @param   u16     The 16-bit value to assign to *pu16.
     3366 */
     3367DECLINLINE(void) ASMAtomicWriteU16(volatile uint16_t *pu16, uint16_t u16)
     3368{
     3369    ASMAtomicXchgU16(pu16, u16);
     3370}
     3371
     3372
     3373/**
     3374 * Atomically writes an unsigned 16-bit value, unordered.
     3375 *
     3376 * @param   pu16    Pointer to the 16-bit variable.
     3377 * @param   u16     The 16-bit value to assign to *pu16.
     3378 */
     3379DECLINLINE(void) ASMAtomicUoWriteU16(volatile uint16_t *pu16, uint16_t u16)
     3380{
     3381    Assert(!((uintptr_t)pu16 & 1));
     3382    *pu16 = u16;
     3383}
     3384
     3385
     3386/**
     3387 * Atomically writes a signed 16-bit value, ordered.
     3388 *
     3389 * @param   pi16    Pointer to the 16-bit variable to read.
     3390 * @param   u16     The 16-bit value to assign to *pu16.
     3391 */
     3392DECLINLINE(void) ASMAtomicWriteS16(volatile int16_t *pi16, int16_t i16)
     3393{
     3394    ASMAtomicXchgS16(pi16, i16);
     3395}
     3396
     3397
     3398/**
     3399 * Atomically writes a signed 16-bit value, unordered.
     3400 *
     3401 * @param   pi16    Pointer to the 16-bit variable to read.
     3402 * @param   u16     The 16-bit value to assign to *pu16.
     3403 */
     3404DECLINLINE(void) ASMAtomicUoWriteS16(volatile int16_t *pi16, int16_t i16)
     3405{
     3406    Assert(!((uintptr_t)pi16 & 1));
     3407    *pi16 = i16;
     3408}
     3409
     3410
     3411/**
     3412 * Atomically writes an unsigned 32-bit value, ordered.
     3413 *
     3414 * @param   pu32    Pointer to the 32-bit variable.
     3415 * @param   u32     The 32-bit value to assign to *pu32.
     3416 */
     3417DECLINLINE(void) ASMAtomicWriteU32(volatile uint32_t *pu32, uint32_t u32)
     3418{
     3419    ASMAtomicXchgU32(pu32, u32);
     3420}
     3421
     3422
     3423/**
     3424 * Atomically writes an unsigned 32-bit value, unordered.
     3425 *
     3426 * @param   pu32    Pointer to the 32-bit variable.
     3427 * @param   u32     The 32-bit value to assign to *pu32.
     3428 */
     3429DECLINLINE(void) ASMAtomicUoWriteU32(volatile uint32_t *pu32, uint32_t u32)
     3430{
     3431    Assert(!((uintptr_t)pu32 & 3));
     3432    *pu32 = u32;
     3433}
     3434
     3435
     3436/**
     3437 * Atomically writes a signed 32-bit value, ordered.
     3438 *
     3439 * @param   pi32    Pointer to the 32-bit variable to read.
     3440 * @param   u32     The 32-bit value to assign to *pu32.
     3441 */
     3442DECLINLINE(void) ASMAtomicWriteS32(volatile int32_t *pi32, int32_t i32)
     3443{
     3444    ASMAtomicXchgS32(pi32, i32);
     3445}
     3446
     3447
     3448/**
     3449 * Atomically writes a signed 32-bit value, unordered.
     3450 *
     3451 * @param   pi32    Pointer to the 32-bit variable to read.
     3452 * @param   u32     The 32-bit value to assign to *pu32.
     3453 */
     3454DECLINLINE(void) ASMAtomicUoWriteS32(volatile int32_t *pi32, int32_t i32)
     3455{
     3456    Assert(!((uintptr_t)pi32 & 3));
     3457    *pi32 = i32;
     3458}
     3459
     3460
     3461/**
     3462 * Atomically writes an unsigned 64-bit value, ordered.
     3463 *
     3464 * @param   pu64    Pointer to the 64-bit variable.
     3465 * @param   u64     The 64-bit value to assign to *pu64.
     3466 */
     3467DECLINLINE(void) ASMAtomicWriteU64(volatile uint64_t *pu64, uint64_t u64)
     3468{
     3469    ASMAtomicXchgU64(pu64, u64);
     3470}
     3471
     3472
     3473/**
     3474 * Atomically writes an unsigned 64-bit value, unordered.
     3475 *
     3476 * @param   pu64    Pointer to the 64-bit variable.
     3477 * @param   u64     The 64-bit value to assign to *pu64.
     3478 */
     3479DECLINLINE(void) ASMAtomicUoWriteU64(volatile uint64_t *pu64, uint64_t u64)
     3480{
     3481    Assert(!((uintptr_t)pu64 & 7));
     3482#if ARCH_BITS == 64
     3483    *pu64 = u64;
     3484#else
     3485    ASMAtomicXchgU64(pu64, u64);
     3486#endif
     3487}
     3488
     3489
     3490/**
     3491 * Atomically writes a signed 64-bit value, ordered.
     3492 *
     3493 * @param   pi64    Pointer to the 64-bit variable.
     3494 * @param   u64     The 64-bit value to assign to *pu64.
     3495 */
     3496DECLINLINE(void) ASMAtomicWriteS64(volatile int64_t *pi64, int64_t i64)
     3497{
     3498    ASMAtomicXchgS64(pi64, i64);
     3499}
     3500
     3501
     3502/**
     3503 * Atomically writes a signed 64-bit value, unordered.
     3504 *
     3505 * @param   pi64    Pointer to the 64-bit variable.
     3506 * @param   u64     The 64-bit value to assign to *pu64.
     3507 */
     3508DECLINLINE(void) ASMAtomicUoWriteS64(volatile int64_t *pi64, int64_t i64)
     3509{
     3510    Assert(!((uintptr_t)pi64 & 7));
     3511#if ARCH_BITS == 64
     3512    *pi64 = i64;
     3513#else
     3514    ASMAtomicXchgS64(pi64, i64);
     3515#endif
     3516}
     3517
     3518
     3519/**
     3520 * Atomically writes a boolean value, unordered.
     3521 *
     3522 * @param   pf      Pointer to the boolean variable.
     3523 * @param   f       The boolean value to assign to *pf.
     3524 */
     3525DECLINLINE(void) ASMAtomicWriteBool(volatile bool *pf, bool f)
     3526{
     3527    ASMAtomicWriteU8((uint8_t volatile *)pf, f);
     3528}
     3529
     3530
     3531/**
     3532 * Atomically writes a boolean value, unordered.
     3533 *
     3534 * @param   pf      Pointer to the boolean variable.
     3535 * @param   f       The boolean value to assign to *pf.
     3536 */
     3537DECLINLINE(void) ASMAtomicUoWriteBool(volatile bool *pf, bool f)
     3538{
     3539    *pf = f;    /* byte writes are atomic on x86 */
     3540}
     3541
     3542
     3543/**
     3544 * Atomically writes a pointer value, ordered.
     3545 *
     3546 * @returns Current *pv value
     3547 * @param   ppv     Pointer to the pointer variable.
     3548 * @param   pv      The pointer value to assigne to *ppv.
     3549 */
     3550DECLINLINE(void) ASMAtomicWritePtr(void * volatile *ppv, void *pv)
     3551{
     3552#if ARCH_BITS == 32
     3553    ASMAtomicWriteU32((volatile uint32_t *)(void *)ppv, (uint32_t)pv);
     3554#elif ARCH_BITS == 64
     3555    ASMAtomicWriteU64((volatile uint64_t *)(void *)ppv, (uint64_t)pv);
     3556#else
     3557# error "ARCH_BITS is bogus"
     3558#endif
     3559}
     3560
     3561
     3562/**
     3563 * Atomically writes a pointer value, unordered.
     3564 *
     3565 * @returns Current *pv value
     3566 * @param   ppv     Pointer to the pointer variable.
     3567 * @param   pv      The pointer value to assigne to *ppv.
     3568 */
     3569DECLINLINE(void) ASMAtomicUoWritePtr(void * volatile *ppv, void *pv)
     3570{
     3571#if ARCH_BITS == 32
     3572    ASMAtomicUoWriteU32((volatile uint32_t *)(void *)ppv, (uint32_t)pv);
     3573#elif ARCH_BITS == 64
     3574    ASMAtomicUoWriteU64((volatile uint64_t *)(void *)ppv, (uint64_t)pv);
     3575#else
     3576# error "ARCH_BITS is bogus"
     3577#endif
     3578}
     3579
     3580
     3581/**
     3582 * Atomically write a value which size might differ
     3583 * between platforms or compilers, ordered.
     3584 *
     3585 * @param   pu      Pointer to the variable to update.
     3586 * @param   uNew    The value to assign to *pu.
     3587 */
     3588#define ASMAtomicWriteSize(pu, uNew) \
     3589    do { \
     3590        switch (sizeof(*(pu))) { \
     3591            case 1: ASMAtomicWriteU8( (volatile uint8_t  *)(void *)(pu), (uint8_t )(uNew)); break; \
     3592            case 2: ASMAtomicWriteU16((volatile uint16_t *)(void *)(pu), (uint16_t)(uNew)); break; \
     3593            case 4: ASMAtomicWriteU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \
     3594            case 8: ASMAtomicWriteU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \
     3595            default: AssertMsgFailed(("ASMAtomicWriteSize: size %d is not supported\n", sizeof(*(pu)))); \
     3596        } \
     3597    } while (0)
     3598
     3599/**
     3600 * Atomically write a value which size might differ
     3601 * between platforms or compilers, unordered.
     3602 *
     3603 * @param   pu      Pointer to the variable to update.
     3604 * @param   uNew    The value to assign to *pu.
     3605 */
     3606#define ASMAtomicUoWriteSize(pu, uNew) \
     3607    do { \
     3608        switch (sizeof(*(pu))) { \
     3609            case 1: ASMAtomicUoWriteU8( (volatile uint8_t  *)(void *)(pu), (uint8_t )(uNew)); break; \
     3610            case 2: ASMAtomicUoWriteU16((volatile uint16_t *)(void *)(pu), (uint16_t)(uNew)); break; \
     3611            case 4: ASMAtomicUoWriteU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \
     3612            case 8: ASMAtomicUoWriteU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \
     3613            default: AssertMsgFailed(("ASMAtomicWriteSize: size %d is not supported\n", sizeof(*(pu)))); \
     3614        } \
     3615    } while (0)
     3616
     3617
    29203618
    29213619
     
    34684166
    34694167/**
    3470  * Atomically sets a bit in a bitmap.
     4168 * Atomically sets a bit in a bitmap, ordered.
    34714169 *
    34724170 * @param   pvBitmap    Pointer to the bitmap.
     
    35414239
    35424240/**
    3543  * Atomically clears a bit in a bitmap.
     4241 * Atomically clears a bit in a bitmap, ordered.
    35444242 *
    35454243 * @param   pvBitmap    Pointer to the bitmap.
     
    36124310
    36134311/**
    3614  * Atomically toggles a bit in a bitmap.
     4312 * Atomically toggles a bit in a bitmap, ordered.
    36154313 *
    36164314 * @param   pvBitmap    Pointer to the bitmap.
     
    36924390
    36934391/**
    3694  * Atomically tests and sets a bit in a bitmap.
     4392 * Atomically tests and sets a bit in a bitmap, ordered.
    36954393 *
    36964394 * @returns true if the bit was set.
     
    37834481
    37844482/**
    3785  * Atomically tests and clears a bit in a bitmap.
     4483 * Atomically tests and clears a bit in a bitmap, ordered.
    37864484 *
    37874485 * @returns true if the bit was set.
     
    38764574
    38774575/**
    3878  * Atomically tests and toggles a bit in a bitmap.
     4576 * Atomically tests and toggles a bit in a bitmap, ordered.
    38794577 *
    38804578 * @returns true if the bit was set.
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