ack/lang/cem/libcc.ansi/stdlib/malloc/check.c
1989-12-18 13:31:20 +00:00

301 lines
6.4 KiB
C

/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#include <stdio.h>
#ifdef CHECK /* otherwise this whole file is skipped */
/* ??? check these later */
private acquire_malout(void), check_ml_last(const char *s);
private dump_all_mallinks(void), dump_free_list(int i);
private dump_mallink(const char *s), print_loop(mallink *ml);
private working_on(mallink *ml);
private unsigned int checksum(mallink *ml);
static FILE *malout;
private mallink *free_list_entry(int i);
#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(int 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(void) {
static char buf[BUFSIZ];
if (!malout) {
malout = fopen("mal.out", "w");
setbuf(malout, buf);
}
}
private
dump_all_mallinks(void) {
mallink *ml;
for_all_mallinks (ml) {
if (print_loop(ml))
return;
dump_mallink((char *)0, ml);
}
}
private
dump_free_list(int 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(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(const 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
private
check_mallinks(const 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(const 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(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;
}
private
calc_checksum(mallink *ml) {
set_checksum(ml, checksum(ml));
}
#define N_COLOUR 10
static mallink *off_colour[N_COLOUR];
private
started_working_on(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);
}
private
stopped_working_on(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(mallink *ml) {
int i;
for (i = 0; i < N_COLOUR; i++)
if (off_colour[i] == ml)
return 1;
return 0;
}
private
check_work_empty(const 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);
}
private int
Error(const char *fmt, const char *s, mallink *ml) {
setbuf(stdout, (char *) 0);
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 */