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 + -
显示快捷键?