|
@@ -0,0 +1,297 @@
|
|
|
+#include <stdio.h>
|
|
|
+#include "param.h"
|
|
|
+#include "impl.h"
|
|
|
+#include "check.h"
|
|
|
+#include "phys.h"
|
|
|
+#include "log.h"
|
|
|
+
|
|
|
+#ifdef CHECK /* otherwise this whole file is skipped */
|
|
|
+
|
|
|
+private acquire_malout(), check_ml_last();
|
|
|
+private dump_all_mallinks(), dump_free_list(), dump_mallink(), print_loop();
|
|
|
+private working_on();
|
|
|
+private unsigned int checksum();
|
|
|
+static FILE *malout;
|
|
|
+
|
|
|
+public mallink *free_list_entry();
|
|
|
+
|
|
|
+#define for_free_list(i,p) \
|
|
|
+ for (p = free_list_entry(i); p; p = log_next_of(p))
|
|
|
+
|
|
|
+#define for_all_mallinks(ml) /* backwards! */ \
|
|
|
+ for (ml = ml_last; ml; \
|
|
|
+ ml = first_mallink(ml) ? MAL_NULL : phys_prev_of(ml))
|
|
|
+
|
|
|
+/* Maldump */
|
|
|
+
|
|
|
+static int pr_cnt = 0;
|
|
|
+
|
|
|
+maldump(n) {
|
|
|
+ /* Dump pertinent info in pseudo-readable format;
|
|
|
+ abort afterwards if n != 0.
|
|
|
+ */
|
|
|
+ static int dumping = 0;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (dumping)
|
|
|
+ return;
|
|
|
+ dumping++;
|
|
|
+ acquire_malout();
|
|
|
+ fprintf(malout,
|
|
|
+ ">>>>>>>>>>>>>>>> DUMP OF ALL MALLINKS <<<<<<<<<<<<<<<<");
|
|
|
+ fprintf(malout, " ml_last = %ld\n", (long)ml_last);
|
|
|
+ if (++pr_cnt == 100) pr_cnt = 0;
|
|
|
+ dump_all_mallinks();
|
|
|
+ fprintf(malout,
|
|
|
+ ">>>>>>>>>>>>>>>> DUMP OF FREE_LISTS <<<<<<<<<<<<<<<<\n");
|
|
|
+ if (++pr_cnt == 100) pr_cnt = 0;
|
|
|
+ for (i = 0; i < MAX_FLIST; i++)
|
|
|
+ dump_free_list(i);
|
|
|
+ fprintf(malout,
|
|
|
+ ">>>>>>>>>>>>>>>> END OF DUMP <<<<<<<<<<<<<<<<\n");
|
|
|
+ fclose(malout);
|
|
|
+ dumping--;
|
|
|
+ if (n)
|
|
|
+ abort();
|
|
|
+}
|
|
|
+
|
|
|
+private
|
|
|
+acquire_malout() {
|
|
|
+ static char buf[BUFSIZ];
|
|
|
+
|
|
|
+ if (!malout) {
|
|
|
+ malout = fopen("mal.out", "w");
|
|
|
+ setbuf(malout, buf);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+private
|
|
|
+dump_all_mallinks() {
|
|
|
+ mallink *ml;
|
|
|
+
|
|
|
+ for_all_mallinks (ml) {
|
|
|
+ if (print_loop(ml))
|
|
|
+ return;
|
|
|
+ dump_mallink((char *)0, ml);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+private
|
|
|
+dump_free_list(i) {
|
|
|
+ mallink *ml = free_list_entry(i);
|
|
|
+
|
|
|
+ if (!ml)
|
|
|
+ return;
|
|
|
+ fprintf(malout, "%2d: ", i);
|
|
|
+ for_free_list(i, ml) {
|
|
|
+ if (print_loop(ml))
|
|
|
+ return;
|
|
|
+ fprintf(malout, "%ld ", ml);
|
|
|
+ }
|
|
|
+ fprintf(malout, "<\n");
|
|
|
+}
|
|
|
+
|
|
|
+private int
|
|
|
+print_loop(ml) mallink *ml; {
|
|
|
+ if (print_of(ml) == pr_cnt) {
|
|
|
+ fprintf(malout, "... PRINT LOOP\n");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ set_print(ml, pr_cnt);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+private
|
|
|
+dump_mallink(s, ml) char *s; mallink *ml; {
|
|
|
+ acquire_malout();
|
|
|
+ if (s)
|
|
|
+ fprintf(malout, "%s: ", s);
|
|
|
+ fprintf(malout, "@: %ld;", (long)ml);
|
|
|
+ if (ml && checksum_of(ml) != checksum(ml))
|
|
|
+ fprintf(malout, ">>>> CORRUPTED <<<<");
|
|
|
+ if (!ml) {
|
|
|
+ fprintf(malout, "\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (free_of(ml)) {
|
|
|
+ fprintf(malout, " l_p: %ld;", (long)_log_prev_of(ml));
|
|
|
+ fprintf(malout, " l_n: %ld;", (long)_log_next_of(ml));
|
|
|
+ }
|
|
|
+ fprintf(malout, " p_s: %ld;", (long)prev_size_of(ml));
|
|
|
+ fprintf(malout, " t_s: %ld;", (long)_this_size_of(ml));
|
|
|
+ fprintf(malout, " sz: %ld;", (long)size_of(ml));
|
|
|
+ fprintf(malout, " fr: %d;", free_of(ml));
|
|
|
+ fprintf(malout, "\n");
|
|
|
+}
|
|
|
+
|
|
|
+/* Check_mallinks() checks the total data structure as accessible
|
|
|
+ through free_list[] and ml_last. All check_sums should be OK,
|
|
|
+ except those held in the small array off_colour. This is a
|
|
|
+ trick to allow to continue checking even when a few mallinks
|
|
|
+ are temporarily out of order.
|
|
|
+ Check_mallinks() tests for a lot of internal consistency.
|
|
|
+*/
|
|
|
+
|
|
|
+/* Some arbitrary constants */
|
|
|
+#define IN_ML_LAST 93
|
|
|
+#define IN_FREE_LIST 57 /* and in ml_last */
|
|
|
+#define CLEAR 21
|
|
|
+
|
|
|
+#define VRIJ 1
|
|
|
+#define BEZET 2
|
|
|
+
|
|
|
+public
|
|
|
+check_mallinks(s) char *s; {
|
|
|
+ mallink *ml;
|
|
|
+ unsigned int size;
|
|
|
+ int i;
|
|
|
+ char stat;
|
|
|
+
|
|
|
+ check_ml_last(s);
|
|
|
+ stat = BEZET;
|
|
|
+ for_all_mallinks(ml) {
|
|
|
+ if (checksum_of(ml) != checksum(ml))
|
|
|
+ Error("mallink info at %ld corrupted", s, ml);
|
|
|
+ if (working_on(ml)) {
|
|
|
+ stat = BEZET;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if ( !last_mallink(ml) &&
|
|
|
+ phys_prev_of(phys_next_of(ml)) != ml
|
|
|
+ )
|
|
|
+ Error("upward chain bad at %ld", s, ml);
|
|
|
+ if ( !first_mallink(ml) &&
|
|
|
+ phys_next_of(phys_prev_of(ml)) != ml
|
|
|
+ )
|
|
|
+ Error("downward chain bad at %ld", s, ml);
|
|
|
+ if (free_of(ml)) {
|
|
|
+ if (stat == VRIJ)
|
|
|
+ Error("free mallink at %ld follows free mallink",
|
|
|
+ s, ml);
|
|
|
+ stat = VRIJ;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ stat = BEZET;
|
|
|
+ set_mark(ml, IN_ML_LAST);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0, size = MIN_SIZE; i < MAX_FLIST; i++, size *= 2) {
|
|
|
+ for_free_list(i, ml) {
|
|
|
+ if (working_on(ml))
|
|
|
+ continue;
|
|
|
+ if (!free_of(ml))
|
|
|
+ Error("occupied mallink %ld occurs in free_list", s, ml);
|
|
|
+ switch (mark_of(ml)) {
|
|
|
+ case IN_ML_LAST:
|
|
|
+ set_mark(ml, IN_FREE_LIST);
|
|
|
+ break;
|
|
|
+ case IN_FREE_LIST:
|
|
|
+ Error("mallink %ld occurs in 2 free_lists",
|
|
|
+ s, ml);
|
|
|
+ default:
|
|
|
+ Error("unknown mallink %ld in free_list",
|
|
|
+ s, ml);
|
|
|
+ }
|
|
|
+ if (size_of(ml) < size)
|
|
|
+ Error("size of mallink %ld too small", s, ml);
|
|
|
+ if (size_of(ml) >= 2*size)
|
|
|
+ Error("size of mallink %ld too large", s, ml);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for_all_mallinks (ml) {
|
|
|
+ if (working_on(ml))
|
|
|
+ continue;
|
|
|
+ if (free_of(ml) && mark_of(ml) != IN_FREE_LIST)
|
|
|
+ Error("free mallink %ld is in no free_list", s, ml);
|
|
|
+ set_mark(ml, CLEAR);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+private
|
|
|
+check_ml_last(s) char *s; {
|
|
|
+ if (ml_last && _this_size_of(ml_last) == 0)
|
|
|
+ Error("size of ml_last == 0, at %ld", s, ml_last);
|
|
|
+}
|
|
|
+
|
|
|
+private unsigned int
|
|
|
+checksum(ml) mallink *ml; {
|
|
|
+ unsigned int sum = 0;
|
|
|
+
|
|
|
+ if (free_of(ml)) {
|
|
|
+ sum += (unsigned int)_log_prev_of(ml);
|
|
|
+ sum += (unsigned int)_log_next_of(ml);
|
|
|
+ }
|
|
|
+ sum += (unsigned int)prev_size_of(ml);
|
|
|
+ sum += (unsigned int)_this_size_of(ml);
|
|
|
+ return sum;
|
|
|
+}
|
|
|
+
|
|
|
+public
|
|
|
+calc_checksum(ml) mallink *ml; {
|
|
|
+ set_checksum(ml, checksum(ml));
|
|
|
+}
|
|
|
+
|
|
|
+#define N_COLOUR 10
|
|
|
+static mallink *off_colour[N_COLOUR];
|
|
|
+
|
|
|
+public
|
|
|
+started_working_on(ml) mallink *ml; {
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < N_COLOUR; i++)
|
|
|
+ if (off_colour[i] == MAL_NULL) {
|
|
|
+ off_colour[i] = ml;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Error("out of off_colour array at %ld", "started_working_on", ml);
|
|
|
+}
|
|
|
+
|
|
|
+public
|
|
|
+stopped_working_on(ml) mallink *ml; {
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < N_COLOUR; i++)
|
|
|
+ if (off_colour[i] == ml) {
|
|
|
+ off_colour[i] = MAL_NULL;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Error("stopped working on mallink %ld", "stopped_working_on", ml);
|
|
|
+}
|
|
|
+
|
|
|
+private int
|
|
|
+working_on(ml) mallink *ml; {
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < N_COLOUR; i++)
|
|
|
+ if (off_colour[i] == ml)
|
|
|
+ return 1;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+public
|
|
|
+check_work_empty(s) char *s; {
|
|
|
+ int i;
|
|
|
+ int cnt = 0;
|
|
|
+
|
|
|
+ for (i = 0; i < N_COLOUR; i++)
|
|
|
+ if (off_colour[i] != MAL_NULL)
|
|
|
+ cnt++;
|
|
|
+ if (cnt != 0)
|
|
|
+ Error("off_colour not empty", s, MAL_NULL);
|
|
|
+}
|
|
|
+
|
|
|
+public int
|
|
|
+Error(fmt, s, ml) char *fmt, *s; mallink *ml; {
|
|
|
+ printf("%s: ", s);
|
|
|
+ printf(fmt, (long)ml);
|
|
|
+ printf("\n");
|
|
|
+ acquire_malout();
|
|
|
+ fprintf(malout, "%s: ", s);
|
|
|
+ fprintf(malout, fmt, (long)ml);
|
|
|
+ fprintf(malout, "\n");
|
|
|
+ fflush(stdout);
|
|
|
+ maldump(1);
|
|
|
+ return 0; /* to satisfy lint */
|
|
|
+}
|
|
|
+
|
|
|
+#endif CHECK
|