fifo_index.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * Copyright (C) 2016 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <errno.h>
  17. #include <limits.h>
  18. #include <audio_utils/fifo_index.h>
  19. #include <audio_utils/futex.h>
  20. // These are not implemented within <audio_utils/fifo_index.h>
  21. // so that we don't expose futex.
  22. uint32_t audio_utils_fifo_index::loadAcquire()
  23. {
  24. return atomic_load_explicit(&mIndex, std::memory_order_acquire);
  25. }
  26. // FIXME should inline this, so that writer32 can also inline it
  27. void audio_utils_fifo_index::storeRelease(uint32_t value)
  28. {
  29. atomic_store_explicit(&mIndex, value, std::memory_order_release);
  30. }
  31. int audio_utils_fifo_index::wait(int op, uint32_t expected, const struct timespec *timeout)
  32. {
  33. return sys_futex(&mIndex, op, expected, timeout, NULL, 0);
  34. }
  35. int audio_utils_fifo_index::wake(int op, int waiters)
  36. {
  37. return sys_futex(&mIndex, op, waiters, NULL, NULL, 0);
  38. }
  39. uint32_t audio_utils_fifo_index::loadConsume()
  40. {
  41. return atomic_load_explicit(&mIndex, std::memory_order_consume);
  42. }
  43. ////
  44. RefIndexDeferredStoreReleaseDeferredWake::RefIndexDeferredStoreReleaseDeferredWake(
  45. audio_utils_fifo_index& index)
  46. : mIndex(index), mValue(0), mWriteback(false), mWaiters(0), mWakeOp(FUTEX_WAIT_PRIVATE)
  47. {
  48. }
  49. RefIndexDeferredStoreReleaseDeferredWake::~RefIndexDeferredStoreReleaseDeferredWake()
  50. {
  51. writeback();
  52. wakeNowIfNeeded();
  53. }
  54. void RefIndexDeferredStoreReleaseDeferredWake::set(uint32_t value) {
  55. mValue = value;
  56. mWriteback = true;
  57. }
  58. void RefIndexDeferredStoreReleaseDeferredWake::writeback()
  59. {
  60. if (mWriteback) {
  61. // TODO When part of a collection, should use relaxed for all but the last writeback
  62. mIndex.storeRelease(mValue);
  63. mWriteback = false;
  64. }
  65. }
  66. void RefIndexDeferredStoreReleaseDeferredWake::writethrough(uint32_t value) {
  67. set(value);
  68. writeback();
  69. }
  70. void RefIndexDeferredStoreReleaseDeferredWake::wakeDeferred(int op, int waiters)
  71. {
  72. if (waiters <= 0) {
  73. return;
  74. }
  75. // default is FUTEX_WAKE_PRIVATE
  76. if (op == FUTEX_WAKE) {
  77. mWakeOp = FUTEX_WAKE;
  78. }
  79. if (waiters < INT_MAX - mWaiters) {
  80. mWaiters += waiters;
  81. } else {
  82. mWaiters = INT_MAX;
  83. }
  84. }
  85. void RefIndexDeferredStoreReleaseDeferredWake::wakeNowIfNeeded()
  86. {
  87. if (mWaiters > 0) {
  88. mIndex.wake(mWakeOp, mWaiters);
  89. mWaiters = 0;
  90. mWakeOp = FUTEX_WAKE_PRIVATE;
  91. }
  92. }
  93. void RefIndexDeferredStoreReleaseDeferredWake::wakeNow(int op, int waiters)
  94. {
  95. wakeDeferred(op, waiters);
  96. wakeNowIfNeeded();
  97. }
  98. ////
  99. RefIndexCachedLoadAcquireDeferredWait::RefIndexCachedLoadAcquireDeferredWait(
  100. audio_utils_fifo_index& index)
  101. : mIndex(index), mValue(0), mLoaded(false)
  102. {
  103. }
  104. RefIndexCachedLoadAcquireDeferredWait::~RefIndexCachedLoadAcquireDeferredWait()
  105. {
  106. }
  107. uint32_t RefIndexCachedLoadAcquireDeferredWait::get()
  108. {
  109. prefetch();
  110. return mValue;
  111. }
  112. void RefIndexCachedLoadAcquireDeferredWait::prefetch()
  113. {
  114. if (!mLoaded) {
  115. // TODO When part of a collection, should use relaxed for all but the last load
  116. mValue = mIndex.loadAcquire();
  117. mLoaded = true;
  118. }
  119. }
  120. void RefIndexCachedLoadAcquireDeferredWait::invalidate()
  121. {
  122. mLoaded = false;
  123. }
  124. #if 0
  125. uint32_t RefIndexCachedLoadAcquireDeferredWait::readthrough()
  126. {
  127. invalidate();
  128. return get();
  129. }
  130. #endif
  131. int RefIndexCachedLoadAcquireDeferredWait::wait(int op, const struct timespec *timeout)
  132. {
  133. if (!mLoaded) {
  134. return -EINVAL;
  135. }
  136. int err = mIndex.wait(op, mValue /*expected*/, timeout);
  137. invalidate();
  138. return err;
  139. }