erl_mseg.c

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

C
1,383
字号
	if (erts_mtrace_enabled) {	    erts_mtrace_crr_free(atype, SEGTYPE, seg);	    erts_mtrace_crr_alloc(seg, SEGTYPE, SEGTYPE, size);	}	/* ASSERT(no_of_segments_watermark >= no_of_segments + cache_size); */	if (check_limits)	    check_cache_limits();	schedule_cache_check();    }    INC_CC(dealloc);}static void *mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,	     const ErtsMsegOpt_t *opt){    void *new_seg;    Uint new_size;    if (!seg || !old_size) {	new_seg = mseg_alloc(atype, new_size_p, opt);	DEC_CC(alloc);	return new_seg;    }    if (!(*new_size_p)) {	mseg_dealloc(atype, seg, old_size, opt);	DEC_CC(dealloc);	return NULL;    }    new_seg = seg;    new_size = PAGE_CEILING(*new_size_p);    if (new_size == old_size)	;    else if (new_size < old_size) {	Uint shrink_sz = old_size - new_size;#if CAN_PARTLY_DESTROY	if (new_size < min_seg_size)		    min_seg_size = new_size;#endif	if (shrink_sz < opt->abs_shrink_th	    && 100*PAGES(shrink_sz) < opt->rel_shrink_th*PAGES(old_size)) {	    new_size = old_size;	}	else {#if CAN_PARTLY_DESTROY	    if (shrink_sz > min_seg_size		&& free_cache_descs		&& opt->cache) {		cache_desc_t *cd;		cd = alloc_cd();		ASSERT(cd);		cd->seg = ((char *) seg) + new_size;		cd->size = shrink_sz;		end_link_cd(cd);		if (erts_mtrace_enabled) {		    erts_mtrace_crr_realloc(new_seg,					    atype,					    SEGTYPE,					    seg,					    new_size);		    erts_mtrace_crr_alloc(cd->seg, SEGTYPE, SEGTYPE, cd->size);		}		schedule_cache_check();	    }	    else {		if (erts_mtrace_enabled)		    erts_mtrace_crr_realloc(new_seg,					    atype,					    SEGTYPE,					    seg,					    new_size);		mseg_destroy(((char *) seg) + new_size, shrink_sz);	    }#elif HAVE_MSEG_RECREATE	    goto do_recreate;#else	    new_seg = mseg_alloc(atype, &new_size, opt);	    if (!new_seg)		new_size = old_size;	    else {		sys_memcpy(((char *) new_seg),			   ((char *) seg),			   MIN(new_size, old_size));		mseg_dealloc(atype, seg, old_size, opt);	    }#endif	}    }    else {	if (!opt->preserv) {	    mseg_dealloc(atype, seg, old_size, opt);	    new_seg = mseg_alloc(atype, &new_size, opt);	}	else {#if HAVE_MSEG_RECREATE#if !CAN_PARTLY_DESTROY	do_recreate:#endif	    new_seg = mseg_recreate((void *) seg, old_size, new_size);	    if (erts_mtrace_enabled)		erts_mtrace_crr_realloc(new_seg, atype, SEGTYPE, seg, new_size);	    if (!new_seg)		new_size = old_size;#else	    new_seg = mseg_alloc(atype, &new_size, opt);	    if (!new_seg)		new_size = old_size;	    else {		sys_memcpy(((char *) new_seg),			   ((char *) seg),			   MIN(new_size, old_size));		mseg_dealloc(atype, seg, old_size, opt);	    }#endif	}    }    INC_CC(realloc);    *new_size_p = new_size;    return new_seg;}/* --- Info stuff ---------------------------------------------------------- */static struct {    Eterm version;    Eterm options;    Eterm amcbf;    Eterm rmcbf;    Eterm mcs;    Eterm cci;    Eterm status;    Eterm cached_segments;    Eterm cache_hits;    Eterm segments;    Eterm segments_watermark;    Eterm calls;    Eterm mseg_alloc;    Eterm mseg_dealloc;    Eterm mseg_realloc;    Eterm mseg_create;    Eterm mseg_destroy;#if HAVE_MSEG_RECREATE    Eterm mseg_recreate;#endif    Eterm mseg_clear_cache;    Eterm mseg_check_cache;#ifdef DEBUG    Eterm end_of_atoms;#endif} am;static void ERTS_INLINE atom_init(Eterm *atom, char *name){    *atom = am_atom_put(name, strlen(name));}#define AM_INIT(AM) atom_init(&am.AM, #AM)static voidinit_atoms(void){#ifdef DEBUG    Eterm *atom;#endif    erts_mtx_unlock(&mseg_mutex);    erts_mtx_lock(&init_atoms_mutex);    if (!atoms_initialized) {#ifdef DEBUG	for (atom = (Eterm *) &am; atom <= &am.end_of_atoms; atom++) {	    *atom = THE_NON_VALUE;	}#endif	AM_INIT(version);	AM_INIT(options);	AM_INIT(amcbf);	AM_INIT(rmcbf);	AM_INIT(mcs);	AM_INIT(cci);	AM_INIT(status);	AM_INIT(cached_segments);	AM_INIT(cache_hits);	AM_INIT(segments);	AM_INIT(segments_watermark);	AM_INIT(calls);	AM_INIT(mseg_alloc);	AM_INIT(mseg_dealloc);	AM_INIT(mseg_realloc);	AM_INIT(mseg_create);	AM_INIT(mseg_destroy);#if HAVE_MSEG_RECREATE	AM_INIT(mseg_recreate);#endif	AM_INIT(mseg_clear_cache);	AM_INIT(mseg_check_cache);#ifdef DEBUG	for (atom = (Eterm *) &am; atom < &am.end_of_atoms; atom++) {	    ASSERT(*atom != THE_NON_VALUE);	}#endif    }    erts_mtx_lock(&mseg_mutex);    atoms_initialized = 1;    erts_mtx_unlock(&init_atoms_mutex);}#define bld_uint	erts_bld_uint#define bld_cons	erts_bld_cons#define bld_tuple	erts_bld_tuple#define bld_string	erts_bld_string#define bld_2tup_list	erts_bld_2tup_liststatic ERTS_INLINE voidadd_2tup(Uint **hpp, Uint *szp, Eterm *lp, Eterm el1, Eterm el2){    *lp = bld_cons(hpp, szp, bld_tuple(hpp, szp, 2, el1, el2), *lp);}static ERTS_INLINE voidadd_3tup(Uint **hpp, Uint *szp, Eterm *lp, Eterm el1, Eterm el2, Eterm el3){    *lp = bld_cons(hpp, szp, bld_tuple(hpp, szp, 3, el1, el2, el3), *lp);}static Eterminfo_options(char *prefix,	     int *print_to_p,	     void *print_to_arg,	     Uint **hpp,	     Uint *szp){    Eterm res = THE_NON_VALUE;    if (print_to_p) {	int to = *print_to_p;	void *arg = print_to_arg;	erts_print(to, arg, "%samcbf: %bpu\n", prefix, abs_max_cache_bad_fit);	erts_print(to, arg, "%srmcbf: %bpu\n", prefix, rel_max_cache_bad_fit);	erts_print(to, arg, "%smcs: %bpu\n", prefix, max_cache_size);	erts_print(to, arg, "%scci: %bpu\n", prefix, cache_check_interval);    }    if (hpp || szp) {	if (!atoms_initialized)	    init_atoms();	res = NIL;	add_2tup(hpp, szp, &res,		 am.cci,		 bld_uint(hpp, szp, cache_check_interval));	add_2tup(hpp, szp, &res,		 am.mcs,		 bld_uint(hpp, szp, max_cache_size));	add_2tup(hpp, szp, &res,		 am.rmcbf,		 bld_uint(hpp, szp, rel_max_cache_bad_fit));	add_2tup(hpp, szp, &res,		 am.amcbf,		 bld_uint(hpp, szp, abs_max_cache_bad_fit));    }    return res;}static Eterminfo_calls(int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp){    Eterm res = THE_NON_VALUE;    if (print_to_p) {#define PRINT_CC(TO, TOA, CC)						\    if (calls.CC.giga_no == 0)						\	erts_print(TO, TOA, "mseg_%s calls: %bpu\n", #CC, calls.CC.no);	\    else								\	erts_print(TO, TOA, "mseg_%s calls: %bpu%09bpu\n", #CC,		\		   calls.CC.giga_no, calls.CC.no)	int to = *print_to_p;	void *arg = print_to_arg;	PRINT_CC(to, arg, alloc);	PRINT_CC(to, arg, dealloc);	PRINT_CC(to, arg, realloc);	PRINT_CC(to, arg, create);	PRINT_CC(to, arg, destroy);#if HAVE_MSEG_RECREATE	PRINT_CC(to, arg, recreate);#endif	PRINT_CC(to, arg, clear_cache);	PRINT_CC(to, arg, check_cache);#undef PRINT_CC    }    if (hpp || szp) {	res = NIL;	add_3tup(hpp, szp, &res,		 am.mseg_check_cache,		 bld_uint(hpp, szp, calls.check_cache.giga_no),		 bld_uint(hpp, szp, calls.check_cache.no));	add_3tup(hpp, szp, &res,		 am.mseg_clear_cache,		 bld_uint(hpp, szp, calls.clear_cache.giga_no),		 bld_uint(hpp, szp, calls.clear_cache.no));#if HAVE_MSEG_RECREATE	add_3tup(hpp, szp, &res,		 am.mseg_recreate,		 bld_uint(hpp, szp, calls.recreate.giga_no),		 bld_uint(hpp, szp, calls.recreate.no));#endif	add_3tup(hpp, szp, &res,		 am.mseg_destroy,		 bld_uint(hpp, szp, calls.destroy.giga_no),		 bld_uint(hpp, szp, calls.destroy.no));	add_3tup(hpp, szp, &res,		 am.mseg_create,		 bld_uint(hpp, szp, calls.create.giga_no),		 bld_uint(hpp, szp, calls.create.no));	add_3tup(hpp, szp, &res,		 am.mseg_realloc,		 bld_uint(hpp, szp, calls.realloc.giga_no),		 bld_uint(hpp, szp, calls.realloc.no));	add_3tup(hpp, szp, &res,		 am.mseg_dealloc,		 bld_uint(hpp, szp, calls.dealloc.giga_no),		 bld_uint(hpp, szp, calls.dealloc.no));	add_3tup(hpp, szp, &res,		 am.mseg_alloc,		 bld_uint(hpp, szp, calls.alloc.giga_no),		 bld_uint(hpp, szp, calls.alloc.no));    }    return res;}static Eterminfo_status(int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp){    Eterm res = THE_NON_VALUE;        if (print_to_p) {	int to = *print_to_p;	void *arg = print_to_arg;	erts_print(to, arg, "cached_segments: %bpu\n", cache_size);	erts_print(to, arg, "cache_hits: %bpu\n", cache_hits);	erts_print(to, arg, "segments: %bpu\n", no_of_segments);	erts_print(to, arg, "segments_watermark: %bpu\n",		   no_of_segments_watermark);    }    if (hpp || szp) {	res = NIL;	add_2tup(hpp, szp, &res,		 am.segments_watermark,		 bld_uint(hpp, szp, no_of_segments_watermark));	add_2tup(hpp, szp, &res,		 am.segments,		 bld_uint(hpp, szp, no_of_segments));	add_2tup(hpp, szp, &res,		 am.cache_hits,		 bld_uint(hpp, szp, cache_hits));	add_2tup(hpp, szp, &res,		 am.cached_segments,		 bld_uint(hpp, szp, cache_size));    }    return res;}static Eterminfo_version(int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp){    Eterm res = THE_NON_VALUE;    if (print_to_p) {	erts_print(*print_to_p, print_to_arg, "version: %s\n",		   ERTS_MSEG_VSN_STR);    }    if (hpp || szp) {	res = bld_string(hpp, szp, ERTS_MSEG_VSN_STR);    }    return res;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Exported functions                                                        *\*                                                                           */Etermerts_mseg_info_options(int *print_to_p, void *print_to_arg,		       Uint **hpp, Uint *szp){    Eterm res;    erts_mtx_lock(&mseg_mutex);    res = info_options("option ", print_to_p, print_to_arg, hpp, szp);    erts_mtx_unlock(&mseg_mutex);    return res;}Etermerts_mseg_info(int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp){    Eterm res = THE_NON_VALUE;    Eterm atoms[4];    Eterm values[4];    erts_mtx_lock(&mseg_mutex);    if (hpp || szp) {		if (!atoms_initialized)	    init_atoms();	atoms[0] = am.version;	atoms[1] = am.options;	atoms[2] = am.status;	atoms[3] = am.calls;    }    values[0] = info_version(print_to_p, print_to_arg, hpp, szp);    values[1] = info_options("option ", print_to_p, print_to_arg, hpp, szp);    values[2] = info_status(print_to_p, print_to_arg, hpp, szp);    values[3] = info_calls(print_to_p, print_to_arg, hpp, szp);    if (hpp || szp)	res = bld_2tup_list(hpp, szp, 4, atoms, values);    erts_mtx_unlock(&mseg_mutex);    return res;}void *erts_mseg_alloc_opt(ErtsAlcType_t atype, Uint *size_p, const ErtsMsegOpt_t *opt){    void *seg;    erts_mtx_lock(&mseg_mutex);    seg = mseg_alloc(atype, size_p, opt);    erts_mtx_unlock(&mseg_mutex);    return seg;}void *erts_mseg_alloc(ErtsAlcType_t atype, Uint *size_p){    return erts_mseg_alloc_opt(atype, size_p, &default_opt);}voiderts_mseg_dealloc_opt(ErtsAlcType_t atype, void *seg, Uint size,		      const ErtsMsegOpt_t *opt){    erts_mtx_lock(&mseg_mutex);    mseg_dealloc(atype, seg, size, opt);    erts_mtx_unlock(&mseg_mutex);}voiderts_mseg_dealloc(ErtsAlcType_t atype, void *seg, Uint size){    erts_mseg_dealloc_opt(atype, seg, size, &default_opt);}void *erts_mseg_realloc_opt(ErtsAlcType_t atype, void *seg, Uint old_size,		      Uint *new_size_p, const ErtsMsegOpt_t *opt){    void *new_seg;    erts_mtx_lock(&mseg_mutex);    new_seg = mseg_realloc(atype, seg, old_size, new_size_p, opt);    erts_mtx_unlock(&mseg_mutex);    return new_seg;}void *erts_mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size,		  Uint *new_size_p){    return erts_mseg_realloc_opt(atype, seg, old_size, new_size_p, &default_opt);}voiderts_mseg_clear_cache(void){    erts_mtx_lock(&mseg_mutex);    mseg_clear_cache();    erts_mtx_unlock(&mseg_mutex);}Uinterts_mseg_no(void){    Uint n;    erts_mtx_lock(&mseg_mutex);    n = no_of_segments;    erts_mtx_unlock(&mseg_mutex);    return n;}Uinterts_mseg_unit_size(void){    return page_size;}voiderts_mseg_init(ErtsMsegInit_t *init){    unsigned i;    atoms_initialized = 0;    is_init_done = 0;    /* Options ... */    abs_max_cache_bad_fit	= init->amcbf;    rel_max_cache_bad_fit	= init->rmcbf;    max_cache_size		= init->mcs;    cache_check_interval	= init->cci;    /* */#ifdef USE_THREADS    thread_safe_init();#endif#if HAVE_MMAP && !defined(MAP_ANON)    mmap_fd = open("/dev/zero", O_RDWR);    if (mmap_fd < 0)	erl_exit(ERTS_ABORT_EXIT, "erts_mseg: unable to open /dev/zero\n");#endif    page_size = GET_PAGE_SIZE;    page_shift = 1;    while ((page_size >> page_shift) != 1) {	if ((page_size & (1 << (page_shift - 1))) != 0)	    erl_exit(ERTS_ABORT_EXIT,		     "erts_mseg: Unexpected page_size %bpu\n", page_size);	page_shift++;    }    sys_memzero((void *) &calls, sizeof(calls));#if CAN_PARTLY_DESTROY    min_seg_size = ~((Uint) 0);#endif    cache = NULL;    cache_end = NULL;    cache_hits = 0;    max_cached_seg_size = 0;    min_cached_seg_size = ~((Uint) 0);    cache_size = 0;    if (max_cache_size > MAX_CACHE_SIZE)	max_cache_size = MAX_CACHE_SIZE;    if (max_cache_size > 0) {	for (i = 0; i < max_cache_size - 1; i++)	    cache_descs[i].next = &cache_descs[i + 1];	cache_descs[max_cache_size - 1].next = NULL;	free_cache_descs = &cache_descs[0];    }    else	free_cache_descs = NULL;    no_of_segments = 0;    no_of_segments_watermark = 0;}/* * erts_mseg_late_init() have to be called after all allocators, * threads and timers have been initialized. */voiderts_mseg_late_init(void){    mseg_late_init();    erts_mtx_lock(&mseg_mutex);    is_init_done = 1;    if (cache_size)	schedule_cache_check();    erts_mtx_unlock(&mseg_mutex);}voiderts_mseg_exit(void){    mseg_shutdown();}#endif /* #if HAVE_ERTS_MSEG */unsigned longerts_mseg_test(unsigned long op,	       unsigned long a1,	       unsigned long a2,	       unsigned long a3){    switch (op) {#if HAVE_ERTS_MSEG    case 0x400: /* Have erts_mseg */	return (unsigned long) 1;    case 0x401:	return (unsigned long) erts_mseg_alloc(ERTS_ALC_A_INVALID, (Uint *) a1);    case 0x402:	erts_mseg_dealloc(ERTS_ALC_A_INVALID, (void *) a1, (Uint) a2);	return (unsigned long) 0;    case 0x403:	return (unsigned long) erts_mseg_realloc(ERTS_ALC_A_INVALID,						 (void *) a1,						 (Uint) a2,						 (Uint *) a3);    case 0x404:	erts_mseg_clear_cache();	return (unsigned long) 0;    case 0x405:	return (unsigned long) erts_mseg_no();    case 0x406: {	unsigned long res;	erts_mtx_lock(&mseg_mutex);	res = (unsigned long) cache_size;	erts_mtx_unlock(&mseg_mutex);	return res;    }#else /* #if HAVE_ERTS_MSEG */    case 0x400: /* Have erts_mseg */	return (unsigned long) 0;#endif /* #if HAVE_ERTS_MSEG */    default:	ASSERT(0); return ~((unsigned long) 0);    }}

⌨️ 快捷键说明

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