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