FastThread.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /*
  2. * Copyright (C) 2014 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. #define LOG_TAG "FastThread"
  17. //#define LOG_NDEBUG 0
  18. #define ATRACE_TAG ATRACE_TAG_AUDIO
  19. #include "Configuration.h"
  20. #include <linux/futex.h>
  21. #include <sys/syscall.h>
  22. #include <audio_utils/clock.h>
  23. #include <cutils/atomic.h>
  24. #include <utils/Log.h>
  25. #include <utils/Trace.h>
  26. #include "FastThread.h"
  27. #include "FastThreadDumpState.h"
  28. #include "TypedLogger.h"
  29. #define FAST_DEFAULT_NS 999999999L // ~1 sec: default time to sleep
  30. #define FAST_HOT_IDLE_NS 1000000L // 1 ms: time to sleep while hot idling
  31. #define MIN_WARMUP_CYCLES 2 // minimum number of consecutive in-range loop cycles
  32. // to wait for warmup
  33. #define MAX_WARMUP_CYCLES 10 // maximum number of loop cycles to wait for warmup
  34. namespace android {
  35. FastThread::FastThread(const char *cycleMs, const char *loadUs) : Thread(false /*canCallJava*/),
  36. // re-initialized to &sInitial by subclass constructor
  37. mPrevious(NULL), mCurrent(NULL),
  38. /* mOldTs({0, 0}), */
  39. mOldTsValid(false),
  40. mSleepNs(-1),
  41. mPeriodNs(0),
  42. mUnderrunNs(0),
  43. mOverrunNs(0),
  44. mForceNs(0),
  45. mWarmupNsMin(0),
  46. mWarmupNsMax(LONG_MAX),
  47. // re-initialized to &mDummySubclassDumpState by subclass constructor
  48. mDummyDumpState(NULL),
  49. mDumpState(NULL),
  50. mIgnoreNextOverrun(true),
  51. #ifdef FAST_THREAD_STATISTICS
  52. // mOldLoad
  53. mOldLoadValid(false),
  54. mBounds(0),
  55. mFull(false),
  56. // mTcu
  57. #endif
  58. mColdGen(0),
  59. mIsWarm(false),
  60. /* mMeasuredWarmupTs({0, 0}), */
  61. mWarmupCycles(0),
  62. mWarmupConsecutiveInRangeCycles(0),
  63. mTimestampStatus(INVALID_OPERATION),
  64. mCommand(FastThreadState::INITIAL),
  65. #if 0
  66. frameCount(0),
  67. #endif
  68. mAttemptedWrite(false)
  69. // mCycleMs(cycleMs)
  70. // mLoadUs(loadUs)
  71. {
  72. mOldTs.tv_sec = 0;
  73. mOldTs.tv_nsec = 0;
  74. mMeasuredWarmupTs.tv_sec = 0;
  75. mMeasuredWarmupTs.tv_nsec = 0;
  76. strlcpy(mCycleMs, cycleMs, sizeof(mCycleMs));
  77. strlcpy(mLoadUs, loadUs, sizeof(mLoadUs));
  78. }
  79. FastThread::~FastThread()
  80. {
  81. }
  82. bool FastThread::threadLoop()
  83. {
  84. // LOGT now works even if tlNBLogWriter is nullptr, but we're considering changing that,
  85. // so this initialization permits a future change to remove the check for nullptr.
  86. tlNBLogWriter = mDummyNBLogWriter.get();
  87. for (;;) {
  88. // either nanosleep, sched_yield, or busy wait
  89. if (mSleepNs >= 0) {
  90. if (mSleepNs > 0) {
  91. ALOG_ASSERT(mSleepNs < 1000000000);
  92. const struct timespec req = {0, mSleepNs};
  93. nanosleep(&req, NULL);
  94. } else {
  95. sched_yield();
  96. }
  97. }
  98. // default to long sleep for next cycle
  99. mSleepNs = FAST_DEFAULT_NS;
  100. // poll for state change
  101. const FastThreadState *next = poll();
  102. if (next == NULL) {
  103. // continue to use the default initial state until a real state is available
  104. // FIXME &sInitial not available, should save address earlier
  105. //ALOG_ASSERT(mCurrent == &sInitial && previous == &sInitial);
  106. next = mCurrent;
  107. }
  108. mCommand = next->mCommand;
  109. if (next != mCurrent) {
  110. // As soon as possible of learning of a new dump area, start using it
  111. mDumpState = next->mDumpState != NULL ? next->mDumpState : mDummyDumpState;
  112. tlNBLogWriter = next->mNBLogWriter != NULL ?
  113. next->mNBLogWriter : mDummyNBLogWriter.get();
  114. setNBLogWriter(tlNBLogWriter); // FastMixer informs its AudioMixer, FastCapture ignores
  115. // We want to always have a valid reference to the previous (non-idle) state.
  116. // However, the state queue only guarantees access to current and previous states.
  117. // So when there is a transition from a non-idle state into an idle state, we make a
  118. // copy of the last known non-idle state so it is still available on return from idle.
  119. // The possible transitions are:
  120. // non-idle -> non-idle update previous from current in-place
  121. // non-idle -> idle update previous from copy of current
  122. // idle -> idle don't update previous
  123. // idle -> non-idle don't update previous
  124. if (!(mCurrent->mCommand & FastThreadState::IDLE)) {
  125. if (mCommand & FastThreadState::IDLE) {
  126. onIdle();
  127. mOldTsValid = false;
  128. #ifdef FAST_THREAD_STATISTICS
  129. mOldLoadValid = false;
  130. #endif
  131. mIgnoreNextOverrun = true;
  132. }
  133. mPrevious = mCurrent;
  134. }
  135. mCurrent = next;
  136. }
  137. #if !LOG_NDEBUG
  138. next = NULL; // not referenced again
  139. #endif
  140. mDumpState->mCommand = mCommand;
  141. // FIXME what does this comment mean?
  142. // << current, previous, command, dumpState >>
  143. switch (mCommand) {
  144. case FastThreadState::INITIAL:
  145. case FastThreadState::HOT_IDLE:
  146. mSleepNs = FAST_HOT_IDLE_NS;
  147. continue;
  148. case FastThreadState::COLD_IDLE:
  149. // only perform a cold idle command once
  150. // FIXME consider checking previous state and only perform if previous != COLD_IDLE
  151. if (mCurrent->mColdGen != mColdGen) {
  152. int32_t *coldFutexAddr = mCurrent->mColdFutexAddr;
  153. ALOG_ASSERT(coldFutexAddr != NULL);
  154. int32_t old = android_atomic_dec(coldFutexAddr);
  155. if (old <= 0) {
  156. syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL);
  157. }
  158. int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK;
  159. if (!(policy == SCHED_FIFO || policy == SCHED_RR)) {
  160. ALOGE("did not receive expected priority boost on time");
  161. }
  162. // This may be overly conservative; there could be times that the normal mixer
  163. // requests such a brief cold idle that it doesn't require resetting this flag.
  164. mIsWarm = false;
  165. mMeasuredWarmupTs.tv_sec = 0;
  166. mMeasuredWarmupTs.tv_nsec = 0;
  167. mWarmupCycles = 0;
  168. mWarmupConsecutiveInRangeCycles = 0;
  169. mSleepNs = -1;
  170. mColdGen = mCurrent->mColdGen;
  171. #ifdef FAST_THREAD_STATISTICS
  172. mBounds = 0;
  173. mFull = false;
  174. #endif
  175. mOldTsValid = !clock_gettime(CLOCK_MONOTONIC, &mOldTs);
  176. mTimestampStatus = INVALID_OPERATION;
  177. } else {
  178. mSleepNs = FAST_HOT_IDLE_NS;
  179. }
  180. continue;
  181. case FastThreadState::EXIT:
  182. onExit();
  183. return false;
  184. default:
  185. LOG_ALWAYS_FATAL_IF(!isSubClassCommand(mCommand));
  186. break;
  187. }
  188. // there is a non-idle state available to us; did the state change?
  189. if (mCurrent != mPrevious) {
  190. onStateChange();
  191. #if 1 // FIXME shouldn't need this
  192. // only process state change once
  193. mPrevious = mCurrent;
  194. #endif
  195. }
  196. // do work using current state here
  197. mAttemptedWrite = false;
  198. onWork();
  199. // To be exactly periodic, compute the next sleep time based on current time.
  200. // This code doesn't have long-term stability when the sink is non-blocking.
  201. // FIXME To avoid drift, use the local audio clock or watch the sink's fill status.
  202. struct timespec newTs;
  203. int rc = clock_gettime(CLOCK_MONOTONIC, &newTs);
  204. if (rc == 0) {
  205. if (mOldTsValid) {
  206. time_t sec = newTs.tv_sec - mOldTs.tv_sec;
  207. long nsec = newTs.tv_nsec - mOldTs.tv_nsec;
  208. ALOGE_IF(sec < 0 || (sec == 0 && nsec < 0),
  209. "clock_gettime(CLOCK_MONOTONIC) failed: was %ld.%09ld but now %ld.%09ld",
  210. mOldTs.tv_sec, mOldTs.tv_nsec, newTs.tv_sec, newTs.tv_nsec);
  211. if (nsec < 0) {
  212. --sec;
  213. nsec += 1000000000;
  214. }
  215. // To avoid an initial underrun on fast tracks after exiting standby,
  216. // do not start pulling data from tracks and mixing until warmup is complete.
  217. // Warmup is considered complete after the earlier of:
  218. // MIN_WARMUP_CYCLES consecutive in-range write() attempts,
  219. // where "in-range" means mWarmupNsMin <= cycle time <= mWarmupNsMax
  220. // MAX_WARMUP_CYCLES write() attempts.
  221. // This is overly conservative, but to get better accuracy requires a new HAL API.
  222. if (!mIsWarm && mAttemptedWrite) {
  223. mMeasuredWarmupTs.tv_sec += sec;
  224. mMeasuredWarmupTs.tv_nsec += nsec;
  225. if (mMeasuredWarmupTs.tv_nsec >= 1000000000) {
  226. mMeasuredWarmupTs.tv_sec++;
  227. mMeasuredWarmupTs.tv_nsec -= 1000000000;
  228. }
  229. ++mWarmupCycles;
  230. if (mWarmupNsMin <= nsec && nsec <= mWarmupNsMax) {
  231. ALOGV("warmup cycle %d in range: %.03f ms", mWarmupCycles, nsec * 1e-9);
  232. ++mWarmupConsecutiveInRangeCycles;
  233. } else {
  234. ALOGV("warmup cycle %d out of range: %.03f ms", mWarmupCycles, nsec * 1e-9);
  235. mWarmupConsecutiveInRangeCycles = 0;
  236. }
  237. if ((mWarmupConsecutiveInRangeCycles >= MIN_WARMUP_CYCLES) ||
  238. (mWarmupCycles >= MAX_WARMUP_CYCLES)) {
  239. mIsWarm = true;
  240. mDumpState->mMeasuredWarmupTs = mMeasuredWarmupTs;
  241. mDumpState->mWarmupCycles = mWarmupCycles;
  242. const double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1e3) +
  243. (mMeasuredWarmupTs.tv_nsec * 1e-6);
  244. LOG_WARMUP_TIME(measuredWarmupMs);
  245. }
  246. }
  247. mSleepNs = -1;
  248. if (mIsWarm) {
  249. if (sec > 0 || nsec > mUnderrunNs) {
  250. ATRACE_NAME("underrun");
  251. // FIXME only log occasionally
  252. ALOGV("underrun: time since last cycle %d.%03ld sec",
  253. (int) sec, nsec / 1000000L);
  254. mDumpState->mUnderruns++;
  255. LOG_UNDERRUN(audio_utils_ns_from_timespec(&newTs));
  256. mIgnoreNextOverrun = true;
  257. } else if (nsec < mOverrunNs) {
  258. if (mIgnoreNextOverrun) {
  259. mIgnoreNextOverrun = false;
  260. } else {
  261. // FIXME only log occasionally
  262. ALOGV("overrun: time since last cycle %d.%03ld sec",
  263. (int) sec, nsec / 1000000L);
  264. mDumpState->mOverruns++;
  265. LOG_OVERRUN(audio_utils_ns_from_timespec(&newTs));
  266. }
  267. // This forces a minimum cycle time. It:
  268. // - compensates for an audio HAL with jitter due to sample rate conversion
  269. // - works with a variable buffer depth audio HAL that never pulls at a
  270. // rate < than mOverrunNs per buffer.
  271. // - recovers from overrun immediately after underrun
  272. // It doesn't work with a non-blocking audio HAL.
  273. mSleepNs = mForceNs - nsec;
  274. } else {
  275. mIgnoreNextOverrun = false;
  276. }
  277. }
  278. #ifdef FAST_THREAD_STATISTICS
  279. if (mIsWarm) {
  280. // advance the FIFO queue bounds
  281. size_t i = mBounds & (mDumpState->mSamplingN - 1);
  282. mBounds = (mBounds & 0xFFFF0000) | ((mBounds + 1) & 0xFFFF);
  283. if (mFull) {
  284. //mBounds += 0x10000;
  285. __builtin_add_overflow(mBounds, 0x10000, &mBounds);
  286. } else if (!(mBounds & (mDumpState->mSamplingN - 1))) {
  287. mFull = true;
  288. }
  289. // compute the delta value of clock_gettime(CLOCK_MONOTONIC)
  290. uint32_t monotonicNs = nsec;
  291. if (sec > 0 && sec < 4) {
  292. monotonicNs += sec * 1000000000;
  293. }
  294. // compute raw CPU load = delta value of clock_gettime(CLOCK_THREAD_CPUTIME_ID)
  295. uint32_t loadNs = 0;
  296. struct timespec newLoad;
  297. rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &newLoad);
  298. if (rc == 0) {
  299. if (mOldLoadValid) {
  300. sec = newLoad.tv_sec - mOldLoad.tv_sec;
  301. nsec = newLoad.tv_nsec - mOldLoad.tv_nsec;
  302. if (nsec < 0) {
  303. --sec;
  304. nsec += 1000000000;
  305. }
  306. loadNs = nsec;
  307. if (sec > 0 && sec < 4) {
  308. loadNs += sec * 1000000000;
  309. }
  310. } else {
  311. // first time through the loop
  312. mOldLoadValid = true;
  313. }
  314. mOldLoad = newLoad;
  315. }
  316. #ifdef CPU_FREQUENCY_STATISTICS
  317. // get the absolute value of CPU clock frequency in kHz
  318. int cpuNum = sched_getcpu();
  319. uint32_t kHz = mTcu.getCpukHz(cpuNum);
  320. kHz = (kHz << 4) | (cpuNum & 0xF);
  321. #endif
  322. // save values in FIFO queues for dumpsys
  323. // these stores #1, #2, #3 are not atomic with respect to each other,
  324. // or with respect to store #4 below
  325. mDumpState->mMonotonicNs[i] = monotonicNs;
  326. LOG_WORK_TIME(monotonicNs);
  327. mDumpState->mLoadNs[i] = loadNs;
  328. #ifdef CPU_FREQUENCY_STATISTICS
  329. mDumpState->mCpukHz[i] = kHz;
  330. #endif
  331. // this store #4 is not atomic with respect to stores #1, #2, #3 above, but
  332. // the newest open & oldest closed halves are atomic with respect to each other
  333. mDumpState->mBounds = mBounds;
  334. ATRACE_INT(mCycleMs, monotonicNs / 1000000);
  335. ATRACE_INT(mLoadUs, loadNs / 1000);
  336. }
  337. #endif
  338. } else {
  339. // first time through the loop
  340. mOldTsValid = true;
  341. mSleepNs = mPeriodNs;
  342. mIgnoreNextOverrun = true;
  343. }
  344. mOldTs = newTs;
  345. } else {
  346. // monotonic clock is broken
  347. mOldTsValid = false;
  348. mSleepNs = mPeriodNs;
  349. }
  350. } // for (;;)
  351. // never return 'true'; Thread::_threadLoop() locks mutex which can result in priority inversion
  352. }
  353. } // namespace android