Example #1
0
static ERTS_INLINE void
stat_upd_free(ErtsAlcType_t n, Uint size)
{
    ErtsAlcType_t t = ERTS_ALC_N2T(n);
    ErtsAlcType_t a = ERTS_ALC_T2A(t);
    ErtsAlcType_t c = ERTS_ALC_T2C(t);

    ASSERT(stats->ap[a]->size >= size);
    stats->ap[a]->size -= size;

    ASSERT(stats->c[c].size >= size);
    stats->c[c].size -= size;

    ASSERT(stats->n[n].size >= size);
    stats->n[n].size -= size;

    ASSERT(stats->tot.size >= size);
    stats->tot.size -= size;

    ASSERT(stats->ap[a]->blocks > 0);
    stats->ap[a]->blocks--;

    ASSERT(stats->c[c].blocks > 0);
    stats->c[c].blocks--;

    ASSERT(stats->n[n].blocks > 0);
    stats->n[n].blocks--;

    ASSERT(stats->tot.blocks > 0);
    stats->tot.blocks--;

}
Example #2
0
Eterm
erts_instr_get_type_info(Process *proc)
{
    Eterm res, *tpls;
    Uint hsz, *hszp, *hp, **hpp;
    ErtsAlcType_t n;

    if (!am_n)
	init_am_n();
    if (!am_a)
	init_am_a();
    if (!am_c)
	init_am_c();

    tpls = (Eterm *) erts_alloc(ERTS_ALC_T_TMP,
				(ERTS_ALC_N_MAX-ERTS_ALC_N_MIN+1)
				* sizeof(Eterm));
    hsz = 0;
    hszp = &hsz;
    hpp = NULL;

 restart_bld:

#if ERTS_ALC_N_MIN != 1
#error ERTS_ALC_N_MIN is not 1
#endif

    for (n = ERTS_ALC_N_MIN; n <= ERTS_ALC_N_MAX; n++) {
	ErtsAlcType_t t = ERTS_ALC_N2T(n);
	ErtsAlcType_t a = ERTS_ALC_T2A(t);
	ErtsAlcType_t c = ERTS_ALC_T2C(t);

	if (!erts_allctrs_info[a].enabled)
	    a = ERTS_ALC_A_SYSTEM;

	tpls[n - ERTS_ALC_N_MIN]
	    = bld_tuple(hpp, hszp, 3, am_n[n], am_a[a], am_c[c]);
    }

    res = bld_tuplev(hpp, hszp, ERTS_ALC_N_MAX-ERTS_ALC_N_MIN+1, tpls);
    
    if (!hpp) {
	hp = HAlloc(proc, hsz);
	hszp = NULL;
	hpp = &hp;
	goto restart_bld;
    }

    erts_free(ERTS_ALC_T_TMP, tpls);

    return res;
}
Example #3
0
static ERTS_INLINE void
stat_upd_alloc(ErtsAlcType_t n, Uint size)
{
    ErtsAlcType_t t = ERTS_ALC_N2T(n);
    ErtsAlcType_t a = ERTS_ALC_T2A(t);
    ErtsAlcType_t c = ERTS_ALC_T2C(t);

    stats->ap[a]->size += size;
    if (stats->ap[a]->max_size < stats->ap[a]->size)
	stats->ap[a]->max_size = stats->ap[a]->size;

    stats->c[c].size += size;
    if (stats->c[c].max_size < stats->c[c].size)
	stats->c[c].max_size = stats->c[c].size;

    stats->n[n].size += size;
    if (stats->n[n].max_size < stats->n[n].size)
	stats->n[n].max_size = stats->n[n].size;

    stats->tot.size += size;
    if (stats->tot.max_size < stats->tot.size)
	stats->tot.max_size = stats->tot.size;

    stats->ap[a]->blocks++;
    if (stats->ap[a]->max_blocks < stats->ap[a]->blocks)
	stats->ap[a]->max_blocks = stats->ap[a]->blocks;

    stats->c[c].blocks++;
    if (stats->c[c].max_blocks < stats->c[c].blocks)
	stats->c[c].max_blocks = stats->c[c].blocks;

    stats->n[n].blocks++;
    if (stats->n[n].max_blocks < stats->n[n].blocks)
	stats->n[n].max_blocks = stats->n[n].blocks;

    stats->tot.blocks++;
    if (stats->tot.max_blocks < stats->tot.blocks)
	stats->tot.max_blocks = stats->tot.blocks;

}
Example #4
0
Eterm erts_instr_get_memory_map(Process *proc)
{
    MapStatBlock_t *org_mem_anchor;
    Eterm hdr_tuple, md_list, res;
    Eterm *hp;
    Uint hsz;
    MapStatBlock_t *bp;
#ifdef DEBUG
    Eterm *end_hp;
#endif
    
    if (!erts_instr_memory_map)
	return am_false;

    if (!atoms_initialized)
	init_atoms();
    if (!am_n)
	init_am_n();
    if (!am_c)
	init_am_c();
    if (!am_a)
	init_am_a();

    erts_mtx_lock(&instr_x_mutex);
    erts_mtx_lock(&instr_mutex);

    /* Header size */
    hsz = 5 + 1 + (ERTS_ALC_N_MAX+1-ERTS_ALC_N_MIN)*(1 + 4);

    /* Memory data list */
    for (bp = mem_anchor; bp; bp = bp->next) {
	if (is_internal_pid(bp->pid)) {
#if (_PID_NUM_SIZE - 1 > MAX_SMALL)
	    if (internal_pid_number(bp->pid) > MAX_SMALL)
		hsz += BIG_UINT_HEAP_SIZE;
#endif
#if (_PID_SER_SIZE - 1 > MAX_SMALL)
	    if (internal_pid_serial(bp->pid) > MAX_SMALL)
		hsz += BIG_UINT_HEAP_SIZE;
#endif
	    hsz += 4;
	}

	if ((UWord) bp->mem > MAX_SMALL)
	    hsz += BIG_UINT_HEAP_SIZE;
	if (bp->size > MAX_SMALL)
	    hsz += BIG_UINT_HEAP_SIZE;

	hsz += 5 + 2;
    }

    hsz += 3; /* Root tuple */

    org_mem_anchor = mem_anchor;
    mem_anchor = NULL;

    erts_mtx_unlock(&instr_mutex);

    hp = HAlloc(proc, hsz); /* May end up calling map_stat_alloc() */

    erts_mtx_lock(&instr_mutex);

#ifdef DEBUG
    end_hp = hp + hsz;
#endif

    {	/* Build header */
	ErtsAlcType_t n;
	Eterm type_map;
	Uint *hp2 = hp;
#ifdef DEBUG
	Uint *hp2_end;
#endif

	hp += (ERTS_ALC_N_MAX + 1 - ERTS_ALC_N_MIN)*4;

#ifdef DEBUG
	hp2_end = hp;
#endif

	type_map = make_tuple(hp);
	*(hp++) = make_arityval(ERTS_ALC_N_MAX + 1 - ERTS_ALC_N_MIN);

	for (n = ERTS_ALC_N_MIN; n <= ERTS_ALC_N_MAX; n++) {
	    ErtsAlcType_t t = ERTS_ALC_N2T(n);
	    ErtsAlcType_t a = ERTS_ALC_T2A(t);
	    ErtsAlcType_t c = ERTS_ALC_T2C(t);

	    if (!erts_allctrs_info[a].enabled)
		a = ERTS_ALC_A_SYSTEM;

	    *(hp++) = TUPLE3(hp2, am_n[n], am_a[a], am_c[c]);
	    hp2 += 4;
	}

	ASSERT(hp2 == hp2_end);

	hdr_tuple = TUPLE4(hp,
			   am.instr_hdr,
			   make_small(ERTS_INSTR_VSN),
			   make_small(MAP_STAT_BLOCK_HEADER_SIZE),
			   type_map);

	hp += 5;
    }

    /* Build memory data list */

    for (md_list = NIL, bp = org_mem_anchor; bp; bp = bp->next) {
	Eterm tuple;
	Eterm type;
	Eterm ptr;
	Eterm size;
	Eterm pid;

	if (is_not_internal_pid(bp->pid))
	    pid = am_undefined;
	else {
	    Eterm c;
	    Eterm n;
	    Eterm s;

#if (ERST_INTERNAL_CHANNEL_NO > MAX_SMALL)
#error Oversized internal channel number
#endif
	    c = make_small(ERST_INTERNAL_CHANNEL_NO);

#if (_PID_NUM_SIZE - 1 > MAX_SMALL)
	    if (internal_pid_number(bp->pid) > MAX_SMALL) {
		n = uint_to_big(internal_pid_number(bp->pid), hp);
		hp += BIG_UINT_HEAP_SIZE;
	    }
	    else
#endif
		n = make_small(internal_pid_number(bp->pid));

#if (_PID_SER_SIZE - 1 > MAX_SMALL)
	    if (internal_pid_serial(bp->pid) > MAX_SMALL) {
		s = uint_to_big(internal_pid_serial(bp->pid), hp);
		hp += BIG_UINT_HEAP_SIZE;
	    }
	    else
#endif
		s = make_small(internal_pid_serial(bp->pid));
	    pid = TUPLE3(hp, c, n, s);
	    hp += 4;
	}


#if ERTS_ALC_N_MAX > MAX_SMALL
#error Oversized memory type number
#endif
	type = make_small(bp->type_no);

	if ((UWord) bp->mem > MAX_SMALL) {
	    ptr = uint_to_big((UWord) bp->mem, hp);
	    hp += BIG_UINT_HEAP_SIZE;
	}
	else
	    ptr = make_small((UWord) bp->mem);

	if (bp->size > MAX_SMALL) {
	    size = uint_to_big(bp->size, hp);
	    hp += BIG_UINT_HEAP_SIZE;
	}
	else
	    size = make_small(bp->size);

	tuple = TUPLE4(hp, type, ptr, size, pid);
	hp += 5;

	md_list = CONS(hp, tuple, md_list);
	hp += 2;
    }

    res = TUPLE2(hp, hdr_tuple, md_list);
    
    ASSERT(hp + 3 == end_hp);

    if (mem_anchor) {
	for (bp = mem_anchor; bp->next; bp = bp->next)
	    ;
	ASSERT(org_mem_anchor);
	org_mem_anchor->prev = bp; 
	bp->next = org_mem_anchor;
    }
    else {
	mem_anchor = org_mem_anchor;
    }

    erts_mtx_unlock(&instr_mutex);
    erts_mtx_unlock(&instr_x_mutex);

    return res;
}
Example #5
0
static void dump_memory_map_to_stream(FILE *fp)
{
    ErtsAlcType_t n;
    MapStatBlock_t *bp;
    int lock = !ERTS_IS_CRASH_DUMPING;
    if (lock) {
	ASSERT(!erts_is_allctr_wrapper_prelocked());
	erts_mtx_lock(&instr_mutex);
    }

    /* Write header */

    fprintf(fp,
	    "{instr_hdr,\n"
	    " %lu,\n"
	    " %lu,\n"
	    " {",
	    (unsigned long) ERTS_INSTR_VSN,
	    (unsigned long) MAP_STAT_BLOCK_HEADER_SIZE);

#if ERTS_ALC_N_MIN != 1
#error ERTS_ALC_N_MIN is not 1
#endif

    for (n = ERTS_ALC_N_MIN; n <= ERTS_ALC_N_MAX; n++) {
	ErtsAlcType_t t = ERTS_ALC_N2T(n);
	ErtsAlcType_t a = ERTS_ALC_T2A(t);
	ErtsAlcType_t c = ERTS_ALC_T2C(t);
	const char *astr;

	if (erts_allctrs_info[a].enabled)
	    astr = ERTS_ALC_A2AD(a);
	else
	    astr = ERTS_ALC_A2AD(ERTS_ALC_A_SYSTEM);

	fprintf(fp,
		"%s{%s,%s,%s}%s",
		(n == ERTS_ALC_N_MIN) ? "" : "  ",
		ERTS_ALC_N2TD(n),
		astr,
		ERTS_ALC_C2CD(c),
		(n == ERTS_ALC_N_MAX) ? "" : ",\n");
    }

    fprintf(fp, "}}.\n");

    /* Write memory data */
    for (bp = mem_anchor; bp; bp = bp->next) {
	if (is_internal_pid(bp->pid))
	    fprintf(fp,
		    "{%lu, %lu, %lu, {%lu,%lu,%lu}}.\n",
		    (UWord) bp->type_no,
		    (UWord) bp->mem,
		    (UWord) bp->size,
		    (UWord) pid_channel_no(bp->pid),
		    (UWord) pid_number(bp->pid),
		    (UWord) pid_serial(bp->pid));
	else
	    fprintf(fp,
		    "{%lu, %lu, %lu, undefined}.\n",
		    (UWord) bp->type_no,
		    (UWord) bp->mem,
		    (UWord) bp->size);
    }

    if (lock)
	erts_mtx_unlock(&instr_mutex);
}
Example #6
0
static int
write_trace_header(char *nodename, char *pid, char *hostname)
{
#ifdef DEBUG
    byte *startp;
#endif
    Uint16 entry_sz;
    Uint32 flags, n_len, h_len, p_len, hdr_prolog_len;
    int i, no, str_len;
    const char *str;
    struct {
	Uint32 gsec;
	Uint32 sec;
	Uint32 usec;
    } start_time;

    sys_gettimeofday(&last_tv);

    start_time.gsec = (Uint32) (last_tv.tv_sec / 1000000000);
    start_time.sec  = (Uint32) (last_tv.tv_sec % 1000000000);
    start_time.usec = (Uint32) last_tv.tv_usec;

    if (!MAKE_TBUF_SZ(3*UI32_SZ))
	return 0;

    flags = 0;
#ifdef ARCH_64
    flags |= ERTS_MT_64_BIT_FLAG;
#endif
    flags |= ERTS_MT_CRR_INFO;
#ifdef ERTS_CAN_TRACK_MALLOC
    flags |= ERTS_MT_SEG_CRR_INFO;
#endif

    /*
     * The following 3 ui32 words *always* have to come
     * first in the trace.
     */
    PUT_UI32(tracep, ERTS_MT_START_WORD);
    PUT_UI32(tracep, ERTS_MT_MAJOR_VSN);
    PUT_UI32(tracep, ERTS_MT_MINOR_VSN);

    n_len = strlen(nodename);
    h_len = strlen(hostname);
    p_len = strlen(pid);
    hdr_prolog_len = (2*UI32_SZ
		      + 3*UI16_SZ
		      + 3*UI32_SZ
		      + 3*UI8_SZ
		      + n_len
		      + h_len
		      + p_len);

    if (!MAKE_TBUF_SZ(hdr_prolog_len))
	return 0;

    /*
     * New stuff can be added at the end the of header prolog
     * (EOHP). The reader should skip stuff at the end, that it
     * doesn't understand.
     */

#ifdef DEBUG
    startp = tracep;
#endif

    PUT_UI32(tracep, hdr_prolog_len);
    PUT_UI32(tracep, flags);
    PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
    PUT_UI16(tracep, ERTS_ALC_A_MAX);
    PUT_UI16(tracep, ERTS_ALC_N_MAX);

    PUT_UI32(tracep, start_time.gsec);
    PUT_UI32(tracep, start_time.sec);
    PUT_UI32(tracep, start_time.usec);

    PUT_UI8(tracep, (byte) n_len);
    memcpy((void *) tracep, (void *) nodename, n_len);
    tracep += n_len;

    PUT_UI8(tracep, (byte) h_len);
    memcpy((void *) tracep, (void *) hostname, h_len);
    tracep += h_len;

    PUT_UI8(tracep, (byte) p_len);
    memcpy((void *) tracep, (void *) pid, p_len);
    tracep += p_len;

    ASSERT(startp + hdr_prolog_len == tracep);

    /*
     * EOHP
     */

    /*
     * All tags from here on should be followed by an Uint16 size
     * field containing the total size of the entry.
     *
     * New stuff can eigther be added at the end of an entry, or
     * as a new tagged entry. The reader should skip stuff at the
     * end, that it doesn't understand.
     */

    for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
	Uint16 aflags = 0;

#ifndef ERTS_CAN_TRACK_MALLOC
	if (i != ERTS_ALC_A_SYSTEM)
#endif
	    aflags |= ERTS_MT_ALLCTR_USD_CRR_INFO;

	str = ERTS_ALC_A2AD(i);
	ASSERT(str);
	str_len = strlen(str);
	if (str_len >= (1 << 8)) {
	    disable_trace(1, "Excessively large allocator string", 0);
	    return 0;
	}

	entry_sz = UI8_SZ + 3*UI16_SZ + UI8_SZ;
	entry_sz += (erts_allctrs_info[i].alloc_util ? 2 : 1)*UI16_SZ;
	entry_sz += UI8_SZ + str_len;

	if (!MAKE_TBUF_SZ(entry_sz))
	    return 0;

#ifdef DEBUG
	startp = tracep;
#endif
	PUT_UI8(tracep, ERTS_MT_ALLOCATOR_HDR_TAG);
	PUT_UI16(tracep, entry_sz);
	PUT_UI16(tracep, aflags);
	PUT_UI16(tracep, (Uint16) i);
	PUT_UI8( tracep, (byte) str_len);
	memcpy((void *) tracep, (void *) str, str_len);
	tracep += str_len;
	if (erts_allctrs_info[i].alloc_util) {
	    PUT_UI8(tracep, 2);
	    PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
	    PUT_UI16(tracep, ERTS_ALC_A_SYSTEM);
	}
	else {
	    PUT_UI8(tracep, 1);
	    switch (i) {
	    case ERTS_ALC_A_SYSTEM:
		PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
		break;
	    default:
		PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
		break;
	    }
	}
	ASSERT(startp + entry_sz == tracep);
    }

    for (i = ERTS_ALC_N_MIN; i <= ERTS_ALC_N_MAX; i++) {
	Uint16 nflags = 0;
	str = ERTS_ALC_N2TD(i);
	ASSERT(str);

	str_len = strlen(str);
	if (str_len >= (1 << 8)) {
	    disable_trace(1, "Excessively large type string", 0);
	    return 0;
	}

	no = ERTS_ALC_T2A(ERTS_ALC_N2T(i));
	if (!erts_allctrs_info[no].enabled)
	    no = ERTS_ALC_A_SYSTEM;
	ASSERT(ERTS_ALC_A_MIN <= no && no <= ERTS_ALC_A_MAX);

	entry_sz = UI8_SZ + 3*UI16_SZ + UI8_SZ + str_len + UI16_SZ;

	if (!MAKE_TBUF_SZ(entry_sz))
	    return 0;

#ifdef DEBUG
	startp = tracep;
#endif
	PUT_UI8(tracep, ERTS_MT_BLOCK_TYPE_HDR_TAG);
	PUT_UI16(tracep, entry_sz);
	PUT_UI16(tracep, nflags);
	PUT_UI16(tracep, (Uint16) i);
	PUT_UI8(tracep, (byte) str_len);
	memcpy((void *) tracep, (void *) str, str_len);
	tracep += str_len;
	PUT_UI16(tracep, no);
	ASSERT(startp + entry_sz == tracep);
    }

    entry_sz = UI8_SZ + UI16_SZ;
    if (!MAKE_TBUF_SZ(entry_sz))
	return 0;
    PUT_UI8(tracep, ERTS_MT_END_OF_HDR_TAG);
    PUT_UI16(tracep, entry_sz);

    return 1;
}