The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm64/include/atomic.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2013 Andrew Turner <andrew@freebsd.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD: releng/11.2/sys/arm64/include/atomic.h 327195 2017-12-26 10:07:17Z kib $
   27  */
   28 
   29 #ifndef _MACHINE_ATOMIC_H_
   30 #define _MACHINE_ATOMIC_H_
   31 
   32 #include <sys/atomic_common.h>
   33 
   34 #define isb()           __asm __volatile("isb" : : : "memory")
   35 
   36 /*
   37  * Options for DMB and DSB:
   38  *      oshld   Outer Shareable, load
   39  *      oshst   Outer Shareable, store
   40  *      osh     Outer Shareable, all
   41  *      nshld   Non-shareable, load
   42  *      nshst   Non-shareable, store
   43  *      nsh     Non-shareable, all
   44  *      ishld   Inner Shareable, load
   45  *      ishst   Inner Shareable, store
   46  *      ish     Inner Shareable, all
   47  *      ld      Full system, load
   48  *      st      Full system, store
   49  *      sy      Full system, all
   50  */
   51 #define dsb(opt)        __asm __volatile("dsb " __STRING(opt) : : : "memory")
   52 #define dmb(opt)        __asm __volatile("dmb " __STRING(opt) : : : "memory")
   53 
   54 #define mb()    dmb(sy) /* Full system memory barrier all */
   55 #define wmb()   dmb(st) /* Full system memory barrier store */
   56 #define rmb()   dmb(ld) /* Full system memory barrier load */
   57 
   58 #define ATOMIC_OP(op, asm_op, bar, a, l)                                \
   59 static __inline void                                                    \
   60 atomic_##op##_##bar##32(volatile uint32_t *p, uint32_t val)             \
   61 {                                                                       \
   62         uint32_t tmp;                                                   \
   63         int res;                                                        \
   64                                                                         \
   65         __asm __volatile(                                               \
   66             "1: ld"#a"xr   %w0, [%2]      \n"                           \
   67             "   "#asm_op"  %w0, %w0, %w3  \n"                           \
   68             "   st"#l"xr   %w1, %w0, [%2] \n"                           \
   69             "   cbnz       %w1, 1b        \n"                           \
   70             : "=&r"(tmp), "=&r"(res)                                    \
   71             : "r" (p), "r" (val)                                        \
   72             : "memory"                                                  \
   73         );                                                              \
   74 }                                                                       \
   75                                                                         \
   76 static __inline void                                                    \
   77 atomic_##op##_##bar##64(volatile uint64_t *p, uint64_t val)             \
   78 {                                                                       \
   79         uint64_t tmp;                                                   \
   80         int res;                                                        \
   81                                                                         \
   82         __asm __volatile(                                               \
   83             "1: ld"#a"xr   %0, [%2]      \n"                            \
   84             "   "#asm_op"  %0, %0, %3    \n"                            \
   85             "   st"#l"xr   %w1, %0, [%2] \n"                            \
   86             "   cbnz       %w1, 1b       \n"                            \
   87             : "=&r"(tmp), "=&r"(res)                                    \
   88             : "r" (p), "r" (val)                                        \
   89             : "memory"                                                  \
   90         );                                                              \
   91 }
   92 
   93 #define ATOMIC(op, asm_op)                                              \
   94     ATOMIC_OP(op, asm_op,     ,  ,  )                                   \
   95     ATOMIC_OP(op, asm_op, acq_, a,  )                                   \
   96     ATOMIC_OP(op, asm_op, rel_,  , l)                                   \
   97 
   98 ATOMIC(add,      add)
   99 ATOMIC(clear,    bic)
  100 ATOMIC(set,      orr)
  101 ATOMIC(subtract, sub)
  102 
  103 #define ATOMIC_FCMPSET(bar, a, l)                                       \
  104 static __inline int                                                     \
  105 atomic_fcmpset_##bar##32(volatile uint32_t *p, uint32_t *cmpval,        \
  106     uint32_t newval)                                                    \
  107 {                                                                       \
  108         uint32_t tmp;                                                   \
  109         uint32_t _cmpval = *cmpval;                                     \
  110         int res;                                                        \
  111                                                                         \
  112         __asm __volatile(                                               \
  113             "1: mov      %w1, #1        \n"                             \
  114             "   ld"#a"xr %w0, [%2]      \n"                             \
  115             "   cmp      %w0, %w3       \n"                             \
  116             "   b.ne     2f             \n"                             \
  117             "   st"#l"xr %w1, %w4, [%2] \n"                             \
  118             "2:"                                                        \
  119             : "=&r"(tmp), "=&r"(res)                                    \
  120             : "r" (p), "r" (_cmpval), "r" (newval)                      \
  121             : "cc", "memory"                                            \
  122         );                                                              \
  123         *cmpval = tmp;                                                  \
  124                                                                         \
  125         return (!res);                                                  \
  126 }                                                                       \
  127                                                                         \
  128 static __inline int                                                     \
  129 atomic_fcmpset_##bar##64(volatile uint64_t *p, uint64_t *cmpval,        \
  130     uint64_t newval)                                                    \
  131 {                                                                       \
  132         uint64_t tmp;                                                   \
  133         uint64_t _cmpval = *cmpval;                                     \
  134         int res;                                                        \
  135                                                                         \
  136         __asm __volatile(                                               \
  137             "1: mov      %w1, #1       \n"                              \
  138             "   ld"#a"xr %0, [%2]      \n"                              \
  139             "   cmp      %0, %3        \n"                              \
  140             "   b.ne     2f            \n"                              \
  141             "   st"#l"xr %w1, %4, [%2] \n"                              \
  142             "2:"                                                        \
  143             : "=&r"(tmp), "=&r"(res)                                    \
  144             : "r" (p), "r" (_cmpval), "r" (newval)                      \
  145             : "cc", "memory"                                            \
  146         );                                                              \
  147         *cmpval = tmp;                                                  \
  148                                                                         \
  149         return (!res);                                                  \
  150 }
  151 
  152 ATOMIC_FCMPSET(    ,  , )
  153 ATOMIC_FCMPSET(acq_, a, )
  154 ATOMIC_FCMPSET(rel_,  ,l)
  155 
  156 #undef ATOMIC_FCMPSET
  157 
  158 #define ATOMIC_CMPSET(bar, a, l)                                        \
  159 static __inline int                                                     \
  160 atomic_cmpset_##bar##32(volatile uint32_t *p, uint32_t cmpval,          \
  161     uint32_t newval)                                                    \
  162 {                                                                       \
  163         uint32_t tmp;                                                   \
  164         int res;                                                        \
  165                                                                         \
  166         __asm __volatile(                                               \
  167             "1: mov      %w1, #1        \n"                             \
  168             "   ld"#a"xr %w0, [%2]      \n"                             \
  169             "   cmp      %w0, %w3       \n"                             \
  170             "   b.ne     2f             \n"                             \
  171             "   st"#l"xr %w1, %w4, [%2] \n"                             \
  172             "   cbnz     %w1, 1b        \n"                             \
  173             "2:"                                                        \
  174             : "=&r"(tmp), "=&r"(res)                                    \
  175             : "r" (p), "r" (cmpval), "r" (newval)                       \
  176             : "cc", "memory"                                                    \
  177         );                                                              \
  178                                                                         \
  179         return (!res);                                                  \
  180 }                                                                       \
  181                                                                         \
  182 static __inline int                                                     \
  183 atomic_cmpset_##bar##64(volatile uint64_t *p, uint64_t cmpval,          \
  184     uint64_t newval)                                                    \
  185 {                                                                       \
  186         uint64_t tmp;                                                   \
  187         int res;                                                        \
  188                                                                         \
  189         __asm __volatile(                                               \
  190             "1: mov      %w1, #1       \n"                              \
  191             "   ld"#a"xr %0, [%2]      \n"                              \
  192             "   cmp      %0, %3        \n"                              \
  193             "   b.ne     2f            \n"                              \
  194             "   st"#l"xr %w1, %4, [%2] \n"                              \
  195             "   cbnz     %w1, 1b       \n"                              \
  196             "2:"                                                        \
  197             : "=&r"(tmp), "=&r"(res)                                    \
  198             : "r" (p), "r" (cmpval), "r" (newval)                       \
  199             : "cc", "memory"                                                    \
  200         );                                                              \
  201                                                                         \
  202         return (!res);                                                  \
  203 }
  204 
  205 ATOMIC_CMPSET(    ,  , )
  206 ATOMIC_CMPSET(acq_, a, )
  207 ATOMIC_CMPSET(rel_,  ,l)
  208 
  209 static __inline uint32_t
  210 atomic_fetchadd_32(volatile uint32_t *p, uint32_t val)
  211 {
  212         uint32_t tmp, ret;
  213         int res;
  214 
  215         __asm __volatile(
  216             "1: ldxr    %w2, [%3]      \n"
  217             "   add     %w0, %w2, %w4  \n"
  218             "   stxr    %w1, %w0, [%3] \n"
  219             "   cbnz    %w1, 1b        \n"
  220             : "=&r"(tmp), "=&r"(res), "=&r"(ret)
  221             : "r" (p), "r" (val)
  222             : "memory"
  223         );
  224 
  225         return (ret);
  226 }
  227 
  228 static __inline uint64_t
  229 atomic_fetchadd_64(volatile uint64_t *p, uint64_t val)
  230 {
  231         uint64_t tmp, ret;
  232         int res;
  233 
  234         __asm __volatile(
  235             "1: ldxr    %2, [%3]      \n"
  236             "   add     %0, %2, %4    \n"
  237             "   stxr    %w1, %0, [%3] \n"
  238             "   cbnz    %w1, 1b       \n"
  239             : "=&r"(tmp), "=&r"(res), "=&r"(ret)
  240             : "r" (p), "r" (val)
  241             : "memory"
  242         );
  243 
  244         return (ret);
  245 }
  246 
  247 static __inline uint32_t
  248 atomic_readandclear_32(volatile uint32_t *p)
  249 {
  250         uint32_t ret;
  251         int res;
  252 
  253         __asm __volatile(
  254             "1: ldxr    %w1, [%2]      \n"
  255             "   stxr    %w0, wzr, [%2] \n"
  256             "   cbnz    %w0, 1b        \n"
  257             : "=&r"(res), "=&r"(ret)
  258             : "r" (p)
  259             : "memory"
  260         );
  261 
  262         return (ret);
  263 }
  264 
  265 static __inline uint64_t
  266 atomic_readandclear_64(volatile uint64_t *p)
  267 {
  268         uint64_t ret;
  269         int res;
  270 
  271         __asm __volatile(
  272             "1: ldxr    %1, [%2]      \n"
  273             "   stxr    %w0, xzr, [%2] \n"
  274             "   cbnz    %w0, 1b        \n"
  275             : "=&r"(res), "=&r"(ret)
  276             : "r" (p)
  277             : "memory"
  278         );
  279 
  280         return (ret);
  281 }
  282 
  283 static __inline uint32_t
  284 atomic_swap_32(volatile uint32_t *p, uint32_t val)
  285 {
  286         uint32_t ret;
  287         int res;
  288 
  289         __asm __volatile(
  290             "1: ldxr    %w0, [%2]      \n"
  291             "   stxr    %w1, %w3, [%2] \n"
  292             "   cbnz    %w1, 1b        \n"
  293             : "=&r"(ret), "=&r"(res)
  294             : "r" (p), "r" (val)
  295             : "memory"
  296         );
  297 
  298         return (ret);
  299 }
  300 
  301 static __inline uint64_t
  302 atomic_swap_64(volatile uint64_t *p, uint64_t val)
  303 {
  304         uint64_t ret;
  305         int res;
  306 
  307         __asm __volatile(
  308             "1: ldxr    %0, [%2]      \n"
  309             "   stxr    %w1, %3, [%2] \n"
  310             "   cbnz    %w1, 1b       \n"
  311             : "=&r"(ret), "=&r"(res)
  312             : "r" (p), "r" (val)
  313             : "memory"
  314         );
  315 
  316         return (ret);
  317 }
  318 
  319 static __inline uint32_t
  320 atomic_load_acq_32(volatile uint32_t *p)
  321 {
  322         uint32_t ret;
  323 
  324         __asm __volatile(
  325             "ldar       %w0, [%1] \n"
  326             : "=&r" (ret)
  327             : "r" (p)
  328             : "memory");
  329 
  330         return (ret);
  331 }
  332 
  333 static __inline uint64_t
  334 atomic_load_acq_64(volatile uint64_t *p)
  335 {
  336         uint64_t ret;
  337 
  338         __asm __volatile(
  339             "ldar       %0, [%1] \n"
  340             : "=&r" (ret)
  341             : "r" (p)
  342             : "memory");
  343 
  344         return (ret);
  345 }
  346 
  347 static __inline void
  348 atomic_store_rel_32(volatile uint32_t *p, uint32_t val)
  349 {
  350 
  351         __asm __volatile(
  352             "stlr       %w0, [%1] \n"
  353             :
  354             : "r" (val), "r" (p)
  355             : "memory");
  356 }
  357 
  358 static __inline void
  359 atomic_store_rel_64(volatile uint64_t *p, uint64_t val)
  360 {
  361 
  362         __asm __volatile(
  363             "stlr       %0, [%1] \n"
  364             :
  365             : "r" (val), "r" (p)
  366             : "memory");
  367 }
  368 
  369 
  370 #define atomic_add_int                  atomic_add_32
  371 #define atomic_fcmpset_int              atomic_fcmpset_32
  372 #define atomic_clear_int                atomic_clear_32
  373 #define atomic_cmpset_int               atomic_cmpset_32
  374 #define atomic_fetchadd_int             atomic_fetchadd_32
  375 #define atomic_readandclear_int         atomic_readandclear_32
  376 #define atomic_set_int                  atomic_set_32
  377 #define atomic_swap_int                 atomic_swap_32
  378 #define atomic_subtract_int             atomic_subtract_32
  379 
  380 #define atomic_add_acq_int              atomic_add_acq_32
  381 #define atomic_fcmpset_acq_int          atomic_fcmpset_acq_32
  382 #define atomic_clear_acq_int            atomic_clear_acq_32
  383 #define atomic_cmpset_acq_int           atomic_cmpset_acq_32
  384 #define atomic_load_acq_int             atomic_load_acq_32
  385 #define atomic_set_acq_int              atomic_set_acq_32
  386 #define atomic_subtract_acq_int         atomic_subtract_acq_32
  387 
  388 #define atomic_add_rel_int              atomic_add_rel_32
  389 #define atomic_fcmpset_rel_int          atomic_fcmpset_rel_32
  390 #define atomic_clear_rel_int            atomic_clear_rel_32
  391 #define atomic_cmpset_rel_int           atomic_cmpset_rel_32
  392 #define atomic_set_rel_int              atomic_set_rel_32
  393 #define atomic_subtract_rel_int         atomic_subtract_rel_32
  394 #define atomic_store_rel_int            atomic_store_rel_32
  395 
  396 #define atomic_add_long                 atomic_add_64
  397 #define atomic_fcmpset_long             atomic_fcmpset_64
  398 #define atomic_clear_long               atomic_clear_64
  399 #define atomic_cmpset_long              atomic_cmpset_64
  400 #define atomic_fetchadd_long            atomic_fetchadd_64
  401 #define atomic_readandclear_long        atomic_readandclear_64
  402 #define atomic_set_long                 atomic_set_64
  403 #define atomic_swap_long                atomic_swap_64
  404 #define atomic_subtract_long            atomic_subtract_64
  405 
  406 #define atomic_add_ptr                  atomic_add_64
  407 #define atomic_fcmpset_ptr              atomic_fcmpset_64
  408 #define atomic_clear_ptr                atomic_clear_64
  409 #define atomic_cmpset_ptr               atomic_cmpset_64
  410 #define atomic_fetchadd_ptr             atomic_fetchadd_64
  411 #define atomic_readandclear_ptr         atomic_readandclear_64
  412 #define atomic_set_ptr                  atomic_set_64
  413 #define atomic_swap_ptr                 atomic_swap_64
  414 #define atomic_subtract_ptr             atomic_subtract_64
  415 
  416 #define atomic_add_acq_long             atomic_add_acq_64
  417 #define atomic_fcmpset_acq_long         atomic_fcmpset_acq_64
  418 #define atomic_clear_acq_long           atomic_clear_acq_64
  419 #define atomic_cmpset_acq_long          atomic_cmpset_acq_64
  420 #define atomic_load_acq_long            atomic_load_acq_64
  421 #define atomic_set_acq_long             atomic_set_acq_64
  422 #define atomic_subtract_acq_long        atomic_subtract_acq_64
  423 
  424 #define atomic_add_acq_ptr              atomic_add_acq_64
  425 #define atomic_fcmpset_acq_ptr          atomic_fcmpset_acq_64
  426 #define atomic_clear_acq_ptr            atomic_clear_acq_64
  427 #define atomic_cmpset_acq_ptr           atomic_cmpset_acq_64
  428 #define atomic_load_acq_ptr             atomic_load_acq_64
  429 #define atomic_set_acq_ptr              atomic_set_acq_64
  430 #define atomic_subtract_acq_ptr         atomic_subtract_acq_64
  431 
  432 #define atomic_add_rel_long             atomic_add_rel_64
  433 #define atomic_fcmpset_rel_long         atomic_fcmpset_rel_64
  434 #define atomic_clear_rel_long           atomic_clear_rel_64
  435 #define atomic_cmpset_rel_long          atomic_cmpset_rel_64
  436 #define atomic_set_rel_long             atomic_set_rel_64
  437 #define atomic_subtract_rel_long        atomic_subtract_rel_64
  438 #define atomic_store_rel_long           atomic_store_rel_64
  439 
  440 #define atomic_add_rel_ptr              atomic_add_rel_64
  441 #define atomic_fcmpset_rel_ptr          atomic_fcmpset_rel_64
  442 #define atomic_clear_rel_ptr            atomic_clear_rel_64
  443 #define atomic_cmpset_rel_ptr           atomic_cmpset_rel_64
  444 #define atomic_set_rel_ptr              atomic_set_rel_64
  445 #define atomic_subtract_rel_ptr         atomic_subtract_rel_64
  446 #define atomic_store_rel_ptr            atomic_store_rel_64
  447 
  448 static __inline void
  449 atomic_thread_fence_acq(void)
  450 {
  451 
  452         dmb(ld);
  453 }
  454 
  455 static __inline void
  456 atomic_thread_fence_rel(void)
  457 {
  458 
  459         dmb(sy);
  460 }
  461 
  462 static __inline void
  463 atomic_thread_fence_acq_rel(void)
  464 {
  465 
  466         dmb(sy);
  467 }
  468 
  469 static __inline void
  470 atomic_thread_fence_seq_cst(void)
  471 {
  472 
  473         dmb(sy);
  474 }
  475 
  476 #endif /* _MACHINE_ATOMIC_H_ */
  477 

Cache object: c9a4824dd1a439b413adb4aee42d13a9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.