jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
4.4KB

  1. /*
  2. Copyright (C) 2004-2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #ifndef __JackAtomic__
  16. #define __JackAtomic__
  17. #include "JackTypes.h"
  18. #if defined(__APPLE__)
  19. #if defined(__ppc__) || defined(__ppc64__)
  20. static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
  21. {
  22. register int result;
  23. asm volatile (
  24. "# CAS \n"
  25. " lwarx r0, 0, %1 \n" // creates a reservation on addr
  26. " cmpw r0, %2 \n" // test value at addr
  27. " bne- 1f \n"
  28. " sync \n" // synchronize instructions
  29. " stwcx. %3, 0, %1 \n" // if the reservation is not altered
  30. // stores the new value at addr
  31. " bne- 1f \n"
  32. " li %0, 1 \n"
  33. " b 2f \n"
  34. "1: \n"
  35. " li %0, 0 \n"
  36. "2: \n"
  37. : "=r" (result)
  38. : "r" (addr), "r" (value), "r" (newvalue)
  39. : "r0"
  40. );
  41. return result;
  42. }
  43. #endif
  44. #if defined(__i386__) || defined(__x86_64__)
  45. #ifdef __SMP__
  46. # define LOCK "lock ; "
  47. #else
  48. # define LOCK ""
  49. #endif
  50. static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
  51. {
  52. register char ret;
  53. __asm__ __volatile__ (
  54. "# CAS \n\t"
  55. LOCK "cmpxchg %2, (%1) \n\t"
  56. "sete %0 \n\t"
  57. : "=a" (ret)
  58. : "c" (addr), "d" (newvalue), "a" (value)
  59. );
  60. return ret;
  61. }
  62. #endif
  63. #endif
  64. #ifdef __linux__
  65. #ifdef __PPC__
  66. static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
  67. {
  68. register int result;
  69. register UInt32 tmp;
  70. asm volatile (
  71. "# CAS \n"
  72. " lwarx %4, 0, %1 \n" // creates a reservation on addr
  73. " cmpw %4, %2 \n" // test value at addr
  74. " bne- 1f \n"
  75. " sync \n" // synchronize instructions
  76. " stwcx. %3, 0, %1 \n" // if the reservation is not altered
  77. // stores the new value at addr
  78. " bne- 1f \n"
  79. " li %0, 1 \n"
  80. " b 2f \n"
  81. "1: \n"
  82. " li %0, 0 \n"
  83. "2: \n"
  84. : "=r" (result)
  85. : "r" (addr), "r" (value), "r" (newvalue), "r" (tmp)
  86. );
  87. return result;
  88. }
  89. #endif
  90. #if defined(__i386__) || defined(__x86_64__)
  91. #ifdef __SMP__
  92. # define LOCK "lock ; "
  93. #else
  94. # define LOCK ""
  95. #endif
  96. static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
  97. {
  98. register char ret;
  99. __asm__ __volatile__ (
  100. "# CAS \n\t"
  101. LOCK "cmpxchg %2, (%1) \n\t"
  102. "sete %0 \n\t"
  103. : "=a" (ret)
  104. : "c" (addr), "d" (newvalue), "a" (value)
  105. );
  106. return ret;
  107. }
  108. #endif
  109. #endif
  110. #ifdef WIN32
  111. #ifdef __SMP__
  112. # define LOCK lock
  113. #else
  114. # define LOCK
  115. #endif
  116. #define inline __inline
  117. //----------------------------------------------------------------
  118. // CAS functions
  119. //----------------------------------------------------------------
  120. inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void * addr)
  121. {
  122. register char c;
  123. __asm {
  124. push ebx
  125. push esi
  126. mov esi, addr
  127. mov eax, value
  128. mov ebx, newvalue
  129. LOCK cmpxchg dword ptr [esi], ebx
  130. sete c
  131. pop esi
  132. pop ebx
  133. }
  134. return c;
  135. }
  136. #endif
  137. static inline long INC_ATOMIC(volatile SInt32* val)
  138. {
  139. SInt32 actual;
  140. do {
  141. actual = *val;
  142. } while (!CAS(actual, actual + 1, val));
  143. return actual;
  144. }
  145. static inline long DEC_ATOMIC(volatile SInt32* val)
  146. {
  147. SInt32 actual;
  148. do {
  149. actual = *val;
  150. } while (!CAS(actual, actual - 1, val));
  151. return actual;
  152. }
  153. #endif