erl_alloc.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 2,572 行 · 第 1/5 页
C
2,572 行
} }#if HAVE_ERTS_MSEG if (use_mseg) terms[length++] = am_atom_put("mseg_alloc", 10);#endif features = length ? erts_bld_list(hpp, szp, length, terms) : NIL;#if defined(ELIB_ALLOC_IS_CLIB) { Eterm version; int i; int ver[5]; i = sscanf(ERLANG_VERSION, "%d.%d.%d.%d.%d", &ver[0], &ver[1], &ver[2], &ver[3], &ver[4]); version = NIL; for(i--; i >= 0; i--) version = erts_bld_cons(hpp, szp, make_small(ver[i]), version); res = erts_bld_tuple(hpp, szp, 4, am_elib_malloc, version, features, settings); }#elif defined(__GLIBC__) { Eterm AM_glibc = am_atom_put("glibc", 5); Eterm version; version = erts_bld_cons(hpp, szp, make_small(__GLIBC__),#ifdef __GLIBC_MINOR__ erts_bld_cons(hpp, szp, make_small(__GLIBC_MINOR__), NIL)#else NIL#endif ); res = erts_bld_tuple(hpp, szp, 4, AM_glibc, version, features, settings); }#else /* unknown allocator */ res = erts_bld_tuple(hpp, szp, 4, am_undefined, NIL, features, settings);#endif if (szp) { /* ... and then build the term */ hp = HAlloc((Process *) proc, sz); endp = hp + sz; hpp = &hp; szp = NULL; goto bld_term; } ASSERT(endp >= hp); HRelease((Process *) proc, endp, hp); return res;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Deprecated functions * * * * These functions are still defined since "non-OTP linked in drivers" may * * contain (illegal) calls to them. *\* *//* --- DO *NOT* USE THESE FUNCTIONS --- */void *sys_alloc(Uint sz){ return erts_alloc_fnf(ERTS_ALC_T_UNDEF, sz); }void *sys_realloc(void *ptr, Uint sz){ return erts_realloc_fnf(ERTS_ALC_T_UNDEF, ptr, sz); }void sys_free(void *ptr){ erts_free(ERTS_ALC_T_UNDEF, ptr); }void *safe_alloc(Uint sz){ return erts_alloc(ERTS_ALC_T_UNDEF, sz); }void *safe_realloc(void *ptr, Uint sz){ return erts_realloc(ERTS_ALC_T_UNDEF, ptr, sz); }/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * NOTE: erts_alc_test() is only supposed to be used for testing. * * * * Keep alloc_SUITE_data/allocator_test.h updated if changes are made * * to erts_alc_test() *\* */#define ERTS_ALC_TEST_ABORT erl_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error\n")unsigned long erts_alc_test(unsigned long op, unsigned long a1, unsigned long a2, unsigned long a3){ switch (op >> 8) { case 0x0: return erts_alcu_test(op, a1, a2); case 0x1: return erts_gfalc_test(op, a1, a2); case 0x2: return erts_bfalc_test(op, a1, a2); case 0x3: return erts_afalc_test(op, a1, a2); case 0x4: return erts_mseg_test(op, a1, a2, a3); case 0xf: switch (op) { case 0xf00:#ifdef USE_THREADS if (((Allctr_t *) a1)->thread_safe) return (unsigned long) erts_alcu_alloc_ts(ERTS_ALC_T_UNDEF, (void *) a1, (Uint) a2); else#endif return (unsigned long) erts_alcu_alloc(ERTS_ALC_T_UNDEF, (void *) a1, (Uint) a2); case 0xf01:#ifdef USE_THREADS if (((Allctr_t *) a1)->thread_safe) return (unsigned long) erts_alcu_realloc_ts(ERTS_ALC_T_UNDEF, (void *) a1, (void *) a2, (Uint) a3); else#endif return (unsigned long) erts_alcu_realloc(ERTS_ALC_T_UNDEF, (void *) a1, (void *) a2, (Uint) a3); case 0xf02:#ifdef USE_THREADS if (((Allctr_t *) a1)->thread_safe) erts_alcu_free_ts(ERTS_ALC_T_UNDEF, (void *) a1, (void *) a2); else#endif erts_alcu_free(ERTS_ALC_T_UNDEF, (void *) a1, (void *) a2); return 0; case 0xf03: { Allctr_t *allctr; struct au_init init; SET_DEFAULT_ALLOC_OPTS(&init); init.enable = 1; init.atype = GOODFIT; init.init.util.name_prefix = (char *) a1; init.init.util.ts = a2 ? 1 : 0; if ((char **) a3) { char **argv = (char **) a3; int i = 0; while (argv[i]) { if (argv[i][0] == '-' && argv[i][1] == 't') handle_au_arg(&init, &argv[i][2], argv, &i); else return (unsigned long) NULL; i++; } } switch (init.atype) { case GOODFIT: allctr = erts_gfalc_start((GFAllctr_t *) erts_alloc(ERTS_ALC_T_UNDEF, sizeof(GFAllctr_t)), &init.init.gf, &init.init.util); break; case BESTFIT: allctr = erts_bfalc_start((BFAllctr_t *) erts_alloc(ERTS_ALC_T_UNDEF, sizeof(BFAllctr_t)), &init.init.bf, &init.init.util); break; case AFIT: allctr = erts_afalc_start((AFAllctr_t *) erts_alloc(ERTS_ALC_T_UNDEF, sizeof(AFAllctr_t)), &init.init.af, &init.init.util); break; default: ASSERT(0); allctr = NULL; break; } return (unsigned long) allctr; } case 0xf04: erts_alcu_stop((Allctr_t *) a1); erts_free(ERTS_ALC_T_UNDEF, (void *) a1); break;#ifdef USE_THREADS case 0xf05: return (unsigned long) 1; case 0xf06: return (unsigned long) ((Allctr_t *) a1)->thread_safe;#ifdef ETHR_NO_FORKSAFETY case 0xf07: return (unsigned long) 0;#else case 0xf07: return (unsigned long) ((Allctr_t *) a1)->thread_safe;#endif case 0xf08: { ethr_mutex *mtx = erts_alloc(ERTS_ALC_T_UNDEF, sizeof(ethr_mutex)); if (ethr_mutex_init(mtx) != 0) ERTS_ALC_TEST_ABORT; return (unsigned long) mtx; } case 0xf09: { ethr_mutex *mtx = (ethr_mutex *) a1; if (ethr_mutex_destroy(mtx) != 0) ERTS_ALC_TEST_ABORT; erts_free(ERTS_ALC_T_UNDEF, (void *) mtx); break; } case 0xf0a: if (ethr_mutex_lock((ethr_mutex *) a1) != 0) ERTS_ALC_TEST_ABORT; break; case 0xf0b: if (ethr_mutex_unlock((ethr_mutex *) a1) != 0) ERTS_ALC_TEST_ABORT; break; case 0xf0c: { ethr_cond *cnd = erts_alloc(ERTS_ALC_T_UNDEF, sizeof(ethr_cond)); if (ethr_cond_init(cnd) != 0) ERTS_ALC_TEST_ABORT; return (unsigned long) cnd; } case 0xf0d: { ethr_cond *cnd = (ethr_cond *) a1; if (ethr_cond_destroy(cnd) != 0) ERTS_ALC_TEST_ABORT; erts_free(ERTS_ALC_T_UNDEF, (void *) cnd); break; } case 0xf0e: if (ethr_cond_broadcast((ethr_cond *) a1) != 0) ERTS_ALC_TEST_ABORT; break; case 0xf0f: { int res; do { res = ethr_cond_wait((ethr_cond *) a1, (ethr_mutex *) a2); } while (res == EINTR); if (res != 0) ERTS_ALC_TEST_ABORT; break; } case 0xf10: { ethr_tid *tid = erts_alloc(ERTS_ALC_T_UNDEF, sizeof(ethr_tid)); if (ethr_thr_create(tid, (void * (*)(void *)) a1, (void *) a2, NULL) != 0) ERTS_ALC_TEST_ABORT; return (unsigned long) tid; } case 0xf11: { ethr_tid *tid = (ethr_tid *) a1; if (ethr_thr_join(*tid, NULL) != 0) ERTS_ALC_TEST_ABORT; erts_free(ERTS_ALC_T_UNDEF, (void *) tid); break; } case 0xf12: ethr_thr_exit((void *) a1); ERTS_ALC_TEST_ABORT; break;#endif /* #ifdef USE_THREADS */ default: break; } return (unsigned long) 0; default: break; } ASSERT(0); return ~((unsigned long) 0);}#ifdef DEBUG/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Debug stuff *\* */#if 0#define PRINT_OPS#else#undef PRINT_OPS#endif#define FENCE_SZ (3*sizeof(Uint))#ifdef ARCH_64#define FENCE_PATTERN 0xABCDEF97ABCDEF97#else#define FENCE_PATTERN 0xABCDEF97#endif#define TYPE_PATTERN_MASK ERTS_ALC_N_MASK#define TYPE_PATTERN_SHIFT 16#define FIXED_FENCE_PATTERN_MASK \ (~((Uint) (TYPE_PATTERN_MASK << TYPE_PATTERN_SHIFT)))#define FIXED_FENCE_PATTERN \ (FENCE_PATTERN & FIXED_FENCE_PATTERN_MASK)#define MK_PATTERN(T) \ (FIXED_FENCE_PATTERN | (((T) & TYPE_PATTERN_MASK) << TYPE_PATTERN_SHIFT))#define GET_TYPE_OF_PATTERN(P) \ (((P) >> TYPE_PATTERN_SHIFT) & TYPE_PATTERN_MASK)static void *set_memory_fence(void *ptr, Uint sz, ErtsAlcType_t n){ Uint *ui_ptr; Uint pattern; if (!ptr) return NULL; ui_ptr = (Uint *) ptr; pattern = MK_PATTERN(n); *(ui_ptr++) = sz; *(ui_ptr++) = pattern; memcpy((void *) (((char *) ui_ptr)+sz), (void *) &pattern, sizeof(Uint)); return (void *) ui_ptr;}static void *check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func){ Uint sz; Uint found_type; Uint pre_pattern; Uint post_pattern; Uint *ui_ptr; if (!ptr) return NULL; ui_ptr = (Uint *) ptr; pre_pattern = *(--ui_ptr); *size = sz = *(--ui_ptr); found_type = GET_TYPE_OF_PATTERN(pre_pattern); if (pre_pattern != MK_PATTERN(n)) { if ((FIXED_FENCE_PATTERN_MASK & pre_pattern) != FIXED_FENCE_PATTERN) erl_exit(ERTS_ABORT_EXIT, "ERROR: Fence at beginning of memory block (p=0x%u) " "clobbered.\n", (unsigned long) ptr); } memcpy((void *) &post_pattern, (void *) (((char *)ptr)+sz), sizeof(Uint)); if (post_pattern != MK_PATTERN(n) || pre_pattern != post_pattern) { char fbuf[10]; char obuf[10]; char *ftype; char *otype; char *op_str; if ((FIXED_FENCE_PATTERN_MASK & post_pattern) != FIXED_FENCE_PATTERN) erl_exit(ERTS_ABORT_EXIT, "ERROR: Fence at end of memory block (p=0x%u, sz=%u) " "clobbered.\n", (unsigned long) ptr, (unsigned long) sz); if (found_type != GET_TYPE_OF_PATTERN(post_pattern)) erl_exit(ERTS_ABORT_EXIT, "ERROR: Fence around memory block (p=0x%u, sz=%u) " "clobbered.\n", (unsigned long) ptr, (unsigned long) sz); ftype = type_no_str(found_type); if (!ftype) { sprintf(fbuf, "%d", (int) found_type); ftype = fbuf; } otype = type_no_str(n); if (!otype) { sprintf(obuf, "%d", (int) n); otype = obuf; } switch (func) { case ERTS_ALC_O_ALLOC: op_str = "allocated"; break; case ERTS_ALC_O_REALLOC: op_str = "reallocated"; break; case ERTS_ALC_O_FREE: op_str = "freed"; break; default: op_str = "???"; break; } erl_exit(ERTS_ABORT_EXIT, "ERROR: Memory block (p=0x%u, sz=%u) allocated as type \"%s\"," " but %s as type \"%s\".\n", (unsigned long) ptr, (unsigned long) sz, ftype, op_str, otype); } return (void *) ui_ptr;}static ErtsAllocatorFunctions_t real_allctrs[ERTS_ALC_A_MAX+1];static void *debug_alloc(ErtsAlcType_t n, void *extra, Uint size){ ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra; Uint dsize; void *res; ASSERT(ERTS_ALC_N_MIN <= n && n <= ERTS_ALC_N_MAX); dsize = size + FENCE_SZ; res = (*real_af->alloc)(n, real_af->extra, dsize); res = set_memory_fence(res, size, n);#ifdef PRINT_OPS fprintf(stderr, "0x%lx = alloc(%s, %lu)\r\n", (Uint) res, ERTS_ALC_N2TD(n), size);#endif return res;}static void *debug_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size){ ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra; Uint dsize; Uint old_size; void *dptr; void *res; ASSERT(ERTS_ALC_N_MIN <= n && n <= ERTS_ALC_N_MAX); dsize = size + FENCE_SZ; dptr = check_memory_fence(ptr, &old_size, n, ERTS_ALC_O_REALLOC); if (old_size > size) sys_memset((void *) (((char *) ptr) + size), 0xf, sizeof(Uint) + old_size - size); res = (*real_af->realloc)(n, real_af->extra, dptr, dsize); res = set_memory_fence(res, size, n);#ifdef PRINT_OPS fprintf(stderr, "0x%lx = realloc(%s, 0x%lx, %lu)\r\n", (Uint) res, ERTS_ALC_N2TD(n), (Uint) ptr, size);#endif return res;}static voiddebug_free(ErtsAlcType_t n, void *extra, void *ptr){ ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra; void *dptr; Uint size; ASSERT(ERTS_ALC_N_MIN <= n && n <= ERTS_ALC_N_MAX); dptr = check_memory_fence(ptr, &size, n, ERTS_ALC_O_FREE); sys_memset((void *) dptr, n, size + FENCE_SZ); (*real_af->free)(n, real_af->extra, dptr);#ifdef PRINT_OPS fprintf(stderr, "free(%s, 0x%lx)\r\n", ERTS_ALC_N2TD(n), (Uint) ptr);#endif}static Uintinstall_debug_functions(void){ int i; ASSERT(sizeof(erts_allctrs) == sizeof(real_allctrs)); sys_memcpy((void *)real_allctrs,(void *)erts_allctrs,sizeof(erts_allctrs)); for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) { erts_allctrs[i].alloc = debug_alloc; erts_allctrs[i].realloc = debug_realloc; erts_allctrs[i].free = debug_free; erts_allctrs[i].extra = (void *) &real_allctrs[i]; } return FENCE_SZ;}#endif /* #ifdef DEBUG */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?