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_IMPL_CODEGEN_ATM_WINDOWS_H
20 #define GRPC_IMPL_CODEGEN_ATM_WINDOWS_H
21
22 /** Win32 variant of atm_platform.h */
23 #include <grpc/impl/codegen/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 #define GPR_ATM_INC_CAS_THEN(blah) blah
31 #define GPR_ATM_INC_ADD_THEN(blah) blah
32
33 #define gpr_atm_full_barrier MemoryBarrier
34
gpr_atm_acq_load(const gpr_atm * p)35 static __inline gpr_atm gpr_atm_acq_load(const gpr_atm* p) {
36 gpr_atm result = *p;
37 gpr_atm_full_barrier();
38 return result;
39 }
40
gpr_atm_no_barrier_load(const gpr_atm * p)41 static __inline gpr_atm gpr_atm_no_barrier_load(const gpr_atm* p) {
42 /* TODO(dklempner): Can we implement something better here? */
43 return gpr_atm_acq_load(p);
44 }
45
gpr_atm_rel_store(gpr_atm * p,gpr_atm value)46 static __inline void gpr_atm_rel_store(gpr_atm* p, gpr_atm value) {
47 gpr_atm_full_barrier();
48 *p = value;
49 }
50
gpr_atm_no_barrier_store(gpr_atm * p,gpr_atm value)51 static __inline void gpr_atm_no_barrier_store(gpr_atm* p, gpr_atm value) {
52 /* TODO(ctiller): Can we implement something better here? */
53 gpr_atm_rel_store(p, value);
54 }
55
gpr_atm_no_barrier_cas(gpr_atm * p,gpr_atm o,gpr_atm n)56 static __inline int gpr_atm_no_barrier_cas(gpr_atm* p, gpr_atm o, gpr_atm n) {
57 /** InterlockedCompareExchangePointerNoFence() not available on vista or
58 windows7 */
59 #ifdef GPR_ARCH_64
60 return o == (gpr_atm)InterlockedCompareExchangeAcquire64(
61 (volatile LONGLONG*)p, (LONGLONG)n, (LONGLONG)o);
62 #else
63 return o == (gpr_atm)InterlockedCompareExchangeAcquire((volatile LONG*)p,
64 (LONG)n, (LONG)o);
65 #endif
66 }
67
gpr_atm_acq_cas(gpr_atm * p,gpr_atm o,gpr_atm n)68 static __inline int gpr_atm_acq_cas(gpr_atm* p, gpr_atm o, gpr_atm n) {
69 #ifdef GPR_ARCH_64
70 return o == (gpr_atm)InterlockedCompareExchangeAcquire64(
71 (volatile LONGLONG*)p, (LONGLONG)n, (LONGLONG)o);
72 #else
73 return o == (gpr_atm)InterlockedCompareExchangeAcquire((volatile LONG*)p,
74 (LONG)n, (LONG)o);
75 #endif
76 }
77
gpr_atm_rel_cas(gpr_atm * p,gpr_atm o,gpr_atm n)78 static __inline int gpr_atm_rel_cas(gpr_atm* p, gpr_atm o, gpr_atm n) {
79 #ifdef GPR_ARCH_64
80 return o == (gpr_atm)InterlockedCompareExchangeRelease64(
81 (volatile LONGLONG*)p, (LONGLONG)n, (LONGLONG)o);
82 #else
83 return o == (gpr_atm)InterlockedCompareExchangeRelease((volatile LONG*)p,
84 (LONG)n, (LONG)o);
85 #endif
86 }
87
gpr_atm_full_cas(gpr_atm * p,gpr_atm o,gpr_atm n)88 static __inline int gpr_atm_full_cas(gpr_atm* p, gpr_atm o, gpr_atm n) {
89 #ifdef GPR_ARCH_64
90 return o == (gpr_atm)InterlockedCompareExchange64((volatile LONGLONG*)p,
91 (LONGLONG)n, (LONGLONG)o);
92 #else
93 return o == (gpr_atm)InterlockedCompareExchange((volatile LONG*)p, (LONG)n,
94 (LONG)o);
95 #endif
96 }
97
gpr_atm_no_barrier_fetch_add(gpr_atm * p,gpr_atm delta)98 static __inline gpr_atm gpr_atm_no_barrier_fetch_add(gpr_atm* p,
99 gpr_atm delta) {
100 /** Use the CAS operation to get pointer-sized fetch and add */
101 gpr_atm old;
102 do {
103 old = *p;
104 } while (!gpr_atm_no_barrier_cas(p, old, old + delta));
105 return old;
106 }
107
gpr_atm_full_fetch_add(gpr_atm * p,gpr_atm delta)108 static __inline gpr_atm gpr_atm_full_fetch_add(gpr_atm* p, gpr_atm delta) {
109 /** Use a CAS operation to get pointer-sized fetch and add */
110 gpr_atm old;
111 #ifdef GPR_ARCH_64
112 do {
113 old = *p;
114 } while (old != (gpr_atm)InterlockedCompareExchange64((volatile LONGLONG*)p,
115 (LONGLONG)old + delta,
116 (LONGLONG)old));
117 #else
118 do {
119 old = *p;
120 } while (old != (gpr_atm)InterlockedCompareExchange(
121 (volatile LONG*)p, (LONG)old + delta, (LONG)old));
122 #endif
123 return old;
124 }
125
gpr_atm_full_xchg(gpr_atm * p,gpr_atm n)126 static __inline gpr_atm gpr_atm_full_xchg(gpr_atm* p, gpr_atm n) {
127 return (gpr_atm)InterlockedExchangePointer((PVOID*)p, (PVOID)n);
128 }
129
130 #endif /* GPR_WINDOWS */
131
132 #endif /* GRPC_IMPL_CODEGEN_ATM_WINDOWS_H */
133