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/riscv/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) 2015 Ruslan Bukin <br@bsdpad.com>
    3  * All rights reserved.
    4  *
    5  * Portions of this software were developed by SRI International and the
    6  * University of Cambridge Computer Laboratory under DARPA/AFRL contract
    7  * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
    8  *
    9  * Portions of this software were developed by the University of Cambridge
   10  * Computer Laboratory as part of the CTSRD Project, with support from the
   11  * UK Higher Education Innovation Fund (HEIF).
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  * $FreeBSD$
   35  */
   36 
   37 #ifndef _MACHINE_ATOMIC_H_
   38 #define _MACHINE_ATOMIC_H_
   39 
   40 #include <sys/atomic_common.h>
   41 
   42 #define fence() __asm __volatile("fence" ::: "memory");
   43 #define mb()    fence()
   44 #define rmb()   fence()
   45 #define wmb()   fence()
   46 
   47 static __inline int atomic_cmpset_8(__volatile uint8_t *, uint8_t, uint8_t);
   48 static __inline int atomic_fcmpset_8(__volatile uint8_t *, uint8_t *, uint8_t);
   49 static __inline int atomic_cmpset_16(__volatile uint16_t *, uint16_t, uint16_t);
   50 static __inline int atomic_fcmpset_16(__volatile uint16_t *, uint16_t *,
   51     uint16_t);
   52 
   53 #define ATOMIC_ACQ_REL(NAME, WIDTH)                                     \
   54 static __inline  void                                                   \
   55 atomic_##NAME##_acq_##WIDTH(__volatile uint##WIDTH##_t *p, uint##WIDTH##_t v)\
   56 {                                                                       \
   57         atomic_##NAME##_##WIDTH(p, v);                                  \
   58         fence();                                                        \
   59 }                                                                       \
   60                                                                         \
   61 static __inline  void                                                   \
   62 atomic_##NAME##_rel_##WIDTH(__volatile uint##WIDTH##_t *p, uint##WIDTH##_t v)\
   63 {                                                                       \
   64         fence();                                                        \
   65         atomic_##NAME##_##WIDTH(p, v);                                  \
   66 }
   67 
   68 #define ATOMIC_CMPSET_ACQ_REL(WIDTH)                                    \
   69 static __inline  int                                                    \
   70 atomic_cmpset_acq_##WIDTH(__volatile uint##WIDTH##_t *p,                \
   71     uint##WIDTH##_t cmpval, uint##WIDTH##_t newval)                     \
   72 {                                                                       \
   73         int retval;                                                     \
   74                                                                         \
   75         retval = atomic_cmpset_##WIDTH(p, cmpval, newval);              \
   76         fence();                                                        \
   77         return (retval);                                                \
   78 }                                                                       \
   79                                                                         \
   80 static __inline  int                                                    \
   81 atomic_cmpset_rel_##WIDTH(__volatile uint##WIDTH##_t *p,                \
   82     uint##WIDTH##_t cmpval, uint##WIDTH##_t newval)                     \
   83 {                                                                       \
   84         fence();                                                        \
   85         return (atomic_cmpset_##WIDTH(p, cmpval, newval));              \
   86 }
   87 
   88 #define ATOMIC_FCMPSET_ACQ_REL(WIDTH)                                   \
   89 static __inline  int                                                    \
   90 atomic_fcmpset_acq_##WIDTH(__volatile uint##WIDTH##_t *p,               \
   91     uint##WIDTH##_t *cmpval, uint##WIDTH##_t newval)                    \
   92 {                                                                       \
   93         int retval;                                                     \
   94                                                                         \
   95         retval = atomic_fcmpset_##WIDTH(p, cmpval, newval);             \
   96         fence();                                                        \
   97         return (retval);                                                \
   98 }                                                                       \
   99                                                                         \
  100 static __inline  int                                                    \
  101 atomic_fcmpset_rel_##WIDTH(__volatile uint##WIDTH##_t *p,               \
  102     uint##WIDTH##_t *cmpval, uint##WIDTH##_t newval)                    \
  103 {                                                                       \
  104         fence();                                                        \
  105         return (atomic_fcmpset_##WIDTH(p, cmpval, newval));             \
  106 }
  107 
  108 ATOMIC_CMPSET_ACQ_REL(8);
  109 ATOMIC_FCMPSET_ACQ_REL(8);
  110 ATOMIC_CMPSET_ACQ_REL(16);
  111 ATOMIC_FCMPSET_ACQ_REL(16);
  112 
  113 #define atomic_cmpset_char              atomic_cmpset_8
  114 #define atomic_cmpset_acq_char          atomic_cmpset_acq_8
  115 #define atomic_cmpset_rel_char          atomic_cmpset_rel_8
  116 #define atomic_fcmpset_char             atomic_fcmpset_8
  117 #define atomic_fcmpset_acq_char         atomic_fcmpset_acq_8
  118 #define atomic_fcmpset_rel_char         atomic_fcmpset_rel_8
  119 
  120 #define atomic_cmpset_short             atomic_cmpset_16
  121 #define atomic_cmpset_acq_short         atomic_cmpset_acq_16
  122 #define atomic_cmpset_rel_short         atomic_cmpset_rel_16
  123 #define atomic_fcmpset_short            atomic_fcmpset_16
  124 #define atomic_fcmpset_acq_short        atomic_fcmpset_acq_16
  125 #define atomic_fcmpset_rel_short        atomic_fcmpset_rel_16
  126 
  127 static __inline void
  128 atomic_add_32(volatile uint32_t *p, uint32_t val)
  129 {
  130 
  131         __asm __volatile("amoadd.w zero, %1, %0"
  132                         : "+A" (*p)
  133                         : "r" (val)
  134                         : "memory");
  135 }
  136 
  137 static __inline void
  138 atomic_subtract_32(volatile uint32_t *p, uint32_t val)
  139 {
  140 
  141         __asm __volatile("amoadd.w zero, %1, %0"
  142                         : "+A" (*p)
  143                         : "r" (-val)
  144                         : "memory");
  145 }
  146 
  147 static __inline void
  148 atomic_set_32(volatile uint32_t *p, uint32_t val)
  149 {
  150 
  151         __asm __volatile("amoor.w zero, %1, %0"
  152                         : "+A" (*p)
  153                         : "r" (val)
  154                         : "memory");
  155 }
  156 
  157 static __inline void
  158 atomic_clear_32(volatile uint32_t *p, uint32_t val)
  159 {
  160 
  161         __asm __volatile("amoand.w zero, %1, %0"
  162                         : "+A" (*p)
  163                         : "r" (~val)
  164                         : "memory");
  165 }
  166 
  167 static __inline int
  168 atomic_cmpset_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval)
  169 {
  170         uint32_t tmp;
  171         int res;
  172 
  173         res = 0;
  174 
  175         __asm __volatile(
  176                 "0:"
  177                         "li   %1, 1\n" /* Preset to fail */
  178                         "lr.w %0, %2\n"
  179                         "bne  %0, %z3, 1f\n"
  180                         "sc.w %1, %z4, %2\n"
  181                         "bnez %1, 0b\n"
  182                 "1:"
  183                         : "=&r" (tmp), "=&r" (res), "+A" (*p)
  184                         : "rJ" ((long)(int32_t)cmpval), "rJ" (newval)
  185                         : "memory");
  186 
  187         return (!res);
  188 }
  189 
  190 static __inline int
  191 atomic_fcmpset_32(volatile uint32_t *p, uint32_t *cmpval, uint32_t newval)
  192 {
  193         uint32_t tmp;
  194         int res;
  195 
  196         res = 0;
  197 
  198         __asm __volatile(
  199                 "0:"
  200                         "li   %1, 1\n"          /* Preset to fail */
  201                         "lr.w %0, %2\n"         /* Load old value */
  202                         "bne  %0, %z4, 1f\n"    /* Compare */
  203                         "sc.w %1, %z5, %2\n"    /* Try to store new value */
  204                         "j 2f\n"
  205                 "1:"
  206                         "sw   %0, %3\n"         /* Save old value */
  207                 "2:"
  208                         : "=&r" (tmp), "=&r" (res), "+A" (*p), "+A" (*cmpval)
  209                         : "rJ" ((long)(int32_t)*cmpval), "rJ" (newval)
  210                         : "memory");
  211 
  212         return (!res);
  213 }
  214 
  215 static __inline uint32_t
  216 atomic_fetchadd_32(volatile uint32_t *p, uint32_t val)
  217 {
  218         uint32_t ret;
  219 
  220         __asm __volatile("amoadd.w %0, %2, %1"
  221                         : "=&r" (ret), "+A" (*p)
  222                         : "r" (val)
  223                         : "memory");
  224 
  225         return (ret);
  226 }
  227 
  228 static __inline uint32_t
  229 atomic_readandclear_32(volatile uint32_t *p)
  230 {
  231         uint32_t ret;
  232         uint32_t val;
  233 
  234         val = 0;
  235 
  236         __asm __volatile("amoswap.w %0, %2, %1"
  237                         : "=&r"(ret), "+A" (*p)
  238                         : "r" (val)
  239                         : "memory");
  240 
  241         return (ret);
  242 }
  243 
  244 #define atomic_add_int          atomic_add_32
  245 #define atomic_clear_int        atomic_clear_32
  246 #define atomic_cmpset_int       atomic_cmpset_32
  247 #define atomic_fcmpset_int      atomic_fcmpset_32
  248 #define atomic_fetchadd_int     atomic_fetchadd_32
  249 #define atomic_readandclear_int atomic_readandclear_32
  250 #define atomic_set_int          atomic_set_32
  251 #define atomic_subtract_int     atomic_subtract_32
  252 
  253 ATOMIC_ACQ_REL(set, 32)
  254 ATOMIC_ACQ_REL(clear, 32)
  255 ATOMIC_ACQ_REL(add, 32)
  256 ATOMIC_ACQ_REL(subtract, 32)
  257 
  258 ATOMIC_CMPSET_ACQ_REL(32);
  259 ATOMIC_FCMPSET_ACQ_REL(32);
  260 
  261 static __inline uint32_t
  262 atomic_load_acq_32(volatile uint32_t *p)
  263 {
  264         uint32_t ret;
  265 
  266         ret = *p;
  267 
  268         fence();
  269 
  270         return (ret);
  271 }
  272 
  273 static __inline void
  274 atomic_store_rel_32(volatile uint32_t *p, uint32_t val)
  275 {
  276 
  277         fence();
  278 
  279         *p = val;
  280 }
  281 
  282 #define atomic_add_acq_int      atomic_add_acq_32
  283 #define atomic_clear_acq_int    atomic_clear_acq_32
  284 #define atomic_cmpset_acq_int   atomic_cmpset_acq_32
  285 #define atomic_fcmpset_acq_int  atomic_fcmpset_acq_32
  286 #define atomic_load_acq_int     atomic_load_acq_32
  287 #define atomic_set_acq_int      atomic_set_acq_32
  288 #define atomic_subtract_acq_int atomic_subtract_acq_32
  289 
  290 #define atomic_add_rel_int      atomic_add_rel_32
  291 #define atomic_clear_rel_int    atomic_clear_rel_32
  292 #define atomic_cmpset_rel_int   atomic_cmpset_rel_32
  293 #define atomic_fcmpset_rel_int  atomic_fcmpset_rel_32
  294 #define atomic_set_rel_int      atomic_set_rel_32
  295 #define atomic_subtract_rel_int atomic_subtract_rel_32
  296 #define atomic_store_rel_int    atomic_store_rel_32
  297 
  298 static __inline void
  299 atomic_add_64(volatile uint64_t *p, uint64_t val)
  300 {
  301 
  302         __asm __volatile("amoadd.d zero, %1, %0"
  303                         : "+A" (*p)
  304                         : "r" (val)
  305                         : "memory");
  306 }
  307 
  308 static __inline void
  309 atomic_subtract_64(volatile uint64_t *p, uint64_t val)
  310 {
  311 
  312         __asm __volatile("amoadd.d zero, %1, %0"
  313                         : "+A" (*p)
  314                         : "r" (-val)
  315                         : "memory");
  316 }
  317 
  318 static __inline void
  319 atomic_set_64(volatile uint64_t *p, uint64_t val)
  320 {
  321 
  322         __asm __volatile("amoor.d zero, %1, %0"
  323                         : "+A" (*p)
  324                         : "r" (val)
  325                         : "memory");
  326 }
  327 
  328 static __inline void
  329 atomic_clear_64(volatile uint64_t *p, uint64_t val)
  330 {
  331 
  332         __asm __volatile("amoand.d zero, %1, %0"
  333                         : "+A" (*p)
  334                         : "r" (~val)
  335                         : "memory");
  336 }
  337 
  338 static __inline int
  339 atomic_cmpset_64(volatile uint64_t *p, uint64_t cmpval, uint64_t newval)
  340 {
  341         uint64_t tmp;
  342         int res;
  343 
  344         res = 0;
  345 
  346         __asm __volatile(
  347                 "0:"
  348                         "li   %1, 1\n" /* Preset to fail */
  349                         "lr.d %0, %2\n"
  350                         "bne  %0, %z3, 1f\n"
  351                         "sc.d %1, %z4, %2\n"
  352                         "bnez %1, 0b\n"
  353                 "1:"
  354                         : "=&r" (tmp), "=&r" (res), "+A" (*p)
  355                         : "rJ" (cmpval), "rJ" (newval)
  356                         : "memory");
  357 
  358         return (!res);
  359 }
  360 
  361 static __inline int
  362 atomic_fcmpset_64(volatile uint64_t *p, uint64_t *cmpval, uint64_t newval)
  363 {
  364         uint64_t tmp;
  365         int res;
  366 
  367         res = 0;
  368 
  369         __asm __volatile(
  370                 "0:"
  371                         "li   %1, 1\n"          /* Preset to fail */
  372                         "lr.d %0, %2\n"         /* Load old value */
  373                         "bne  %0, %z4, 1f\n"    /* Compare */
  374                         "sc.d %1, %z5, %2\n"    /* Try to store new value */
  375                         "j 2f\n"
  376                 "1:"
  377                         "sd   %0, %3\n"         /* Save old value */
  378                 "2:"
  379                         : "=&r" (tmp), "=&r" (res), "+A" (*p), "+A" (*cmpval)
  380                         : "rJ" (*cmpval), "rJ" (newval)
  381                         : "memory");
  382 
  383         return (!res);
  384 }
  385 
  386 static __inline uint64_t
  387 atomic_fetchadd_64(volatile uint64_t *p, uint64_t val)
  388 {
  389         uint64_t ret;
  390 
  391         __asm __volatile("amoadd.d %0, %2, %1"
  392                         : "=&r" (ret), "+A" (*p)
  393                         : "r" (val)
  394                         : "memory");
  395 
  396         return (ret);
  397 }
  398 
  399 static __inline uint64_t
  400 atomic_readandclear_64(volatile uint64_t *p)
  401 {
  402         uint64_t ret;
  403         uint64_t val;
  404 
  405         val = 0;
  406 
  407         __asm __volatile("amoswap.d %0, %2, %1"
  408                         : "=&r"(ret), "+A" (*p)
  409                         : "r" (val)
  410                         : "memory");
  411 
  412         return (ret);
  413 }
  414 
  415 static __inline uint32_t
  416 atomic_swap_32(volatile uint32_t *p, uint32_t val)
  417 {
  418         uint32_t old;
  419 
  420         __asm __volatile("amoswap.w %0, %2, %1"
  421                         : "=&r"(old), "+A" (*p)
  422                         : "r" (val)
  423                         : "memory");
  424 
  425         return (old);
  426 }
  427 
  428 static __inline uint64_t
  429 atomic_swap_64(volatile uint64_t *p, uint64_t val)
  430 {
  431         uint64_t old;
  432 
  433         __asm __volatile("amoswap.d %0, %2, %1"
  434                         : "=&r"(old), "+A" (*p)
  435                         : "r" (val)
  436                         : "memory");
  437 
  438         return (old);
  439 }
  440 
  441 #define atomic_swap_int                 atomic_swap_32
  442 
  443 #define atomic_add_long                 atomic_add_64
  444 #define atomic_clear_long               atomic_clear_64
  445 #define atomic_cmpset_long              atomic_cmpset_64
  446 #define atomic_fcmpset_long             atomic_fcmpset_64
  447 #define atomic_fetchadd_long            atomic_fetchadd_64
  448 #define atomic_readandclear_long        atomic_readandclear_64
  449 #define atomic_set_long                 atomic_set_64
  450 #define atomic_subtract_long            atomic_subtract_64
  451 #define atomic_swap_long                atomic_swap_64
  452 
  453 #define atomic_add_ptr                  atomic_add_64
  454 #define atomic_clear_ptr                atomic_clear_64
  455 #define atomic_cmpset_ptr               atomic_cmpset_64
  456 #define atomic_fcmpset_ptr              atomic_fcmpset_64
  457 #define atomic_fetchadd_ptr             atomic_fetchadd_64
  458 #define atomic_readandclear_ptr         atomic_readandclear_64
  459 #define atomic_set_ptr                  atomic_set_64
  460 #define atomic_subtract_ptr             atomic_subtract_64
  461 #define atomic_swap_ptr                 atomic_swap_64
  462 
  463 ATOMIC_ACQ_REL(set, 64)
  464 ATOMIC_ACQ_REL(clear, 64)
  465 ATOMIC_ACQ_REL(add, 64)
  466 ATOMIC_ACQ_REL(subtract, 64)
  467 
  468 ATOMIC_CMPSET_ACQ_REL(64);
  469 ATOMIC_FCMPSET_ACQ_REL(64);
  470 
  471 static __inline uint64_t
  472 atomic_load_acq_64(volatile uint64_t *p)
  473 {
  474         uint64_t ret;
  475 
  476         ret = *p;
  477 
  478         fence();
  479 
  480         return (ret);
  481 }
  482 
  483 static __inline void
  484 atomic_store_rel_64(volatile uint64_t *p, uint64_t val)
  485 {
  486 
  487         fence();
  488 
  489         *p = val;
  490 }
  491 
  492 #define atomic_add_acq_long             atomic_add_acq_64
  493 #define atomic_clear_acq_long           atomic_clear_acq_64
  494 #define atomic_cmpset_acq_long          atomic_cmpset_acq_64
  495 #define atomic_fcmpset_acq_long         atomic_fcmpset_acq_64
  496 #define atomic_load_acq_long            atomic_load_acq_64
  497 #define atomic_set_acq_long             atomic_set_acq_64
  498 #define atomic_subtract_acq_long        atomic_subtract_acq_64
  499 
  500 #define atomic_add_acq_ptr              atomic_add_acq_64
  501 #define atomic_clear_acq_ptr            atomic_clear_acq_64
  502 #define atomic_cmpset_acq_ptr           atomic_cmpset_acq_64
  503 #define atomic_fcmpset_acq_ptr          atomic_fcmpset_acq_64
  504 #define atomic_load_acq_ptr             atomic_load_acq_64
  505 #define atomic_set_acq_ptr              atomic_set_acq_64
  506 #define atomic_subtract_acq_ptr         atomic_subtract_acq_64
  507 
  508 #undef ATOMIC_ACQ_REL
  509 
  510 static __inline void
  511 atomic_thread_fence_acq(void)
  512 {
  513 
  514         fence();
  515 }
  516 
  517 static __inline void
  518 atomic_thread_fence_rel(void)
  519 {
  520 
  521         fence();
  522 }
  523 
  524 static __inline void
  525 atomic_thread_fence_acq_rel(void)
  526 {
  527 
  528         fence();
  529 }
  530 
  531 static __inline void
  532 atomic_thread_fence_seq_cst(void)
  533 {
  534 
  535         fence();
  536 }
  537 
  538 #define atomic_add_rel_long             atomic_add_rel_64
  539 #define atomic_clear_rel_long           atomic_clear_rel_64
  540 
  541 #define atomic_add_rel_long             atomic_add_rel_64
  542 #define atomic_clear_rel_long           atomic_clear_rel_64
  543 #define atomic_cmpset_rel_long          atomic_cmpset_rel_64
  544 #define atomic_fcmpset_rel_long         atomic_fcmpset_rel_64
  545 #define atomic_set_rel_long             atomic_set_rel_64
  546 #define atomic_subtract_rel_long        atomic_subtract_rel_64
  547 #define atomic_store_rel_long           atomic_store_rel_64
  548 
  549 #define atomic_add_rel_ptr              atomic_add_rel_64
  550 #define atomic_clear_rel_ptr            atomic_clear_rel_64
  551 #define atomic_cmpset_rel_ptr           atomic_cmpset_rel_64
  552 #define atomic_fcmpset_rel_ptr          atomic_fcmpset_rel_64
  553 #define atomic_set_rel_ptr              atomic_set_rel_64
  554 #define atomic_subtract_rel_ptr         atomic_subtract_rel_64
  555 #define atomic_store_rel_ptr            atomic_store_rel_64
  556 
  557 #include <sys/_atomic_subword.h>
  558 
  559 #endif /* _MACHINE_ATOMIC_H_ */

Cache object: a54f599661ee94444ee0709e88834e1e


[ 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.