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