checksums.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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, March 29, 1995 12:51 pm PST */
  14. # ifdef CHECKSUMS
  15. # include "private/gc_priv.h"
  16. /* This is debugging code intended to verify the results of dirty bit */
  17. /* computations. Works only in a single threaded environment. */
  18. /* We assume that stubborn objects are changed only when they are */
  19. /* enabled for writing. (Certain kinds of writing are actually */
  20. /* safe under other conditions.) */
  21. # define NSUMS 10000
  22. # define OFFSET 0x10000
  23. typedef struct {
  24. GC_bool new_valid;
  25. word old_sum;
  26. word new_sum;
  27. struct hblk * block; /* Block to which this refers + OFFSET */
  28. /* to hide it from collector. */
  29. } page_entry;
  30. page_entry GC_sums [NSUMS];
  31. word GC_checksum(h)
  32. struct hblk *h;
  33. {
  34. register word *p = (word *)h;
  35. register word *lim = (word *)(h+1);
  36. register word result = 0;
  37. while (p < lim) {
  38. result += *p++;
  39. }
  40. return(result | 0x80000000 /* doesn't look like pointer */);
  41. }
  42. # ifdef STUBBORN_ALLOC
  43. /* Check whether a stubborn object from the given block appears on */
  44. /* the appropriate free list. */
  45. GC_bool GC_on_free_list(h)
  46. struct hblk *h;
  47. {
  48. register hdr * hhdr = HDR(h);
  49. register int sz = hhdr -> hb_sz;
  50. ptr_t p;
  51. if (sz > MAXOBJSZ) return(FALSE);
  52. for (p = GC_sobjfreelist[sz]; p != 0; p = obj_link(p)) {
  53. if (HBLKPTR(p) == h) return(TRUE);
  54. }
  55. return(FALSE);
  56. }
  57. # endif
  58. int GC_n_dirty_errors;
  59. int GC_n_changed_errors;
  60. int GC_n_clean;
  61. int GC_n_dirty;
  62. void GC_update_check_page(h, index)
  63. struct hblk *h;
  64. int index;
  65. {
  66. page_entry *pe = GC_sums + index;
  67. register hdr * hhdr = HDR(h);
  68. struct hblk *b;
  69. if (pe -> block != 0 && pe -> block != h + OFFSET) ABORT("goofed");
  70. pe -> old_sum = pe -> new_sum;
  71. pe -> new_sum = GC_checksum(h);
  72. # if !defined(MSWIN32) && !defined(MSWINCE)
  73. if (pe -> new_sum != 0x80000000 && !GC_page_was_ever_dirty(h)) {
  74. GC_printf1("GC_page_was_ever_dirty(0x%lx) is wrong\n",
  75. (unsigned long)h);
  76. }
  77. # endif
  78. if (GC_page_was_dirty(h)) {
  79. GC_n_dirty++;
  80. } else {
  81. GC_n_clean++;
  82. }
  83. b = h;
  84. while (IS_FORWARDING_ADDR_OR_NIL(hhdr) && hhdr != 0) {
  85. b -= (word)hhdr;
  86. hhdr = HDR(b);
  87. }
  88. if (pe -> new_valid
  89. && hhdr != 0 && hhdr -> hb_descr != 0 /* may contain pointers */
  90. && pe -> old_sum != pe -> new_sum) {
  91. if (!GC_page_was_dirty(h) || !GC_page_was_ever_dirty(h)) {
  92. /* Set breakpoint here */GC_n_dirty_errors++;
  93. }
  94. # ifdef STUBBORN_ALLOC
  95. if ( hhdr -> hb_map != GC_invalid_map
  96. && hhdr -> hb_obj_kind == STUBBORN
  97. && !GC_page_was_changed(h)
  98. && !GC_on_free_list(h)) {
  99. /* if GC_on_free_list(h) then reclaim may have touched it */
  100. /* without any allocations taking place. */
  101. /* Set breakpoint here */GC_n_changed_errors++;
  102. }
  103. # endif
  104. }
  105. pe -> new_valid = TRUE;
  106. pe -> block = h + OFFSET;
  107. }
  108. word GC_bytes_in_used_blocks;
  109. void GC_add_block(h, dummy)
  110. struct hblk *h;
  111. word dummy;
  112. {
  113. register hdr * hhdr = HDR(h);
  114. register bytes = WORDS_TO_BYTES(hhdr -> hb_sz);
  115. bytes += HBLKSIZE-1;
  116. bytes &= ~(HBLKSIZE-1);
  117. GC_bytes_in_used_blocks += bytes;
  118. }
  119. void GC_check_blocks()
  120. {
  121. word bytes_in_free_blocks = GC_large_free_bytes;
  122. GC_bytes_in_used_blocks = 0;
  123. GC_apply_to_all_blocks(GC_add_block, (word)0);
  124. GC_printf2("GC_bytes_in_used_blocks = %ld, bytes_in_free_blocks = %ld ",
  125. GC_bytes_in_used_blocks, bytes_in_free_blocks);
  126. GC_printf1("GC_heapsize = %ld\n", GC_heapsize);
  127. if (GC_bytes_in_used_blocks + bytes_in_free_blocks != GC_heapsize) {
  128. GC_printf0("LOST SOME BLOCKS!!\n");
  129. }
  130. }
  131. /* Should be called immediately after GC_read_dirty and GC_read_changed. */
  132. void GC_check_dirty()
  133. {
  134. register int index;
  135. register unsigned i;
  136. register struct hblk *h;
  137. register ptr_t start;
  138. GC_check_blocks();
  139. GC_n_dirty_errors = 0;
  140. GC_n_changed_errors = 0;
  141. GC_n_clean = 0;
  142. GC_n_dirty = 0;
  143. index = 0;
  144. for (i = 0; i < GC_n_heap_sects; i++) {
  145. start = GC_heap_sects[i].hs_start;
  146. for (h = (struct hblk *)start;
  147. h < (struct hblk *)(start + GC_heap_sects[i].hs_bytes);
  148. h++) {
  149. GC_update_check_page(h, index);
  150. index++;
  151. if (index >= NSUMS) goto out;
  152. }
  153. }
  154. out:
  155. GC_printf2("Checked %lu clean and %lu dirty pages\n",
  156. (unsigned long) GC_n_clean, (unsigned long) GC_n_dirty);
  157. if (GC_n_dirty_errors > 0) {
  158. GC_printf1("Found %lu dirty bit errors\n",
  159. (unsigned long)GC_n_dirty_errors);
  160. }
  161. if (GC_n_changed_errors > 0) {
  162. GC_printf1("Found %lu changed bit errors\n",
  163. (unsigned long)GC_n_changed_errors);
  164. GC_printf0("These may be benign (provoked by nonpointer changes)\n");
  165. # ifdef THREADS
  166. GC_printf0(
  167. "Also expect 1 per thread currently allocating a stubborn obj.\n");
  168. # endif
  169. }
  170. }
  171. # else
  172. extern int GC_quiet;
  173. /* ANSI C doesn't allow translation units to be empty. */
  174. /* So we guarantee this one is nonempty. */
  175. # endif /* CHECKSUMS */