eathread_fake_atomic_64.cpp 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. /// Pseudo implementation of 64 bit primitives modelled after Android's internals.
  5. /// Return values and semantics are intended to be the same as 32 bit versions.
  6. ///
  7. /// Basically just does a mutex lock around the operation. Rather than just
  8. /// one global lock, uses a fixed set of mutexes to lock based on incoming
  9. /// address to reduce contention.
  10. ///
  11. /// Abuses the fact that the initializer for a pthread_mutex_t in Android is
  12. /// simply "{0}" on a volatile int to avoid requiring global initialization of
  13. /// these mutexes.
  14. #include <EABase/eabase.h>
  15. #if defined(EA_PLATFORM_ANDROID)
  16. #include <pthread.h>
  17. namespace EA
  18. {
  19. namespace Thread
  20. {
  21. #define EAT_FAKE_ATOMIC_SWAP_LOCK_COUNT 32U
  22. static pthread_mutex_t sFakeAtomic64SwapLocks[EAT_FAKE_ATOMIC_SWAP_LOCK_COUNT];
  23. #define EAT_SWAP_LOCK(addr) &sFakeAtomic64SwapLocks[((unsigned)(void*)(addr) >> 3U) % EAT_FAKE_ATOMIC_SWAP_LOCK_COUNT]
  24. int64_t android_fake_atomic_swap_64(int64_t value, volatile int64_t* addr)
  25. {
  26. int64_t oldValue;
  27. pthread_mutex_t* lock = EAT_SWAP_LOCK(addr);
  28. pthread_mutex_lock(lock);
  29. oldValue = *addr;
  30. *addr = value;
  31. pthread_mutex_unlock(lock);
  32. return oldValue;
  33. }
  34. int android_fake_atomic_cmpxchg_64(int64_t oldvalue, int64_t newvalue, volatile int64_t* addr)
  35. {
  36. int ret;
  37. pthread_mutex_t* lock = EAT_SWAP_LOCK(addr);
  38. pthread_mutex_lock(lock);
  39. if (*addr == oldvalue)
  40. {
  41. *addr = newvalue;
  42. ret = 0;
  43. }
  44. else
  45. {
  46. ret = 1;
  47. }
  48. pthread_mutex_unlock(lock);
  49. return ret;
  50. }
  51. int64_t android_fake_atomic_read_64(volatile int64_t* addr)
  52. {
  53. int64_t ret;
  54. pthread_mutex_t* lock = EAT_SWAP_LOCK(addr);
  55. pthread_mutex_lock(lock);
  56. ret = *addr;
  57. pthread_mutex_unlock(lock);
  58. return ret;
  59. }
  60. } // namespace Thread
  61. } // namespace EA
  62. #endif // #if defined(EA_PLATFORM_ANDROID)