"Fossies" - the Fresh Open Source Software Archive

Member "openpa-1.0.4/src/primitives/opa_gcc_sicortex.h" (5 Dec 2012, 18617 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_sicortex.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 /* Atomic primitives for SiCortex machines.
    8  * Originally contributed by Lawrence Stewart at SiCortex.
    9  */
   10 
   11 #ifndef OPA_GCC_SICORTEX_H
   12 #define OPA_GCC_SICORTEX_H
   13 
   14 /* FIXME do these need alignment? */
   15 typedef struct { volatile int v;  } OPA_int_t;
   16 typedef struct { int * volatile v; } OPA_ptr_t;
   17 
   18 #define OPA_INT_T_INITIALIZER(val_) { (val_) }
   19 #define OPA_PTR_T_INITIALIZER(val_) { (val_) }
   20 
   21 #define OPA_write_barrier()      __asm__ __volatile__  ("sync" ::: "memory" )
   22 #define OPA_read_barrier()       __asm__ __volatile__  ("sync" ::: "memory" )
   23 #define OPA_read_write_barrier() __asm__ __volatile__  ("sync" ::: "memory" )
   24 #define OPA_compiler_barrier()   __asm__ __volatile__  ( ""    ::: "memory" )
   25 
   26 /* Aligned loads and stores are atomic. */
   27 static _opa_inline int OPA_load_int(_opa_const OPA_int_t *ptr)
   28 {
   29     return ptr->v;
   30 }
   31 
   32 /* Aligned loads and stores are atomic. */
   33 static _opa_inline void OPA_store_int(OPA_int_t *ptr, int val)
   34 {
   35     ptr->v = val;
   36 }
   37 
   38 /* Aligned loads and stores are atomic. */
   39 static _opa_inline void *OPA_load_ptr(_opa_const OPA_ptr_t *ptr)
   40 {
   41     return ptr->v;
   42 }
   43 
   44 /* Aligned loads and stores are atomic. */
   45 static _opa_inline void OPA_store_ptr(OPA_ptr_t *ptr, void *val)
   46 {
   47     ptr->v = val;
   48 }
   49 
   50 /* NOTE: these acquire/release operations have not been optimized, I just threw
   51  * down a full memory barrier.  Spending much time working on the SiCortex platform
   52  * doesn't really make a lot of sense since there are so few machines in
   53  * existence and no more will ever be built. */
   54 static _opa_inline int OPA_load_acquire_int(_opa_const OPA_int_t *ptr)
   55 {
   56     int tmp;
   57     tmp = ptr->v;
   58     OPA_read_write_barrier();
   59     return tmp;
   60 }
   61 
   62 static _opa_inline void OPA_store_release_int(OPA_int_t *ptr, int val)
   63 {
   64     OPA_read_write_barrier();
   65     ptr->v = val;
   66 }
   67 
   68 static _opa_inline void *OPA_load_acquire_ptr(_opa_const OPA_ptr_t *ptr)
   69 {
   70     void *tmp;
   71     tmp = ptr->v;
   72     OPA_read_write_barrier();
   73     return tmp;
   74 }
   75 
   76 static _opa_inline void OPA_store_release_ptr(OPA_ptr_t *ptr, void *val)
   77 {
   78     OPA_read_write_barrier();
   79     ptr->v = val;
   80 }
   81 
   82 #include <stdint.h>
   83 
   84 /* ICE9 rev A1 chips have a low-frequency bug that causes LL to
   85    fail. The workaround is to do the LL twice to make sure the data
   86    is in L1
   87 
   88    very few systems are affected
   89 
   90    FIXME We should either remove the workaround entirely or make it
   91    configurable/autodetected somehow. [goodell@ 2008/01/06]
   92  */
   93 #define ICE9A_LLSC_WAR 0
   94 
   95 /* For a description of the _opa_inline assembly constraints, see the MIPS section of:
   96    http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Machine-Constraints.html#Machine-Constraints
   97 
   98    relevant excerpt:
   99        I - A signed 16-bit constant (for arithmetic instructions).
  100        J - Integer zero.
  101 
  102    Other _opa_inline asm knowledge worth remembering:
  103        r - a general register operand is allowed
  104        m - a memory address operand
  105        & - earlyclobber; operand is modified before instruction is finished using the input operands
  106        = - this operand is write-only
  107 
  108    general format:
  109        asm volatile ("instructions" : [outputs] : [inputs] : [clobbered_regs]);
  110        "memory" should be included as a clobbered reg for most of these operations.
  111  */
  112 
  113 /* Atomic increment of a 32 bit value, returning the old value */
  114 static _opa_inline int OPA_shmemi_fetch_add_4(volatile int * v, int inc)
  115 {
  116         unsigned long result;
  117         if (ICE9A_LLSC_WAR) {
  118                 unsigned long temp;
  119 
  120                 __asm__ __volatile__(
  121                 "       .set    mips3                                   \n"
  122                 "       .set    noreorder                               \n"
  123                 "1:     ll      %0, %2          # fetch_add_4           \n"
  124                 "       ll      %0, %2          # fetch_add_4           \n"
  125                 "       addu    %1, %0, %3                              \n"
  126                 "       sc      %1, %2                                  \n"
  127                 "       beqz    %1, 1b                                  \n"
  128                 "        nop                                            \n"
  129                 "       .set    reorder                                 \n"
  130                 "       .set    mips0                                   \n"
  131                 : "=&r" (result), "=&r" (temp), "=m" (*v)
  132                 : "Ir" (inc)
  133                 : "memory");
  134         } else {
  135                 unsigned long temp;
  136 
  137                 __asm__ __volatile__(
  138                 "       .set    mips3                                   \n"
  139                 "       .set    noreorder                               \n"
  140                 "1:     ll      %0, %2          # fetch_add_4           \n"
  141                 "       addu    %1, %0, %3                              \n"
  142                 "       sc      %1, %2                                  \n"
  143                 "       beqz    %1, 1b                                  \n"
  144                 "        nop                                            \n"
  145                 "       .set    reorder                                 \n"
  146                 "       .set    mips0                                   \n"
  147                 : "=&r" (result), "=&r" (temp), "=m" (*v)
  148                 : "Ir" (inc)
  149                 : "memory");
  150         }
  151 
  152         return result;
  153 }
  154 
  155 /* Atomic increment of a 64 bit value, returning the old value */
  156 static _opa_inline long int OPA_shmemi_fetch_add_8(volatile long int * v, long int inc)
  157 {
  158         unsigned long result;
  159         if (ICE9A_LLSC_WAR) {
  160                 unsigned long temp;
  161 
  162                 __asm__ __volatile__(
  163                 "       .set    mips3                                   \n"
  164                 "       .set    noreorder                               \n"
  165                 "1:     lld     %0, %2          # fetch_add_8           \n"
  166                 "       lld     %0, %2          # fetch_add_8           \n"
  167                 "       daddu   %1, %0, %3                              \n"
  168                 "       scd     %1, %2                                  \n"
  169                 "       beqz    %1, 1b                                  \n"
  170                 "        nop                                            \n"
  171                 "       .set    reorder                                 \n"
  172                 "       .set    mips0                                   \n"
  173                 : "=&r" (result), "=&r" (temp), "=m" (*v)
  174                 : "Ir" (inc)
  175                 : "memory");
  176         } else {
  177                 unsigned long temp;
  178 
  179                 __asm__ __volatile__(
  180                 "       .set    mips3                                   \n"
  181                 "       .set    noreorder                               \n"
  182                 "1:     lld     %0, %2          # fetch_add_8           \n"
  183                 "       daddu   %1, %0, %3                              \n"
  184                 "       scd     %1, %2                                  \n"
  185                 "       beqz    %1, 1b                                  \n"
  186                 "        nop                                            \n"
  187                 "       .set    reorder                                 \n"
  188                 "       .set    mips0                                   \n"
  189                 : "=&r" (result), "=&r" (temp), "=m" (*v)
  190                 : "Ir" (inc)
  191                 : "memory");
  192         }
  193 
  194         return result;
  195 }
  196 
  197 /* Atomic swap of a 32 bit value, returning the old contents */
  198 static _opa_inline int OPA_shmemi_swap_4(volatile int * v, int val)
  199 {
  200         unsigned long result;
  201         if (ICE9A_LLSC_WAR) {
  202                 unsigned long temp;
  203 
  204                 __asm__ __volatile__(
  205                 "       .set    mips3                                   \n"
  206                 "       .set    noreorder                               \n"
  207                 "1:     ll      %0, %2          # swap_4                \n"
  208                 "       ll      %0, %2          # swap_4                \n"
  209                 "       move    %1, %3                                  \n"
  210                 "       sc      %1, %2                                  \n"
  211                 "       beqz    %1, 1b                                  \n"
  212                 "        nop                                            \n"
  213                 "       .set    reorder                                 \n"
  214                 "       .set    mips0                                   \n"
  215                 : "=&r" (result), "=&r" (temp), "=m" (*v)
  216                 : "r" (val)
  217                 : "memory");
  218         } else {
  219                 unsigned long temp;
  220 
  221                 __asm__ __volatile__(
  222                 "       .set    mips3                                   \n"
  223                 "       .set    noreorder                               \n"
  224                 "1:     ll      %0, %2          # swap_4                \n"
  225                 "       move    %1, %3                                  \n"
  226                 "       sc      %1, %2                                  \n"
  227                 "       beqz    %1, 1b                                  \n"
  228                 "        nop                                            \n"
  229                 "       .set    reorder                                 \n"
  230                 "       .set    mips0                                   \n"
  231                 : "=&r" (result), "=&r" (temp), "=m" (*v)
  232                 : "r" (val)
  233                 : "memory");
  234         }
  235 
  236         return result;
  237 }
  238 
  239 /* Atomic swap of a 64 bit value, returning the old contents */
  240 static _opa_inline long int OPA_shmemi_swap_8(volatile long int * v, long int val)
  241 {
  242         unsigned long result;
  243         if (ICE9A_LLSC_WAR) {
  244                 unsigned long temp;
  245 
  246                 __asm__ __volatile__(
  247                 "       .set    mips3                                   \n"
  248                 "       .set    noreorder                               \n"
  249                 "1:     lld     %0, %2          # swap_8                \n"
  250                 "       lld     %0, %2          # swap_8                \n"
  251                 "       move    %1, %3                                  \n"
  252                 "       scd     %1, %2                                  \n"
  253                 "       beqz    %1, 1b                                  \n"
  254                 "        nop                                            \n"
  255                 "       .set    reorder                                 \n"
  256                 "       .set    mips0                                   \n"
  257                 : "=&r" (result), "=&r" (temp), "=m" (*v)
  258                 : "r" (val)
  259                 : "memory");
  260         } else {
  261                 unsigned long temp;
  262 
  263                 __asm__ __volatile__(
  264                 "       .set    mips3                                   \n"
  265                 "       .set    noreorder                               \n"
  266                 "1:     lld     %0, %2          # swap_8                \n"
  267                 "       move    %1, %3                                  \n"
  268                 "       scd     %1, %2                                  \n"
  269                 "       beqz    %1, 1b                                  \n"
  270                 "        nop                                            \n"
  271                 "       .set    reorder                                 \n"
  272                 "       .set    mips0                                   \n"
  273                 : "=&r" (result), "=&r" (temp), "=m" (*v)
  274                 : "r" (val)
  275                 : "memory");
  276         }
  277 
  278         return result;
  279 }
  280 
  281 /* Atomic compare and swap of a 32 bit value, returns the old value
  282  * but only does the store of the val value if the old value == expect */
  283 static _opa_inline int OPA_shmemi_cswap_4(volatile int * v, int expect, int val)
  284 {
  285         unsigned long result;
  286         if (ICE9A_LLSC_WAR) {
  287                 unsigned long temp;
  288 
  289                 __asm__ __volatile__(
  290                 "       .set    mips3                                   \n"
  291                 "       .set    noreorder                               \n"
  292                 "1:     ll      %0, %2          # cswap_4               \n"
  293                 "       ll      %0, %2          # cswap_4               \n"
  294                 "       bne     %0, %4, 1f                              \n"
  295                 "       move    %1, %3                                  \n"
  296                 "       sc      %1, %2                                  \n"
  297                 "       beqz    %1, 1b                                  \n"
  298                 "        nop                                            \n"
  299                 "       .set    reorder                                 \n"
  300                 "1:                                                     \n"
  301                 "       .set    mips0                                   \n"
  302                 : "=&r" (result), "=&r" (temp), "=m" (*v)
  303                 : "r" (val), "Jr" (expect)
  304                 : "memory");
  305         } else {
  306                 unsigned long temp;
  307 
  308                 __asm__ __volatile__(
  309                 "       .set    mips3                                   \n"
  310                 "       .set    noreorder                               \n"
  311                 "1:     ll      %0, %2          # cswap_4               \n"
  312                 "       bne     %0, %4, 1f                              \n"
  313                 "       move    %1, %3                                  \n"
  314                 "       sc      %1, %2                                  \n"
  315                 "       beqz    %1, 1b                                  \n"
  316                 "        nop                                            \n"
  317                 "       .set    reorder                                 \n"
  318                 "1:                                                     \n"
  319                 "       .set    mips0                                   \n"
  320                 : "=&r" (result), "=&r" (temp), "=m" (*v)
  321                 : "r" (val), "Jr" (expect)
  322                 : "memory");
  323         }
  324 
  325         return result;
  326 }
  327 
  328 /* Atomic compare and swap of a 64 bit value, returns the old value
  329  * but only does the store of the val value if the old value == expect */
  330 static _opa_inline long int OPA_shmemi_cswap_8(volatile long int * v, long int expect, long int val)
  331 {
  332         unsigned long result;
  333         if (ICE9A_LLSC_WAR) {
  334                 unsigned long temp;
  335 
  336                 __asm__ __volatile__(
  337                 "       .set    mips3                                   \n"
  338                 "       .set    noreorder                               \n"
  339                 "1:     lld     %0, %2          # cswap_8               \n"
  340                 "       lld     %0, %2          # cswap_8               \n"
  341                 "       bne     %0, %4, 1f                              \n"
  342                 "       move    %1, %3                                  \n"
  343                 "       scd     %1, %2                                  \n"
  344                 "       beqz    %1, 1b                                  \n"
  345                 "        nop                                            \n"
  346                 "       .set    reorder                                 \n"
  347                 "1:                                                     \n"
  348                 "       .set    mips0                                   \n"
  349                 : "=&r" (result), "=&r" (temp), "=m" (*v)
  350                 : "r" (val), "Jr" (expect)
  351                 : "memory");
  352         } else {
  353                 unsigned long temp;
  354 
  355                 __asm__ __volatile__(
  356                 "       .set    mips3                                   \n"
  357                 "       .set    noreorder                               \n"
  358                 "1:     lld     %0, %2          # cswap_8               \n"
  359                 "       bne     %0, %4, 1f                              \n"
  360                 "       move    %1, %3                                  \n"
  361                 "       scd     %1, %2                                  \n"
  362                 "       beqz    %1, 1b                                  \n"
  363                 "        nop                                            \n"
  364                 "       .set    reorder                                 \n"
  365                 "1:                                                     \n"
  366                 "       .set    mips0                                   \n"
  367                 : "=&r" (result), "=&r" (temp), "=m" (*v)
  368                 : "r" (val), "Jr" (expect)
  369                 : "memory");
  370         }
  371 
  372         return result;
  373 }
  374 
  375 static _opa_inline void OPA_add_int(OPA_int_t *ptr, int val)
  376 {
  377     OPA_shmemi_fetch_add_4(&ptr->v, val);
  378 }
  379 
  380 static _opa_inline void *OPA_cas_ptr(OPA_ptr_t *ptr, void *oldv, void *newv)
  381 {
  382 #if (OPA_SIZEOF_VOID_P == 8)
  383     return((int *) OPA_shmemi_cswap_8((volatile long int *) &ptr->v, (uintptr_t) oldv, (uintptr_t) newv));
  384 #elif (OPA_SIZEOF_VOID_P == 4)
  385     return((int *) OPA_shmemi_cswap_4((volatile int *) &ptr->v, (uintptr_t) oldv, (uintptr_t) newv));
  386 #else
  387 #error "OPA_SIZEOF_VOID_P has an unexpected value :" OPA_QUOTE(OPA_SIZEOF_VOID_P);
  388 #endif
  389 }
  390 
  391 static _opa_inline int OPA_cas_int(OPA_int_t *ptr, int oldv, int newv)
  392 {
  393     return(OPA_shmemi_cswap_4(&ptr->v, oldv, newv));
  394 }
  395 
  396 static _opa_inline void OPA_decr_int(OPA_int_t *ptr)
  397 {
  398     OPA_shmemi_fetch_add_4(&ptr->v, -1);
  399 }
  400 
  401 static _opa_inline int OPA_decr_and_test_int(OPA_int_t *ptr)
  402 {
  403     int old = OPA_shmemi_fetch_add_4(&ptr->v, -1);
  404     return (old == 1);
  405 }
  406 
  407 static _opa_inline int OPA_fetch_and_add_int(OPA_int_t *ptr, int val)
  408 {
  409     return(OPA_shmemi_fetch_add_4(&ptr->v, val));
  410 }
  411 
  412 static _opa_inline int OPA_fetch_and_decr_int(OPA_int_t *ptr)
  413 {
  414     return(OPA_shmemi_fetch_add_4(&ptr->v, -1));
  415 }
  416 
  417 static _opa_inline int OPA_fetch_and_incr_int(OPA_int_t *ptr)
  418 {
  419     return(OPA_shmemi_fetch_add_4(&ptr->v, 1));
  420 }
  421 
  422 static _opa_inline void OPA_incr_int(OPA_int_t *ptr)
  423 {
  424     OPA_shmemi_fetch_add_4(&ptr->v, 1);
  425 }
  426 
  427 static _opa_inline int *OPA_swap_ptr(OPA_ptr_t *ptr, int *val)
  428 {
  429 #if (OPA_SIZEOF_VOID_P == 8)
  430     return((int *) OPA_shmemi_swap_8((volatile long int *) &ptr->v, (uintptr_t) val));
  431 #elif (OPA_SIZEOF_VOID_P == 4)
  432     return((int *) OPA_shmemi_swap_4((volatile int *) &ptr->v, (uintptr_t) val));
  433 #else
  434 #error "OPA_SIZEOF_VOID_P has an unexpected value :" OPA_QUOTE(OPA_SIZEOF_VOID_P);
  435 #endif
  436 }
  437 
  438 static _opa_inline int OPA_swap_int(OPA_int_t *ptr, int val)
  439 {
  440     return(OPA_shmemi_swap_4(&ptr->v, val));
  441 }
  442 
  443 #endif /* OPA_GCC_SICORTEX_H */