atomic.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #ifndef _rA_ATOMIC_H_
  4. #define _rA_ATOMIC_H_
  5. // Atomic Operations
  6. // (Interlocked CompareExchange, Add .. and so on ..)
  7. //
  8. // Implementation varies / depends on:
  9. // - Architecture
  10. // - Compiler
  11. // - Operating System
  12. //
  13. // our Abstraction is fully API-Compatible to Microsofts implementation @ NT5.0+
  14. //
  15. #include "../common/cbasetypes.h"
  16. #if defined(_MSC_VER)
  17. #include "../common/winapi.h"
  18. #if !defined(_M_X64)
  19. // When compiling for windows 32bit, the 8byte interlocked operations are not provided by microsoft
  20. // (because they need at least i586 so its not generic enough.. ... )
  21. forceinline int64 InterlockedCompareExchange64(volatile int64 *dest, int64 exch, int64 _cmp){
  22. _asm{
  23. lea esi,_cmp;
  24. lea edi,exch;
  25. mov eax,[esi];
  26. mov edx,4[esi];
  27. mov ebx,[edi];
  28. mov ecx,4[edi];
  29. mov esi,dest;
  30. lock CMPXCHG8B [esi];
  31. }
  32. }
  33. forceinline volatile int64 InterlockedIncrement64(volatile int64 *addend){
  34. __int64 old;
  35. do{
  36. old = *addend;
  37. }while(InterlockedCompareExchange64(addend, (old+1), old) != old);
  38. return (old + 1);
  39. }
  40. forceinline volatile int64 InterlockedDecrement64(volatile int64 *addend){
  41. __int64 old;
  42. do{
  43. old = *addend;
  44. }while(InterlockedCompareExchange64(addend, (old-1), old) != old);
  45. return (old - 1);
  46. }
  47. forceinline volatile int64 InterlockedExchangeAdd64(volatile int64 *addend, int64 increment){
  48. __int64 old;
  49. do{
  50. old = *addend;
  51. }while(InterlockedCompareExchange64(addend, (old + increment), old) != old);
  52. return old;
  53. }
  54. forceinline volatile int64 InterlockedExchange64(volatile int64 *target, int64 val){
  55. __int64 old;
  56. do{
  57. old = *target;
  58. }while(InterlockedCompareExchange64(target, val, old) != old);
  59. return old;
  60. }
  61. #endif //endif 32bit windows
  62. #elif defined(__GNUC__)
  63. #if !defined(__x86_64__) && !defined(__i386__)
  64. #error Your Target Platfrom is not supported
  65. #endif
  66. static forceinline int64 InterlockedExchangeAdd64(volatile int64 *addend, int64 increment){
  67. return __sync_fetch_and_add(addend, increment);
  68. }//end: InterlockedExchangeAdd64()
  69. static forceinline int32 InterlockedExchangeAdd(volatile int32 *addend, int32 increment){
  70. return __sync_fetch_and_add(addend, increment);
  71. }//end: InterlockedExchangeAdd()
  72. static forceinline int64 InterlockedIncrement64(volatile int64 *addend){
  73. return __sync_add_and_fetch(addend, 1);
  74. }//end: InterlockedIncrement64()
  75. static forceinline int32 InterlockedIncrement(volatile int32 *addend){
  76. return __sync_add_and_fetch(addend, 1);
  77. }//end: InterlockedIncrement()
  78. static forceinline int64 InterlockedDecrement64(volatile int64 *addend){
  79. return __sync_sub_and_fetch(addend, 1);
  80. }//end: InterlockedDecrement64()
  81. static forceinline int32 InterlockedDecrement(volatile int32 *addend){
  82. return __sync_sub_and_fetch(addend, 1);
  83. }//end: InterlockedDecrement()
  84. static forceinline int64 InterlockedCompareExchange64(volatile int64 *dest, int64 exch, int64 cmp){
  85. return __sync_val_compare_and_swap(dest, cmp, exch);
  86. }//end: InterlockedCompareExchange64()
  87. static forceinline int32 InterlockedCompareExchange(volatile int32 *dest, int32 exch, int32 cmp){
  88. return __sync_val_compare_and_swap(dest, cmp, exch);
  89. }//end: InterlockedCompareExchnage()
  90. static forceinline int64 InterlockedExchange64(volatile int64 *target, int64 val){
  91. return __sync_lock_test_and_set(target, val);
  92. }//end: InterlockedExchange64()
  93. static forceinline int32 InterlockedExchange(volatile int32 *target, int32 val){
  94. return __sync_lock_test_and_set(target, val);
  95. }//end: InterlockedExchange()
  96. #endif //endif compiler decission
  97. #endif