diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2012-11-11 11:26:38 +0400 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2012-11-11 11:26:38 +0400 |
commit | 653fb51a5a9d45b7833d5b3a09d8d2fa596125a3 (patch) | |
tree | 4b0831e78729fc1ca61a59416590e58314c2705c | |
parent | 3d84e7d8f7985b2a13d0ac591be37dbed847388a (diff) | |
download | bdwgc-653fb51a5a9d45b7833d5b3a09d8d2fa596125a3.tar.gz |
Improve GC output atomicity in GC_print_obj, GC_print_all_errors
(as well as in GC_print_backtrace, GC_print_all_smashed_proc)
* blacklst.c (GC_default_print_heap_obj_proc): Refine printed message;
output object kind; output trailing "\n".
* reclaim.c (GC_print_all_errors): Do not print object kind (before
GC_print_heap_obj call).
* dbg_mlc.c (GC_print_backtrace): Remove redundant printed "\n" after
GC_print_heap_obj call.
* reclaim.c (GC_print_all_errors): Likewise.
* dbg_mlc.c (GC_print_type): Remove (move code to GC_print_obj
replacing "p" local variable with "q").
* dbg_mlc.c (GC_print_obj): Merge adjacent GC_err_printf and
GC_err_puts invocation into a single GC_err_printf one (for output
atomicity).
* dbg_mlc.c (GC_print_all_smashed_proc): Print number of found objects
first.
* reclaim.c (GC_print_all_errors): Likewise.
* dbg_mlc.c (GC_print_all_smashed_proc): Remove printed "\n" at list
end.
* include/private/gc_priv.h (GC_print_heap_obj, GC_printf): Refine
comments.
-rw-r--r-- | blacklst.c | 8 | ||||
-rw-r--r-- | dbg_mlc.c | 89 | ||||
-rw-r--r-- | include/private/gc_priv.h | 7 | ||||
-rw-r--r-- | reclaim.c | 11 |
4 files changed, 60 insertions, 55 deletions
@@ -57,8 +57,12 @@ STATIC void GC_clear_bl(word *); GC_INNER void GC_default_print_heap_obj_proc(ptr_t p) { ptr_t base = GC_base(p); - GC_err_printf("start: %p, appr. length: %lu", - base, (unsigned long)GC_size(base)); + int kind = HDR(base)->hb_obj_kind; + + GC_err_printf("object at %p of appr. %lu bytes (%s)\n", + base, (unsigned long)GC_size(base), + kind == PTRFREE ? "atomic" : + IS_UNCOLLECTABLE(kind) ? "uncollectable" : "composite"); } GC_INNER void (*GC_print_heap_obj)(ptr_t p) = GC_default_print_heap_obj_proc; @@ -189,7 +189,7 @@ void *base; GC_print_heap_obj(GC_base(current)); - GC_err_printf("\n"); + for (i = 0; ; ++i) { source = GC_get_back_ptr_info(current, &base, &offset); if (GC_UNREFERENCED == source) { @@ -215,7 +215,6 @@ GC_err_printf("offset %ld in object:\n", (long)offset); /* Take GC_base(base) to get real base, i.e. header. */ GC_print_heap_obj(GC_base(base)); - GC_err_printf("\n"); break; default: GC_err_printf("INTERNAL ERROR: UNEXPECTED SOURCE!!!!\n"); @@ -322,20 +321,42 @@ GC_API void GC_CALL GC_register_describe_type_fn(int kind, GC_describe_type_fns[kind] = fn; } -/* Print a type description for the object whose client-visible address */ -/* is p. */ -STATIC void GC_print_type(ptr_t p) +#define GET_OH_LINENUM(ohdr) ((int)(ohdr)->oh_int) + +#ifndef SHORT_DBG_HDRS +# define IF_NOT_SHORTDBG_HDRS(x) x +# define COMMA_IFNOT_SHORTDBG_HDRS(x) /* comma */, x +#else +# define IF_NOT_SHORTDBG_HDRS(x) /* empty */ +# define COMMA_IFNOT_SHORTDBG_HDRS(x) /* empty */ +#endif + +/* Print a human-readable description of the object to stderr. */ +/* p points to somewhere inside an object with the debugging info. */ +STATIC void GC_print_obj(ptr_t p) { - hdr * hhdr = GC_find_header(p); - char buffer[GC_TYPE_DESCR_LEN + 1]; - int kind = hhdr -> hb_obj_kind; + oh * ohdr = (oh *)GC_base(p); + ptr_t q; + hdr * hhdr; + int kind; char *kind_str; + char buffer[GC_TYPE_DESCR_LEN + 1]; + + GC_ASSERT(I_DONT_HOLD_LOCK()); +# ifdef LINT2 + if (!ohdr) ABORT("Invalid GC_print_obj argument"); +# endif - if (0 != GC_describe_type_fns[kind] && GC_is_marked(GC_base(p))) { + q = (ptr_t)(ohdr + 1); + /* Print a type description for the object whose client-visible */ + /* address is q. */ + hhdr = GC_find_header(q); + kind = hhdr -> hb_obj_kind; + if (0 != GC_describe_type_fns[kind] && GC_is_marked(ohdr)) { /* This should preclude free list objects except with */ /* thread-local allocation. */ buffer[GC_TYPE_DESCR_LEN] = 0; - (GC_describe_type_fns[kind])(p, buffer); + (GC_describe_type_fns[kind])(q, buffer); GC_ASSERT(buffer[GC_TYPE_DESCR_LEN] == 0); kind_str = buffer; } else { @@ -351,7 +372,7 @@ STATIC void GC_print_type(ptr_t p) break; # ifdef ATOMIC_UNCOLLECTABLE case AUNCOLLECTABLE: - kind_str = "ATOMIC UNCOLLECTABLE"; + kind_str = "ATOMIC_UNCOLLECTABLE"; break; # endif case STUBBORN: @@ -359,42 +380,24 @@ STATIC void GC_print_type(ptr_t p) break; default: kind_str = NULL; + /* The alternative is to use snprintf(buffer) but it is */ + /* not quite portable (see vsnprintf in misc.c). */ } } + if (NULL != kind_str) { - GC_err_puts(kind_str); + GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz=%lu,") " %s)\n", + (ptr_t)ohdr + sizeof(oh), + ohdr->oh_string, GET_OH_LINENUM(ohdr) /*, */ + COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz), + kind_str); } else { - GC_err_printf("kind=%d descr=0x%lx", + GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz=%lu,") + " kind=%d descr=0x%lx)\n", (ptr_t)ohdr + sizeof(oh), + ohdr->oh_string, GET_OH_LINENUM(ohdr) /*, */ + COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz), kind, (unsigned long)hhdr->hb_descr); } -} - -#define GET_OH_LINENUM(ohdr) ((int)(ohdr)->oh_int) - -#ifndef SHORT_DBG_HDRS -# define IF_NOT_SHORTDBG_HDRS(x) x -# define COMMA_IFNOT_SHORTDBG_HDRS(x) /* comma */, x -#else -# define IF_NOT_SHORTDBG_HDRS(x) /* empty */ -# define COMMA_IFNOT_SHORTDBG_HDRS(x) /* empty */ -#endif - -/* Print a human-readable description of the object to stderr. p points */ -/* to somewhere inside an object with the debugging info. */ -STATIC void GC_print_obj(ptr_t p) -{ - oh * ohdr = (oh *)GC_base(p); - - GC_ASSERT(I_DONT_HOLD_LOCK()); -# ifdef LINT2 - if (!ohdr) ABORT("Invalid GC_print_obj argument"); -# endif - GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz=%lu,") " ", - (ptr_t)ohdr + sizeof(oh), ohdr->oh_string, - GET_OH_LINENUM(ohdr) /*, */ - COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz)); - GC_print_type((ptr_t)(ohdr + 1)); - GC_err_puts(")\n"); PRINT_CALL_CHAIN(ohdr); } @@ -925,7 +928,8 @@ STATIC void GC_print_all_smashed_proc(void) GC_ASSERT(I_DONT_HOLD_LOCK()); if (GC_n_smashed == 0) return; - GC_err_printf("GC_check_heap_block: found smashed heap objects:\n"); + GC_err_printf("GC_check_heap_block: found %u smashed heap objects:\n", + GC_n_smashed); for (i = 0; i < GC_n_smashed; ++i) { ptr_t base = (ptr_t)GC_base(GC_smashed[i]); @@ -936,7 +940,6 @@ STATIC void GC_print_all_smashed_proc(void) GC_smashed[i] = 0; } GC_n_smashed = 0; - GC_err_printf("\n"); } /* Check all marked objects in the given block for validity */ diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 3eca2b1f..c33e0188 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1863,9 +1863,9 @@ GC_EXTERN void (*GC_print_all_smashed)(void); /* Print GC_smashed if it's not empty. */ /* Clear GC_smashed list. */ GC_EXTERN void (*GC_print_heap_obj)(ptr_t p); - /* If possible print s followed by a more */ - /* detailed description of the object */ - /* referred to by p. */ + /* If possible print (using GC_err_printf) */ + /* a more detailed description (terminated with */ + /* "\n") of the object referred to by p. */ #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG) void GC_print_address_map(void); @@ -2018,6 +2018,7 @@ GC_API void GC_CALL GC_noop1(word); /* Logging and diagnostic output: */ /* GC_printf is used typically on client explicit print requests. */ +/* It's recommended to put "\n" at 'format' string end (for atomicity). */ GC_API_PRIV void GC_printf(const char * format, ...) GC_ATTR_FORMAT_PRINTF(1, 2); /* A version of printf that doesn't allocate, */ @@ -89,18 +89,15 @@ GC_INNER void GC_print_all_errors(void) have_errors = FALSE; } + if (GC_n_leaked > 0) { + GC_err_printf("Found %u leaked objects:\n", GC_n_leaked); + have_errors = TRUE; + } for (i = 0; i < GC_n_leaked; ++i) { ptr_t p = GC_leaked[i]; - if (HDR(p) -> hb_obj_kind == PTRFREE) { - GC_err_printf("Leaked atomic object at "); - } else { - GC_err_printf("Leaked composite object at "); - } GC_print_heap_obj(p); - GC_err_printf("\n"); GC_free(p); GC_leaked[i] = 0; - have_errors = TRUE; } GC_n_leaked = 0; |