11fb62fb0SOlivier Houchard /* 21fb62fb0SOlivier Houchard * Copyright 2010 Samy Al Bahra. 31fb62fb0SOlivier Houchard * All rights reserved. 41fb62fb0SOlivier Houchard * 51fb62fb0SOlivier Houchard * Redistribution and use in source and binary forms, with or without 61fb62fb0SOlivier Houchard * modification, are permitted provided that the following conditions 71fb62fb0SOlivier Houchard * are met: 81fb62fb0SOlivier Houchard * 1. Redistributions of source code must retain the above copyright 91fb62fb0SOlivier Houchard * notice, this list of conditions and the following disclaimer. 101fb62fb0SOlivier Houchard * 2. Redistributions in binary form must reproduce the above copyright 111fb62fb0SOlivier Houchard * notice, this list of conditions and the following disclaimer in the 121fb62fb0SOlivier Houchard * documentation and/or other materials provided with the distribution. 131fb62fb0SOlivier Houchard * 141fb62fb0SOlivier Houchard * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151fb62fb0SOlivier Houchard * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161fb62fb0SOlivier Houchard * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171fb62fb0SOlivier Houchard * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181fb62fb0SOlivier Houchard * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191fb62fb0SOlivier Houchard * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201fb62fb0SOlivier Houchard * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211fb62fb0SOlivier Houchard * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221fb62fb0SOlivier Houchard * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231fb62fb0SOlivier Houchard * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241fb62fb0SOlivier Houchard * SUCH DAMAGE. 251fb62fb0SOlivier Houchard */ 261fb62fb0SOlivier Houchard 271fb62fb0SOlivier Houchard #ifndef CK_PR_GCC_H 281fb62fb0SOlivier Houchard #define CK_PR_GCC_H 291fb62fb0SOlivier Houchard 301fb62fb0SOlivier Houchard #ifndef CK_PR_H 311fb62fb0SOlivier Houchard #error Do not include this file directly, use ck_pr.h 321fb62fb0SOlivier Houchard #endif 331fb62fb0SOlivier Houchard 341fb62fb0SOlivier Houchard #include <ck_cc.h> 351fb62fb0SOlivier Houchard 361fb62fb0SOlivier Houchard CK_CC_INLINE static void 371fb62fb0SOlivier Houchard ck_pr_barrier(void) 381fb62fb0SOlivier Houchard { 391fb62fb0SOlivier Houchard 401fb62fb0SOlivier Houchard __asm__ __volatile__("" ::: "memory"); 411fb62fb0SOlivier Houchard return; 421fb62fb0SOlivier Houchard } 431fb62fb0SOlivier Houchard 441fb62fb0SOlivier Houchard #ifndef CK_F_PR 451fb62fb0SOlivier Houchard #define CK_F_PR 461fb62fb0SOlivier Houchard 471fb62fb0SOlivier Houchard #include <ck_stdbool.h> 481fb62fb0SOlivier Houchard #include <ck_stdint.h> 491fb62fb0SOlivier Houchard 501fb62fb0SOlivier Houchard /* 511fb62fb0SOlivier Houchard * The following represent supported atomic operations. 521fb62fb0SOlivier Houchard * These operations may be emulated. 531fb62fb0SOlivier Houchard */ 541fb62fb0SOlivier Houchard #include "ck_f_pr.h" 551fb62fb0SOlivier Houchard 561fb62fb0SOlivier Houchard #define CK_PR_ACCESS(x) (*(volatile __typeof__(x) *)&(x)) 571fb62fb0SOlivier Houchard 581fb62fb0SOlivier Houchard #define CK_PR_LOAD(S, M, T) \ 591fb62fb0SOlivier Houchard CK_CC_INLINE static T \ 601fb62fb0SOlivier Houchard ck_pr_md_load_##S(const M *target) \ 611fb62fb0SOlivier Houchard { \ 621fb62fb0SOlivier Houchard T r; \ 631fb62fb0SOlivier Houchard ck_pr_barrier(); \ 641fb62fb0SOlivier Houchard r = CK_PR_ACCESS(*(const T *)target); \ 651fb62fb0SOlivier Houchard ck_pr_barrier(); \ 661fb62fb0SOlivier Houchard return (r); \ 671fb62fb0SOlivier Houchard } \ 681fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 691fb62fb0SOlivier Houchard ck_pr_md_store_##S(M *target, T v) \ 701fb62fb0SOlivier Houchard { \ 711fb62fb0SOlivier Houchard ck_pr_barrier(); \ 721fb62fb0SOlivier Houchard CK_PR_ACCESS(*(T *)target) = v; \ 731fb62fb0SOlivier Houchard ck_pr_barrier(); \ 741fb62fb0SOlivier Houchard return; \ 751fb62fb0SOlivier Houchard } 761fb62fb0SOlivier Houchard 771fb62fb0SOlivier Houchard CK_CC_INLINE static void * 781fb62fb0SOlivier Houchard ck_pr_md_load_ptr(const void *target) 791fb62fb0SOlivier Houchard { 801fb62fb0SOlivier Houchard void *r; 811fb62fb0SOlivier Houchard 821fb62fb0SOlivier Houchard ck_pr_barrier(); 831fb62fb0SOlivier Houchard r = CK_CC_DECONST_PTR(CK_PR_ACCESS(target)); 841fb62fb0SOlivier Houchard ck_pr_barrier(); 851fb62fb0SOlivier Houchard 861fb62fb0SOlivier Houchard return r; 871fb62fb0SOlivier Houchard } 881fb62fb0SOlivier Houchard 891fb62fb0SOlivier Houchard CK_CC_INLINE static void 901fb62fb0SOlivier Houchard ck_pr_md_store_ptr(void *target, const void *v) 911fb62fb0SOlivier Houchard { 921fb62fb0SOlivier Houchard 931fb62fb0SOlivier Houchard ck_pr_barrier(); 941fb62fb0SOlivier Houchard CK_PR_ACCESS(target) = CK_CC_DECONST_PTR(v); 951fb62fb0SOlivier Houchard ck_pr_barrier(); 961fb62fb0SOlivier Houchard return; 971fb62fb0SOlivier Houchard } 981fb62fb0SOlivier Houchard 991fb62fb0SOlivier Houchard #define CK_PR_LOAD_S(S, T) CK_PR_LOAD(S, T, T) 1001fb62fb0SOlivier Houchard 1011fb62fb0SOlivier Houchard CK_PR_LOAD_S(char, char) 1021fb62fb0SOlivier Houchard CK_PR_LOAD_S(uint, unsigned int) 1031fb62fb0SOlivier Houchard CK_PR_LOAD_S(int, int) 104*8f87df16SOlivier Houchard #ifndef CK_PR_DISABLE_DOUBLE 1051fb62fb0SOlivier Houchard CK_PR_LOAD_S(double, double) 106*8f87df16SOlivier Houchard #endif 1071fb62fb0SOlivier Houchard CK_PR_LOAD_S(64, uint64_t) 1081fb62fb0SOlivier Houchard CK_PR_LOAD_S(32, uint32_t) 1091fb62fb0SOlivier Houchard CK_PR_LOAD_S(16, uint16_t) 1101fb62fb0SOlivier Houchard CK_PR_LOAD_S(8, uint8_t) 1111fb62fb0SOlivier Houchard 1121fb62fb0SOlivier Houchard #undef CK_PR_LOAD_S 1131fb62fb0SOlivier Houchard #undef CK_PR_LOAD 1141fb62fb0SOlivier Houchard 1151fb62fb0SOlivier Houchard CK_CC_INLINE static void 1161fb62fb0SOlivier Houchard ck_pr_stall(void) 1171fb62fb0SOlivier Houchard { 1181fb62fb0SOlivier Houchard 1191fb62fb0SOlivier Houchard ck_pr_barrier(); 1201fb62fb0SOlivier Houchard } 1211fb62fb0SOlivier Houchard 1221fb62fb0SOlivier Houchard /* 1231fb62fb0SOlivier Houchard * Load and store fences are equivalent to full fences in the GCC port. 1241fb62fb0SOlivier Houchard */ 1251fb62fb0SOlivier Houchard #define CK_PR_FENCE(T) \ 1261fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 1271fb62fb0SOlivier Houchard ck_pr_fence_strict_##T(void) \ 1281fb62fb0SOlivier Houchard { \ 1291fb62fb0SOlivier Houchard __sync_synchronize(); \ 1301fb62fb0SOlivier Houchard } 1311fb62fb0SOlivier Houchard 1321fb62fb0SOlivier Houchard CK_PR_FENCE(atomic) 1331fb62fb0SOlivier Houchard CK_PR_FENCE(atomic_atomic) 1341fb62fb0SOlivier Houchard CK_PR_FENCE(atomic_load) 1351fb62fb0SOlivier Houchard CK_PR_FENCE(atomic_store) 1361fb62fb0SOlivier Houchard CK_PR_FENCE(store_atomic) 1371fb62fb0SOlivier Houchard CK_PR_FENCE(load_atomic) 1381fb62fb0SOlivier Houchard CK_PR_FENCE(load) 1391fb62fb0SOlivier Houchard CK_PR_FENCE(load_load) 1401fb62fb0SOlivier Houchard CK_PR_FENCE(load_store) 1411fb62fb0SOlivier Houchard CK_PR_FENCE(store) 1421fb62fb0SOlivier Houchard CK_PR_FENCE(store_store) 1431fb62fb0SOlivier Houchard CK_PR_FENCE(store_load) 1441fb62fb0SOlivier Houchard CK_PR_FENCE(memory) 1451fb62fb0SOlivier Houchard CK_PR_FENCE(acquire) 1461fb62fb0SOlivier Houchard CK_PR_FENCE(release) 1471fb62fb0SOlivier Houchard CK_PR_FENCE(acqrel) 1481fb62fb0SOlivier Houchard CK_PR_FENCE(lock) 1491fb62fb0SOlivier Houchard CK_PR_FENCE(unlock) 1501fb62fb0SOlivier Houchard 1511fb62fb0SOlivier Houchard #undef CK_PR_FENCE 1521fb62fb0SOlivier Houchard 1531fb62fb0SOlivier Houchard /* 1541fb62fb0SOlivier Houchard * Atomic compare and swap. 1551fb62fb0SOlivier Houchard */ 1561fb62fb0SOlivier Houchard #define CK_PR_CAS(S, M, T) \ 1571fb62fb0SOlivier Houchard CK_CC_INLINE static bool \ 1581fb62fb0SOlivier Houchard ck_pr_cas_##S(M *target, T compare, T set) \ 1591fb62fb0SOlivier Houchard { \ 1601fb62fb0SOlivier Houchard bool z; \ 1611fb62fb0SOlivier Houchard z = __sync_bool_compare_and_swap((T *)target, compare, set); \ 1621fb62fb0SOlivier Houchard return z; \ 1631fb62fb0SOlivier Houchard } 1641fb62fb0SOlivier Houchard 1651fb62fb0SOlivier Houchard CK_PR_CAS(ptr, void, void *) 1661fb62fb0SOlivier Houchard 1671fb62fb0SOlivier Houchard #define CK_PR_CAS_S(S, T) CK_PR_CAS(S, T, T) 1681fb62fb0SOlivier Houchard 1691fb62fb0SOlivier Houchard CK_PR_CAS_S(char, char) 1701fb62fb0SOlivier Houchard CK_PR_CAS_S(int, int) 1711fb62fb0SOlivier Houchard CK_PR_CAS_S(uint, unsigned int) 1721fb62fb0SOlivier Houchard CK_PR_CAS_S(64, uint64_t) 1731fb62fb0SOlivier Houchard CK_PR_CAS_S(32, uint32_t) 1741fb62fb0SOlivier Houchard CK_PR_CAS_S(16, uint16_t) 1751fb62fb0SOlivier Houchard CK_PR_CAS_S(8, uint8_t) 1761fb62fb0SOlivier Houchard 1771fb62fb0SOlivier Houchard #undef CK_PR_CAS_S 1781fb62fb0SOlivier Houchard #undef CK_PR_CAS 1791fb62fb0SOlivier Houchard 1801fb62fb0SOlivier Houchard /* 1811fb62fb0SOlivier Houchard * Compare and swap, set *v to old value of target. 1821fb62fb0SOlivier Houchard */ 1831fb62fb0SOlivier Houchard CK_CC_INLINE static bool 1841fb62fb0SOlivier Houchard ck_pr_cas_ptr_value(void *target, void *compare, void *set, void *v) 1851fb62fb0SOlivier Houchard { 1861fb62fb0SOlivier Houchard set = __sync_val_compare_and_swap((void **)target, compare, set); 1871fb62fb0SOlivier Houchard *(void **)v = set; 1881fb62fb0SOlivier Houchard return (set == compare); 1891fb62fb0SOlivier Houchard } 1901fb62fb0SOlivier Houchard 1911fb62fb0SOlivier Houchard #define CK_PR_CAS_O(S, T) \ 1921fb62fb0SOlivier Houchard CK_CC_INLINE static bool \ 1931fb62fb0SOlivier Houchard ck_pr_cas_##S##_value(T *target, T compare, T set, T *v) \ 1941fb62fb0SOlivier Houchard { \ 1951fb62fb0SOlivier Houchard set = __sync_val_compare_and_swap(target, compare, set);\ 1961fb62fb0SOlivier Houchard *v = set; \ 1971fb62fb0SOlivier Houchard return (set == compare); \ 1981fb62fb0SOlivier Houchard } 1991fb62fb0SOlivier Houchard 2001fb62fb0SOlivier Houchard CK_PR_CAS_O(char, char) 2011fb62fb0SOlivier Houchard CK_PR_CAS_O(int, int) 2021fb62fb0SOlivier Houchard CK_PR_CAS_O(uint, unsigned int) 2031fb62fb0SOlivier Houchard CK_PR_CAS_O(64, uint64_t) 2041fb62fb0SOlivier Houchard CK_PR_CAS_O(32, uint32_t) 2051fb62fb0SOlivier Houchard CK_PR_CAS_O(16, uint16_t) 2061fb62fb0SOlivier Houchard CK_PR_CAS_O(8, uint8_t) 2071fb62fb0SOlivier Houchard 2081fb62fb0SOlivier Houchard #undef CK_PR_CAS_O 2091fb62fb0SOlivier Houchard 2101fb62fb0SOlivier Houchard /* 2111fb62fb0SOlivier Houchard * Atomic fetch-and-add operations. 2121fb62fb0SOlivier Houchard */ 2131fb62fb0SOlivier Houchard #define CK_PR_FAA(S, M, T) \ 2141fb62fb0SOlivier Houchard CK_CC_INLINE static T \ 2151fb62fb0SOlivier Houchard ck_pr_faa_##S(M *target, T d) \ 2161fb62fb0SOlivier Houchard { \ 2171fb62fb0SOlivier Houchard d = __sync_fetch_and_add((T *)target, d); \ 2181fb62fb0SOlivier Houchard return (d); \ 2191fb62fb0SOlivier Houchard } 2201fb62fb0SOlivier Houchard 2211fb62fb0SOlivier Houchard CK_PR_FAA(ptr, void, void *) 2221fb62fb0SOlivier Houchard 2231fb62fb0SOlivier Houchard #define CK_PR_FAA_S(S, T) CK_PR_FAA(S, T, T) 2241fb62fb0SOlivier Houchard 2251fb62fb0SOlivier Houchard CK_PR_FAA_S(char, char) 2261fb62fb0SOlivier Houchard CK_PR_FAA_S(uint, unsigned int) 2271fb62fb0SOlivier Houchard CK_PR_FAA_S(int, int) 2281fb62fb0SOlivier Houchard CK_PR_FAA_S(64, uint64_t) 2291fb62fb0SOlivier Houchard CK_PR_FAA_S(32, uint32_t) 2301fb62fb0SOlivier Houchard CK_PR_FAA_S(16, uint16_t) 2311fb62fb0SOlivier Houchard CK_PR_FAA_S(8, uint8_t) 2321fb62fb0SOlivier Houchard 2331fb62fb0SOlivier Houchard #undef CK_PR_FAA_S 2341fb62fb0SOlivier Houchard #undef CK_PR_FAA 2351fb62fb0SOlivier Houchard 2361fb62fb0SOlivier Houchard /* 2371fb62fb0SOlivier Houchard * Atomic store-only binary operations. 2381fb62fb0SOlivier Houchard */ 2391fb62fb0SOlivier Houchard #define CK_PR_BINARY(K, S, M, T) \ 2401fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 2411fb62fb0SOlivier Houchard ck_pr_##K##_##S(M *target, T d) \ 2421fb62fb0SOlivier Houchard { \ 2431fb62fb0SOlivier Houchard d = __sync_fetch_and_##K((T *)target, d); \ 2441fb62fb0SOlivier Houchard return; \ 2451fb62fb0SOlivier Houchard } 2461fb62fb0SOlivier Houchard 2471fb62fb0SOlivier Houchard #define CK_PR_BINARY_S(K, S, T) CK_PR_BINARY(K, S, T, T) 2481fb62fb0SOlivier Houchard 2491fb62fb0SOlivier Houchard #define CK_PR_GENERATE(K) \ 2501fb62fb0SOlivier Houchard CK_PR_BINARY(K, ptr, void, void *) \ 2511fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, char, char) \ 2521fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, int, int) \ 2531fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, uint, unsigned int) \ 2541fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, 64, uint64_t) \ 2551fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, 32, uint32_t) \ 2561fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, 16, uint16_t) \ 2571fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, 8, uint8_t) 2581fb62fb0SOlivier Houchard 2591fb62fb0SOlivier Houchard CK_PR_GENERATE(add) 2601fb62fb0SOlivier Houchard CK_PR_GENERATE(sub) 2611fb62fb0SOlivier Houchard CK_PR_GENERATE(and) 2621fb62fb0SOlivier Houchard CK_PR_GENERATE(or) 2631fb62fb0SOlivier Houchard CK_PR_GENERATE(xor) 2641fb62fb0SOlivier Houchard 2651fb62fb0SOlivier Houchard #undef CK_PR_GENERATE 2661fb62fb0SOlivier Houchard #undef CK_PR_BINARY_S 2671fb62fb0SOlivier Houchard #undef CK_PR_BINARY 2681fb62fb0SOlivier Houchard 2691fb62fb0SOlivier Houchard #define CK_PR_UNARY(S, M, T) \ 2701fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 2711fb62fb0SOlivier Houchard ck_pr_inc_##S(M *target) \ 2721fb62fb0SOlivier Houchard { \ 2731fb62fb0SOlivier Houchard ck_pr_add_##S(target, (T)1); \ 2741fb62fb0SOlivier Houchard return; \ 2751fb62fb0SOlivier Houchard } \ 2761fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 2771fb62fb0SOlivier Houchard ck_pr_dec_##S(M *target) \ 2781fb62fb0SOlivier Houchard { \ 2791fb62fb0SOlivier Houchard ck_pr_sub_##S(target, (T)1); \ 2801fb62fb0SOlivier Houchard return; \ 2811fb62fb0SOlivier Houchard } 2821fb62fb0SOlivier Houchard 2831fb62fb0SOlivier Houchard #define CK_PR_UNARY_S(S, M) CK_PR_UNARY(S, M, M) 2841fb62fb0SOlivier Houchard 2851fb62fb0SOlivier Houchard CK_PR_UNARY(ptr, void, void *) 2861fb62fb0SOlivier Houchard CK_PR_UNARY_S(char, char) 2871fb62fb0SOlivier Houchard CK_PR_UNARY_S(int, int) 2881fb62fb0SOlivier Houchard CK_PR_UNARY_S(uint, unsigned int) 2891fb62fb0SOlivier Houchard CK_PR_UNARY_S(64, uint64_t) 2901fb62fb0SOlivier Houchard CK_PR_UNARY_S(32, uint32_t) 2911fb62fb0SOlivier Houchard CK_PR_UNARY_S(16, uint16_t) 2921fb62fb0SOlivier Houchard CK_PR_UNARY_S(8, uint8_t) 2931fb62fb0SOlivier Houchard 2941fb62fb0SOlivier Houchard #undef CK_PR_UNARY_S 2951fb62fb0SOlivier Houchard #undef CK_PR_UNARY 2961fb62fb0SOlivier Houchard #endif /* !CK_F_PR */ 2971fb62fb0SOlivier Houchard #endif /* CK_PR_GCC_H */ 298