-/*
- *=====================================================================
- * debug_caller_loc -- keep track of all allocation callers
- *
- * const char *debug_caller_loc(const char *file, int line)
- *
- * entry: file = source file
- * line = source line
- * exit: a string like "genversion.c@999"
- *
- * The debug malloc library has a concept of a call stack that can be used
- * to fine tune what was running when a particular allocation was done.
- * We use it to tell who called our various allocation wrappers since
- * it wouldn't do much good to tell us a problem happened because of
- * the malloc call in alloc (they are all from there at some point).
- *
- * But the library expects the string passed to malloc_enter/malloc_leave
- * to be static, so we build a linked list of each one we get (there are
- * not really that many during a given execution). When we get a repeat
- * we return the previously allocated string. For a bit of performance,
- * we keep the list in least recently used order, which helps because
- * the calls to us come in pairs (one for malloc_enter and one right
- * after for malloc_leave).
- *=====================================================================
- */
-
-const char *
-debug_caller_loc(
- const char *file,
- int line)
-{
- /*@keep@*/
- struct loc_str {
- char *str;
- LIST_ENTRY(loc_str) le;
- } *ls;
- static LIST_HEAD(, loc_str) root = LIST_HEAD_INITIALIZER(root);
- static char loc[256]; /* big enough for filename@lineno */
- const char *p;
-
- if ((p = strrchr(file, '/')) != NULL)
- file = p + 1; /* just the last path element */
-
- snprintf(loc, SIZEOF(loc), "%s@%d", file, line);
-
- for (ls = LIST_FIRST(&root); ls != NULL; ls = LIST_NEXT(ls, le)) {
- if (strcmp(loc, ls->str) == 0) {
- if (ls != LIST_FIRST(&root)) {
- /*
- * This is a repeat and was not at the head of the list.
- * Unlink it and move it to the front.
- */
- LIST_REMOVE(ls, le);
- LIST_INSERT_HEAD(&root, ls, le);
- }
- return (ls->str);
- }
- }
-
- /*
- * This is a new entry. Put it at the head of the list.
- */
- ls = malloc(SIZEOF(*ls));
- if (ls == NULL)
- return ("??"); /* not much better than abort */
- ls->str = malloc(strlen(loc) + 1);
- if (ls->str == NULL) {
- free(ls);
- return ("??"); /* not much better than abort */
- }
- strcpy(ls->str, loc);
- malloc_mark(ls);
- malloc_mark(ls->str);
- LIST_INSERT_HEAD(&root, ls, le);
- return (ls->str);
-}
-
-/*
- *=====================================================================
- * Save the current source line for vstralloc/newvstralloc.
- *
- * int debug_alloc_push (char *s, int l)
- *
- * entry: s = source file
- * l = source line
- * exit: always zero
- *
- * See the comments in amanda.h about what this is used for.
- *=====================================================================
- */
-
-#define DEBUG_ALLOC_SAVE_MAX 10
-
-static struct {
- char *file;
- int line;
-} debug_alloc_loc_info[DEBUG_ALLOC_SAVE_MAX];
-static int debug_alloc_ptr = 0;
-
-static char *saved_file;
-static int saved_line;
-
-int
-debug_alloc_push(
- char *s,
- int l)
-{
- debug_alloc_loc_info[debug_alloc_ptr].file = s;
- debug_alloc_loc_info[debug_alloc_ptr].line = l;
- debug_alloc_ptr = (debug_alloc_ptr + 1) % DEBUG_ALLOC_SAVE_MAX;
- return 0;
-}
-
-/*
- *=====================================================================
- * Pop the current source line information for vstralloc/newvstralloc.
- *
- * int debug_alloc_pop (void)
- *
- * entry: none
- * exit: none
- *
- * See the comments in amanda.h about what this is used for.
- *=====================================================================
- */
-
-void
-debug_alloc_pop(void)
-{
- debug_alloc_ptr =
- (debug_alloc_ptr + DEBUG_ALLOC_SAVE_MAX - 1) % DEBUG_ALLOC_SAVE_MAX;
- saved_file = debug_alloc_loc_info[debug_alloc_ptr].file;
- saved_line = debug_alloc_loc_info[debug_alloc_ptr].line;
-}