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

📄 erl_instrument.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include "global.h"#include "big.h"#include "erl_instrument.h"#include "erl_threads.h"typedef union { long l; double d; } Align_t;typedef struct {    Uint size;    Align_t mem[1];} StatBlock_t;#define STAT_BLOCK_HEADER_SIZE (sizeof(StatBlock_t) - sizeof(Align_t))typedef struct MapStatBlock_t_ MapStatBlock_t;struct MapStatBlock_t_ {    Uint size;    ErtsAlcType_t type_no;    Eterm pid;    MapStatBlock_t *prev;    MapStatBlock_t *next;    Align_t mem[1];};#define MAP_STAT_BLOCK_HEADER_SIZE (sizeof(MapStatBlock_t) - sizeof(Align_t))typedef struct {    Uint size;    Uint max_size;    Uint max_size_ever;    Uint blocks;    Uint max_blocks;    Uint max_blocks_ever;} Stat_t;static erts_mtx_t instr_mutex;static erts_mtx_t instr_x_mutex;int erts_instr_memory_map;int erts_instr_stat;static ErtsAllocatorFunctions_t real_allctrs[ERTS_ALC_A_MAX+1];struct stats_ {    Stat_t tot;    Stat_t a[ERTS_ALC_A_MAX+1];    Stat_t *ap[ERTS_ALC_A_MAX+1];    Stat_t c[ERTS_ALC_C_MAX+1];    Stat_t n[ERTS_ALC_N_MAX+1];};static struct stats_ *stats;static MapStatBlock_t *mem_anchor;static Eterm *am_tot;static Eterm *am_n;static Eterm *am_a;static Eterm *am_c;static int atoms_initialized;static struct {    Eterm total;    Eterm allocators;    Eterm classes;    Eterm types;    Eterm sizes;    Eterm blocks;    Eterm instr_hdr;#ifdef DEBUG    Eterm end_of_atoms;#endif} am;static void ERTS_INLINE atom_init(Eterm *atom, const char *name){    *atom = am_atom_put((char *) name, strlen(name));}#define AM_INIT(AM) atom_init(&am.AM, #AM)static voidinit_atoms(void){#ifdef DEBUG    Eterm *atom;    for (atom = (Eterm *) &am; atom <= &am.end_of_atoms; atom++) {	*atom = THE_NON_VALUE;    }#endif    AM_INIT(total);    AM_INIT(allocators);    AM_INIT(classes);    AM_INIT(types);    AM_INIT(sizes);    AM_INIT(blocks);    AM_INIT(instr_hdr);#ifdef DEBUG    for (atom = (Eterm *) &am; atom < &am.end_of_atoms; atom++) {	ASSERT(*atom != THE_NON_VALUE);    }#endif    atoms_initialized = 1;}#undef AM_INITstatic voidinit_am_tot(void){    am_tot = (Eterm *) erts_alloc(ERTS_ALC_T_INSTR_INFO,				  sizeof(Eterm));    atom_init(am_tot, "total");}static voidinit_am_n(void){    int i;    am_n = (Eterm *) erts_alloc(ERTS_ALC_T_INSTR_INFO,				(ERTS_ALC_N_MAX+1)*sizeof(Eterm));    for (i = ERTS_ALC_N_MIN; i <= ERTS_ALC_N_MAX; i++) {	atom_init(&am_n[i], ERTS_ALC_N2TD(i));    }}static voidinit_am_c(void){    int i;    am_c = (Eterm *) erts_alloc(ERTS_ALC_T_INSTR_INFO,				(ERTS_ALC_C_MAX+1)*sizeof(Eterm));    for (i = ERTS_ALC_C_MIN; i <= ERTS_ALC_C_MAX; i++) {	atom_init(&am_c[i], ERTS_ALC_C2CD(i));    }}static voidinit_am_a(void){    int i;    am_a = (Eterm *) erts_alloc(ERTS_ALC_T_INSTR_INFO,				(ERTS_ALC_A_MAX+1)*sizeof(Eterm));    for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {	atom_init(&am_a[i], ERTS_ALC_A2AD(i));    }}static ERTS_INLINE voidstat_upd_alloc(ErtsAlcType_t n, Uint size){    ErtsAlcType_t t = ERTS_ALC_N2T(n);    ErtsAlcType_t a = ERTS_ALC_T2A(t);    ErtsAlcType_t c = ERTS_ALC_T2C(t);    stats->ap[a]->size += size;    if (stats->ap[a]->max_size < stats->ap[a]->size)	stats->ap[a]->max_size = stats->ap[a]->size;    stats->c[c].size += size;    if (stats->c[c].max_size < stats->c[c].size)	stats->c[c].max_size = stats->c[c].size;    stats->n[n].size += size;    if (stats->n[n].max_size < stats->n[n].size)	stats->n[n].max_size = stats->n[n].size;    stats->tot.size += size;    if (stats->tot.max_size < stats->tot.size)	stats->tot.max_size = stats->tot.size;    stats->ap[a]->blocks++;    if (stats->ap[a]->max_blocks < stats->ap[a]->blocks)	stats->ap[a]->max_blocks = stats->ap[a]->blocks;    stats->c[c].blocks++;    if (stats->c[c].max_blocks < stats->c[c].blocks)	stats->c[c].max_blocks = stats->c[c].blocks;    stats->n[n].blocks++;    if (stats->n[n].max_blocks < stats->n[n].blocks)	stats->n[n].max_blocks = stats->n[n].blocks;    stats->tot.blocks++;    if (stats->tot.max_blocks < stats->tot.blocks)	stats->tot.max_blocks = stats->tot.blocks;}static ERTS_INLINE voidstat_upd_free(ErtsAlcType_t n, Uint size){    ErtsAlcType_t t = ERTS_ALC_N2T(n);    ErtsAlcType_t a = ERTS_ALC_T2A(t);    ErtsAlcType_t c = ERTS_ALC_T2C(t);    ASSERT(stats->ap[a]->size >= size);    stats->ap[a]->size -= size;    ASSERT(stats->c[c].size >= size);    stats->c[c].size -= size;    ASSERT(stats->n[n].size >= size);    stats->n[n].size -= size;    ASSERT(stats->tot.size >= size);    stats->tot.size -= size;    ASSERT(stats->ap[a]->blocks > 0);    stats->ap[a]->blocks--;    ASSERT(stats->c[c].blocks > 0);    stats->c[c].blocks--;    ASSERT(stats->n[n].blocks > 0);    stats->n[n].blocks--;    ASSERT(stats->tot.blocks > 0);    stats->tot.blocks--;}static ERTS_INLINE voidstat_upd_realloc(ErtsAlcType_t n, Uint size, Uint old_size){    if (old_size)	stat_upd_free(n, old_size);    stat_upd_alloc(n, size);}/* * stat instrumentation callback functions */static void *stat_alloc(ErtsAlcType_t n, void *extra, Uint size){    ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;    Uint ssize;    void *res;    erts_mtx_lock(&instr_mutex);    ssize = size + STAT_BLOCK_HEADER_SIZE;    res = (*real_af->alloc)(n, real_af->extra, ssize);    if (res) {	stat_upd_alloc(n, size);	((StatBlock_t *) res)->size = size;	res = (void *) ((StatBlock_t *) res)->mem;    }    erts_mtx_unlock(&instr_mutex);    return res;}static void *stat_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size){    ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;    Uint old_size;    Uint ssize;    void *sptr;    void *res;    erts_mtx_lock(&instr_mutex);    if (ptr) {	sptr = (void *) (((char *) ptr) - STAT_BLOCK_HEADER_SIZE);	old_size = ((StatBlock_t *) sptr)->size;    }    else {	sptr = NULL;	old_size = 0;    }    ssize = size + STAT_BLOCK_HEADER_SIZE;    res = (*real_af->realloc)(n, real_af->extra, sptr, ssize);    if (res) {	stat_upd_realloc(n, size, old_size);	((StatBlock_t *) res)->size = size;	res = (void *) ((StatBlock_t *) res)->mem;    }    erts_mtx_unlock(&instr_mutex);    return res;}static voidstat_free(ErtsAlcType_t n, void *extra, void *ptr){    ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;    void *sptr;    erts_mtx_lock(&instr_mutex);    if (ptr) {	sptr = (void *) (((char *) ptr) - STAT_BLOCK_HEADER_SIZE);	stat_upd_free(n, ((StatBlock_t *) sptr)->size);    }    else {	sptr = NULL;    }    (*real_af->free)(n, real_af->extra, sptr);    erts_mtx_unlock(&instr_mutex);}/* * map stat instrumentation callback functions */static void *map_stat_alloc(ErtsAlcType_t n, void *extra, Uint size){    ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;    Uint msize;    void *res;    erts_mtx_lock(&instr_mutex);    msize = size + MAP_STAT_BLOCK_HEADER_SIZE;    res = (*real_af->alloc)(n, real_af->extra, msize);    if (res) {	MapStatBlock_t *mb = (MapStatBlock_t *) res;	stat_upd_alloc(n, size);	mb->size = size;	mb->type_no = n;	mb->pid = erts_get_current_pid();	mb->prev = NULL;	mb->next = mem_anchor;	if (mem_anchor)	    mem_anchor->prev = mb;	mem_anchor = mb;	res = (void *) mb->mem;    }    erts_mtx_unlock(&instr_mutex);    return res;}static void *map_stat_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size){    ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;    Uint old_size;    Uint msize;    void *mptr;    void *res;    erts_mtx_lock(&instr_x_mutex);    erts_mtx_lock(&instr_mutex);    if (ptr) {	mptr = (void *) (((char *) ptr) - MAP_STAT_BLOCK_HEADER_SIZE);	old_size = ((MapStatBlock_t *) mptr)->size;    }    else {	mptr = NULL;	old_size = 0;    }    msize = size + MAP_STAT_BLOCK_HEADER_SIZE;    res = (*real_af->realloc)(n, real_af->extra, mptr, msize);    if (res) {	MapStatBlock_t *mb = (MapStatBlock_t *) res;	mb->size = size;	mb->type_no = n;	mb->pid = erts_get_current_pid();	stat_upd_realloc(n, size, old_size);	if (mptr != res) {	    if (mptr) {		if (mb->prev)		    mb->prev->next = mb;		else {		    ASSERT(mem_anchor == (MapStatBlock_t *) mptr);		    mem_anchor = mb;		}		if (mb->next)		    mb->next->prev = mb;	    }	    else {		mb->prev = NULL;		mb->next = mem_anchor;		if (mem_anchor)		    mem_anchor->prev = mb;		mem_anchor = mb;	    }	}	res = (void *) mb->mem;    }    erts_mtx_unlock(&instr_mutex);    erts_mtx_unlock(&instr_x_mutex);    return res;}static voidmap_stat_free(ErtsAlcType_t n, void *extra, void *ptr){    ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;    void *mptr;    erts_mtx_lock(&instr_x_mutex);    erts_mtx_lock(&instr_mutex);    if (ptr) {	MapStatBlock_t *mb;	mptr = (void *) (((char *) ptr) - MAP_STAT_BLOCK_HEADER_SIZE);	mb = (MapStatBlock_t *) mptr;	stat_upd_free(n, mb->size);	if (mb->prev)	    mb->prev->next = mb->next;	else	    mem_anchor = mb->next;	if (mb->next)	    mb->next->prev = mb->prev;    }    else {	mptr = NULL;    }    (*real_af->free)(n, real_af->extra, mptr);    erts_mtx_unlock(&instr_mutex);    erts_mtx_unlock(&instr_x_mutex);}static void dump_memory_map_to_stream(FILE *fp){    ErtsAlcType_t n;    MapStatBlock_t *bp;    int lock = !ERTS_IS_CRASH_DUMPING;    if (lock)	erts_mtx_lock(&instr_mutex);    /* Write header */    fprintf(fp,	    "{instr_hdr,\n"	    " %lu,\n"	    " %lu,\n"	    " {",	    (unsigned long) ERTS_INSTR_VSN,	    (unsigned long) MAP_STAT_BLOCK_HEADER_SIZE);#if ERTS_ALC_N_MIN != 1#error ERTS_ALC_N_MIN is not 1#endif    for (n = ERTS_ALC_N_MIN; n <= ERTS_ALC_N_MAX; n++) {	ErtsAlcType_t t = ERTS_ALC_N2T(n);	ErtsAlcType_t a = ERTS_ALC_T2A(t);	ErtsAlcType_t c = ERTS_ALC_T2C(t);	const char *astr;	if (erts_allctrs_info[a].enabled)	    astr = ERTS_ALC_A2AD(a);	else	    astr = ERTS_ALC_A2AD(ERTS_ALC_A_SYSTEM);	fprintf(fp,		"%s{%s,%s,%s}%s",		(n == ERTS_ALC_N_MIN) ? "" : "  ",		ERTS_ALC_N2TD(n),		astr,		ERTS_ALC_C2CD(c),		(n == ERTS_ALC_N_MAX) ? "" : ",\n");    }    fprintf(fp, "}}.\n");    /* Write memory data */    for (bp = mem_anchor; bp; bp = bp->next) {	if (is_internal_pid(bp->pid))	    fprintf(fp,		    "{%lu, %lu, %lu, {%lu,%lu,%lu}}.\n",		    (Uint) bp->type_no,		    (Uint) bp->mem,		    (Uint) bp->size,		    (Uint) pid_channel_no(bp->pid),		    (Uint) pid_number(bp->pid),		    (Uint) pid_serial(bp->pid));	else	    fprintf(fp,		    "{%lu, %lu, %lu, undefined}.\n",		    (Uint) bp->type_no,		    (Uint) bp->mem,		    (Uint) bp->size);    }    if (lock)	erts_mtx_unlock(&instr_mutex);}int erts_instr_dump_memory_map_to_fd(int fd){    char buf[BUFSIZ];    FILE *f;    if (!erts_instr_memory_map)	return 0;    f = fdopen(fd, "w");    if (f == NULL)	return 0;    /* Avoid allocating memory; we may have run out of it at this point. */    setbuf(f, buf);    dump_memory_map_to_stream(f);    fflush(f);    return 1;}int erts_instr_dump_memory_map(const char *name){    FILE *f;    if (!erts_instr_memory_map)	return 0;    f = fopen(name, "w");    if (f == NULL)	return 0;    dump_memory_map_to_stream(f);    fclose(f);    return 1;}Eterm erts_instr_get_memory_map(Process *proc){    MapStatBlock_t *org_mem_anchor;    Eterm hdr_tuple, md_list, res;    Eterm *hp;    Uint hsz;    MapStatBlock_t *bp;#ifdef DEBUG    Eterm *end_hp;#endif        if (!erts_instr_memory_map)	return am_false;    if (!atoms_initialized)	init_atoms();    if (!am_n)	init_am_n();    if (!am_c)	init_am_c();    if (!am_a)

⌨️ 快捷键说明

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