[dtrace] GC heap allocation probes for SGen.
authorMark Probst <mark.probst@gmail.com>
Fri, 21 Sep 2012 12:34:41 +0000 (14:34 +0200)
committerMark Probst <mark.probst@gmail.com>
Fri, 28 Sep 2012 21:18:16 +0000 (23:18 +0200)
These trigger whenever a segment of heap memory is allocated from the
OS, or freed to the OS again.

12 files changed:
data/mono.d
mono/metadata/sgen-cardtable.c
mono/metadata/sgen-debug.c
mono/metadata/sgen-internal.c
mono/metadata/sgen-los.c
mono/metadata/sgen-major-copying.c
mono/metadata/sgen-marksweep.c
mono/metadata/sgen-memory-governor.c
mono/metadata/sgen-memory-governor.h
mono/metadata/sgen-pinned-allocator.c
mono/metadata/sgen-protocol.c
mono/utils/dtrace.h

index 3d27128b736fbb5302dc79ccab0611335a80375f..14591aa483862dbd9931db5bd0c58eab5dfbb3f6 100644 (file)
@@ -18,6 +18,9 @@ provider mono {
        /* Garbage Collector (GC) */    
        probe gc__begin (int generation);
        probe gc__end (int generation);
+
+       probe gc__heap__alloc (void *addr, uintptr_t len);
+       probe gc__heap__free (void *addr, uintptr_t len);
 };
 
 #pragma D attributes Evolving/Evolving/Common provider mono provider
index c83aac3e367d897dcb32c4378fd0b1187e9b1a24..6d9906cc28c9ee321e56c2dc650a65a8d593d265 100644 (file)
@@ -655,10 +655,10 @@ sgen_card_tables_collect_stats (gboolean begin)
 void
 sgen_card_table_init (SgenRemeberedSet *remset)
 {
-       sgen_cardtable = sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, TRUE, "card table");
+       sgen_cardtable = sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, TRUE, FALSE, "card table");
 
 #ifdef SGEN_HAVE_OVERLAPPING_CARDS
-       sgen_shadow_cardtable = sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, TRUE, "shadow card table");
+       sgen_shadow_cardtable = sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, TRUE, FALSE, "shadow card table");
 #endif
 
 #ifdef HEAVY_STATISTICS
index e9252095111c2f771ba1b6291f9b33ae47bfeeda..5496ca97846900fa8ce0d585e3846d4f25620588 100644 (file)
@@ -364,7 +364,7 @@ sgen_check_whole_heap (void)
 {
        /*setup valid_nursery_objects*/
        if (!valid_nursery_objects)
-               valid_nursery_objects = sgen_alloc_os_memory (DEFAULT_NURSERY_SIZE, TRUE, "debugging data");
+               valid_nursery_objects = sgen_alloc_os_memory (DEFAULT_NURSERY_SIZE, TRUE, FALSE, "debugging data");
        valid_nursery_object_count = 0;
        sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE);
 
index 53d8c62d25168681760792fc36d5697fb100500a..b6b0c3c54f79edd82214fdbe956c3a41f27cfe1a 100644 (file)
@@ -121,7 +121,7 @@ sgen_alloc_internal_dynamic (size_t size, int type, gboolean assert_on_failure)
        void *p;
 
        if (size > allocator_sizes [NUM_ALLOCATORS - 1]) {
-               p = sgen_alloc_os_memory (size, TRUE, NULL);
+               p = sgen_alloc_os_memory (size, TRUE, FALSE, NULL);
                if (!p)
                        sgen_assert_memory_alloc (NULL, description_for_type (type));
                return p;
@@ -139,15 +139,13 @@ sgen_alloc_internal_dynamic (size_t size, int type, gboolean assert_on_failure)
 void
 sgen_free_internal_dynamic (void *addr, size_t size, int type)
 {
-       int index;
-
        if (!addr)
                return;
 
-       if (size > allocator_sizes [NUM_ALLOCATORS - 1])
-               return sgen_free_os_memory (addr, size);
-
-       index = index_for_size (size);
+       if (size > allocator_sizes [NUM_ALLOCATORS - 1]) {
+               sgen_free_os_memory (addr, size, FALSE);
+               return;
+       }
 
        mono_lock_free_free (addr);
 }
index 516210c20c30653db27dd01f46bf1025bb91b5ba..f9f9a4ef9c14c425cb92de48ad2680c73a926ee2 100644 (file)
@@ -244,7 +244,7 @@ get_los_section_memory (size_t size)
        if (!sgen_memgov_try_alloc_space (LOS_SECTION_SIZE, SPACE_LOS))
                return NULL;
 
-       section = sgen_alloc_os_memory_aligned (LOS_SECTION_SIZE, LOS_SECTION_SIZE, TRUE, NULL);
+       section = sgen_alloc_os_memory_aligned (LOS_SECTION_SIZE, LOS_SECTION_SIZE, TRUE, TRUE, NULL);
 
        if (!section)
                return NULL;
@@ -323,7 +323,7 @@ sgen_los_free_object (LOSObject *obj)
                size += sizeof (LOSObject);
                size += pagesize - 1;
                size &= ~(pagesize - 1);
-               sgen_free_os_memory (obj, size);
+               sgen_free_os_memory (obj, size, TRUE);
                sgen_memgov_release_space (size, SPACE_LOS);
        } else {
                free_los_section_memory (obj, size + sizeof (LOSObject));
@@ -351,7 +351,7 @@ sgen_los_alloc_large_inner (MonoVTable *vtable, size_t size)
 
 #ifdef LOS_DUMMY
        if (!los_segment)
-               los_segment = sgen_alloc_os_memory (LOS_SEGMENT_SIZE, TRUE, NULL);
+               los_segment = sgen_alloc_os_memory (LOS_SEGMENT_SIZE, TRUE, TRUE, NULL);
        los_segment_index = ALIGN_UP (los_segment_index);
 
        obj = (LOSObject*)(los_segment + los_segment_index);
@@ -372,7 +372,7 @@ sgen_los_alloc_large_inner (MonoVTable *vtable, size_t size)
                alloc_size += pagesize - 1;
                alloc_size &= ~(pagesize - 1);
                if (sgen_memgov_try_alloc_space (alloc_size, SPACE_LOS)) {
-                       obj = sgen_alloc_os_memory (alloc_size, TRUE, NULL);
+                       obj = sgen_alloc_os_memory (alloc_size, TRUE, TRUE, NULL);
                        if (obj)
                                obj->huge_object = TRUE;
                }
@@ -423,7 +423,7 @@ sgen_los_sweep (void)
                                prev->next = next;
                        else
                                los_sections = next;
-                       sgen_free_os_memory (section, LOS_SECTION_SIZE);
+                       sgen_free_os_memory (section, LOS_SECTION_SIZE, TRUE);
                        sgen_memgov_release_space (LOS_SECTION_SIZE, SPACE_LOS);
                        section = next;
                        --los_num_sections;
index 6992644d7eef1ff2144d63ab772c790264e7d723..d1737a6b787b6630f0779dcdf7499eafc1463e90 100644 (file)
@@ -98,9 +98,9 @@ static void*
 major_alloc_heap (mword nursery_size, mword nursery_align, int the_nursery_bits)
 {
        if (nursery_align)
-               nursery_start = sgen_alloc_os_memory_aligned (nursery_size, nursery_align, TRUE, "nursery");
+               nursery_start = sgen_alloc_os_memory_aligned (nursery_size, nursery_align, TRUE, TRUE, "nursery");
        else
-               nursery_start = sgen_alloc_os_memory (nursery_size, TRUE, "nursery");
+               nursery_start = sgen_alloc_os_memory (nursery_size, TRUE, TRUE, "nursery");
 
        nursery_end = nursery_start + nursery_size;
        nursery_bits = the_nursery_bits;
@@ -129,7 +129,7 @@ alloc_major_section (void)
        GCMemSection *section;
        int scan_starts;
 
-       section = sgen_alloc_os_memory_aligned (MAJOR_SECTION_SIZE, MAJOR_SECTION_SIZE, TRUE, "major heap section");
+       section = sgen_alloc_os_memory_aligned (MAJOR_SECTION_SIZE, MAJOR_SECTION_SIZE, TRUE, TRUE, "major heap section");
        section->next_data = section->data = (char*)section + SGEN_SIZEOF_GC_MEM_SECTION;
        g_assert (!((mword)section->data & 7));
        section->size = MAJOR_SECTION_SIZE - SGEN_SIZEOF_GC_MEM_SECTION;
@@ -157,7 +157,7 @@ free_major_section (GCMemSection *section)
        DEBUG (3, fprintf (gc_debug_file, "Freed major section %p (%p-%p)\n", section, section->data, section->end_data));
        sgen_free_internal_dynamic (section->scan_starts,
                        (section->size + SGEN_SCAN_START_SIZE - 1) / SGEN_SCAN_START_SIZE * sizeof (char*), INTERNAL_MEM_SCAN_STARTS);
-       sgen_free_os_memory (section, MAJOR_SECTION_SIZE);
+       sgen_free_os_memory (section, MAJOR_SECTION_SIZE, TRUE);
 
        --num_major_sections;
 }
index de1b4f23b03575c87008f6ddee5921bcb3af7951..a3d52f7fd63752e553838684dd38ae0da52437e4 100644 (file)
@@ -311,7 +311,7 @@ major_alloc_heap (mword nursery_size, mword nursery_align, int the_nursery_bits)
        if (nursery_align)
                g_assert (nursery_align % MS_BLOCK_SIZE == 0);
 
-       nursery_start = sgen_alloc_os_memory_aligned (alloc_size, nursery_align ? nursery_align : MS_BLOCK_SIZE, TRUE, "heap");
+       nursery_start = sgen_alloc_os_memory_aligned (alloc_size, nursery_align ? nursery_align : MS_BLOCK_SIZE, TRUE, TRUE, "heap");
        ms_heap_start = nursery_start + nursery_size;
        ms_heap_end = ms_heap_start + major_heap_size;
 
@@ -336,9 +336,9 @@ major_alloc_heap (mword nursery_size, mword nursery_align, int the_nursery_bits)
 {
        char *start;
        if (nursery_align)
-               start = sgen_alloc_os_memory_aligned (nursery_size, nursery_align, TRUE, "nursery");
+               start = sgen_alloc_os_memory_aligned (nursery_size, nursery_align, TRUE, TRUE, "nursery");
        else
-               start = sgen_alloc_os_memory (nursery_size, TRUE, "nursery");
+               start = sgen_alloc_os_memory (nursery_size, TRUE, TRUE, "nursery");
 
        return start;
 }
@@ -389,7 +389,7 @@ ms_get_empty_block (void)
 
  retry:
        if (!empty_blocks) {
-               p = sgen_alloc_os_memory_aligned (MS_BLOCK_SIZE * MS_BLOCK_ALLOC_NUM, MS_BLOCK_SIZE, TRUE, "major heap section");
+               p = sgen_alloc_os_memory_aligned (MS_BLOCK_SIZE * MS_BLOCK_ALLOC_NUM, MS_BLOCK_SIZE, TRUE, TRUE, "major heap section");
 
                for (i = 0; i < MS_BLOCK_ALLOC_NUM; ++i) {
                        block = p;
@@ -1697,7 +1697,7 @@ major_have_computer_minor_collection_allowance (void)
 
        while (num_empty_blocks > section_reserve) {
                void *next = *(void**)empty_blocks;
-               sgen_free_os_memory (empty_blocks, MS_BLOCK_SIZE);
+               sgen_free_os_memory (empty_blocks, MS_BLOCK_SIZE, TRUE);
                empty_blocks = next;
                /*
                 * Needs not be atomic because this is running
index 99e2306141195edd377fb88c866e4fd43cd6a899..dc7fb75d54baf06ed8d24afbb1df90830f7b641c 100644 (file)
@@ -40,6 +40,7 @@
 #include "utils/mono-counters.h"
 #include "utils/mono-mmap.h"
 #include "utils/mono-logger-internal.h"
+#include "utils/dtrace.h"
 
 #define MIN_MINOR_COLLECTION_ALLOWANCE ((mword)(DEFAULT_NURSERY_SIZE * default_allowance_nursery_size_ratio))
 
@@ -301,23 +302,29 @@ sgen_assert_memory_alloc (void *ptr, const char *assert_description)
  * This must not require any lock.
  */
 void*
-sgen_alloc_os_memory (size_t size, int activate, const char *assert_description)
+sgen_alloc_os_memory (size_t size, int activate, gboolean is_heap_memory, const char *assert_description)
 {
        void *ptr = mono_valloc (0, size, prot_flags_for_activate (activate));
        sgen_assert_memory_alloc (ptr, assert_description);
-       if (ptr)
+       if (ptr) {
                SGEN_ATOMIC_ADD_P (total_alloc, size);
+               if (is_heap_memory)
+                       MONO_PROBE_GC_HEAP_ALLOC (ptr, size);
+       }
        return ptr;
 }
 
 /* size must be a power of 2 */
 void*
-sgen_alloc_os_memory_aligned (size_t size, mword alignment, gboolean activate, const char *assert_description)
+sgen_alloc_os_memory_aligned (size_t size, mword alignment, gboolean activate, gboolean is_heap_memory, const char *assert_description)
 {
        void *ptr = mono_valloc_aligned (size, alignment, prot_flags_for_activate (activate));
        sgen_assert_memory_alloc (ptr, assert_description);
-       if (ptr)
+       if (ptr) {
                SGEN_ATOMIC_ADD_P (total_alloc, size);
+               if (is_heap_memory)
+                       MONO_PROBE_GC_HEAP_ALLOC (ptr, size);
+       }
        return ptr;
 }
 
@@ -325,10 +332,12 @@ sgen_alloc_os_memory_aligned (size_t size, mword alignment, gboolean activate, c
  * Free the memory returned by sgen_alloc_os_memory (), returning it to the OS.
  */
 void
-sgen_free_os_memory (void *addr, size_t size)
+sgen_free_os_memory (void *addr, size_t size, gboolean is_heap_memory)
 {
        mono_vfree (addr, size);
        SGEN_ATOMIC_ADD_P (total_alloc, -size);
+       if (is_heap_memory)
+               MONO_PROBE_GC_HEAP_FREE (addr, size);
 }
 
 int64_t
index 0a6fc99f5d2dd7e3bbdaa2970542dc073f39cf57..7140bf7313b1d6eacd1383725ca70acba4b7edd6 100644 (file)
@@ -45,9 +45,9 @@ gboolean sgen_need_major_collection (mword space_needed) MONO_INTERNAL;
 
 
 /* OS memory allocation */
-void* sgen_alloc_os_memory (size_t size, int activate, const char *assert_description) MONO_INTERNAL;
-void* sgen_alloc_os_memory_aligned (size_t size, mword alignment, gboolean activate, const char *assert_description) MONO_INTERNAL;
-void sgen_free_os_memory (void *addr, size_t size) MONO_INTERNAL;
+void* sgen_alloc_os_memory (size_t size, int activate, gboolean is_heap_memory, const char *assert_description) MONO_INTERNAL;
+void* sgen_alloc_os_memory_aligned (size_t size, mword alignment, gboolean activate, gboolean is_heap_memory, const char *assert_description) MONO_INTERNAL;
+void sgen_free_os_memory (void *addr, size_t size, gboolean is_heap_memory) MONO_INTERNAL;
 
 /* Error handling */
 void sgen_assert_memory_alloc (void *ptr, const char *assert_description) MONO_INTERNAL;
index 02cf8cb94ff442936baba74569c75fadb30e3ea2..661f597f8aac1ecd6662669f388f14bf1507abb9 100644 (file)
@@ -111,6 +111,8 @@ static const int freelist_sizes [] = {
 
 #define LARGE_PINNED_MEM_HEADER_MAGIC  0x7d289f3a
 
+/* FIXME: Do we even need these anymore?  Large objects are always
+   allocated in the LOS. */
 typedef struct _LargePinnedMemHeader LargePinnedMemHeader;
 struct _LargePinnedMemHeader {
        guint32 magic;
@@ -217,7 +219,7 @@ alloc_pinned_chunk (SgenPinnedAllocator *alc)
        int offset;
        int size = SGEN_PINNED_CHUNK_SIZE;
 
-       chunk = sgen_alloc_os_memory_aligned (size, size, TRUE, "pinned chunk");
+       chunk = sgen_alloc_os_memory_aligned (size, size, TRUE, TRUE, "pinned chunk");
        chunk->block.role = MEMORY_ROLE_PINNED;
 
        sgen_update_heap_boundaries ((mword)chunk, ((mword)chunk + size));
@@ -329,7 +331,7 @@ sgen_alloc_pinned (SgenPinnedAllocator *alc, size_t size)
                LargePinnedMemHeader *mh;
 
                size += sizeof (LargePinnedMemHeader);
-               mh = sgen_alloc_os_memory (size, TRUE, "large pinned object");
+               mh = sgen_alloc_os_memory (size, TRUE, TRUE, "large pinned object");
                mh->magic = LARGE_PINNED_MEM_HEADER_MAGIC;
                mh->size = size;
                /* FIXME: do a CAS here */
@@ -383,7 +385,7 @@ sgen_free_pinned (SgenPinnedAllocator *alc, void *addr, size_t size)
        g_assert (mh->size == size + sizeof (LargePinnedMemHeader));
        /* FIXME: do a CAS */
        large_pinned_bytes_alloced -= mh->size;
-       sgen_free_os_memory (mh, mh->size);
+       sgen_free_os_memory (mh, mh->size, TRUE);
 }
 
 void
index 92b4d9571c04070f992ad3333d7cd826333ea284..75ae316704ede6058b32d9c928c8c81c8466fa5e 100644 (file)
@@ -66,7 +66,7 @@ binary_protocol_flush_buffers_rec (BinaryProtocolBuffer *buffer)
        g_assert (buffer->index > 0);
        fwrite (buffer->buffer, 1, buffer->index, binary_protocol_file);
 
-       sgen_free_os_memory (buffer, sizeof (BinaryProtocolBuffer));
+       sgen_free_os_memory (buffer, sizeof (BinaryProtocolBuffer), FALSE);
 }
 
 void
@@ -94,12 +94,12 @@ binary_protocol_get_buffer (int length)
        if (buffer && buffer->index + length <= BINARY_PROTOCOL_BUFFER_SIZE)
                return buffer;
 
-       new_buffer = sgen_alloc_os_memory (sizeof (BinaryProtocolBuffer), TRUE, "debugging memory");
+       new_buffer = sgen_alloc_os_memory (sizeof (BinaryProtocolBuffer), TRUE, FALSE, "debugging memory");
        new_buffer->next = buffer;
        new_buffer->index = 0;
 
        if (InterlockedCompareExchangePointer ((void**)&binary_protocol_buffers, new_buffer, buffer) != buffer) {
-               sgen_free_os_memory (new_buffer, sizeof (BinaryProtocolBuffer));
+               sgen_free_os_memory (new_buffer, sizeof (BinaryProtocolBuffer), FALSE);
                goto retry;
        }
 
index 1b540f705da5c1423d74796dcaa09a6aa14a4004..69fe38b390f6959a303bf6e644828a8f8b7a2d6b 100644 (file)
@@ -46,6 +46,9 @@
 #define MONO_PROBE_GC_END_ENABLED()    MONO_GC_END_ENABLED ()
 
 
+#define MONO_PROBE_GC_HEAP_ALLOC(addr,size)    MONO_GC_HEAP_ALLOC ((addr), (size))
+#define MONO_PROBE_GC_HEAP_FREE(addr,size)     MONO_GC_HEAP_FREE ((addr), (size))
+
 #else
 
 
@@ -70,6 +73,9 @@
 #define MONO_PROBE_GC_END_ENABLED() (0)
 
 
+#define MONO_PROBE_GC_HEAP_ALLOC(addr,size)
+#define MONO_PROBE_GC_HEAP_FREE(addr,size)
+
 #endif
 
 #endif