Changeset 6782 in vbox for trunk/include
- Timestamp:
- Feb 4, 2008 12:42:58 PM (17 years ago)
- svn:sync-xref-src-repo-rev:
- 27875
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/asm.h
r6653 r6782 29 29 #include <iprt/cdefs.h> 30 30 #include <iprt/types.h> 31 #include <iprt/assert.h> 31 32 /** @todo #include <iprt/param.h> for PAGE_SIZE. */ 32 33 /** @def RT_INLINE_ASM_USES_INTRIN … … 98 99 /** @defgroup grp_asm ASM - Assembly Routines 99 100 * @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 * 100 112 * @{ 101 113 */ … … 1614 1626 1615 1627 /** 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. 1617 1629 * 1618 1630 * @param Port I/O port to read from. … … 1645 1657 1646 1658 /** 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. 1648 1660 * 1649 1661 * @returns 8-bit integer. … … 1678 1690 1679 1691 /** 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. 1681 1693 * 1682 1694 * @param Port I/O port to read from. … … 1709 1721 1710 1722 /** 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. 1712 1724 * 1713 1725 * @returns 16-bit integer. … … 1742 1754 1743 1755 /** 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. 1745 1757 * 1746 1758 * @param Port I/O port to read from. … … 1773 1785 1774 1786 /** 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. 1776 1788 * 1777 1789 * @returns 32-bit integer. … … 1804 1816 #endif 1805 1817 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. 1809 1823 * 1810 1824 * @returns Current *pu8 value … … 1844 1858 1845 1859 /** 1846 * Atomically Exchange a signed 8-bit value .1860 * Atomically Exchange a signed 8-bit value, ordered. 1847 1861 * 1848 1862 * @returns Current *pu8 value … … 1857 1871 1858 1872 /** 1859 * Atomically Exchange a bool value .1873 * Atomically Exchange a bool value, ordered. 1860 1874 * 1861 1875 * @returns Current *pf value … … 1874 1888 1875 1889 /** 1876 * Atomically Exchange an unsigned 16-bit value .1890 * Atomically Exchange an unsigned 16-bit value, ordered. 1877 1891 * 1878 1892 * @returns Current *pu16 value … … 1912 1926 1913 1927 /** 1914 * Atomically Exchange a signed 16-bit value .1928 * Atomically Exchange a signed 16-bit value, ordered. 1915 1929 * 1916 1930 * @returns Current *pu16 value … … 1925 1939 1926 1940 /** 1927 * Atomically Exchange an unsigned 32-bit value .1941 * Atomically Exchange an unsigned 32-bit value, ordered. 1928 1942 * 1929 1943 * @returns Current *pu32 value … … 1967 1981 1968 1982 /** 1969 * Atomically Exchange a signed 32-bit value .1983 * Atomically Exchange a signed 32-bit value, ordered. 1970 1984 * 1971 1985 * @returns Current *pu32 value … … 1980 1994 1981 1995 /** 1982 * Atomically Exchange an unsigned 64-bit value .1996 * Atomically Exchange an unsigned 64-bit value, ordered. 1983 1997 * 1984 1998 * @returns Current *pu64 value … … 2058 2072 2059 2073 /** 2060 * Atomically Exchange an signed 64-bit value .2074 * Atomically Exchange an signed 64-bit value, ordered. 2061 2075 * 2062 2076 * @returns Current *pi64 value … … 2072 2086 #ifdef RT_ARCH_AMD64 2073 2087 /** 2074 * Atomically Exchange an unsigned 128-bit value .2088 * Atomically Exchange an unsigned 128-bit value, ordered. 2075 2089 * 2076 2090 * @returns Current *pu128. … … 2132 2146 2133 2147 /** 2134 * Atomically Reads a unsigned 64-bit value.2135 *2136 * @returns Current *pu64 value2137 * @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_EXTERNAL2142 DECLASM(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64);2143 #else2144 DECLINLINE(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64)2145 {2146 uint64_t u64;2147 # ifdef RT_ARCH_AMD642148 # if RT_INLINE_ASM_GNU_STYLE2149 __asm__ __volatile__("movq %1, %0\n\t"2150 : "=r" (u64)2151 : "m" (*pu64));2152 # else2153 __asm2154 {2155 mov rdx, [pu64]2156 mov rax, [rdx]2157 mov [u64], rax2158 }2159 # endif2160 # else /* !RT_ARCH_AMD64 */2161 # if RT_INLINE_ASM_GNU_STYLE2162 # 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 # endif2181 # else2182 __asm2183 {2184 xor eax, eax2185 xor edx, edx2186 mov edi, pu642187 xor ecx, ecx2188 xor ebx, ebx2189 lock cmpxchg8b [edi]2190 mov dword ptr [u64], eax2191 mov dword ptr [u64 + 4], edx2192 }2193 # endif2194 # endif /* !RT_ARCH_AMD64 */2195 return u64;2196 }2197 #endif2198 2199 2200 /**2201 * Atomically Reads a signed 64-bit value.2202 *2203 * @returns Current *pi64 value2204 * @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 /**2215 2148 * Atomically Exchange a value which size might differ 2216 * between platforms or compilers .2149 * between platforms or compilers, ordered. 2217 2150 * 2218 2151 * @param pu Pointer to the variable to update. … … 2232 2165 2233 2166 /** 2234 * Atomically Exchange a pointer value .2167 * Atomically Exchange a pointer value, ordered. 2235 2168 * 2236 2169 * @returns Current *ppv value … … 2251 2184 2252 2185 /** 2253 * Atomically Compare and Exchange an unsigned 32-bit value .2186 * Atomically Compare and Exchange an unsigned 32-bit value, ordered. 2254 2187 * 2255 2188 * @returns true if xchg was done. … … 2305 2238 2306 2239 /** 2307 * Atomically Compare and Exchange a signed 32-bit value .2240 * Atomically Compare and Exchange a signed 32-bit value, ordered. 2308 2241 * 2309 2242 * @returns true if xchg was done. … … 2321 2254 2322 2255 /** 2323 * Atomically Compare and exchange an unsigned 64-bit value .2256 * Atomically Compare and exchange an unsigned 64-bit value, ordered. 2324 2257 * 2325 2258 * @returns true if xchg was done. … … 2413 2346 2414 2347 /** 2415 * Atomically Compare and exchange a signed 64-bit value .2348 * Atomically Compare and exchange a signed 64-bit value, ordered. 2416 2349 * 2417 2350 * @returns true if xchg was done. … … 2430 2363 /** @def ASMAtomicCmpXchgSize 2431 2364 * Atomically Compare and Exchange a value which size might differ 2432 * between platforms or compilers .2365 * between platforms or compilers, ordered. 2433 2366 * 2434 2367 * @param pu Pointer to the value to update. … … 2452 2385 2453 2386 /** 2454 * Atomically Compare and Exchange a pointer value .2387 * Atomically Compare and Exchange a pointer value, ordered. 2455 2388 * 2456 2389 * @returns true if xchg was done. … … 2475 2408 /** 2476 2409 * Atomically Compare and Exchange an unsigned 32-bit value, additionally 2477 * passes back old value .2410 * passes back old value, ordered. 2478 2411 * 2479 2412 * @returns true if xchg was done. … … 2536 2469 /** 2537 2470 * Atomically Compare and Exchange a signed 32-bit value, additionally 2538 * passes back old value .2471 * passes back old value, ordered. 2539 2472 * 2540 2473 * @returns true if xchg was done. … … 2554 2487 /** 2555 2488 * Atomically Compare and exchange an unsigned 64-bit value, additionally 2556 * passing back old value .2489 * passing back old value, ordered. 2557 2490 * 2558 2491 * @returns true if xchg was done. … … 2653 2586 /** 2654 2587 * Atomically Compare and exchange a signed 64-bit value, additionally 2655 * passing back old value .2588 * passing back old value, ordered. 2656 2589 * 2657 2590 * @returns true if xchg was done. … … 2696 2629 /** 2697 2630 * Atomically Compare and Exchange a pointer value, additionally 2698 * passing back old value .2631 * passing back old value, ordered. 2699 2632 * 2700 2633 * @returns true if xchg was done. … … 2719 2652 2720 2653 /** 2721 * Atomically increment a 32-bit value .2654 * Atomically increment a 32-bit value, ordered. 2722 2655 * 2723 2656 * @returns The new value. … … 2761 2694 2762 2695 /** 2763 * Atomically increment a signed 32-bit value .2696 * Atomically increment a signed 32-bit value, ordered. 2764 2697 * 2765 2698 * @returns The new value. … … 2773 2706 2774 2707 /** 2775 * Atomically decrement an unsigned 32-bit value .2708 * Atomically decrement an unsigned 32-bit value, ordered. 2776 2709 * 2777 2710 * @returns The new value. … … 2815 2748 2816 2749 /** 2817 * Atomically decrement a signed 32-bit value .2750 * Atomically decrement a signed 32-bit value, ordered. 2818 2751 * 2819 2752 * @returns The new value. … … 2827 2760 2828 2761 /** 2829 * Atomically Or an unsigned 32-bit value .2762 * Atomically Or an unsigned 32-bit value, ordered. 2830 2763 * 2831 2764 * @param pu32 Pointer to the pointer variable to OR u32 with. … … 2862 2795 2863 2796 /** 2864 * Atomically Or a signed 32-bit value .2797 * Atomically Or a signed 32-bit value, ordered. 2865 2798 * 2866 2799 * @param pi32 Pointer to the pointer variable to OR u32 with. … … 2874 2807 2875 2808 /** 2876 * Atomically And an unsigned 32-bit value .2809 * Atomically And an unsigned 32-bit value, ordered. 2877 2810 * 2878 2811 * @param pu32 Pointer to the pointer variable to AND u32 with. … … 2909 2842 2910 2843 /** 2911 * Atomically And a signed 32-bit value .2844 * Atomically And a signed 32-bit value, ordered. 2912 2845 * 2913 2846 * @param pi32 Pointer to the pointer variable to AND i32 with. … … 2918 2851 ASMAtomicAndU32((uint32_t volatile *)pi32, (uint32_t)i32); 2919 2852 } 2853 2854 2855 /** 2856 * Memory fence, waits for any pending writes and reads to complete. 2857 */ 2858 DECLINLINE(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 */ 2869 DECLINLINE(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 */ 2879 DECLINLINE(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 */ 2892 DECLINLINE(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 */ 2905 DECLINLINE(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 */ 2917 DECLINLINE(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 */ 2930 DECLINLINE(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 */ 2942 DECLINLINE(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 */ 2956 DECLINLINE(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 */ 2969 DECLINLINE(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 */ 2983 DECLINLINE(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 */ 2996 DECLINLINE(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 */ 3010 DECLINLINE(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 */ 3023 DECLINLINE(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 */ 3037 DECLINLINE(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 3053 DECLASM(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64); 3054 #else 3055 DECLINLINE(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 3125 DECLASM(uint64_t) ASMAtomicUoReadU64(volatile uint64_t *pu64); 3126 #else 3127 DECLINLINE(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 */ 3194 DECLINLINE(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 */ 3208 DECLINLINE(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 */ 3220 DECLINLINE(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 */ 3238 DECLINLINE(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 */ 3256 DECLINLINE(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 */ 3269 DECLINLINE(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 */ 3319 DECLINLINE(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 */ 3331 DECLINLINE(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 */ 3343 DECLINLINE(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 */ 3355 DECLINLINE(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 */ 3367 DECLINLINE(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 */ 3379 DECLINLINE(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 */ 3392 DECLINLINE(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 */ 3404 DECLINLINE(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 */ 3417 DECLINLINE(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 */ 3429 DECLINLINE(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 */ 3442 DECLINLINE(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 */ 3454 DECLINLINE(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 */ 3467 DECLINLINE(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 */ 3479 DECLINLINE(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 */ 3496 DECLINLINE(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 */ 3508 DECLINLINE(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 */ 3525 DECLINLINE(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 */ 3537 DECLINLINE(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 */ 3550 DECLINLINE(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 */ 3569 DECLINLINE(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 2920 3618 2921 3619 … … 3468 4166 3469 4167 /** 3470 * Atomically sets a bit in a bitmap .4168 * Atomically sets a bit in a bitmap, ordered. 3471 4169 * 3472 4170 * @param pvBitmap Pointer to the bitmap. … … 3541 4239 3542 4240 /** 3543 * Atomically clears a bit in a bitmap .4241 * Atomically clears a bit in a bitmap, ordered. 3544 4242 * 3545 4243 * @param pvBitmap Pointer to the bitmap. … … 3612 4310 3613 4311 /** 3614 * Atomically toggles a bit in a bitmap .4312 * Atomically toggles a bit in a bitmap, ordered. 3615 4313 * 3616 4314 * @param pvBitmap Pointer to the bitmap. … … 3692 4390 3693 4391 /** 3694 * Atomically tests and sets a bit in a bitmap .4392 * Atomically tests and sets a bit in a bitmap, ordered. 3695 4393 * 3696 4394 * @returns true if the bit was set. … … 3783 4481 3784 4482 /** 3785 * Atomically tests and clears a bit in a bitmap .4483 * Atomically tests and clears a bit in a bitmap, ordered. 3786 4484 * 3787 4485 * @returns true if the bit was set. … … 3876 4574 3877 4575 /** 3878 * Atomically tests and toggles a bit in a bitmap .4576 * Atomically tests and toggles a bit in a bitmap, ordered. 3879 4577 * 3880 4578 * @returns true if the bit was set.
Note:
See TracChangeset
for help on using the changeset viewer.