home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sa104os2.zip / SATHR104.ZIP / SATHER / SYSTEM / GC / CHECKSUM.C < prev    next >
C/C++ Source or Header  |  1994-07-14  |  5KB  |  163 lines

  1. /*
  2.  * Copyright (c) 1992-1994 by Xerox Corporation.  All rights reserved.
  3.  *
  4.  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  5.  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  6.  *
  7.  * Permission is hereby granted to use or copy this program
  8.  * for any purpose,  provided the above notices are retained on all copies.
  9.  * Permission to modify the code and to distribute modified code is granted,
  10.  * provided the above notices are retained, and a notice that the code was
  11.  * modified is included with the above copyright notice.
  12.  */
  13. /* Boehm, July 14, 1994 3:27 pm PDT */
  14. # ifdef CHECKSUMS
  15.  
  16. # include "gc_priv.h"
  17.  
  18. /* This is debugging code intended to verify the results of dirty bit    */
  19. /* computations. Works only in a single threaded environment.        */
  20. /* We assume that stubborn objects are changed only when they are     */
  21. /* enabled for writing.  (Certain kinds of writing are actually        */
  22. /* safe under other conditions.)                    */
  23. # define NSUMS 2000
  24.  
  25. # define OFFSET 100000
  26.  
  27. typedef struct {
  28.     bool new_valid;
  29.     word old_sum;
  30.     word new_sum;
  31.     struct hblk * block;    /* Block to which this refers + OFFSET  */
  32.                 /* to hide it from colector.        */
  33. } page_entry;
  34.  
  35. page_entry GC_sums [NSUMS];
  36.  
  37. word GC_checksum(h)
  38. struct hblk *h;
  39. {
  40.     register word *p = (word *)h;
  41.     register word *lim = (word *)(h+1);
  42.     register word result = 0;
  43.     
  44.     while (p < lim) {
  45.         result += *p++;
  46.     }
  47.     return(result);
  48. }
  49.  
  50. # ifdef STUBBORN_ALLOC
  51. /* Check whether a stubborn object from the given block appears on    */
  52. /* the appropriate free list.                        */
  53. bool GC_on_free_list(h)
  54. struct hblk *h;
  55. {
  56.     register hdr * hhdr = HDR(h);
  57.     register int sz = hhdr -> hb_sz;
  58.     ptr_t p;
  59.     
  60.     if (sz > MAXOBJSZ) return(FALSE);
  61.     for (p = GC_sobjfreelist[sz]; p != 0; p = obj_link(p)) {
  62.         if (HBLKPTR(p) == h) return(TRUE);
  63.     }
  64.     return(FALSE);
  65. }
  66. # endif
  67.  
  68. int GC_n_dirty_errors;
  69. int GC_n_changed_errors;
  70. int GC_n_clean;
  71. int GC_n_dirty;
  72.  
  73. void GC_update_check_page(h, index)
  74. struct hblk *h;
  75. int index;
  76. {
  77.     page_entry *pe = GC_sums + index;
  78.     register hdr * hhdr = HDR(h);
  79.     
  80.     if (pe -> block != 0 && pe -> block != h + OFFSET) ABORT("goofed");
  81.     pe -> old_sum = pe -> new_sum;
  82.     pe -> new_sum = GC_checksum(h);
  83. #   ifndef MSWIN32
  84.         if (pe -> new_sum != 0 && !GC_page_was_ever_dirty(h)) {
  85.             GC_printf1("GC_page_was_ever_dirty(0x%lx) is wrong\n",
  86.                    (unsigned long)h);
  87.         }
  88. #   endif
  89.     if (GC_page_was_dirty(h)) {
  90.         GC_n_dirty++;
  91.     } else {
  92.         GC_n_clean++;
  93.     }
  94.     if (pe -> new_valid && pe -> old_sum != pe -> new_sum) {
  95.         if (!GC_page_was_dirty(h) || !GC_page_was_ever_dirty(h)) {
  96.             /* Set breakpoint here */GC_n_dirty_errors++;
  97.         }
  98. #    ifdef STUBBORN_ALLOC
  99.           if (!IS_FORWARDING_ADDR_OR_NIL(hhdr)
  100.             && hhdr -> hb_map != GC_invalid_map
  101.             && hhdr -> hb_obj_kind == STUBBORN
  102.             && !GC_page_was_changed(h)
  103.             && !GC_on_free_list(h)) {
  104.             /* if GC_on_free_list(h) then reclaim may have touched it    */
  105.             /* without any allocations taking place.            */
  106.             /* Set breakpoint here */GC_n_changed_errors++;
  107.           }
  108. #    endif
  109.     }
  110.     pe -> new_valid = TRUE;
  111.     pe -> block = h + OFFSET;
  112. }
  113.  
  114. /* Should be called immediately after GC_read_dirty and GC_read_changed. */
  115. void GC_check_dirty()
  116. {
  117.     register int index;
  118.     register int i;
  119.     register struct hblk *h;
  120.     register ptr_t start;
  121.     
  122.     GC_n_dirty_errors = 0;
  123.     GC_n_changed_errors = 0;
  124.     GC_n_clean = 0;
  125.     GC_n_dirty = 0;
  126.     
  127.     index = 0;
  128.     for (i = 0; i < GC_n_heap_sects; i++) {
  129.         start = GC_heap_sects[i].hs_start;
  130.         for (h = (struct hblk *)start;
  131.              h < (struct hblk *)(start + GC_heap_sects[i].hs_bytes);
  132.              h++) {
  133.              GC_update_check_page(h, index);
  134.              index++;
  135.              if (index >= NSUMS) goto out;
  136.         }
  137.     }
  138. out:
  139.     GC_printf2("Checked %lu clean and %lu dirty pages\n",
  140.               (unsigned long) GC_n_clean, (unsigned long) GC_n_dirty);
  141.     if (GC_n_dirty_errors > 0) {
  142.         GC_printf1("Found %lu dirty bit errors\n",
  143.                (unsigned long)GC_n_dirty_errors);
  144.     }
  145.     if (GC_n_changed_errors > 0) {
  146.         GC_printf1("Found %lu changed bit errors\n",
  147.                (unsigned long)GC_n_changed_errors);
  148.     GC_printf0("These may be benign (provoked by nonpointer changes)\n");
  149. #    ifdef THREADS
  150.         GC_printf0(
  151.         "Also expect 1 per thread currently allocating a stubborn obj.\n");
  152. #    endif
  153.     }
  154. }
  155.  
  156. # else
  157.  
  158. extern int GC_quiet;
  159.     /* ANSI C doesn't allow translation units to be empty.    */
  160.     /* So we guarantee this one is nonempty.        */
  161.  
  162. # endif /* CHECKSUMS */
  163.