1/**
2 * hdr_atomic.h
3 * Written by Philip Orwig and released to the public domain,
4 * as explained at http://creativecommons.org/publicdomain/zero/1.0/
5 */
6
7#ifndef HDR_ATOMIC_H__
8#define HDR_ATOMIC_H__
9
10
11#if defined(_MSC_VER)
12
13#include <stdint.h>
14#include <intrin.h>
15
16static void __inline * hdr_atomic_load_pointer(void** pointer)
17{
18	_ReadBarrier();
19	return *pointer;
20}
21
22static void hdr_atomic_store_pointer(void** pointer, void* value)
23{
24	_WriteBarrier();
25	*pointer = value;
26}
27
28static int64_t __inline hdr_atomic_load_64(int64_t* field)
29{
30	_ReadBarrier();
31	return *field;
32}
33
34static void __inline hdr_atomic_store_64(int64_t* field, int64_t value)
35{
36	_WriteBarrier();
37	*field = value;
38}
39
40static int64_t __inline hdr_atomic_exchange_64(volatile int64_t* field, int64_t initial)
41{
42	return _InterlockedExchange64(field, initial);
43}
44
45static int64_t __inline hdr_atomic_add_fetch_64(volatile int64_t* field, int64_t value)
46{
47	return _InterlockedExchangeAdd64(field, value) + value;
48}
49
50#elif defined(__ATOMIC_SEQ_CST)
51
52#define hdr_atomic_load_pointer(x) __atomic_load_n(x, __ATOMIC_SEQ_CST)
53#define hdr_atomic_store_pointer(f,v) __atomic_store_n(f,v, __ATOMIC_SEQ_CST)
54#define hdr_atomic_load_64(x) __atomic_load_n(x, __ATOMIC_SEQ_CST)
55#define hdr_atomic_store_64(f,v) __atomic_store_n(f,v, __ATOMIC_SEQ_CST)
56#define hdr_atomic_exchange_64(f,i) __atomic_exchange_n(f,i, __ATOMIC_SEQ_CST)
57#define hdr_atomic_add_fetch_64(field, value) __atomic_add_fetch(field, value, __ATOMIC_SEQ_CST)
58
59#elif defined(__x86_64__)
60
61static void inline * hdr_atomic_load_pointer(void** pointer)
62{
63   void* p =  *(volatile void**)pointer;
64	__asm__ volatile ("" ::: "memory");
65	return p;
66}
67
68static void inline hdr_atomic_store_pointer(void** pointer, void* value)
69{
70    __asm__ volatile ("lock; xchg %0, %1" : "+q" (value) "+m" (*pointer));
71}
72
73static int64_t inline hdr_atomic_load_64(int64_t* field)
74{
75    int64_t i = *field;
76	__asm__ volatile ("" ::: "memory");
77	return *field;
78}
79
80static void inline hdr_atomic_store_64(int64_t* field, int64_t value)
81{
82    __asm__ volatile ("lock; xchgq %0, %1" : "+q" (value) "+m" (*field));
83}
84
85static int64_t inline hdr_atomic_exchange_64(volatile int64_t* field, int64_t initial)
86{
87    int64_t result = 0;
88    __asm__ volatile ("lock; xchgq %0, %1" : "=r" (result) "+q" (value) "+m" (*field));
89    return result;
90}
91
92static int64_t inline hdr_atomic_add_fetch_64(volatile int64_t* field, int64_t value)
93{
94    int64_t result;
95    __asm__ volatile("lock; xaddq %0, %1" : "=r"(result), "+m"(*field) : "0"(value));
96    return result;
97}
98
99#else
100
101#error "Unable to determine atomic operations for your platform"
102
103#endif /* HDR_ATOMIC_H__ */
104