1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #ifndef GRPC_SUPPORT_ATM_WINDOWS_H
20 #define GRPC_SUPPORT_ATM_WINDOWS_H
21
22 /** Win32 variant of atm_platform.h */
23 #include <grpc/support/port_platform.h>
24
25 #ifdef GPR_WINDOWS
26
27 typedef intptr_t gpr_atm;
28 #define GPR_ATM_MAX INTPTR_MAX
29 #define GPR_ATM_MIN INTPTR_MIN
30
31 #define gpr_atm_full_barrier MemoryBarrier
32
gpr_atm_acq_load(const gpr_atm * p)33 static __inline gpr_atm gpr_atm_acq_load(const gpr_atm* p) {
34 gpr_atm result = *p;
35 gpr_atm_full_barrier();
36 return result;
37 }
38
gpr_atm_no_barrier_load(const gpr_atm * p)39 static __inline gpr_atm gpr_atm_no_barrier_load(const gpr_atm* p) {
40 /* TODO(dklempner): Can we implement something better here? */
41 return gpr_atm_acq_load(p);
42 }
43
gpr_atm_rel_store(gpr_atm * p,gpr_atm value)44 static __inline void gpr_atm_rel_store(gpr_atm* p, gpr_atm value) {
45 gpr_atm_full_barrier();
46 *p = value;
47 }
48
gpr_atm_no_barrier_store(gpr_atm * p,gpr_atm value)49 static __inline void gpr_atm_no_barrier_store(gpr_atm* p, gpr_atm value) {
50 /* TODO(ctiller): Can we implement something better here? */
51 gpr_atm_rel_store(p, value);
52 }
53
gpr_atm_no_barrier_cas(gpr_atm * p,gpr_atm o,gpr_atm n)54 static __inline int gpr_atm_no_barrier_cas(gpr_atm* p, gpr_atm o, gpr_atm n) {
55 /** InterlockedCompareExchangePointerNoFence() not available on vista or
56 windows7 */
57 #ifdef GPR_ARCH_64
58 return o == (gpr_atm)InterlockedCompareExchangeAcquire64(
59 (volatile LONGLONG*)p, (LONGLONG)n, (LONGLONG)o);
60 #else
61 return o == (gpr_atm)InterlockedCompareExchangeAcquire((volatile LONG*)p,
62 (LONG)n, (LONG)o);
63 #endif
64 }
65
gpr_atm_acq_cas(gpr_atm * p,gpr_atm o,gpr_atm n)66 static __inline int gpr_atm_acq_cas(gpr_atm* p, gpr_atm o, gpr_atm n) {
67 #ifdef GPR_ARCH_64
68 return o == (gpr_atm)InterlockedCompareExchangeAcquire64(
69 (volatile LONGLONG*)p, (LONGLONG)n, (LONGLONG)o);
70 #else
71 return o == (gpr_atm)InterlockedCompareExchangeAcquire((volatile LONG*)p,
72 (LONG)n, (LONG)o);
73 #endif
74 }
75
gpr_atm_rel_cas(gpr_atm * p,gpr_atm o,gpr_atm n)76 static __inline int gpr_atm_rel_cas(gpr_atm* p, gpr_atm o, gpr_atm n) {
77 #ifdef GPR_ARCH_64
78 return o == (gpr_atm)InterlockedCompareExchangeRelease64(
79 (volatile LONGLONG*)p, (LONGLONG)n, (LONGLONG)o);
80 #else
81 return o == (gpr_atm)InterlockedCompareExchangeRelease((volatile LONG*)p,
82 (LONG)n, (LONG)o);
83 #endif
84 }
85
gpr_atm_full_cas(gpr_atm * p,gpr_atm o,gpr_atm n)86 static __inline int gpr_atm_full_cas(gpr_atm* p, gpr_atm o, gpr_atm n) {
87 #ifdef GPR_ARCH_64
88 return o == (gpr_atm)InterlockedCompareExchange64((volatile LONGLONG*)p,
89 (LONGLONG)n, (LONGLONG)o);
90 #else
91 return o == (gpr_atm)InterlockedCompareExchange((volatile LONG*)p, (LONG)n,
92 (LONG)o);
93 #endif
94 }
95
gpr_atm_no_barrier_fetch_add(gpr_atm * p,gpr_atm delta)96 static __inline gpr_atm gpr_atm_no_barrier_fetch_add(gpr_atm* p,
97 gpr_atm delta) {
98 /** Use the CAS operation to get pointer-sized fetch and add */
99 gpr_atm old;
100 do {
101 old = *p;
102 } while (!gpr_atm_no_barrier_cas(p, old, old + delta));
103 return old;
104 }
105
gpr_atm_full_fetch_add(gpr_atm * p,gpr_atm delta)106 static __inline gpr_atm gpr_atm_full_fetch_add(gpr_atm* p, gpr_atm delta) {
107 /** Use a CAS operation to get pointer-sized fetch and add */
108 gpr_atm old;
109 #ifdef GPR_ARCH_64
110 do {
111 old = *p;
112 } while (old != (gpr_atm)InterlockedCompareExchange64((volatile LONGLONG*)p,
113 (LONGLONG)old + delta,
114 (LONGLONG)old));
115 #else
116 do {
117 old = *p;
118 } while (old != (gpr_atm)InterlockedCompareExchange(
119 (volatile LONG*)p, (LONG)old + delta, (LONG)old));
120 #endif
121 return old;
122 }
123
gpr_atm_full_xchg(gpr_atm * p,gpr_atm n)124 static __inline gpr_atm gpr_atm_full_xchg(gpr_atm* p, gpr_atm n) {
125 return (gpr_atm)InterlockedExchangePointer((PVOID*)p, (PVOID)n);
126 }
127
128 #endif /* GPR_WINDOWS */
129
130 #endif /* GRPC_SUPPORT_ATM_WINDOWS_H */
131