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