check.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /* $Header$ */
  2. /*
  3. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  4. * See the copyright notice in the ACK home directory, in the file "Copyright".
  5. */
  6. #include <stdio.h>
  7. #include "param.h"
  8. #include "impl.h"
  9. #include "check.h"
  10. #include "phys.h"
  11. #include "log.h"
  12. #ifdef CHECK /* otherwise this whole file is skipped */
  13. private acquire_malout(), check_ml_last();
  14. private dump_all_mallinks(), dump_free_list(), dump_mallink(), print_loop();
  15. private working_on();
  16. private size_type checksum();
  17. static FILE *malout;
  18. public mallink *free_list_entry();
  19. #define for_free_list(i,p) \
  20. for (p = free_list_entry(i); p; p = log_next_of(p))
  21. #define for_all_mallinks(ml) /* backwards! */ \
  22. for (ml = ml_last; ml; \
  23. ml = first_mallink(ml) ? MAL_NULL : phys_prev_of(ml))
  24. /* Maldump */
  25. static int pr_cnt = 0;
  26. maldump(n) {
  27. /* Dump pertinent info in pseudo-readable format;
  28. abort afterwards if n != 0.
  29. */
  30. static int dumping = 0;
  31. int i;
  32. if (dumping)
  33. return;
  34. dumping++;
  35. acquire_malout();
  36. fprintf(malout,
  37. ">>>>>>>>>>>>>>>> DUMP OF ALL MALLINKS <<<<<<<<<<<<<<<<");
  38. fprintf(malout, " ml_last = %ld\n", (long)ml_last);
  39. if (++pr_cnt == 100) pr_cnt = 0;
  40. dump_all_mallinks();
  41. fprintf(malout,
  42. ">>>>>>>>>>>>>>>> DUMP OF FREE_LISTS <<<<<<<<<<<<<<<<\n");
  43. if (++pr_cnt == 100) pr_cnt = 0;
  44. for (i = 0; i < MAX_FLIST; i++)
  45. dump_free_list(i);
  46. fprintf(malout,
  47. ">>>>>>>>>>>>>>>> END OF DUMP <<<<<<<<<<<<<<<<\n");
  48. fclose(malout);
  49. dumping--;
  50. if (n)
  51. abort();
  52. }
  53. private
  54. acquire_malout() {
  55. static char buf[BUFSIZ];
  56. if (!malout) {
  57. malout = freopen("mal.out", "w", stderr);
  58. setbuf(malout, buf);
  59. }
  60. }
  61. private
  62. dump_all_mallinks() {
  63. mallink *ml;
  64. for_all_mallinks (ml) {
  65. if (print_loop(ml))
  66. return;
  67. dump_mallink((char *)0, ml);
  68. }
  69. }
  70. private
  71. dump_free_list(i) {
  72. mallink *ml = free_list_entry(i);
  73. if (!ml)
  74. return;
  75. fprintf(malout, "%2d: ", i);
  76. for_free_list(i, ml) {
  77. if (print_loop(ml))
  78. return;
  79. fprintf(malout, "%ld ", (long) ml);
  80. }
  81. fprintf(malout, "<\n");
  82. }
  83. private int
  84. print_loop(ml) mallink *ml; {
  85. if (print_of(ml) == pr_cnt) {
  86. fprintf(malout, "... PRINT LOOP\n");
  87. return 1;
  88. }
  89. set_print(ml, pr_cnt);
  90. return 0;
  91. }
  92. private
  93. dump_mallink(s, ml) char *s; mallink *ml; {
  94. acquire_malout();
  95. if (s)
  96. fprintf(malout, "%s: ", s);
  97. fprintf(malout, "@: %ld;", (long)ml);
  98. if (ml && checksum_of(ml) != checksum(ml))
  99. fprintf(malout, ">>>> CORRUPTED <<<<");
  100. if (!ml) {
  101. fprintf(malout, "\n");
  102. return;
  103. }
  104. if (free_of(ml)) {
  105. fprintf(malout, " l_p: %ld;", (long)_log_prev_of(ml));
  106. fprintf(malout, " l_n: %ld;", (long)_log_next_of(ml));
  107. }
  108. fprintf(malout, " p_s: %ld;", (long)prev_size_of(ml));
  109. fprintf(malout, " t_s: %ld;", (long)_this_size_of(ml));
  110. fprintf(malout, " sz: %ld;", (long)size_of(ml));
  111. fprintf(malout, " fr: %d;", free_of(ml));
  112. fprintf(malout, "\n");
  113. }
  114. /* Check_mallinks() checks the total data structure as accessible
  115. through free_list[] and ml_last. All check_sums should be OK,
  116. except those held in the small array off_colour. This is a
  117. trick to allow to continue checking even when a few mallinks
  118. are temporarily out of order.
  119. Check_mallinks() tests for a lot of internal consistency.
  120. */
  121. /* Some arbitrary constants */
  122. #define IN_ML_LAST 93
  123. #define IN_FREE_LIST 57 /* and in ml_last */
  124. #define CLEAR 21
  125. #define VRIJ 1
  126. #define BEZET 2
  127. public
  128. check_mallinks(s) char *s; {
  129. mallink *ml;
  130. size_type size;
  131. int i;
  132. char stat;
  133. check_ml_last(s);
  134. stat = BEZET;
  135. for_all_mallinks(ml) {
  136. if (checksum_of(ml) != checksum(ml))
  137. Error("mallink info at %lx corrupted", s, (long)ml);
  138. if (working_on(ml)) {
  139. stat = BEZET;
  140. continue;
  141. }
  142. if ( !last_mallink(ml) &&
  143. phys_prev_of(phys_next_of(ml)) != ml
  144. )
  145. Error("upward chain bad at %lx", s, (long)ml);
  146. if ( !first_mallink(ml) &&
  147. phys_next_of(phys_prev_of(ml)) != ml
  148. )
  149. Error("downward chain bad at %lx", s, (long)ml);
  150. if (free_of(ml)) {
  151. if (stat == VRIJ)
  152. Error("free mallink at %lx follows free mallink",
  153. s, (long)ml);
  154. stat = VRIJ;
  155. }
  156. else
  157. stat = BEZET;
  158. set_mark(ml, IN_ML_LAST);
  159. }
  160. for (i = 0, size = MIN_SIZE; i < MAX_FLIST; i++, size *= 2) {
  161. for_free_list(i, ml) {
  162. if (working_on(ml))
  163. continue;
  164. if (!free_of(ml))
  165. Error("occupied mallink %lx occurs in free_list", s, (long)ml);
  166. switch (mark_of(ml)) {
  167. case IN_ML_LAST:
  168. set_mark(ml, IN_FREE_LIST);
  169. break;
  170. case IN_FREE_LIST:
  171. Error("mallink %lx occurs in 2 free_lists",
  172. s, (long)ml);
  173. default:
  174. Error("unknown mallink %lx in free_list",
  175. s, (long)ml);
  176. }
  177. if (size_of(ml) < size)
  178. Error("size of mallink %lx too small", s, (long)ml);
  179. if (size_of(ml) >= 2*size)
  180. Error("size of mallink %lx too large", s, (long)ml);
  181. }
  182. }
  183. for_all_mallinks (ml) {
  184. if (working_on(ml))
  185. continue;
  186. if (free_of(ml) && mark_of(ml) != IN_FREE_LIST)
  187. Error("free mallink %lx is in no free_list", s, (long)ml);
  188. set_mark(ml, CLEAR);
  189. }
  190. }
  191. private
  192. check_ml_last(s) char *s; {
  193. if (ml_last && _this_size_of(ml_last) == 0)
  194. Error("size of ml_last == 0, at %ld", s, ml_last);
  195. }
  196. private size_type
  197. checksum(ml) mallink *ml; {
  198. size_type sum = 0;
  199. if (free_of(ml)) {
  200. sum += (size_type)_log_prev_of(ml);
  201. sum += (size_type)_log_next_of(ml);
  202. }
  203. sum += (size_type)prev_size_of(ml);
  204. sum += (size_type)_this_size_of(ml);
  205. return sum;
  206. }
  207. public
  208. calc_checksum(ml) mallink *ml; {
  209. set_checksum(ml, checksum(ml));
  210. }
  211. #define N_COLOUR 10
  212. static mallink *off_colour[N_COLOUR];
  213. public
  214. started_working_on(ml) mallink *ml; {
  215. int i;
  216. for (i = 0; i < N_COLOUR; i++)
  217. if (off_colour[i] == MAL_NULL) {
  218. off_colour[i] = ml;
  219. return;
  220. }
  221. Error("out of off_colour array at %ld", "started_working_on", ml);
  222. }
  223. public
  224. stopped_working_on(ml) mallink *ml; {
  225. int i;
  226. for (i = 0; i < N_COLOUR; i++)
  227. if (off_colour[i] == ml) {
  228. off_colour[i] = MAL_NULL;
  229. return;
  230. }
  231. Error("stopped working on mallink %ld", "stopped_working_on", ml);
  232. }
  233. private int
  234. working_on(ml) mallink *ml; {
  235. int i;
  236. for (i = 0; i < N_COLOUR; i++)
  237. if (off_colour[i] == ml)
  238. return 1;
  239. return 0;
  240. }
  241. public
  242. check_work_empty(s) char *s; {
  243. int i;
  244. int cnt = 0;
  245. for (i = 0; i < N_COLOUR; i++)
  246. if (off_colour[i] != MAL_NULL)
  247. cnt++;
  248. if (cnt != 0)
  249. Error("off_colour not empty", s, MAL_NULL);
  250. }
  251. public int
  252. Error(fmt, s, ml) char *fmt, *s; mallink *ml; {
  253. static int already_called = 0;
  254. if (already_called++) return 0;
  255. setbuf(stdout, (char *) 0);
  256. printf("%s: ", s);
  257. printf(fmt, (long)ml);
  258. printf("\n");
  259. acquire_malout();
  260. fprintf(malout, "%s: ", s);
  261. fprintf(malout, fmt, (long)ml);
  262. fprintf(malout, "\n");
  263. fflush(stdout);
  264. maldump(1);
  265. return 0; /* to satisfy lint */
  266. }
  267. #endif /* CHECK */