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.

206 lines
4.7KB

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