| 133 | } |
| 134 | |
| 135 | size_t mem_usage_impl(u32* pBlocksUsed, u32* pBlocksFree) |
| 136 | { |
| 137 | static bool no_memory_usage = !strstr(Core.Params, "-memory_usage"); |
| 138 | if (no_memory_usage) |
| 139 | return 0; |
| 140 | |
| 141 | auto heap_handle = reinterpret_cast<HANDLE>(_get_heap_handle()); |
| 142 | if (!HeapLock(heap_handle)) |
| 143 | return 0; |
| 144 | |
| 145 | _HEAPINFO hinfo; |
| 146 | int heapstatus; |
| 147 | hinfo._pentry = nullptr; |
| 148 | size_t total = 0; |
| 149 | u32 blocks_free = 0; |
| 150 | u32 blocks_used = 0; |
| 151 | while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK) |
| 152 | { |
| 153 | if (hinfo._useflag == _USEDENTRY) |
| 154 | { |
| 155 | total += hinfo._size; |
| 156 | blocks_used += 1; |
| 157 | } |
| 158 | else |
| 159 | { |
| 160 | blocks_free += 1; |
| 161 | } |
| 162 | } |
| 163 | if (pBlocksFree) |
| 164 | *pBlocksFree = 1024 * blocks_free; |
| 165 | if (pBlocksUsed) |
| 166 | *pBlocksUsed = 1024 * blocks_used; |
| 167 | |
| 168 | HeapUnlock(heap_handle); |
| 169 | |
| 170 | switch (heapstatus) |
| 171 | { |
| 172 | case _HEAPEMPTY: break; |
| 173 | case _HEAPEND: break; |
| 174 | case _HEAPBADPTR: Msg("!![%s] bad pointer to heap", __FUNCTION__); break; |
| 175 | case _HEAPBADBEGIN: Msg("!![%s] bad start of heap", __FUNCTION__); break; |
| 176 | case _HEAPBADNODE: Msg("!![%s] bad node in heap", __FUNCTION__); break; |
| 177 | } |
| 178 | return total; |
| 179 | } |
no test coverage detected