Beispiel #1
0
static void
init_am_a(void)
{
    int i;
    am_a = (Eterm *) erts_alloc(ERTS_ALC_T_INSTR_INFO,
				(ERTS_ALC_A_MAX+1)*sizeof(Eterm));

    for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
	atom_init(&am_a[i], ERTS_ALC_A2AD(i));
    }

}
Beispiel #2
0
static void
dump_stat_to_stream(FILE *fp, int begin_max_period)
{
    ErtsAlcType_t i, a_max, a_min;

    erts_mtx_lock(&instr_mutex);

    fprintf(fp,
	    "{instr_vsn,%lu}.\n",
	    (unsigned long) ERTS_INSTR_VSN);
    
    update_max_ever_values(&stats->tot, 0, 0);

    fprintf(fp,
	    "{total,[{total,[{sizes,%lu,%lu,%lu},{blocks,%lu,%lu,%lu}]}]}.\n",
	    (UWord) stats->tot.size,
	    (UWord) stats->tot.max_size,
	    (UWord) stats->tot.max_size_ever,
	    (UWord) stats->tot.blocks,
	    (UWord) stats->tot.max_blocks,
	    (UWord) stats->tot.max_blocks_ever);

    a_max = 0;
    a_min = ~0;
    for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
	if (erts_allctrs_info[i].enabled) {
	    if (a_min > i)
		a_min = i;
	    if (a_max < i)
		a_max = i;
	}
    }

    ASSERT(ERTS_ALC_A_MIN <= a_min && a_min <= ERTS_ALC_A_MAX);
    ASSERT(ERTS_ALC_A_MIN <= a_max && a_max <= ERTS_ALC_A_MAX);
    ASSERT(a_min <= a_max);

    update_max_ever_values(stats->a, a_min, a_max);

    for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
	if (erts_allctrs_info[i].enabled) {
	    fprintf(fp,
		    "%s{%s,[{sizes,%lu,%lu,%lu},{blocks,%lu,%lu,%lu}]}%s",
		    i == a_min ? "{allocators,\n [" : "  ",
		    ERTS_ALC_A2AD(i),
		    (UWord) stats->a[i].size,
		    (UWord) stats->a[i].max_size,
		    (UWord) stats->a[i].max_size_ever,
		    (UWord) stats->a[i].blocks,
		    (UWord) stats->a[i].max_blocks,
		    (UWord) stats->a[i].max_blocks_ever,
		    i == a_max ? "]}.\n" : ",\n");
	}
    }

    update_max_ever_values(stats->c, ERTS_ALC_C_MIN, ERTS_ALC_C_MAX);

    for (i = ERTS_ALC_C_MIN; i <= ERTS_ALC_C_MAX; i++) {
	fprintf(fp,
		"%s{%s,[{sizes,%lu,%lu,%lu},{blocks,%lu,%lu,%lu}]}%s",
		i == ERTS_ALC_C_MIN ? "{classes,\n [" : "  ",
		ERTS_ALC_C2CD(i),
		(UWord) stats->c[i].size,
		(UWord) stats->c[i].max_size,
		(UWord) stats->c[i].max_size_ever,
		(UWord) stats->c[i].blocks,
		(UWord) stats->c[i].max_blocks,
		(UWord) stats->c[i].max_blocks_ever,
		i == ERTS_ALC_C_MAX ? "]}.\n" :  ",\n" );
    }

    update_max_ever_values(stats->n, ERTS_ALC_N_MIN, ERTS_ALC_N_MAX);

    for (i = ERTS_ALC_N_MIN; i <= ERTS_ALC_N_MAX; i++) {
	fprintf(fp,
		"%s{%s,[{sizes,%lu,%lu,%lu},{blocks,%lu,%lu,%lu}]}%s",
		i == ERTS_ALC_N_MIN ? "{types,\n [" : "  ",
		ERTS_ALC_N2TD(i),
		(UWord) stats->n[i].size,
		(UWord) stats->n[i].max_size,
		(UWord) stats->n[i].max_size_ever,
		(UWord) stats->n[i].blocks,
		(UWord) stats->n[i].max_blocks,
		(UWord) stats->n[i].max_blocks_ever,
		i == ERTS_ALC_N_MAX ? "]}.\n" :  ",\n" );
    }

    if (begin_max_period) {
	begin_new_max_period(&stats->tot, 0, 0);
	begin_new_max_period(stats->a, a_min, a_max);
	begin_new_max_period(stats->c, ERTS_ALC_C_MIN, ERTS_ALC_C_MAX);
	begin_new_max_period(stats->n, ERTS_ALC_N_MIN, ERTS_ALC_N_MAX);
    }

    erts_mtx_unlock(&instr_mutex);

}
Beispiel #3
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);
}
Beispiel #4
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;
}