-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmemory.cpp
166 lines (142 loc) · 4.39 KB
/
memory.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
* Memory.cpp
*
* Created on: Oct 24, 2017
* Author: kolban
*/
#include "sdkconfig.h"
#ifdef CONFIG_HEAP_TRACING
#include "memory.h"
#include <stdlib.h>
#include "GeneralUtils.h"
extern "C" {
#include <esp_heap_trace.h>
#include <esp_heap_caps.h>
}
#include <esp_log.h>
#include <esp_err.h>
static const char* LOG_TAG = "Memory";
heap_trace_record_t* Memory::m_pRecords = nullptr;
size_t Memory::m_lastHeapSize = 0;
/**
* @brief Check the integrity of memory.
* @return True if all integrity checks passed
*/
/* STATIC */ bool Memory::checkIntegrity() {
bool rc = ::heap_caps_check_integrity_all(true);
if (rc == false && m_pRecords != nullptr) {
dumpRanges();
abort();
}
return rc;
} // checkIntegrity
/**
* @brief Dump the trace records from the heap.
*/
/* STATIC */ void Memory::dump() {
::heap_trace_dump();
} // dump
/* STATIC */ void Memory::dumpHeapChange(std::string tag) {
size_t currentUsage = heap_caps_get_free_size(MALLOC_CAP_8BIT);
int diff = currentUsage - m_lastHeapSize;
ESP_LOGD(LOG_TAG, "%s: Heap changed by %d bytes (%d to %d)", tag.c_str(), diff, m_lastHeapSize, currentUsage);
m_lastHeapSize = currentUsage;
} // dumpHeapChange
/**
* @brief Dump the ranges of allocations found.
*/
/* STATIC */ void Memory::dumpRanges() {
// Each record contained in the Heap trace has the following format:
//
// * uint32_t ccount – Timestamp of record.
// * void* address – Address that was allocated or released.
// * size_t size – Size of the block that was requested and allocated.
// * void* alloced_by[CONFIG_HEAP_TRACING_STACK_DEPTH] – Call stack of allocator
// * void* freed_by[CONFIG_HEAP_TRACING_STACK_DEPTH] – Call stack of releasor
//
if (m_pRecords == nullptr) {
return;
}
esp_log_level_set("*", ESP_LOG_NONE);
size_t count = heap_trace_get_count();
heap_trace_record_t record;
printf(">>> dumpRanges\n");
for (size_t i=0; i<count; i++) {
esp_err_t errRc = heap_trace_get(i, &record);
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "heap_trace_get: %d", errRc);
}
printf("0x%x:0x%x:%d:", (uint32_t)record.address, ((uint32_t)record.address) + record.size, record.size);
for (size_t j=0; j<CONFIG_HEAP_TRACING_STACK_DEPTH; j++) {
printf("%x ", (uint32_t)record.alloced_by[j]);
}
printf(":");
for (size_t j=0; j<CONFIG_HEAP_TRACING_STACK_DEPTH; j++) {
printf("%x ", (uint32_t)record.freed_by[j]);
}
printf("\n");
}
printf("<<< dumpRanges\n");
esp_log_level_set("*", ESP_LOG_VERBOSE);
} // dumpRanges
/**
* @brief Initialize heap recording.
* @param [in] recordCount The maximum number of records to be recorded.
*/
/* STATIC */ void Memory::init(uint32_t recordCount) {
assert(recordCount > 0);
if (m_pRecords != nullptr) {
ESP_LOGE(LOG_TAG, "Already initialized");
return;
}
m_pRecords = new heap_trace_record_t[recordCount]; // Allocate the maximum number of records to be recorded.
if (m_pRecords == nullptr) {
ESP_LOGE(LOG_TAG, "Unable to create %d heap records", recordCount);
}
esp_err_t errRc = ::heap_trace_init_standalone(m_pRecords, recordCount);
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "heap_trace_init_standalone: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
abort();
}
} // init
/**
* @brief Resume previously paused trace.
*/
/* STATIC */ void Memory::resumeTrace() {
esp_err_t errRc = ::heap_trace_resume();
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "heap_trace_resume: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
abort();
}
} // resumeTrace
/**
* @brief Start tracing all allocate and free calls.
*/
/* STATIC */ void Memory::startTraceAll() {
esp_err_t errRc = ::heap_trace_start(HEAP_TRACE_ALL);
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "heap_trace_start: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
abort();
}
} // startTraceAll
/**
* Start tracing leaks. Matched allocate and free calls are removed.
*/
/* STATIC */ void Memory::startTraceLeaks() {
esp_err_t errRc = ::heap_trace_start(HEAP_TRACE_LEAKS);
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "heap_trace_start: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
abort();
}
} // startTraceLeaks
/**
* @brief Stop recording heap trace.
*/
/* STATIC */ void Memory::stopTrace() {
esp_err_t errRc = ::heap_trace_stop();
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "heap_trace_start: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
abort();
}
} // stopTrace
#endif