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/contrib/ck/include/gcc/x86_64/ck_pr.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 2009-2015 Samy Al Bahra.
    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 
   27 #ifndef CK_PR_X86_64_H
   28 #define CK_PR_X86_64_H
   29 
   30 #ifndef CK_PR_H
   31 #error Do not include this file directly, use ck_pr.h
   32 #endif
   33 
   34 #include <ck_cc.h>
   35 #include <ck_md.h>
   36 #include <ck_stdint.h>
   37 
   38 /*
   39  * The following represent supported atomic operations.
   40  * These operations may be emulated.
   41  */
   42 #include "ck_f_pr.h"
   43 
   44 /*
   45  * Support for TSX extensions.
   46  */
   47 #ifdef CK_MD_RTM_ENABLE
   48 #include "ck_pr_rtm.h"
   49 #endif
   50 
   51 /* Minimum requirements for the CK_PR interface are met. */
   52 #define CK_F_PR
   53 
   54 #ifdef CK_MD_UMP
   55 #define CK_PR_LOCK_PREFIX
   56 #else
   57 #define CK_PR_LOCK_PREFIX "lock "
   58 #endif
   59 
   60 /*
   61  * Prevent speculative execution in busy-wait loops (P4 <=) or "predefined
   62  * delay".
   63  */
   64 CK_CC_INLINE static void
   65 ck_pr_stall(void)
   66 {
   67         __asm__ __volatile__("pause" ::: "memory");
   68         return;
   69 }
   70 
   71 #define CK_PR_FENCE(T, I)                               \
   72         CK_CC_INLINE static void                        \
   73         ck_pr_fence_strict_##T(void)                    \
   74         {                                               \
   75                 __asm__ __volatile__(I ::: "memory");   \
   76         }
   77 
   78 /* Atomic operations are always serializing. */
   79 CK_PR_FENCE(atomic, "")
   80 CK_PR_FENCE(atomic_store, "")
   81 CK_PR_FENCE(atomic_load, "")
   82 CK_PR_FENCE(store_atomic, "")
   83 CK_PR_FENCE(load_atomic, "")
   84 
   85 /* Traditional fence interface. */
   86 CK_PR_FENCE(load, "lfence")
   87 CK_PR_FENCE(load_store, "mfence")
   88 CK_PR_FENCE(store, "sfence")
   89 CK_PR_FENCE(store_load, "mfence")
   90 CK_PR_FENCE(memory, "mfence")
   91 
   92 /* Below are stdatomic-style fences. */
   93 
   94 /*
   95  * Provides load-store and store-store ordering. However, Intel specifies that
   96  * the WC memory model is relaxed. It is likely an sfence *is* sufficient (in
   97  * particular, stores are not re-ordered with respect to prior loads and it is
   98  * really just the stores that are subject to re-ordering). However, we take
   99  * the conservative route as the manuals are too ambiguous for my taste.
  100  */
  101 CK_PR_FENCE(release, "mfence")
  102 
  103 /*
  104  * Provides load-load and load-store ordering. The lfence instruction ensures
  105  * all prior load operations are complete before any subsequent instructions
  106  * actually begin execution. However, the manual also ends up going to describe
  107  * WC memory as a relaxed model.
  108  */
  109 CK_PR_FENCE(acquire, "mfence")
  110 
  111 CK_PR_FENCE(acqrel, "mfence")
  112 CK_PR_FENCE(lock, "mfence")
  113 CK_PR_FENCE(unlock, "mfence")
  114 
  115 #undef CK_PR_FENCE
  116 
  117 /*
  118  * Read for ownership. Older compilers will generate the 32-bit
  119  * 3DNow! variant which is binary compatible with x86-64 variant
  120  * of prefetchw.
  121  */
  122 #ifndef CK_F_PR_RFO
  123 #define CK_F_PR_RFO
  124 CK_CC_INLINE static void
  125 ck_pr_rfo(const void *m)
  126 {
  127 
  128         __asm__ __volatile__("prefetchw (%0)"
  129             :
  130             : "r" (m)
  131             : "memory");
  132 
  133         return;
  134 }
  135 #endif /* CK_F_PR_RFO */
  136 
  137 /*
  138  * Atomic fetch-and-store operations.
  139  */
  140 #define CK_PR_FAS(S, M, T, C, I)                                \
  141         CK_CC_INLINE static T                                   \
  142         ck_pr_fas_##S(M *target, T v)                           \
  143         {                                                       \
  144                 __asm__ __volatile__(I " %0, %1"                \
  145                                         : "+m" (*(C *)target),  \
  146                                           "+q" (v)              \
  147                                         :                       \
  148                                         : "memory");            \
  149                 return v;                                       \
  150         }
  151 
  152 CK_PR_FAS(ptr, void, void *, uint64_t, "xchgq")
  153 
  154 #define CK_PR_FAS_S(S, T, I) CK_PR_FAS(S, T, T, T, I)
  155 
  156 #ifndef CK_PR_DISABLE_DOUBLE
  157 CK_PR_FAS_S(double, double, "xchgq")
  158 #endif
  159 CK_PR_FAS_S(char, char, "xchgb")
  160 CK_PR_FAS_S(uint, unsigned int, "xchgl")
  161 CK_PR_FAS_S(int, int, "xchgl")
  162 CK_PR_FAS_S(64, uint64_t, "xchgq")
  163 CK_PR_FAS_S(32, uint32_t, "xchgl")
  164 CK_PR_FAS_S(16, uint16_t, "xchgw")
  165 CK_PR_FAS_S(8,  uint8_t,  "xchgb")
  166 
  167 #undef CK_PR_FAS_S
  168 #undef CK_PR_FAS
  169 
  170 /*
  171  * Atomic load-from-memory operations.
  172  */
  173 #define CK_PR_LOAD(S, M, T, C, I)                               \
  174         CK_CC_INLINE static T                                   \
  175         ck_pr_md_load_##S(const M *target)                      \
  176         {                                                       \
  177                 T r;                                            \
  178                 __asm__ __volatile__(I " %1, %0"                \
  179                     : "=q" (r)                                  \
  180                     : "m"  (*(const C *)target)                 \
  181                     : "memory");                                \
  182                 return (r);                                     \
  183         }
  184 
  185 CK_PR_LOAD(ptr, void, void *, uint64_t, "movq")
  186 
  187 #define CK_PR_LOAD_S(S, T, I) CK_PR_LOAD(S, T, T, T, I)
  188 
  189 CK_PR_LOAD_S(char, char, "movb")
  190 CK_PR_LOAD_S(uint, unsigned int, "movl")
  191 CK_PR_LOAD_S(int, int, "movl")
  192 #ifndef CK_PR_DISABLE_DOUBLE
  193 CK_PR_LOAD_S(double, double, "movq")
  194 #endif
  195 CK_PR_LOAD_S(64, uint64_t, "movq")
  196 CK_PR_LOAD_S(32, uint32_t, "movl")
  197 CK_PR_LOAD_S(16, uint16_t, "movw")
  198 CK_PR_LOAD_S(8,  uint8_t,  "movb")
  199 
  200 #undef CK_PR_LOAD_S
  201 #undef CK_PR_LOAD
  202 
  203 CK_CC_INLINE static void
  204 ck_pr_load_64_2(const uint64_t target[2], uint64_t v[2])
  205 {
  206         __asm__ __volatile__("movq %%rdx, %%rcx;"
  207                              "movq %%rax, %%rbx;"
  208                              CK_PR_LOCK_PREFIX "cmpxchg16b %2;"
  209                                 : "=a" (v[0]),
  210                                   "=d" (v[1])
  211                                 : "m" (*(const uint64_t *)target)
  212                                 : "rbx", "rcx", "memory", "cc");
  213         return;
  214 }
  215 
  216 CK_CC_INLINE static void
  217 ck_pr_load_ptr_2(const void *t, void *v)
  218 {
  219         ck_pr_load_64_2(CK_CPP_CAST(const uint64_t *, t),
  220                         CK_CPP_CAST(uint64_t *, v));
  221         return;
  222 }
  223 
  224 #define CK_PR_LOAD_2(S, W, T)                                                   \
  225         CK_CC_INLINE static void                                                \
  226         ck_pr_md_load_##S##_##W(const T t[2], T v[2])                           \
  227         {                                                                       \
  228                 ck_pr_load_64_2((const uint64_t *)(const void *)t,              \
  229                                 (uint64_t *)(void *)v);                         \
  230                 return;                                                         \
  231         }
  232 
  233 CK_PR_LOAD_2(char, 16, char)
  234 CK_PR_LOAD_2(int, 4, int)
  235 CK_PR_LOAD_2(uint, 4, unsigned int)
  236 CK_PR_LOAD_2(32, 4, uint32_t)
  237 CK_PR_LOAD_2(16, 8, uint16_t)
  238 CK_PR_LOAD_2(8, 16, uint8_t)
  239 
  240 #undef CK_PR_LOAD_2
  241 
  242 /*
  243  * Atomic store-to-memory operations.
  244  */
  245 #define CK_PR_STORE_IMM(S, M, T, C, I, K)                               \
  246         CK_CC_INLINE static void                                        \
  247         ck_pr_md_store_##S(M *target, T v)                              \
  248         {                                                               \
  249                 __asm__ __volatile__(I " %1, %0"                        \
  250                                         : "=m" (*(C *)target)           \
  251                                         : K "q" (v)                     \
  252                                         : "memory");                    \
  253                 return;                                                 \
  254         }
  255 
  256 #define CK_PR_STORE(S, M, T, C, I)                              \
  257         CK_CC_INLINE static void                                \
  258         ck_pr_md_store_##S(M *target, T v)                      \
  259         {                                                       \
  260                 __asm__ __volatile__(I " %1, %0"                \
  261                                         : "=m" (*(C *)target)   \
  262                                         : "q" (v)               \
  263                                         : "memory");            \
  264                 return;                                         \
  265         }
  266 
  267 CK_PR_STORE_IMM(ptr, void, const void *, uint64_t, "movq", CK_CC_IMM_U32)
  268 #ifndef CK_PR_DISABLE_DOUBLE
  269 CK_PR_STORE(double, double, double, double, "movq")
  270 #endif
  271 
  272 #define CK_PR_STORE_S(S, T, I, K) CK_PR_STORE_IMM(S, T, T, T, I, K)
  273 
  274 CK_PR_STORE_S(char, char, "movb", CK_CC_IMM_S32)
  275 CK_PR_STORE_S(int, int, "movl", CK_CC_IMM_S32)
  276 CK_PR_STORE_S(uint, unsigned int, "movl", CK_CC_IMM_U32)
  277 CK_PR_STORE_S(64, uint64_t, "movq", CK_CC_IMM_U32)
  278 CK_PR_STORE_S(32, uint32_t, "movl", CK_CC_IMM_U32)
  279 CK_PR_STORE_S(16, uint16_t, "movw", CK_CC_IMM_U32)
  280 CK_PR_STORE_S(8,  uint8_t, "movb", CK_CC_IMM_U32)
  281 
  282 #undef CK_PR_STORE_S
  283 #undef CK_PR_STORE_IMM
  284 #undef CK_PR_STORE
  285 
  286 /*
  287  * Atomic fetch-and-add operations.
  288  */
  289 #define CK_PR_FAA(S, M, T, C, I)                                        \
  290         CK_CC_INLINE static T                                           \
  291         ck_pr_faa_##S(M *target, T d)                                   \
  292         {                                                               \
  293                 __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %1, %0"      \
  294                                         : "+m" (*(C *)target),          \
  295                                           "+q" (d)                      \
  296                                         :                               \
  297                                         : "memory", "cc");              \
  298                 return (d);                                             \
  299         }
  300 
  301 CK_PR_FAA(ptr, void, uintptr_t, uint64_t, "xaddq")
  302 
  303 #define CK_PR_FAA_S(S, T, I) CK_PR_FAA(S, T, T, T, I)
  304 
  305 CK_PR_FAA_S(char, char, "xaddb")
  306 CK_PR_FAA_S(uint, unsigned int, "xaddl")
  307 CK_PR_FAA_S(int, int, "xaddl")
  308 CK_PR_FAA_S(64, uint64_t, "xaddq")
  309 CK_PR_FAA_S(32, uint32_t, "xaddl")
  310 CK_PR_FAA_S(16, uint16_t, "xaddw")
  311 CK_PR_FAA_S(8,  uint8_t,  "xaddb")
  312 
  313 #undef CK_PR_FAA_S
  314 #undef CK_PR_FAA
  315 
  316 /*
  317  * Atomic store-only unary operations.
  318  */
  319 #define CK_PR_UNARY(K, S, T, C, I)                              \
  320         CK_PR_UNARY_R(K, S, T, C, I)                            \
  321         CK_PR_UNARY_V(K, S, T, C, I)
  322 
  323 #define CK_PR_UNARY_R(K, S, T, C, I)                            \
  324         CK_CC_INLINE static void                                \
  325         ck_pr_##K##_##S(T *target)                              \
  326         {                                                       \
  327                 __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %0"  \
  328                                         : "+m" (*(C *)target)   \
  329                                         :                       \
  330                                         : "memory", "cc");      \
  331                 return;                                         \
  332         }
  333 
  334 #define CK_PR_UNARY_V(K, S, T, C, I)                                    \
  335         CK_CC_INLINE static bool                                        \
  336         ck_pr_##K##_##S##_is_zero(T *target)                            \
  337         {                                                               \
  338                 bool ret;                                               \
  339                 __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %0; setz %1" \
  340                                         : "+m" (*(C *)target),          \
  341                                           "=rm" (ret)                   \
  342                                         :                               \
  343                                         : "memory", "cc");              \
  344                 return ret;                                             \
  345         }
  346 
  347 #define CK_PR_UNARY_S(K, S, T, I) CK_PR_UNARY(K, S, T, T, I)
  348 
  349 #define CK_PR_GENERATE(K)                               \
  350         CK_PR_UNARY(K, ptr, void, uint64_t, #K "q")     \
  351         CK_PR_UNARY_S(K, char, char, #K "b")            \
  352         CK_PR_UNARY_S(K, int, int, #K "l")              \
  353         CK_PR_UNARY_S(K, uint, unsigned int, #K "l")    \
  354         CK_PR_UNARY_S(K, 64, uint64_t, #K "q")          \
  355         CK_PR_UNARY_S(K, 32, uint32_t, #K "l")          \
  356         CK_PR_UNARY_S(K, 16, uint16_t, #K "w")          \
  357         CK_PR_UNARY_S(K, 8, uint8_t, #K "b")
  358 
  359 CK_PR_GENERATE(inc)
  360 CK_PR_GENERATE(dec)
  361 CK_PR_GENERATE(neg)
  362 
  363 /* not does not affect condition flags. */
  364 #undef CK_PR_UNARY_V
  365 #define CK_PR_UNARY_V(a, b, c, d, e)
  366 CK_PR_GENERATE(not)
  367 
  368 #undef CK_PR_GENERATE
  369 #undef CK_PR_UNARY_S
  370 #undef CK_PR_UNARY_V
  371 #undef CK_PR_UNARY_R
  372 #undef CK_PR_UNARY
  373 
  374 /*
  375  * Atomic store-only binary operations.
  376  */
  377 #define CK_PR_BINARY(K, S, M, T, C, I, O)                               \
  378         CK_CC_INLINE static void                                        \
  379         ck_pr_##K##_##S(M *target, T d)                                 \
  380         {                                                               \
  381                 __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %1, %0"      \
  382                                         : "+m" (*(C *)target)           \
  383                                         : O "q" (d)                     \
  384                                         : "memory", "cc");              \
  385                 return;                                                 \
  386         }
  387 
  388 #define CK_PR_BINARY_S(K, S, T, I, O) CK_PR_BINARY(K, S, T, T, T, I, O)
  389 
  390 #define CK_PR_GENERATE(K)                                                       \
  391         CK_PR_BINARY(K, ptr, void, uintptr_t, uint64_t, #K "q", CK_CC_IMM_U32)  \
  392         CK_PR_BINARY_S(K, char, char, #K "b", CK_CC_IMM_S32)                    \
  393         CK_PR_BINARY_S(K, int, int, #K "l", CK_CC_IMM_S32)                      \
  394         CK_PR_BINARY_S(K, uint, unsigned int, #K "l", CK_CC_IMM_U32)            \
  395         CK_PR_BINARY_S(K, 64, uint64_t, #K "q", CK_CC_IMM_U32)                  \
  396         CK_PR_BINARY_S(K, 32, uint32_t, #K "l", CK_CC_IMM_U32)                  \
  397         CK_PR_BINARY_S(K, 16, uint16_t, #K "w", CK_CC_IMM_U32)                  \
  398         CK_PR_BINARY_S(K, 8, uint8_t, #K "b", CK_CC_IMM_U32)
  399 
  400 CK_PR_GENERATE(add)
  401 CK_PR_GENERATE(sub)
  402 CK_PR_GENERATE(and)
  403 CK_PR_GENERATE(or)
  404 CK_PR_GENERATE(xor)
  405 
  406 #undef CK_PR_GENERATE
  407 #undef CK_PR_BINARY_S
  408 #undef CK_PR_BINARY
  409 
  410 /*
  411  * Atomic compare and swap, with a variant that sets *v to the old value of target.
  412  */
  413 #ifdef __GCC_ASM_FLAG_OUTPUTS__
  414 #define CK_PR_CAS(S, M, T, C, I)                                                \
  415         CK_CC_INLINE static bool                                                \
  416         ck_pr_cas_##S(M *target, T compare, T set)                              \
  417         {                                                                       \
  418                 bool z;                                                         \
  419                 __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %3, %0"              \
  420                                         : "+m"    (*(C *)target),               \
  421                                           "=@ccz" (z),                          \
  422                                           /* RAX is clobbered by cmpxchg. */    \
  423                                           "+a"    (compare)                     \
  424                                         : "q"     (set)                         \
  425                                         : "memory", "cc");                      \
  426                 return z;                                                       \
  427         }                                                                       \
  428                                                                                 \
  429         CK_CC_INLINE static bool                                                \
  430         ck_pr_cas_##S##_value(M *target, T compare, T set, M *v)                \
  431         {                                                                       \
  432                 bool z;                                                         \
  433                 __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %3, %0;"             \
  434                                         : "+m"    (*(C *)target),               \
  435                                           "=@ccz" (z),                          \
  436                                           "+a"    (compare)                     \
  437                                         : "q"     (set)                         \
  438                                         : "memory", "cc");                      \
  439                 *(T *)v = compare;                                              \
  440                 return z;                                                       \
  441         }
  442 #else
  443 #define CK_PR_CAS(S, M, T, C, I)                                                \
  444         CK_CC_INLINE static bool                                                \
  445         ck_pr_cas_##S(M *target, T compare, T set)                              \
  446         {                                                                       \
  447                 bool z;                                                         \
  448                 __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %2, %0; setz %1"     \
  449                                         : "+m"  (*(C *)target),                 \
  450                                           "=a"  (z)                             \
  451                                         : "q"   (set),                          \
  452                                           "a"   (compare)                       \
  453                                         : "memory", "cc");                      \
  454                 return z;                                                       \
  455         }                                                                       \
  456                                                                                 \
  457         CK_CC_INLINE static bool                                                \
  458         ck_pr_cas_##S##_value(M *target, T compare, T set, M *v)                \
  459         {                                                                       \
  460                 bool z;                                                         \
  461                 __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %3, %0;"             \
  462                                      "setz %1;"                                 \
  463                                         : "+m"  (*(C *)target),                 \
  464                                           "=q"  (z),                            \
  465                                           "+a"  (compare)                       \
  466                                         : "q"   (set)                           \
  467                                         : "memory", "cc");                      \
  468                 *(T *)v = compare;                                              \
  469                 return z;                                                       \
  470         }
  471 #endif
  472 
  473 CK_PR_CAS(ptr, void, void *, uint64_t, "cmpxchgq")
  474 
  475 #define CK_PR_CAS_S(S, T, I) CK_PR_CAS(S, T, T, T, I)
  476 
  477 CK_PR_CAS_S(char, char, "cmpxchgb")
  478 CK_PR_CAS_S(int, int, "cmpxchgl")
  479 CK_PR_CAS_S(uint, unsigned int, "cmpxchgl")
  480 #ifndef CK_PR_DISABLE_DOUBLE
  481 CK_PR_CAS_S(double, double, "cmpxchgq")
  482 #endif
  483 CK_PR_CAS_S(64, uint64_t, "cmpxchgq")
  484 CK_PR_CAS_S(32, uint32_t, "cmpxchgl")
  485 CK_PR_CAS_S(16, uint16_t, "cmpxchgw")
  486 CK_PR_CAS_S(8,  uint8_t,  "cmpxchgb")
  487 
  488 #undef CK_PR_CAS_S
  489 #undef CK_PR_CAS
  490 
  491 /*
  492  * Contrary to C-interface, alignment requirements are that of uint64_t[2].
  493  */
  494 CK_CC_INLINE static bool
  495 ck_pr_cas_64_2(uint64_t target[2], uint64_t compare[2], uint64_t set[2])
  496 {
  497         bool z;
  498 
  499         __asm__ __volatile__("movq 0(%4), %%rax;"
  500                              "movq 8(%4), %%rdx;"
  501                              CK_PR_LOCK_PREFIX "cmpxchg16b %0; setz %1"
  502                                 : "+m" (*target),
  503                                   "=q" (z)
  504                                 : "b"  (set[0]),
  505                                   "c"  (set[1]),
  506                                   "q"  (compare)
  507                                 : "memory", "cc", "%rax", "%rdx");
  508         return z;
  509 }
  510 
  511 CK_CC_INLINE static bool
  512 ck_pr_cas_ptr_2(void *t, void *c, void *s)
  513 {
  514         return ck_pr_cas_64_2(CK_CPP_CAST(uint64_t *, t),
  515                               CK_CPP_CAST(uint64_t *, c),
  516                               CK_CPP_CAST(uint64_t *, s));
  517 }
  518 
  519 CK_CC_INLINE static bool
  520 ck_pr_cas_64_2_value(uint64_t target[2],
  521                      uint64_t compare[2],
  522                      uint64_t set[2],
  523                      uint64_t v[2])
  524 {
  525         bool z;
  526 
  527         __asm__ __volatile__(CK_PR_LOCK_PREFIX "cmpxchg16b %0;"
  528                              "setz %3"
  529                                 : "+m" (*target),
  530                                   "=a" (v[0]),
  531                                   "=d" (v[1]),
  532                                   "=q" (z)
  533                                 : "a" (compare[0]),
  534                                   "d" (compare[1]),
  535                                   "b" (set[0]),
  536                                   "c" (set[1])
  537                                 : "memory", "cc");
  538         return z;
  539 }
  540 
  541 CK_CC_INLINE static bool
  542 ck_pr_cas_ptr_2_value(void *t, void *c, void *s, void *v)
  543 {
  544         return ck_pr_cas_64_2_value(CK_CPP_CAST(uint64_t *,t),
  545                                     CK_CPP_CAST(uint64_t *,c),
  546                                     CK_CPP_CAST(uint64_t *,s),
  547                                     CK_CPP_CAST(uint64_t *,v));
  548 }
  549 
  550 #define CK_PR_CAS_V(S, W, T)                                    \
  551 CK_CC_INLINE static bool                                        \
  552 ck_pr_cas_##S##_##W(T t[W], T c[W], T s[W])                     \
  553 {                                                               \
  554         return ck_pr_cas_64_2((uint64_t *)(void *)t,            \
  555                               (uint64_t *)(void *)c,            \
  556                               (uint64_t *)(void *)s);           \
  557 }                                                               \
  558 CK_CC_INLINE static bool                                        \
  559 ck_pr_cas_##S##_##W##_value(T *t, T c[W], T s[W], T *v)         \
  560 {                                                               \
  561         return ck_pr_cas_64_2_value((uint64_t *)(void *)t,      \
  562                                     (uint64_t *)(void *)c,      \
  563                                     (uint64_t *)(void *)s,      \
  564                                     (uint64_t *)(void *)v);     \
  565 }
  566 
  567 #ifndef CK_PR_DISABLE_DOUBLE
  568 CK_PR_CAS_V(double, 2, double)
  569 #endif
  570 CK_PR_CAS_V(char, 16, char)
  571 CK_PR_CAS_V(int, 4, int)
  572 CK_PR_CAS_V(uint, 4, unsigned int)
  573 CK_PR_CAS_V(32, 4, uint32_t)
  574 CK_PR_CAS_V(16, 8, uint16_t)
  575 CK_PR_CAS_V(8, 16, uint8_t)
  576 
  577 #undef CK_PR_CAS_V
  578 
  579 /*
  580  * Atomic bit test operations.
  581  */
  582 #define CK_PR_BT(K, S, T, P, C, I)                                      \
  583         CK_CC_INLINE static bool                                        \
  584         ck_pr_##K##_##S(T *target, unsigned int b)                      \
  585         {                                                               \
  586                 bool c;                                                 \
  587                 __asm__ __volatile__(CK_PR_LOCK_PREFIX I "; setc %1"    \
  588                                         : "+m" (*(C *)target),          \
  589                                           "=q" (c)                      \
  590                                         : "q"  ((P)b)                   \
  591                                         : "memory", "cc");              \
  592                 return c;                                               \
  593         }
  594 
  595 #define CK_PR_BT_S(K, S, T, I) CK_PR_BT(K, S, T, T, T, I)
  596 
  597 #define CK_PR_GENERATE(K)                                               \
  598         CK_PR_BT(K, ptr, void, uint64_t, uint64_t, #K "q %2, %0")       \
  599         CK_PR_BT_S(K, uint, unsigned int, #K "l %2, %0")                \
  600         CK_PR_BT_S(K, int, int, #K "l %2, %0")                          \
  601         CK_PR_BT_S(K, 64, uint64_t, #K "q %2, %0")                      \
  602         CK_PR_BT_S(K, 32, uint32_t, #K "l %2, %0")                      \
  603         CK_PR_BT_S(K, 16, uint16_t, #K "w %w2, %0")
  604 
  605 CK_PR_GENERATE(btc)
  606 CK_PR_GENERATE(bts)
  607 CK_PR_GENERATE(btr)
  608 
  609 #undef CK_PR_GENERATE
  610 #undef CK_PR_BT
  611 
  612 #endif /* CK_PR_X86_64_H */
  613 

Cache object: 73271860ef2c470dc0b9df29b6726c5c


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