P99
p99_atomic_x86.h
Go to the documentation of this file.
1 /* This may look like nonsense, but it really is -*- mode: C; coding: utf-8 -*- */
2 /* */
3 /* Except for parts copied from previous work and as explicitly stated below, */
4 /* the authors and copyright holders for this work are as follows: */
5 /* (C) copyright 2012-2014 Jens Gustedt, INRIA, France */
6 /* (C) copyright 2012 William Morris */
7 /* */
8 /* This file is free software; it is part of the P99 project. */
9 /* */
10 /* Licensed under the Apache License, Version 2.0 (the "License"); */
11 /* you may not use this file except in compliance with the License. */
12 /* You may obtain a copy of the License at */
13 /* */
14 /* http://www.apache.org/licenses/LICENSE-2.0 */
15 /* */
16 /* Unless required by applicable law or agreed to in writing, software */
17 /* distributed under the License is distributed on an "AS IS" BASIS, */
18 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
19 /* See the License for the specific language governing permissions and */
20 /* limitations under the License. */
21 /* */
22 #ifndef P99_ATOMIC_X86_H
23 #define P99_ATOMIC_X86_H 1
24 
25 #ifndef P99_ATOMIC_H
26 # warning "never include this file directly, use p99_atomic.h, instead"
27 #endif
28 
29 
31 uint8_t p00_atomic_exchange_1(uint8_t volatile* p00_objp, uint8_t p00_ret) {
32  __asm__ __volatile__("xchgb %1, %b0"
33  : "=r"(p00_ret)
34  : "m"(*p00_objp), "0"(p00_ret)
35  : "memory");
36  return p00_ret;
37 }
38 
40 uint16_t p00_atomic_exchange_2(uint16_t volatile* p00_objp, uint16_t p00_ret) {
41  __asm__ __volatile__("xchgw %1, %w0"
42  : "=r"(p00_ret)
43  : "m"(*p00_objp), "0"(p00_ret)
44  : "memory");
45  return p00_ret;
46 }
47 
49 uint32_t p00_atomic_exchange_4(uint32_t volatile* p00_objp, uint32_t p00_ret) {
50  __asm__ __volatile__("xchgl %1, %k0"
51  : "=r"(p00_ret)
52  : "m"(*p00_objp), "0"(p00_ret)
53  : "memory");
54  return p00_ret;
55 }
56 
57 #if defined(__x86_64__) || defined(P00_DOXYGEN)
58 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) || defined(P00_DOXYGEN)
60 uint64_t p00_atomic_exchange_8(uint64_t volatile* p00_objp, uint64_t p00_ret) {
61  __asm__ __volatile__("xchgq %1, %0"
62  : "=r"(p00_ret)
63  : "m"(*p00_objp), "0"(p00_ret)
64  : "memory");
65  return p00_ret;
66 }
67 # endif
68 #else
69 #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
70 #endif
71 
93 void p00_sync_lock_release_internal(uint32_t volatile *p00_objp) {
94  __asm__ __volatile__("movl $0, %0"
95  :
96  : "m"(*p00_objp)
97  : "memory");
98 }
99 
101 void p00_mfence_internal(memory_order p00_ord) {
102  __asm__ __volatile__("mfence":::"memory");
103 }
104 
105 #define p00_mfence(...) \
106 P99_IF_EMPTY(__VA_ARGS__) \
107  (p00_mfence_internal(memory_order_seq_cst)) \
108  (p00_mfence_internal(__VA_ARGS__))
109 
110 #define p00_sync_lock_release(...) \
111  P99_IF_LT(P99_NARG(__VA_ARGS__), 2) \
112  (p00_sync_lock_release_internal(__VA_ARGS__)) \
113  (p00_sync_lock_release_internal(P99_ALLBUTLAST(__VA_ARGS__)))
114 #define p00_sync_lock_test_and_set(...) \
115  P99_IF_LT(P99_NARG(__VA_ARGS__), 2) \
116  (p00_atomic_exchange_4(__VA_ARGS__, 1)) \
117  (p00_atomic_exchange_4(P99_ALLBUTLAST(__VA_ARGS__), 1))
118 
119 
120 
125 #endif
p99_inline
#define p99_inline
Try to force a function always to be inlined.
Definition: p99_compiler.h:496