atm_windows.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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. #ifndef GRPC_IMPL_CODEGEN_ATM_WINDOWS_H
  19. #define GRPC_IMPL_CODEGEN_ATM_WINDOWS_H
  20. // IWYU pragma: private, include <grpc/support/atm.h>
  21. /** Win32 variant of atm_platform.h */
  22. #include <grpc/impl/codegen/port_platform.h>
  23. #ifdef GPR_WINDOWS
  24. typedef intptr_t gpr_atm;
  25. #define GPR_ATM_MAX INTPTR_MAX
  26. #define GPR_ATM_MIN INTPTR_MIN
  27. #define GPR_ATM_INC_CAS_THEN(blah) blah
  28. #define GPR_ATM_INC_ADD_THEN(blah) blah
  29. #define gpr_atm_full_barrier MemoryBarrier
  30. static __inline gpr_atm gpr_atm_acq_load(const gpr_atm* p) {
  31. gpr_atm result = *p;
  32. gpr_atm_full_barrier();
  33. return result;
  34. }
  35. static __inline gpr_atm gpr_atm_no_barrier_load(const gpr_atm* p) {
  36. /* TODO(dklempner): Can we implement something better here? */
  37. return gpr_atm_acq_load(p);
  38. }
  39. static __inline void gpr_atm_rel_store(gpr_atm* p, gpr_atm value) {
  40. gpr_atm_full_barrier();
  41. *p = value;
  42. }
  43. static __inline void gpr_atm_no_barrier_store(gpr_atm* p, gpr_atm value) {
  44. /* TODO(ctiller): Can we implement something better here? */
  45. gpr_atm_rel_store(p, value);
  46. }
  47. static __inline int gpr_atm_no_barrier_cas(gpr_atm* p, gpr_atm o, gpr_atm n) {
  48. /** InterlockedCompareExchangePointerNoFence() not available on vista or
  49. windows7 */
  50. #ifdef GPR_ARCH_64
  51. return o == (gpr_atm)InterlockedCompareExchangeAcquire64(
  52. (volatile LONGLONG*)p, (LONGLONG)n, (LONGLONG)o);
  53. #else
  54. return o == (gpr_atm)InterlockedCompareExchangeAcquire((volatile LONG*)p,
  55. (LONG)n, (LONG)o);
  56. #endif
  57. }
  58. static __inline int gpr_atm_acq_cas(gpr_atm* p, gpr_atm o, gpr_atm n) {
  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. static __inline int gpr_atm_rel_cas(gpr_atm* p, gpr_atm o, gpr_atm n) {
  68. #ifdef GPR_ARCH_64
  69. return o == (gpr_atm)InterlockedCompareExchangeRelease64(
  70. (volatile LONGLONG*)p, (LONGLONG)n, (LONGLONG)o);
  71. #else
  72. return o == (gpr_atm)InterlockedCompareExchangeRelease((volatile LONG*)p,
  73. (LONG)n, (LONG)o);
  74. #endif
  75. }
  76. static __inline int gpr_atm_full_cas(gpr_atm* p, gpr_atm o, gpr_atm n) {
  77. #ifdef GPR_ARCH_64
  78. return o == (gpr_atm)InterlockedCompareExchange64((volatile LONGLONG*)p,
  79. (LONGLONG)n, (LONGLONG)o);
  80. #else
  81. return o == (gpr_atm)InterlockedCompareExchange((volatile LONG*)p, (LONG)n,
  82. (LONG)o);
  83. #endif
  84. }
  85. static __inline gpr_atm gpr_atm_no_barrier_fetch_add(gpr_atm* p,
  86. gpr_atm delta) {
  87. /** Use the CAS operation to get pointer-sized fetch and add */
  88. gpr_atm old;
  89. do {
  90. old = *p;
  91. } while (!gpr_atm_no_barrier_cas(p, old, old + delta));
  92. return old;
  93. }
  94. static __inline gpr_atm gpr_atm_full_fetch_add(gpr_atm* p, gpr_atm delta) {
  95. /** Use a CAS operation to get pointer-sized fetch and add */
  96. gpr_atm old;
  97. #ifdef GPR_ARCH_64
  98. do {
  99. old = *p;
  100. } while (old != (gpr_atm)InterlockedCompareExchange64((volatile LONGLONG*)p,
  101. (LONGLONG)old + delta,
  102. (LONGLONG)old));
  103. #else
  104. do {
  105. old = *p;
  106. } while (old != (gpr_atm)InterlockedCompareExchange(
  107. (volatile LONG*)p, (LONG)old + delta, (LONG)old));
  108. #endif
  109. return old;
  110. }
  111. static __inline gpr_atm gpr_atm_full_xchg(gpr_atm* p, gpr_atm n) {
  112. return (gpr_atm)InterlockedExchangePointer((PVOID*)p, (PVOID)n);
  113. }
  114. #endif /* GPR_WINDOWS */
  115. #endif /* GRPC_IMPL_CODEGEN_ATM_WINDOWS_H */