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.

198 lines
4.5KB

  1. /*
  2. Copyright (C) 2004-2006 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. typedef unsigned short UInt16;
  18. typedef unsigned long UInt32;
  19. typedef long SInt32;
  20. #ifdef WIN32
  21. #include <windows.h>
  22. typedef ULONGLONG UInt64;
  23. #else
  24. typedef unsigned long long UInt64;
  25. #endif
  26. #if defined(__APPLE__)
  27. #if defined(__ppc__)
  28. static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
  29. {
  30. register int result;
  31. asm volatile (
  32. "# CAS \n"
  33. " lwarx r0, 0, %1 \n" // creates a reservation on addr
  34. " cmpw r0, %2 \n" // test value at addr
  35. " bne- 1f \n"
  36. " sync \n" // synchronize instructions
  37. " stwcx. %3, 0, %1 \n" // if the reservation is not altered
  38. // stores the new value at addr
  39. " bne- 1f \n"
  40. " li %0, 1 \n"
  41. " b 2f \n"
  42. "1: \n"
  43. " li %0, 0 \n"
  44. "2: \n"
  45. : "=r" (result)
  46. : "r" (addr), "r" (value), "r" (newvalue)
  47. : "r0"
  48. );
  49. return result;
  50. }
  51. #endif
  52. #if defined(__i386__) || defined(__x86_64__)
  53. #ifdef __SMP__
  54. # define LOCK "lock ; "
  55. #else
  56. # define LOCK ""
  57. #endif
  58. static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
  59. {
  60. register char ret;
  61. __asm__ __volatile__ (
  62. "# CAS \n\t"
  63. LOCK "cmpxchg %2, (%1) \n\t"
  64. "sete %0 \n\t"
  65. : "=a" (ret)
  66. : "c" (addr), "d" (newvalue), "a" (value)
  67. );
  68. return ret;
  69. }
  70. #endif
  71. #endif
  72. #ifdef __linux__
  73. #ifdef __PPC__
  74. static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
  75. {
  76. register int result;
  77. register UInt32 tmp;
  78. asm volatile (
  79. "# CAS \n"
  80. " lwarx %4, 0, %1 \n" // creates a reservation on addr
  81. " cmpw %4, %2 \n" // test value at addr
  82. " bne- 1f \n"
  83. " sync \n" // synchronize instructions
  84. " stwcx. %3, 0, %1 \n" // if the reservation is not altered
  85. // stores the new value at addr
  86. " bne- 1f \n"
  87. " li %0, 1 \n"
  88. " b 2f \n"
  89. "1: \n"
  90. " li %0, 0 \n"
  91. "2: \n"
  92. : "=r" (result)
  93. : "r" (addr), "r" (value), "r" (newvalue), "r" (tmp)
  94. );
  95. return result;
  96. }
  97. #endif
  98. #if defined(__i386__) || defined(__x86_64__)
  99. #ifdef __SMP__
  100. # define LOCK "lock ; "
  101. #else
  102. # define LOCK ""
  103. #endif
  104. static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
  105. {
  106. register char ret;
  107. __asm__ __volatile__ (
  108. "# CAS \n\t"
  109. LOCK "cmpxchg %2, (%1) \n\t"
  110. "sete %0 \n\t"
  111. : "=a" (ret)
  112. : "c" (addr), "d" (newvalue), "a" (value)
  113. );
  114. return ret;
  115. }
  116. #endif
  117. #endif
  118. #ifdef WIN32
  119. #ifdef __SMP__
  120. # define LOCK lock
  121. #else
  122. # define LOCK
  123. #endif
  124. #define inline __inline
  125. //----------------------------------------------------------------
  126. // CAS functions
  127. //----------------------------------------------------------------
  128. inline char CAS (volatile UInt32 value, UInt32 newvalue, volatile void * addr)
  129. {
  130. register char c;
  131. __asm {
  132. push ebx
  133. push esi
  134. mov esi, addr
  135. mov eax, value
  136. mov ebx, newvalue
  137. LOCK cmpxchg dword ptr [esi], ebx
  138. sete c
  139. pop esi
  140. pop ebx
  141. }
  142. return c;
  143. }
  144. #endif
  145. static inline long INC_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. static inline long DEC_ATOMIC(volatile SInt32* val)
  154. {
  155. SInt32 actual;
  156. do {
  157. actual = *val;
  158. } while (!CAS(actual, actual - 1, val));
  159. return actual;
  160. }
  161. #endif