erl_alloc.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 2,572 行 · 第 1/5 页

C
2,572
字号
    char buf[10];    char *t_str;    char *allctr_str;    ASSERT(n >= ERTS_ALC_N_MIN);    ASSERT(n <= ERTS_ALC_N_MAX);    if (n < ERTS_ALC_N_MIN || ERTS_ALC_N_MAX < n)	allctr_str = "UNKNOWN";    else {	ErtsAlcType_t a = ERTS_ALC_T2A(ERTS_ALC_N2T(n));	if (erts_allctrs_info[a].enabled)	    allctr_str = (char *) ERTS_ALC_A2AD(a);	else	    allctr_str = (char *) ERTS_ALC_A2AD(ERTS_ALC_A_SYSTEM);    }    t_str = type_no_str(n);    if (!t_str) {	sprintf(buf, "%d", (int) n);	t_str = buf;    }    switch (error) {    case ERTS_ALC_E_NOTSUP: {	char *op_str;	switch (func) {	case ERTS_ALC_O_ALLOC:		op_str = "alloc";	break;	case ERTS_ALC_O_REALLOC:	op_str = "realloc";	break;	case ERTS_ALC_O_FREE:		op_str = "free";	break;	default:			op_str = "UNKNOWN";	break;	}	erl_exit(ERTS_ABORT_EXIT,		 "%s: %s operation not supported (memory type: \"%s\")\n",		 allctr_str, op_str, t_str);	break;    }    case ERTS_ALC_E_NOMEM: {	Uint size;	va_list argp;	char *op = func == ERTS_ALC_O_REALLOC ? "reallocate" : "allocate";		va_start(argp, n);	size = va_arg(argp, Uint);	va_end(argp);	erl_exit(1,		 "%s: Cannot %s %lu bytes of memory (of type \"%s\").\n",		 allctr_str, op, size, t_str);	break;    }    case ERTS_ALC_E_NOALLCTR:	erl_exit(ERTS_ABORT_EXIT,		 "erts_alloc: Unknown allocator type: %d\n",		 ERTS_ALC_T2A(ERTS_ALC_N2T(n)));	break;    default:	erl_exit(ERTS_ABORT_EXIT, "erts_alloc: Unknown error: %d\n", error);	break;    }}voiderts_alloc_enomem(ErtsAlcType_t type, Uint size){    erts_alloc_n_enomem(ERTS_ALC_T2N(type), size);}voiderts_alloc_n_enomem(ErtsAlcType_t n, Uint size){    erts_alc_fatal_error(ERTS_ALC_E_NOMEM, ERTS_ALC_O_ALLOC, n, size);}voiderts_realloc_enomem(ErtsAlcType_t type, void *ptr, Uint size){    erts_realloc_n_enomem(ERTS_ALC_T2N(type), ptr, size);}voiderts_realloc_n_enomem(ErtsAlcType_t n, void *ptr, Uint size){    erts_alc_fatal_error(ERTS_ALC_E_NOMEM, ERTS_ALC_O_REALLOC, n, size);}static ERTS_INLINE intis_atom_text(Eterm atom, const char *str){    int i;    char *atxt = (char*) atom_tab(atom_val(atom))->name;    int alen = atom_tab(atom_val(atom))->len;    for (i = 0; i < alen && str[i]; i++)	if (atxt[i] != str[i])	    return 0;    if (alen == i && !str[i])	return 1;    return 0;}Etermerts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg){#define MEM_NEED_PARTS (!erts_instr_stat && want_tot_or_sys)    ErtsFixInfo efi;    struct {	int total;	int processes;	int processes_used;	int system;	int atom;	int atom_used;	int binary;	int code;	int ets;	int maximum;    } want = {0};    struct {	Uint total;	Uint processes;	Uint processes_used;	Uint system;	Uint atom;	Uint atom_used;	Uint binary;	Uint code;	Uint ets;	Uint maximum;    } size = {0};    Eterm atoms[sizeof(size)/sizeof(Uint)];    Uint *uintps[sizeof(size)/sizeof(Uint)];    Eterm euints[sizeof(size)/sizeof(Uint)];    int need_atom;    int want_tot_or_sys;    int length;    Eterm res = THE_NON_VALUE;    int block = !ERTS_IS_CRASH_DUMPING;    /* Figure out whats wanted... */    length = 0;    if (earg == THE_NON_VALUE) { /* i.e. wants all */	want.total = 1;	atoms[length] = am_total;	uintps[length++] = &size.total;	want.processes = 1;	atoms[length] = am_processes;	uintps[length++] = &size.processes;	want.processes_used = 1;	atoms[length] = am_processes_used;	uintps[length++] = &size.processes_used;	want.system = 1;	atoms[length] = am_system;	uintps[length++] = &size.system;	want.atom = 1;	atoms[length] = am_atom;	uintps[length++] = &size.atom;	want.atom_used = 1;	atoms[length] = am_atom_used;	uintps[length++] = &size.atom_used;	want.binary = 1;	atoms[length] = am_binary;	uintps[length++] = &size.binary;	want.code = 1;	atoms[length] = am_code;	uintps[length++] = &size.code;	want.ets = 1;	atoms[length] = am_ets;	uintps[length++] = &size.ets;	want.maximum = erts_instr_stat;	if (want.maximum) {	    atoms[length] = am_maximum;	    uintps[length++] = &size.maximum;	}    }    else {	Eterm wanted_list;	if (is_nil(earg))	    return NIL;	wanted_list = earg;	while (is_list(wanted_list)) {	    switch (CAR(list_val(wanted_list))) {	    case am_total:		if (!want.total) {		    want.total = 1;		    atoms[length] = am_total;		    uintps[length++] = &size.total;		}		break;	    case am_processes:		if (!want.processes) {		    want.processes = 1;		    atoms[length] = am_processes;		    uintps[length++] = &size.processes;		}		break;	    case am_processes_used:		if (!want.processes_used) {		    want.processes_used = 1;		    atoms[length] = am_processes_used;		    uintps[length++] = &size.processes_used;		}		break;	    case am_system:		if (!want.system) {		    want.system = 1;		    atoms[length] = am_system;		    uintps[length++] = &size.system;		}		break;	    case am_atom:		if (!want.atom) {		    want.atom = 1;		    atoms[length] = am_atom;		    uintps[length++] = &size.atom;		}		break;	    case am_atom_used:		if (!want.atom_used) {		    want.atom_used = 1;		    atoms[length] = am_atom_used;		    uintps[length++] = &size.atom_used;		}		break;	    case am_binary:		if (!want.binary) {		    want.binary = 1;		    atoms[length] = am_binary;		    uintps[length++] = &size.binary;		}		break;	    case am_code:		if (!want.code) {		    want.code = 1;		    atoms[length] = am_code;		    uintps[length++] = &size.code;		}		break;	    case am_ets:		if (!want.ets) {		    want.ets = 1;		    atoms[length] = am_ets;		    uintps[length++] = &size.ets;		}		break;	    case am_maximum:		if (erts_instr_stat) {		    if (!want.maximum) {			want.maximum = 1;			atoms[length] = am_maximum;			uintps[length++] = &size.maximum;		    }		}		else		    return am_badarg;		break;	    default:		return am_badarg;	    }	    wanted_list = CDR(list_val(wanted_list));	}	if (is_not_nil(wanted_list))	    return am_badarg;    }    ASSERT(length <= sizeof(atoms)/sizeof(Eterm));    ASSERT(length <= sizeof(euints)/sizeof(Eterm));    ASSERT(length <= sizeof(uintps)/sizeof(Uint));    if (block)	erts_smp_block_system(0);    /* Calculate values needed... */    want_tot_or_sys = want.total || want.system;    need_atom = MEM_NEED_PARTS || want.atom;    size.processes = size.processes_used = erts_get_tot_proc_mem();    if (MEM_NEED_PARTS || want.processes) {	erts_fix_info(ERTS_ALC_T_NLINK_SH, &efi);	size.processes += efi.total - efi.used;	erts_fix_info(ERTS_ALC_T_MONITOR_SH, &efi);	size.processes += efi.total - efi.used;	erts_fix_info(ERTS_ALC_T_PROC, &efi);	size.processes += efi.total - efi.used;	erts_fix_info(ERTS_ALC_T_REG_PROC, &efi);	size.processes += efi.total - efi.used;    }    if (need_atom || want.atom_used) {	Uint reserved_atom_space, atom_space;	erts_atom_get_text_space_sizes(&reserved_atom_space, &atom_space);	size.atom = size.atom_used = atom_table_sz();	erts_fix_info(ERTS_ALC_T_ATOM, &efi);	if (need_atom) {	    size.atom += reserved_atom_space;	    size.atom += efi.total;	}	if (want.atom_used) {	    size.atom_used += atom_space;	    size.atom_used += efi.used;	}    }    size.binary = erts_get_binaries_size();    if (MEM_NEED_PARTS || want.code) {	size.code = module_table_sz();	erts_fix_info(ERTS_ALC_T_MODULE, &efi);	size.code += efi.used;	size.code += export_table_sz();	erts_fix_info(ERTS_ALC_T_EXPORT, &efi);	size.code += efi.used;	size.code += erts_fun_table_sz();	erts_fix_info(ERTS_ALC_T_FUN_ENTRY, &efi);	size.code += efi.used;	size.code += allocated_modules*sizeof(Range);	size.code += erts_total_code_size;    }    size.ets = erts_ets_memory_size();    if (erts_instr_stat && (want_tot_or_sys || want.maximum)) {	size.total = erts_instr_get_total();	size.system = size.total - size.processes;	size.maximum = erts_instr_get_max_total();    }    else if (want_tot_or_sys) {	/* Static stuff ... */	size.system = erts_max_ports*sizeof(Port);	size.system += erts_timer_wheel_memory_size();#ifdef SYS_TMP_BUF_SIZE	size.system += SYS_TMP_BUF_SIZE; /* tmp_buf in sys on vxworks & ose */#endif	/* Misc stuff ... */	size.system += erts_sys_misc_mem_sz();	size.system += erts_dist_table_size();	size.system += erts_node_table_size();	size.system += erts_bits_bufs_size();	size.system += process_reg_sz();	erts_fix_info(ERTS_ALC_T_REG_PROC, &efi);	size.system += efi.total;	erts_fix_info(ERTS_ALC_T_PROC_LIST, &efi);	size.system += efi.total;        	/* Atom, binary, code, and ets */	size.system += size.atom;	size.system += size.binary;	size.system += size.code;	size.system += size.ets;	size.total = size.system + size.processes;    }    if (block)	erts_smp_release_system();    if (print_to_p) {	int i;	int to = *print_to_p;	void *arg = print_to_arg;	/* Print result... */	erts_print(to, arg, "=memory\n");	for (i = 0; i < length; i++)	    erts_print(to, arg, "%T: %bpu\n", atoms[i], *uintps[i]);    }    if (proc) {	/* Build erlang term result... */	Uint *hp;	Uint **hpp;	Uint hsz;	Uint *hszp;	hpp = NULL;	hsz = 0;	hszp = &hsz;	while (1) {	    int i;	    for (i = 0; i < length; i++)		euints[i] = erts_bld_uint(hpp, hszp, *uintps[i]);	    res = erts_bld_2tup_list(hpp, hszp, length, atoms, euints);	    if (hpp)		break;	    hp = HAlloc((Process *) proc, hsz);	    hpp = &hp;	    hszp = NULL;	}    }    return res;#undef MEM_NEED_PARTS}struct aa_values {    Uint arity;    const char *name;    Uint ui[2];};Etermerts_allocated_areas(int *print_to_p, void *print_to_arg, void *proc){#define MAX_AA_VALUES \  (20 + (ERTS_ALC_N_MAX_A_FIXED_SIZE - ERTS_ALC_N_MIN_A_FIXED_SIZE + 1))    struct aa_values values[MAX_AA_VALUES];    Eterm res = THE_NON_VALUE;    int i, length;    ErtsFixInfo efi;    Uint reserved_atom_space, atom_space;    i = 0;    if (erts_instr_stat) {	values[i].arity = 2;	values[i].name = "total";	values[i].ui[0] = erts_instr_get_total();	i++;	values[i].arity = 2;	values[i].name = "maximum";	values[i].ui[0] = erts_instr_get_max_total();	i++;    }    values[i].arity = 3;    values[i].name = "processes";    values[i].ui[0] = erts_get_tot_proc_mem();    values[i].ui[1] = erts_get_tot_proc_mem();    erts_fix_info(ERTS_ALC_T_NLINK_SH, &efi);    values[i].ui[1] += efi.total - efi.used;    erts_fix_info(ERTS_ALC_T_MONITOR_SH, &efi);    values[i].ui[1] += efi.total - efi.used;    erts_fix_info(ERTS_ALC_T_PROC, &efi);    values[i].ui[1] += efi.total - efi.used;    erts_fix_info(ERTS_ALC_T_REG_PROC, &efi);    values[i].ui[1] += efi.total - efi.used;    i++;    values[i].arity = 2;    values[i].name = "ets";    values[i].ui[0] = erts_ets_memory_size();    i++;    values[i].arity = 2;    values[i].name = "sys_misc";    values[i].ui[0] = erts_sys_misc_mem_sz();    i++;    values[i].arity = 2;    values[i].name = "static";    values[i].ui[0] = 	erts_max_ports*sizeof(Port)		/* Port table */	+ erts_timer_wheel_memory_size()	/* Timer wheel */#ifdef SYS_TMP_BUF_SIZE	+ SYS_TMP_BUF_SIZE		/* tmp_buf in sys on vxworks & ose */#endif	;    i++;    erts_atom_get_text_space_sizes(&reserved_atom_space, &atom_space);    values[i].arity = 3;    values[i].name = "atom_space";    values[i].ui[0] = reserved_atom_space;    values[i].ui[1] = atom_space;    i++;    values[i].arity = 2;    values[i].name = "binary";    values[i].ui[0] = erts_get_binaries_size();    i++;    values[i].arity = 2;    values[i].name = "atom_table";    values[i].ui[0] = atom_table_sz();    i++;    values[i].arity = 2;    values[i].name = "module_table";    values[i].ui[0] = module_table_sz();    i++;    values[i].arity = 2;    values[i].name = "export_table";    values[i].ui[0] = export_table_sz();    i++;    values[i].arity = 2;    values[i].name = "register_table";    values[i].ui[0] = process_reg_sz();    i++;

⌨️ 快捷键说明

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