1 /*
2 * Copyright (C) 2017 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/memory_manager.h"
18
19 #include "chre/util/system/debug_dump.h"
20
21 namespace chre {
22
nanoappAlloc(Nanoapp * app,uint32_t bytes)23 void *MemoryManager::nanoappAlloc(Nanoapp *app, uint32_t bytes) {
24 AllocHeader *header = nullptr;
25 if (bytes > 0) {
26 if (mAllocationCount >= kMaxAllocationCount) {
27 LOGE("Failed to allocate memory from Nanoapp ID %" PRIu32
28 ": allocation count exceeded limit.",
29 app->getInstanceId());
30 } else if ((bytes > kMaxAllocationBytes) ||
31 ((mTotalAllocatedBytes + bytes) > kMaxAllocationBytes)) {
32 LOGE("Failed to allocate memory from Nanoapp ID %" PRIu32
33 ": not enough space.",
34 app->getInstanceId());
35 } else {
36 header =
37 static_cast<AllocHeader *>(doAlloc(app, sizeof(AllocHeader) + bytes));
38
39 if (header != nullptr) {
40 app->setTotalAllocatedBytes(app->getTotalAllocatedBytes() + bytes);
41 mTotalAllocatedBytes += bytes;
42 if (mTotalAllocatedBytes > mPeakAllocatedBytes) {
43 mPeakAllocatedBytes = mTotalAllocatedBytes;
44 }
45 mAllocationCount++;
46 header->data.bytes = bytes;
47 header->data.instanceId = app->getInstanceId();
48 header++;
49 }
50 }
51 }
52 return header;
53 }
54
nanoappFree(Nanoapp * app,void * ptr)55 void MemoryManager::nanoappFree(Nanoapp *app, void *ptr) {
56 if (ptr != nullptr) {
57 AllocHeader *header = static_cast<AllocHeader *>(ptr);
58 header--;
59
60 // TODO: Clean up API contract of chreSendEvent to specify nanoapps can't
61 // release ownership of data to other nanoapps so a CHRE_ASSERT_LOG can be
62 // used below and the code can return.
63 if (app->getInstanceId() != header->data.instanceId) {
64 LOGW("Nanoapp ID=%" PRIu32 " tried to free data from nanoapp ID=%" PRIu32,
65 app->getInstanceId(), header->data.instanceId);
66 }
67
68 size_t nanoAppTotalAllocatedBytes = app->getTotalAllocatedBytes();
69 if (nanoAppTotalAllocatedBytes >= header->data.bytes) {
70 app->setTotalAllocatedBytes(nanoAppTotalAllocatedBytes -
71 header->data.bytes);
72 } else {
73 app->setTotalAllocatedBytes(0);
74 }
75
76 if (mTotalAllocatedBytes >= header->data.bytes) {
77 mTotalAllocatedBytes -= header->data.bytes;
78 } else {
79 mTotalAllocatedBytes = 0;
80 }
81 if (mAllocationCount > 0) {
82 mAllocationCount--;
83 }
84
85 doFree(app, header);
86 }
87 }
88
logStateToBuffer(DebugDumpWrapper & debugDump) const89 void MemoryManager::logStateToBuffer(DebugDumpWrapper &debugDump) const {
90 debugDump.print(
91 "\nNanoapp heap usage: %zu bytes allocated, %zu peak bytes"
92 " allocated, count %zu\n",
93 getTotalAllocatedBytes(), getPeakAllocatedBytes(), getAllocationCount());
94 }
95
96 } // namespace chre
97