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/sparc64/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) 1998 Doug Rabson.
    3  * Copyright (c) 2001 Jake Burkholder.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  *      from: FreeBSD: src/sys/i386/include/atomic.h,v 1.20 2001/02/11
   28  * $FreeBSD: releng/8.2/sys/sparc64/include/atomic.h 185162 2008-11-22 05:55:56Z kmacy $
   29  */
   30 
   31 #ifndef _MACHINE_ATOMIC_H_
   32 #define _MACHINE_ATOMIC_H_
   33 
   34 #include <machine/cpufunc.h>
   35 
   36 /* Userland needs different ASI's. */
   37 #ifdef _KERNEL
   38 #define __ASI_ATOMIC    ASI_N
   39 #else
   40 #define __ASI_ATOMIC    ASI_P
   41 #endif
   42 
   43 #define mb()    __asm__ __volatile__ ("membar #MemIssue": : :"memory")
   44 #define wmb()   mb()
   45 #define rmb()   mb()
   46 
   47 /*
   48  * Various simple arithmetic on memory which is atomic in the presence
   49  * of interrupts and multiple processors.  See atomic(9) for details.
   50  * Note that efficient hardware support exists only for the 32 and 64
   51  * bit variants; the 8 and 16 bit versions are not provided and should
   52  * not be used in MI code.
   53  *
   54  * This implementation takes advantage of the fact that the sparc64
   55  * cas instruction is both a load and a store.  The loop is often coded
   56  * as follows:
   57  *
   58  *      do {
   59  *              expect = *p;
   60  *              new = expect + 1;
   61  *      } while (cas(p, expect, new) != expect);
   62  *
   63  * which performs an unnnecessary load on each iteration that the cas
   64  * operation fails.  Modified as follows:
   65  *
   66  *      expect = *p;
   67  *      for (;;) {
   68  *              new = expect + 1;
   69  *              result = cas(p, expect, new);
   70  *              if (result == expect)
   71  *                      break;
   72  *              expect = result;
   73  *      }
   74  *
   75  * the return value of cas is used to avoid the extra reload.
   76  *
   77  * The memory barriers provided by the acq and rel variants are intended
   78  * to be sufficient for use of relaxed memory ordering.  Due to the
   79  * suggested assembly syntax of the membar operands containing a #
   80  * character, they cannot be used in macros.  The cmask and mmask bits
   81  * are hard coded in machine/cpufunc.h and used here through macros.
   82  * Hopefully sun will choose not to change the bit numbers.
   83  */
   84 
   85 #define itype(sz)       uint ## sz ## _t
   86 
   87 #define atomic_cas_32(p, e, s)  casa(p, e, s, __ASI_ATOMIC)
   88 #define atomic_cas_64(p, e, s)  casxa(p, e, s, __ASI_ATOMIC)
   89 
   90 #define atomic_cas(p, e, s, sz)                                         \
   91         atomic_cas_ ## sz(p, e, s)
   92 
   93 #define atomic_cas_acq(p, e, s, sz) ({                                  \
   94         itype(sz) v;                                                    \
   95         v = atomic_cas(p, e, s, sz);                                    \
   96         membar(LoadLoad | LoadStore);                                   \
   97         v;                                                              \
   98 })
   99 
  100 #define atomic_cas_rel(p, e, s, sz) ({                                  \
  101         itype(sz) v;                                                    \
  102         membar(LoadStore | StoreStore);                                 \
  103         v = atomic_cas(p, e, s, sz);                                    \
  104         v;                                                              \
  105 })
  106 
  107 #define atomic_op(p, op, v, sz) ({                                      \
  108         itype(sz) e, r, s;                                              \
  109         for (e = *(volatile itype(sz) *)p;; e = r) {                    \
  110                 s = e op v;                                             \
  111                 r = atomic_cas_ ## sz(p, e, s);                         \
  112                 if (r == e)                                             \
  113                         break;                                          \
  114         }                                                               \
  115         e;                                                              \
  116 })
  117 
  118 #define atomic_op_acq(p, op, v, sz) ({                                  \
  119         itype(sz) t;                                                    \
  120         t = atomic_op(p, op, v, sz);                                    \
  121         membar(LoadLoad | LoadStore);                                   \
  122         t;                                                              \
  123 })
  124 
  125 #define atomic_op_rel(p, op, v, sz) ({                                  \
  126         itype(sz) t;                                                    \
  127         membar(LoadStore | StoreStore);                                 \
  128         t = atomic_op(p, op, v, sz);                                    \
  129         t;                                                              \
  130 })
  131 
  132 #define atomic_load(p, sz)                                              \
  133         atomic_cas(p, 0, 0, sz)
  134 
  135 #define atomic_load_acq(p, sz) ({                                       \
  136         itype(sz) v;                                                    \
  137         v = atomic_load(p, sz);                                         \
  138         membar(LoadLoad | LoadStore);                                   \
  139         v;                                                              \
  140 })
  141 
  142 #define atomic_load_clear(p, sz) ({                                     \
  143         itype(sz) e, r;                                                 \
  144         for (e = *(volatile itype(sz) *)p;; e = r) {                    \
  145                 r = atomic_cas(p, e, 0, sz);                            \
  146                 if (r == e)                                             \
  147                         break;                                          \
  148         }                                                               \
  149         e;                                                              \
  150 })
  151 
  152 #define atomic_store(p, v, sz) do {                                     \
  153         itype(sz) e, r;                                                 \
  154         for (e = *(volatile itype(sz) *)p;; e = r) {                    \
  155                 r = atomic_cas(p, e, v, sz);                            \
  156                 if (r == e)                                             \
  157                         break;                                          \
  158         }                                                               \
  159 } while (0)
  160 
  161 #define atomic_store_rel(p, v, sz) do {                                 \
  162         membar(LoadStore | StoreStore);                                 \
  163         atomic_store(p, v, sz);                                         \
  164 } while (0)
  165 
  166 #define ATOMIC_GEN(name, ptype, vtype, atype, sz)                       \
  167                                                                         \
  168 static __inline vtype                                                   \
  169 atomic_add_ ## name(volatile ptype p, atype v)                          \
  170 {                                                                       \
  171         return ((vtype)atomic_op(p, +, v, sz));                         \
  172 }                                                                       \
  173 static __inline vtype                                                   \
  174 atomic_add_acq_ ## name(volatile ptype p, atype v)                      \
  175 {                                                                       \
  176         return ((vtype)atomic_op_acq(p, +, v, sz));                     \
  177 }                                                                       \
  178 static __inline vtype                                                   \
  179 atomic_add_rel_ ## name(volatile ptype p, atype v)                      \
  180 {                                                                       \
  181         return ((vtype)atomic_op_rel(p, +, v, sz));                     \
  182 }                                                                       \
  183                                                                         \
  184 static __inline vtype                                                   \
  185 atomic_clear_ ## name(volatile ptype p, atype v)                        \
  186 {                                                                       \
  187         return ((vtype)atomic_op(p, &, ~v, sz));                        \
  188 }                                                                       \
  189 static __inline vtype                                                   \
  190 atomic_clear_acq_ ## name(volatile ptype p, atype v)                    \
  191 {                                                                       \
  192         return ((vtype)atomic_op_acq(p, &, ~v, sz));                    \
  193 }                                                                       \
  194 static __inline vtype                                                   \
  195 atomic_clear_rel_ ## name(volatile ptype p, atype v)                    \
  196 {                                                                       \
  197         return ((vtype)atomic_op_rel(p, &, ~v, sz));                    \
  198 }                                                                       \
  199                                                                         \
  200 static __inline int                                                     \
  201 atomic_cmpset_ ## name(volatile ptype p, vtype e, vtype s)              \
  202 {                                                                       \
  203         return (((vtype)atomic_cas(p, e, s, sz)) == e);                 \
  204 }                                                                       \
  205 static __inline int                                                     \
  206 atomic_cmpset_acq_ ## name(volatile ptype p, vtype e, vtype s)          \
  207 {                                                                       \
  208         return (((vtype)atomic_cas_acq(p, e, s, sz)) == e);             \
  209 }                                                                       \
  210 static __inline int                                                     \
  211 atomic_cmpset_rel_ ## name(volatile ptype p, vtype e, vtype s)          \
  212 {                                                                       \
  213         return (((vtype)atomic_cas_rel(p, e, s, sz)) == e);             \
  214 }                                                                       \
  215                                                                         \
  216 static __inline vtype                                                   \
  217 atomic_load_ ## name(volatile ptype p)                                  \
  218 {                                                                       \
  219         return ((vtype)atomic_cas(p, 0, 0, sz));                        \
  220 }                                                                       \
  221 static __inline vtype                                                   \
  222 atomic_load_acq_ ## name(volatile ptype p)                              \
  223 {                                                                       \
  224         return ((vtype)atomic_cas_acq(p, 0, 0, sz));                    \
  225 }                                                                       \
  226                                                                         \
  227 static __inline vtype                                                   \
  228 atomic_readandclear_ ## name(volatile ptype p)                          \
  229 {                                                                       \
  230         return ((vtype)atomic_load_clear(p, sz));                       \
  231 }                                                                       \
  232                                                                         \
  233 static __inline vtype                                                   \
  234 atomic_set_ ## name(volatile ptype p, atype v)                          \
  235 {                                                                       \
  236         return ((vtype)atomic_op(p, |, v, sz));                         \
  237 }                                                                       \
  238 static __inline vtype                                                   \
  239 atomic_set_acq_ ## name(volatile ptype p, atype v)                      \
  240 {                                                                       \
  241         return ((vtype)atomic_op_acq(p, |, v, sz));                     \
  242 }                                                                       \
  243 static __inline vtype                                                   \
  244 atomic_set_rel_ ## name(volatile ptype p, atype v)                      \
  245 {                                                                       \
  246         return ((vtype)atomic_op_rel(p, |, v, sz));                     \
  247 }                                                                       \
  248                                                                         \
  249 static __inline vtype                                                   \
  250 atomic_subtract_ ## name(volatile ptype p, atype v)                     \
  251 {                                                                       \
  252         return ((vtype)atomic_op(p, -, v, sz));                         \
  253 }                                                                       \
  254 static __inline vtype                                                   \
  255 atomic_subtract_acq_ ## name(volatile ptype p, atype v)                 \
  256 {                                                                       \
  257         return ((vtype)atomic_op_acq(p, -, v, sz));                     \
  258 }                                                                       \
  259 static __inline vtype                                                   \
  260 atomic_subtract_rel_ ## name(volatile ptype p, atype v)                 \
  261 {                                                                       \
  262         return ((vtype)atomic_op_rel(p, -, v, sz));                     \
  263 }                                                                       \
  264                                                                         \
  265 static __inline void                                                    \
  266 atomic_store_ ## name(volatile ptype p, vtype v)                        \
  267 {                                                                       \
  268         atomic_store(p, v, sz);                                         \
  269 }                                                                       \
  270 static __inline void                                                    \
  271 atomic_store_rel_ ## name(volatile ptype p, vtype v)                    \
  272 {                                                                       \
  273         atomic_store_rel(p, v, sz);                                     \
  274 }
  275 
  276 ATOMIC_GEN(int, u_int *, u_int, u_int, 32);
  277 ATOMIC_GEN(32, uint32_t *, uint32_t, uint32_t, 32);
  278 
  279 ATOMIC_GEN(long, u_long *, u_long, u_long, 64);
  280 ATOMIC_GEN(64, uint64_t *, uint64_t, uint64_t, 64);
  281 
  282 ATOMIC_GEN(ptr, uintptr_t *, uintptr_t, uintptr_t, 64);
  283 
  284 #define atomic_fetchadd_int     atomic_add_int
  285 #define atomic_fetchadd_32      atomic_add_32
  286 #define atomic_fetchadd_long    atomic_add_long
  287 
  288 #undef ATOMIC_GEN
  289 #undef atomic_cas
  290 #undef atomic_cas_acq
  291 #undef atomic_cas_rel
  292 #undef atomic_op
  293 #undef atomic_op_acq
  294 #undef atomic_op_rel
  295 #undef atomic_load_acq
  296 #undef atomic_store_rel
  297 #undef atomic_load_clear
  298 
  299 #endif /* !_MACHINE_ATOMIC_H_ */

Cache object: 1b1f973585a1bdf93fa2995902323664


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