Improve GC output atomicity in GC_print_obj, GC_print_all_errors
authorIvan Maidanski <ivmai@mail.ru>
Sun, 11 Nov 2012 07:26:38 +0000 (11:26 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Sun, 11 Nov 2012 07:26:38 +0000 (11:26 +0400)
(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.

blacklst.c
dbg_mlc.c
include/private/gc_priv.h
reclaim.c

index 778b2af..11556a4 100644 (file)
@@ -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;
index 7e7a347..9422b71 100644 (file)
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
     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) {
           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     */
index 3eca2b1..c33e018 100644 (file)
@@ -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,   */
index cf2a4e9..1cf7555 100644 (file)
--- a/reclaim.c
+++ b/reclaim.c
@@ -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;