⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flower_malloc.c

📁 xorp源码hg
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*- *//* vim:set sts=4 ts=8: *//* * Copyright (c) 2001-2007 International Computer Science Institute * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software") * to deal in the Software without restriction, subject to the conditions * listed in the XORP LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the XORP LICENSE file; the license in that file is * legally binding. */#ident "$XORP: xorp/utils/flower_malloc/flower_malloc.c,v 1.7 2007/02/16 22:47:33 pavlin Exp $"/* * Library interposer to collect malloc/calloc/realloc statistics  *  * To compile use:   *     gcc -shared -fpic -o flower_malloc.so flower_malloc.c * * To run use (in BASH): *     LD_PRELOAD=$cwd/flower_malloc.so <your application here> *  * The results will be in ./flower_report.<prog_name>.<pid> for each * process invoked by current application. * * How to use it... * * Start your application as mentioned above, and send it SIGUSR2 whenever you * want to examine the state of the different allocation points in your * program.   *  * If you see that one of the tracked allocation points growing suspciously, * create a file called flower_limits.cfg, with the same format a the report * file generated by flower_malloc.  When a SIGUSR2 signal is sent to * flower_malloc, it checks for such a file, and if found, it will load the * limits specified therein for 'allocs' and 'total size' (the other fields are * ignored).  When any tracker exceeds those limits, the program will abort. * For instance, if your flower_report looks like this: *    ***********************************************    allocs/watermark  total size/watermark avg size  tracker_id       0/120                0/252000         2100           3bab4               300/300            90000/90000         300           3d55c +            4/5             280000/350000        70000           3d7ac +              3/3              20480/20480          6826           4d3a9            * and you are worried about the allocation tracked by tracker_id 3d55c, you * can edit the columns 'allocs' and/or 'total size' on the file to be:    ***********************************************    allocs/watermark  total size/watermark avg size   tracker_id       200/300            80000/90000           300          3d55c +          *                 * and save it as flower_limits.cfg.  You must remove the trackers you are not * interested on.  The next time you run your program, it will abort when there * are 200 outstanding allocations or 80 kbytes from that point in your * program.  If the limits you provide have already been exceeded by the time * you send the SIGUSR2 signal, flower_malloc will abort the next time an * allocation happens from the execution point identified by the tracker. * * * Sending a SIGUSR2 will also force flower_malloc to read your * limits configuration file, so you will not need to restart your application. *  * SIGUSR1 can be used to reset all trackers. */#include "libxorp/xorp.h"#ifdef HOST_OS_FREEBSD   #include <dlfcn.h>#include <memory.h>#include <assert.h>#ifdef APPL_IS_MULTITHREADED#include <thread.h>#endif				/* APPL_IS_MULTITHREADED */#include <stdio.h>#include <fcntl.h>#include <signal.h>#include <errno.h>#include <stdlib.h>#include <limits.h>#include <unistd.h>/* * XXX: If BACKTRACE_DEPTH is larger than 2, then the program coredumps * on amd64 + FreeBSD-6.1. * If it is larger than 4, the program coredumps on i386 + FreeBSD-4.10. */#define BACKTRACE_DEPTH 2#define HASH_TABLE_SIZE 343051  /* prime, max 31 bits */#define ADMIN_DATA_SIZE 2 * sizeof(uint32_t)typedef struct alloc_tracker {    uint32_t count;    uint32_t max_count;    uint32_t last_read_max;    uint32_t total_size;    uint32_t watermark;} alloc_tracker_t;typedef struct limit_tracker {    uint32_t  enabled;    uint32_t count;    uint32_t total_size;} limit_tracker_t;static FILE *output = NULL;static int pid;static char path[64] = "uninitialized";static alloc_tracker_t tracker_table[HASH_TABLE_SIZE];static limit_tracker_t limits_table[HASH_TABLE_SIZE];static int32_t no_tracking;/* prototypes */static uint32_t within_limits (uint32_t trk_idx);static void init_flower_malloc(void);/*************************************************************************** * print_data - dumps the state of the alloc tracking table * */static void print_data(void){    int i;    char growing[2] = " ";    no_tracking = 1; /* prevent mallocs in fprintf from spoiling our report */    fprintf(output, "***********************************************\n");    fprintf(output, "allocs/watermark  total size/watermark");    fprintf(output, "     avg size  tracker_id [+]\n");    for (i=0; i < HASH_TABLE_SIZE; i++)	if (tracker_table[i].watermark) {	    fprintf(output, "%8u/%-8u  %10u/%-10u ",		tracker_table[i].count, tracker_table[i].max_count,		tracker_table[i].total_size, tracker_table[i].watermark);	    if (tracker_table[i].count)		fprintf(output, "%8u ", 		tracker_table[i].total_size / tracker_table[i].count);	    else /* use watermark to determine avg size */		fprintf(output, "%8u ", 		tracker_table[i].watermark / tracker_table[i].max_count);	    if (tracker_table[i].max_count > tracker_table[i].last_read_max) {		if (tracker_table[i].last_read_max) growing[0] = '+';		tracker_table[i].last_read_max = tracker_table[i].max_count;	    } else growing[0] = ' ';	    fprintf(output, "%8x %s\n", i, growing);	}    fflush(output);  /* untentionally leaving file open */    no_tracking = 0;}/*************************************************************************** * read_config - read flower_malloc config file * */static voidread_config(void){    unsigned long trk_idx, count, max_count, total_size, watermark, avg_size;    int assig;    FILE *config;    #define MAX_CFG_LINE_WIDTH 80    char ignored[MAX_CFG_LINE_WIDTH];    config = fopen("./flower_limits.cfg","r");    if (!config) return;    no_tracking = 1; /* prevent mallocs in fprintf from spoiling our report */    do {	assig = fscanf(config, "%8lu/%8lu %10lu/%10lu %8lu %8lx %*[+ ]\n", 	    &count, &max_count, &total_size, &watermark, &avg_size, &trk_idx);	if (assig == 6) {	    fprintf(output, "Abort if tracker %8lx exceeds %8lu outst "		"allocs or %10lu bytes\n", trk_idx, count, total_size);	    fflush(stdout);	    limits_table[trk_idx].enabled = 1;	    limits_table[trk_idx].count = count;	    limits_table[trk_idx].total_size = total_size;	} else {	    fgets(ignored, MAX_CFG_LINE_WIDTH, config);	}	    } while (assig != EOF);    fclose(config);    no_tracking = 0;}/*************************************************************************** * sigusr1_handler - handler for the SIGUSR1 signal * * This signal is used to reset the tracker and limits tables */static void sigusr1_handler(int unused){    uint32_t i;    unused = unused;    for (i=0; i < HASH_TABLE_SIZE; i++) {	tracker_table[i].count = 0;	tracker_table[i].max_count = 0;	tracker_table[i].last_read_max = 0;	tracker_table[i].total_size = 0;	tracker_table[i].watermark = 0;	limits_table[i].enabled = 0;	limits_table[i].count = 0;	limits_table[i].total_size = 0;    }	}/*************************************************************************** * sigusr2_handler - handler for the SIGUSR2 signal * * This signal is used to dump the current state of the alloc tracking table to * the output file. */static void sigusr2_handler(int unused){    unused = unused;    read_config();    print_data();}/*************************************************************************** * within_limits - check if a tracker is within its configured limits * * Return zero if not */ static uint32_twithin_limits (uint32_t trk_idx){    if (!limits_table[trk_idx].enabled) return 1;    return (tracker_table[trk_idx].count <= limits_table[trk_idx].count &&	tracker_table[trk_idx].total_size <= limits_table[trk_idx].total_size);}/*************************************************************************** * hash - calculate hash value based on backtrace stack * * This will be used to assign the same tracker to all the allocations that are * made from the same point in a program. */ static uint32_thash (void ** addr_array, size_t depth){    size_t i;    size_t hash_value = 0;    for (i=0; i<depth; i++) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -