-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatomic_ops.h
144 lines (120 loc) · 7.92 KB
/
atomic_ops.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/**
* This file is part of the atomic_ops project.
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code.
*
* @copyright (c) the atomic_ops project
* @author Luca Longinotti <[email protected]>
* @license BSD 2-clause
* @version $Id: atomic_ops.h 1098 2012-07-30 17:56:14Z llongi $
*/
#ifndef ATOMIC_OPS_H
#define ATOMIC_OPS_H 1
/*
* Includes and defines
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
// Compiler define: align types to boundary X
#if !defined(ATTR_ALIGNED)
#define ATTR_ALIGNED(X)
#endif
// Compiler define: always inline functions
#if !defined(ATTR_ALWAYSINLINE)
#define ATTR_ALWAYSINLINE
#endif
// Suppress unused argument warnings, if needed
#define UNUSED_ARGUMENT(arg) (void)(arg)
/*
* Type Definitions
*/
typedef struct { volatile intptr_t v; } atomic_ops_int ATTR_ALIGNED(sizeof( intptr_t));
typedef struct { volatile uintptr_t v; } atomic_ops_uint ATTR_ALIGNED(sizeof(uintptr_t));
#define ATOMIC_OPS_INT_INIT(X) { (( intptr_t)(X)) }
#define ATOMIC_OPS_UINT_INIT(X) { ((uintptr_t)(X)) }
typedef struct { void * volatile v; } atomic_ops_ptr ATTR_ALIGNED(sizeof(void *));
#define ATOMIC_OPS_PTR_INIT(X) { ((void *)(X)) }
typedef struct { atomic_ops_ptr p; } atomic_ops_flagptr ATTR_ALIGNED(sizeof(void *));
#define ATOMIC_OPS_FLAGPTR_INIT(P, F) { (ATOMIC_OPS_PTR_INIT((void *)(((uintptr_t)(P)) | ((uintptr_t)(F))))) }
typedef enum {
ATOMIC_OPS_FENCE_NONE = (1 << 0), // Compiler barrier (don't let the compiler reorder)
ATOMIC_OPS_FENCE_ACQUIRE = (1 << 1), // Acquire barrier (nothing from after is reordered before)
ATOMIC_OPS_FENCE_RELEASE = (1 << 2), // Release barrier (nothing from before is reordered after)
ATOMIC_OPS_FENCE_FULL = (1 << 3), // Full barrier (nothing moves around, at all)
ATOMIC_OPS_FENCE_READ = (1 << 4), // Read barrier (order reads, like full but only wrt reads)
ATOMIC_OPS_FENCE_WRITE = (1 << 5), // Write barrier (order writes, like full but only wrt writes)
} ATOMIC_OPS_FENCE;
/*
* Functions
*/
static inline intptr_t atomic_ops_int_load(const atomic_ops_int *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_int_store(atomic_ops_int *atomic, intptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_int_not(atomic_ops_int *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_int_and(atomic_ops_int *atomic, intptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_int_or(atomic_ops_int *atomic, intptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_int_xor(atomic_ops_int *atomic, intptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_int_add(atomic_ops_int *atomic, intptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_int_inc(atomic_ops_int *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_int_dec(atomic_ops_int *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline intptr_t atomic_ops_int_fetch_and_add(atomic_ops_int *atomic, intptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline intptr_t atomic_ops_int_fetch_and_inc(atomic_ops_int *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline intptr_t atomic_ops_int_fetch_and_dec(atomic_ops_int *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline intptr_t atomic_ops_int_casr(atomic_ops_int *atomic, intptr_t oldval, intptr_t newval, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline bool atomic_ops_int_cas(atomic_ops_int *atomic, intptr_t oldval, intptr_t newval, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline intptr_t atomic_ops_int_swap(atomic_ops_int *atomic, intptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline uintptr_t atomic_ops_uint_load(const atomic_ops_uint *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_uint_store(atomic_ops_uint *atomic, uintptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_uint_not(atomic_ops_uint *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_uint_and(atomic_ops_uint *atomic, uintptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_uint_or(atomic_ops_uint *atomic, uintptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_uint_xor(atomic_ops_uint *atomic, uintptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_uint_add(atomic_ops_uint *atomic, uintptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_uint_inc(atomic_ops_uint *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_uint_dec(atomic_ops_uint *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline uintptr_t atomic_ops_uint_fetch_and_add(atomic_ops_uint *atomic, uintptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline uintptr_t atomic_ops_uint_fetch_and_inc(atomic_ops_uint *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline uintptr_t atomic_ops_uint_fetch_and_dec(atomic_ops_uint *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline uintptr_t atomic_ops_uint_casr(atomic_ops_uint *atomic, uintptr_t oldval, uintptr_t newval, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline bool atomic_ops_uint_cas(atomic_ops_uint *atomic, uintptr_t oldval, uintptr_t newval, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline uintptr_t atomic_ops_uint_swap(atomic_ops_uint *atomic, uintptr_t val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void * atomic_ops_ptr_load(const atomic_ops_ptr *atomic, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_ptr_store(atomic_ops_ptr *atomic, void *val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void * atomic_ops_ptr_casr(atomic_ops_ptr *atomic, void *oldval, void *newval, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline bool atomic_ops_ptr_cas(atomic_ops_ptr *atomic, void *oldval, void *newval, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void * atomic_ops_ptr_swap(atomic_ops_ptr *atomic, void *val, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_fence(ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_pause(void) ATTR_ALWAYSINLINE;
/*
* Flag-Pointer Functions
*/
static inline void * atomic_ops_flagptr_load(const atomic_ops_flagptr *atomic, bool *flag, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void * atomic_ops_flagptr_load_full(const atomic_ops_flagptr *atomic, bool *flag, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void atomic_ops_flagptr_store(atomic_ops_flagptr *atomic, void *newptr, bool newflag, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void * atomic_ops_flagptr_casr(atomic_ops_flagptr *atomic, bool *flag, void *oldptr, bool oldflag, void *newptr, bool newflag, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline bool atomic_ops_flagptr_cas(atomic_ops_flagptr *atomic, void *oldptr, bool oldflag, void *newptr, bool newflag, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
static inline void * atomic_ops_flagptr_swap(atomic_ops_flagptr *atomic, bool *flag, void *newptr, bool newflag, ATOMIC_OPS_FENCE fence) ATTR_ALWAYSINLINE;
/*
* Implementations
*/
#include "atomic_ops/emulation.h"
#if defined(SYSTEM_CC_GNUCC)
#if defined(SYSTEM_CPU_X86) || defined(SYSTEM_CPU_X86_64)
#include "atomic_ops/gcc/x86-64.h"
#elif defined(SYSTEM_CPU_SPARC)
#include "atomic_ops/gcc/sparcv9.h"
#elif defined(SYSTEM_CPU_IA64)
#include "atomic_ops/gcc/ia64.h"
#elif defined(SYSTEM_CPU_PPC)
#include "atomic_ops/gcc/ppc.h"
#elif defined(SYSTEM_CPU_ARM)
#include "atomic_ops/gcc/armv7.h"
#else
#include "atomic_ops/gcc/sync_intrinsics.h"
#endif
#else
#error Compiler not supported.
#endif
#include "atomic_ops/flagptr.h"
#endif /* ATOMIC_OPS_H */