From 04c8c7a42e7736d8653036b349ea81cc2c9a4545 Mon Sep 17 00:00:00 2001 From: Erik Corry Date: Mon, 20 Dec 2021 10:23:45 +0100 Subject: [PATCH] Make use of better heap tagging in cmpctmalloc (#170) * Make use of better heap tagging in cmpctmalloc --- src/heap_report.h | 4 +++- src/os.h | 7 +++++-- src/os_darwin.cc | 2 +- src/os_esp32.cc | 20 +++++++++++++++----- src/os_linux.cc | 7 ++++--- src/os_win.cc | 2 +- src/resources/tls.cc | 1 + src/resources/x509.cc | 1 + 8 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/heap_report.h b/src/heap_report.h index 05979afb8..34d613c22 100644 --- a/src/heap_report.h +++ b/src/heap_report.h @@ -34,7 +34,9 @@ static const uint8 UNKNOWN_MALLOC_TAG = 9; static const uint8 EVENT_SOURCE_MALLOC_TAG = 10; static const uint8 OTHER_THREADS_MALLOC_TAG = 11; static const uint8 THREAD_SPAWN_MALLOC_TAG = 12; -static const uint8 NUMBER_OF_MALLOC_TAGS = 13; +static const uint8 NULL_MALLOC_TAG = 13; +static const uint8 WIFI_MALLOC_TAG = 14; +static const uint8 NUMBER_OF_MALLOC_TAGS = 15; #ifdef TOIT_CMPCTMALLOC diff --git a/src/os.h b/src/os.h index fc5f5a608..e421352d4 100644 --- a/src/os.h +++ b/src/os.h @@ -221,7 +221,7 @@ class OS { // If we are using Cmpctmalloc this lets us set a tag that is used to mark // the origin of allocations on the current thread. static void set_heap_tag(word tag); - static void clear_heap_tag(); + static word get_heap_tag(); static void heap_summary_report(); // Unique 16-bytes uuid of the running image. @@ -245,12 +245,15 @@ class OS { class HeapTagScope { public: HeapTagScope(uword tag) { + old = OS::get_heap_tag(); OS::set_heap_tag(tag); } ~HeapTagScope() { - OS::clear_heap_tag(); + OS::set_heap_tag(old); } + + uword old; }; } // namespace toit diff --git a/src/os_darwin.cc b/src/os_darwin.cc index a0b61184b..2a5c5e4fa 100644 --- a/src/os_darwin.cc +++ b/src/os_darwin.cc @@ -113,7 +113,7 @@ int OS::read_entire_file(char* name, uint8** buffer) { } void OS::set_heap_tag(word tag) { } -void OS::clear_heap_tag() { } +word OS::get_heap_tag() { return 0; } void OS::heap_summary_report() { } } diff --git a/src/os_esp32.cc b/src/os_esp32.cc index 277aa0e1c..8e958f4be 100644 --- a/src/os_esp32.cc +++ b/src/os_esp32.cc @@ -416,8 +416,8 @@ void OS::set_heap_tag(word tag) { heap_caps_set_option(MALLOC_OPTION_THREAD_TAG, reinterpret_cast(tag)); } -void OS::clear_heap_tag() { - heap_caps_set_option(MALLOC_OPTION_THREAD_TAG, null); +word OS::get_heap_tag() { + return reinterpret_cast(heap_caps_get_option(MALLOC_OPTION_THREAD_TAG)); } class HeapSummaryPage { @@ -447,7 +447,11 @@ class HeapSummaryPage { int register_user(uword tag, uword size) { uint16 saturated_size = Utils::min(size, 0xffffu); - if (tag == ITERATE_TAG_FREE) { + if (tag == 0) { + tag = NULL_MALLOC_TAG; + } else if (tag == 'W') { + tag = WIFI_MALLOC_TAG; + } else if (tag == ITERATE_TAG_FREE) { tag = FREE_MALLOC_TAG; } else { tag -= ITERATE_CUSTOM_TAGS; @@ -490,6 +494,8 @@ class HeapSummaryPage { case EVENT_SOURCE_MALLOC_TAG: return "event source"; case OTHER_THREADS_MALLOC_TAG: return "other threads"; case THREAD_SPAWN_MALLOC_TAG: return "thread spawn"; + case NULL_MALLOC_TAG: return "null tag"; + case WIFI_MALLOC_TAG: return "wifi"; } return "unknown"; } @@ -517,6 +523,10 @@ class HeapSummaryCollector { memset(void_cast(counts_), 0, sizeof counts_); } + word allocation_requirement() { + return MAX_PAGES_ * sizeof(HeapSummaryPage); + } + bool out_of_memory() const { return pages_ == null; } ~HeapSummaryCollector() { @@ -570,7 +580,7 @@ bool register_allocation(void* self, void* tag, void* address, uword size) { void OS::heap_summary_report() { HeapSummaryCollector collector; if (collector.out_of_memory()) { - printf("Not enough memory for a heap report\n"); + printf("Not enough memory for a heap report (%d bytes)\n", static_cast(collector.allocation_requirement())); return; } int flags = ITERATE_ALL_ALLOCATIONS | ITERATE_UNALLOCATED; @@ -581,7 +591,7 @@ void OS::heap_summary_report() { #else // def TOIT_CMPCTMALLOC void OS::set_heap_tag(word tag) { } -void OS::clear_heap_tag() { } +word OS::get_heap_tag() { return 0; } void OS::heap_summary_report() { } diff --git a/src/os_linux.cc b/src/os_linux.cc index 2f76e0c43..ce123edbf 100644 --- a/src/os_linux.cc +++ b/src/os_linux.cc @@ -116,18 +116,19 @@ void OS::set_heap_tag(word tag) { } } -void OS::clear_heap_tag() { +word OS::get_heap_tag() { int MALLOC_OPTION_THREAD_TAG = 1; if (heap_caps_set_option != null) { - heap_caps_set_option(MALLOC_OPTION_THREAD_TAG, null); + return reinterpret_cast(heap_caps_get_option(MALLOC_OPTION_THREAD_TAG)); } + return 0; } #else // def TOIT_CMPCTMALLOC void OS::set_heap_tag(word tag) { } -void OS::clear_heap_tag() { } +word OS::get_heap_tag() { return 0; } #endif // def TOIT_CMPCTMALLOC diff --git a/src/os_win.cc b/src/os_win.cc index e3159bf04..2207e86ba 100644 --- a/src/os_win.cc +++ b/src/os_win.cc @@ -320,7 +320,7 @@ int OS::read_entire_file(char* name, uint8** buffer) { void OS::set_heap_tag(word tag) {} -void OS::clear_heap_tag() {} +word OS::get_heap_tag() { return 0; } } // namespace toit diff --git a/src/resources/tls.cc b/src/resources/tls.cc index f16066848..0e41fbe7d 100644 --- a/src/resources/tls.cc +++ b/src/resources/tls.cc @@ -386,6 +386,7 @@ bool ensure_handshake_memory() { // restarted from scratch. This is annoying, but most code will already be // able to restart TLS connections since they can fail because of transient // network issues. + HeapTagScope scope(ITERATE_CUSTOM_TAGS + BIGNUM_MALLOC_TAG); const int BLOCK_SIZE = 1900; const int BLOCK_COUNT = 8; void* blocks[BLOCK_COUNT] = { 0 }; diff --git a/src/resources/x509.cc b/src/resources/x509.cc index ac98e5bd3..4a8ccb683 100644 --- a/src/resources/x509.cc +++ b/src/resources/x509.cc @@ -72,6 +72,7 @@ PRIMITIVE(init) { PRIMITIVE(parse) { ARGS(X509ResourceGroup, resource_group, Object, input); + HeapTagScope scope(ITERATE_CUSTOM_TAGS + BIGNUM_MALLOC_TAG); const uint8_t* data = null; size_t length = 0;