"Fossies" - the Fresh Open Source Software Archive

Member "openpa-1.0.4/src/primitives/opa_gcc_ia64.h" (5 Dec 2012, 7129 Bytes) of package /linux/misc/openpa-1.0.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "opa_gcc_ia64.h" see the Fossies "Dox" file reference documentation.

    1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
    2 /*  
    3  *  (C) 2008 by Argonne National Laboratory.
    4  *      See COPYRIGHT in top-level directory.
    5  */
    6 
    7 /* NOTE: We (@ANL) do not have easy access to any ia64 hosts, so it is difficult
    8  * to develop and test updates to this file.  Any help in this regard is greatly
    9  * appreciated. */
   10 
   11 #ifndef OPA_GCC_IA64_H_INCLUDED
   12 #define OPA_GCC_IA64_H_INCLUDED
   13 
   14 /* FIXME do we need to align these? */
   15 typedef struct { volatile int v;    } OPA_int_t;
   16 typedef struct { void * volatile v; } OPA_ptr_t;
   17 
   18 #define OPA_INT_T_INITIALIZER(val_) { (val_) }
   19 #define OPA_PTR_T_INITIALIZER(val_) { (val_) }
   20 
   21 /* Aligned loads and stores are atomic on ia64. */
   22 static _opa_inline int OPA_load_int(_opa_const OPA_int_t *ptr)
   23 {
   24     return ptr->v;
   25 }
   26 
   27 /* Aligned loads and stores are atomic on ia64. */
   28 static _opa_inline void OPA_store_int(OPA_int_t *ptr, int val)
   29 {
   30     ptr->v = val;
   31 }
   32 
   33 /* Aligned loads and stores are atomic on ia64. */
   34 static _opa_inline void *OPA_load_ptr(_opa_const OPA_ptr_t *ptr)
   35 {
   36     return ptr->v;
   37 }
   38 
   39 /* Aligned loads and stores are atomic on ia64. */
   40 static _opa_inline void OPA_store_ptr(OPA_ptr_t *ptr, void *val)
   41 {
   42     ptr->v = val;
   43 }
   44 
   45 
   46 /* NOTE-IA64-1 ia64 suports half-fence suffixes to ld/st instructions.  It seems
   47  * that compilers also treat any C-language load/store from/to a volatile
   48  * variable as acquire/release and append the corresponding suffix accordingly.
   49  * But we don't have extensive testing to back this up, so we'll explicitly
   50  * force these instructions for now.  When using the C-level approach, it's not
   51  * clear what instructions the compiler is allowed to reorder. */
   52 
   53 #if 0
   54 /* acquire means operations after the acquire will see any memory opeations
   55  * performed before the corresponding paired release operation */
   56 static _opa_inline int   OPA_load_acquire_int(_opa_const OPA_int_t *ptr)
   57 {
   58     int tmp;
   59     __asm__ __volatile__ ("ld.acq %0=[%1]"
   60                           : "=r" (tmp)
   61                           : "r"  (ptr->v)
   62                           : "memory");
   63     return tmp;
   64 }
   65 static _opa_inline void  OPA_store_release_int(OPA_int_t *ptr, int val)
   66 {
   67     __asm__ __volatile__ ("st.rel [%0]=%1"
   68                           : "=m"  (ptr->v)
   69                           : "r" (val)
   70                           : "memory");
   71 }
   72 static _opa_inline void *OPA_load_acquire_ptr(_opa_const OPA_ptr_t *ptr)
   73 {
   74     int tmp;
   75     __asm__ __volatile__ ("ld.acq %0=[%1]"
   76                           : "=r" (tmp)
   77                           : "r"  (ptr->v)
   78                           : "memory");
   79     return tmp;
   80 }
   81 static _opa_inline void  OPA_store_release_ptr(OPA_ptr_t *ptr, void *val)
   82 {
   83     __asm__ __volatile__ ("st.rel [%0]=%1"
   84                           : "=m"  (ptr->v)
   85                           : "r" (val)
   86                           : "memory");
   87 }
   88 #else
   89 /* FIXME because we can't test these implementations, they are currently
   90  * disabled.  The above impls are rough starting points, but probably won't
   91  * compile/assemble correctly as-is.  Patches are welcome :) */
   92 #define OPA_load_acquire_int(ptr_)       ::"choke me"
   93 #define OPA_store_release_int(ptr_,val_) ::"choke me"
   94 #define OPA_load_acquire_ptr(ptr_)       ::"choke me"
   95 #define OPA_store_release_ptr(ptr_,val_) ::"choke me"
   96 #endif
   97 
   98 
   99 #define OPA_add_int_by_faa OPA_add_int
  100 #define OPA_incr_int_by_faa OPA_incr_int
  101 #define OPA_decr_int_by_faa OPA_decr_int
  102 #define OPA_fetch_and_decr_int_by_faa OPA_fetch_and_decr_int
  103 #define OPA_fetch_and_incr_int_by_faa OPA_fetch_and_incr_int
  104 
  105 static _opa_inline int OPA_decr_and_test_int(OPA_int_t *ptr)
  106 {
  107     int val;
  108     __asm__ __volatile__ ("fetchadd4.rel %0=[%2],%3"
  109                           : "=r"(val), "=m"(ptr->v)
  110                           : "r"(&ptr->v), "i"(-1));
  111     return val == 1;
  112 }
  113 
  114 static _opa_inline int OPA_cas_int(OPA_int_t *ptr, int oldv, int newv)
  115 {
  116     int prev;
  117 
  118 #if OPA_SIZEOF_INT == 8
  119     __asm__ __volatile__ ("mov ar.ccv=%1;;"
  120                           "cmpxchg8.rel %0=[%3],%4,ar.ccv"
  121                           : "=r"(prev), "=m"(ptr->v)
  122                           : "rO"(oldv), "r"(&ptr->v), "r"(newv)
  123                           : "memory");
  124     break;
  125 #elif OPA_SIZEOF_INT == 4
  126     __asm__ __volatile__ ("zxt4 %1=%1;;" /* don't want oldv sign-extended to 64 bits */
  127                           "mov ar.ccv=%1;;"
  128                           "cmpxchg4.rel %0=[%3],%4,ar.ccv"
  129                           : "=r"(prev), "=m"(ptr->v)
  130                           : "r0"(oldv), "r"(&ptr->v), "r"(newv)
  131                           : "memory");
  132 #else
  133 #error OPA_SIZEOF_INT is not 4 or 8
  134 #endif
  135 
  136     return prev;
  137 }
  138 
  139 /* IA64 has a fetch-and-add instruction that only accepts immediate
  140    values of -16, -8, -4, -1, 1, 4, 8, and 16.  So we check for these
  141    values before falling back to the CAS implementation. */
  142 #define OPA_IA64_FAA_CASE_MACRO(ptr, val) case val: {   \
  143     int prev;                                           \
  144     __asm__ __volatile__ ("fetchadd4.rel %0=[%2],%3"    \
  145                           : "=r"(prev), "=m"(ptr->v)    \
  146                           : "r"(&ptr->v), "i"(val));    \
  147     return prev;                                        \
  148     }                                                   \
  149     break
  150 
  151 
  152 static _opa_inline int OPA_fetch_and_add_int(OPA_int_t *ptr, int val)
  153 {
  154     switch (val)
  155     {
  156         OPA_IA64_FAA_CASE_MACRO(ptr, -16);
  157         OPA_IA64_FAA_CASE_MACRO(ptr,  -8);
  158         OPA_IA64_FAA_CASE_MACRO(ptr,  -4);
  159         OPA_IA64_FAA_CASE_MACRO(ptr,  -1);
  160         OPA_IA64_FAA_CASE_MACRO(ptr,   1);
  161         OPA_IA64_FAA_CASE_MACRO(ptr,   4);
  162         OPA_IA64_FAA_CASE_MACRO(ptr,   8);
  163         OPA_IA64_FAA_CASE_MACRO(ptr,  16);
  164     default:
  165         {
  166             int cmp;
  167             int prev = OPA_load_int(ptr);
  168 
  169             do {
  170                 cmp = prev;
  171                 prev = OPA_cas_int(ptr, cmp, val);
  172             } while (prev != cmp);
  173 
  174             return prev;
  175         }
  176     }
  177 }
  178 #undef OPA_IA64_FAA_CASE_MACRO
  179 
  180 
  181 static _opa_inline void *OPA_cas_ptr(OPA_ptr_t *ptr, void *oldv, void *newv)
  182 {
  183     void *prev;
  184     __asm__ __volatile__ ("mov ar.ccv=%1;;"
  185                           "cmpxchg8.rel %0=[%3],%4,ar.ccv"
  186                           : "=r"(prev), "=m"(ptr->v)
  187                           : "rO"(oldv), "r"(&ptr->v), "r"(newv));
  188     return prev;
  189 }
  190 
  191 static _opa_inline void *OPA_swap_ptr(OPA_ptr_t *ptr, void *val)
  192 {
  193     __asm__ __volatile__ ("xchg8 %0=[%2],%3"
  194                           : "=r" (val), "=m" (ptr->v)
  195                           : "r" (&ptr->v), "0" (val));
  196     return val;
  197 }
  198 
  199 
  200 static _opa_inline int OPA_swap_int(OPA_int_t *ptr, int val)
  201 {
  202     __asm__ __volatile__ ("xchg8 %0=[%2],%3"
  203                           : "=r" (val), "=m" (ptr->v)
  204                           : "r" (&ptr->v), "0" (val));
  205     return val;
  206 }
  207 
  208 
  209 #define OPA_write_barrier()      __asm__ __volatile__  ("mf" ::: "memory" )
  210 #define OPA_read_barrier()       __asm__ __volatile__  ("mf" ::: "memory" )
  211 #define OPA_read_write_barrier() __asm__ __volatile__  ("mf" ::: "memory" )
  212 #define OPA_compiler_barrier()   __asm__ __volatile__  (""   ::: "memory" )
  213 
  214 #include "opa_emulated.h"
  215 
  216 #endif /* OPA_GCC_IA64_H_INCLUDED */