1 /*
2 * Copyright (C) 2020 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
17 #include "chre/platform/shared/dram_vote_client.h"
18
19 #include <cinttypes>
20
21 #include "chre/platform/assert.h"
22 #include "chre/platform/fatal_error.h"
23 #include "chre/platform/log.h"
24 #include "chre/platform/system_time.h"
25
26 namespace chre {
27
voteDramAccess(bool enabled)28 void DramVoteClient::voteDramAccess(bool enabled) {
29 LockGuard<Mutex> lock(mMutex);
30 mLastDramRequest = enabled;
31
32 bool needDram = (enabled || mDramVoteCount > 0);
33 if (needDram != mLastDramVote) {
34 issueDramVote(needDram);
35 mLastDramVote = needDram;
36 }
37 }
38
incrementDramVoteCount()39 void DramVoteClient::incrementDramVoteCount() {
40 LockGuard<Mutex> lock(mMutex);
41
42 if (mDramVoteCount++ == 0) {
43 mVoteCountStart = Milliseconds(SystemTime::getMonotonicTime());
44 // TODO(b/181172259): Change back to LOGW once buffered logging path is
45 // refactored.
46 // LOGW("DRAM vote count begins");
47 printf("CHRE: DRAM vote count begins");
48
49 if (!mLastDramVote) {
50 // Do not call voteDramAccess() directly as it will override
51 // mLastDramRequest.
52 issueDramVote(true /* enabled */);
53 mLastDramVote = true;
54 }
55 } else {
56 checkDramDuration();
57 }
58 }
59
decrementDramVoteCount()60 void DramVoteClient::decrementDramVoteCount() {
61 LockGuard<Mutex> lock(mMutex);
62 CHRE_ASSERT_LOG(mDramVoteCount > 0,
63 "Tried to decrement DRAM vote count when it's 0");
64
65 if (--mDramVoteCount == 0) {
66 // TODO(b/181172259): Change back to LOGW once buffered logging path is
67 // refactored.
68 // LOGW("DRAM vote count ends: %" PRIu64 " ms", checkDramDuration());
69 printf("CHRE: DRAM vote count ends: %" PRIu64 " ms", checkDramDuration());
70
71 // There's no DRAM activity now, remove CHRE's DRAM access vote.
72 if (!mLastDramRequest) {
73 issueDramVote(false /* enabled */);
74 mLastDramVote = false;
75 }
76 }
77 }
78
checkDramDuration() const79 Milliseconds DramVoteClient::checkDramDuration() const {
80 Milliseconds duration(0);
81 if (mDramVoteCount > 0) {
82 duration = Milliseconds(SystemTime::getMonotonicTime()) - mVoteCountStart;
83 }
84
85 // DRAM memory fallback only intends to handle a surge of DRAM memory
86 // requests. If there's a prolonged period of memory fallback, this might
87 // indicate a memory leak or inadequate SRAM heap size.
88 if (duration > kMaxDramDuration) {
89 FATAL_ERROR("Forced into DRAM for %" PRIu64 " msec",
90 duration.getMilliseconds());
91 }
92 return duration;
93 }
94
95 //! Explicitly instantiate the DramVoteClient singleton to reduce code size.
96 template class Singleton<DramVoteClient>;
97
98 } // namespace chre
99