📄 erl_memory.c
字号:
}static INLINE voidwrote_area_aux(em_area *area, em_state *state, em_buf_queue *queue, int do_lock){ em_buffer *buf; if (do_lock) mutex_lock(&queue->mutex); buf = queue->last; ASSERT(area->ptr); ASSERT(area->size); ASSERT(buf); ASSERT(buf->data_end == area->ptr); ASSERT(buf->end >= area->ptr + area->size); buf->data_end = area->ptr + area->size; area->ptr = NULL; area->size = 0; cond_signal(&queue->cond); if (do_lock) mutex_unlock(&queue->mutex);}static INLINE voidwrote_area(em_area *area, em_state *state, em_buf_queue *queue){ wrote_area_aux(area, state, queue, 1);}static voidget_next_write_area(em_area *area, em_state *state, em_buf_queue *queue, size_t size){ em_buffer *buf; mutex_lock(&queue->mutex); ASSERT(!area->size || area->ptr); if (area->size) wrote_area_aux(area, state, queue, 0); buf = ((queue->last && queue->last->end - queue->last->data_end >= size) ? queue->last : enqueue(state, queue, size)); if (buf) { ASSERT(buf->end - buf->data_end >= size); area->ptr = buf->data_end; area->size = buf->end - buf->data_end; } else { area->ptr = NULL; area->size = 0; } if (queue->tot_buf_size > queue->max_buf_size) { fprintf(stderr, "emem: Maximum %s buffer size (%lu) exceeded. " "Terminating...\n", queue->name, (unsigned long) queue->max_buf_size); exit(1); } mutex_unlock(&queue->mutex);}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Output * * *\* */static INLINE size_twrite_str(usgnd_int_8 **dstpp, char *srcp){ size_t i = 0; if (dstpp) while (srcp[i]) *((*dstpp)++) = (usgnd_int_8) srcp[i++]; else while (srcp[i]) i++; return i;}static size_twrite_strings(usgnd_int_8 **ptr, char **strings, char *first_line_prefix, char *line_prefix, size_t max_line_size){ size_t size; size_t tot_size = 0; size_t line_size = 0; size_t line_prefix_size; sgnd_int_32 ix; tot_size = line_size = line_prefix_size = write_str(ptr, first_line_prefix); for (ix = 0; strings[ix]; ix++) { size = write_str(NULL, strings[ix]); if (line_size + 1 + size > max_line_size) { tot_size += write_str(ptr, "\n"); tot_size += write_str(ptr, line_prefix); line_size = line_prefix_size; } tot_size += write_str(ptr, " "); tot_size += ptr ? write_str(ptr, strings[ix]) : size; line_size += 1 + size; } tot_size += write_str(ptr, "\n"); return tot_size;}static size_twrite_title(usgnd_int_8 **bufp, size_t *overflow, size_t width, char *str){ size_t i, sz, ws; usgnd_int_8 *p, *endp; /* * Writes at least one '|' character at the beginning. * Right aligns "str". * If "str" is larger than "width - 1" and overflow is NULL, * then "str" is trucated; otherwise, string is not truncated. */ if (width <= 0) return 0; if (!bufp && !overflow) return width; sz = strlen(str) + 1; if (sz > width) { ws = 0; if (overflow) *overflow += sz - width; else sz = width; } else { ws = width - sz; if (overflow) { if (ws >= *overflow) { ws -= *overflow; *overflow = 0; } else { *overflow -= ws; ws = 0; } } sz += ws; } if (!bufp) return sz; p = *bufp; endp = p + width; *(p++) = '|'; while (ws > 1) { ws--; *(p++) = (usgnd_int_8) ' '; } i = 0; while (str[i] && (overflow || p < endp)) *(p++) = (usgnd_int_8) str[i++]; while (ws) { ws--; *(p++) = (usgnd_int_8) ' '; } ASSERT(overflow || p == endp); ASSERT(sz == (size_t) (p - *bufp)); *bufp = p; return sz;}static size_twrite_obj_sub_titles(em_state *state, usgnd_int_8 **bufp, size_t *overflow){ size_t field_width = state->output.field_width; size_t size = write_title(bufp, overflow, field_width, "size"); if (state->output.max_min_values) { size += write_title(bufp, overflow, field_width, "min size"); size += write_title(bufp, overflow, field_width, "max size"); } if (state->output.block_counts) { size += write_title(bufp, overflow, field_width, "no"); if (state->output.max_min_values) { size += write_title(bufp, overflow, field_width, "min no"); size += write_title(bufp, overflow, field_width, "max no"); } } if (state->output.op_counts) { size += write_title(bufp, overflow, field_width, "alloc()"); size += write_title(bufp, overflow, field_width, "realloc()"); size += write_title(bufp, overflow, field_width, "free()"); } return size;}static size_twrite_header(em_state *state, usgnd_int_8 *ptr, int trunc){#define MIN_LTEXT_SZ 18#define HEADER_EOL_STR "|\n" usgnd_int_8 *p; usgnd_int_8 **pp; int i; size_t overflow; size_t *ofp; size_t obj_size = state->output.values_per_object*state->output.field_width; size_t size = 0; int have_seg_crr = state->trace_info.have_segment_carrier_info; if (ptr) { p = ptr; pp = &p; } else { p = NULL; pp = NULL; } overflow = 0; ofp = trunc ? NULL : &overflow; size += write_title(pp, ofp, EM_TIME_FIELD_WIDTH, "time"); if (state->output.total) { int no = 1; if (have_seg_crr) { if (state->info.allctr_prv_crr[state->trace_info.segment_ix]) no++; if (state->info.allctr_usd_crr[state->trace_info.segment_ix]) no++; } size += write_title(pp, ofp, (have_seg_crr ? 3 : 1)*obj_size, "total"); } for (i = 0; i < state->output.no_allctrs; i++) { int no = 1; if (state->info.allctr_prv_crr[state->output.allctrs[i].ix]) no++; if (state->info.allctr_usd_crr[state->output.allctrs[i].ix]) no++; size += write_title(pp, ofp, no*obj_size, state->output.allctrs[i].name); } for (i = 0; i < state->output.no_btypes; i++) size += write_title(pp, ofp, obj_size, state->output.btypes[i].name); size += write_str(pp, HEADER_EOL_STR); overflow = 0; size += write_title(pp, ofp, EM_TIME_FIELD_WIDTH, ""); if (state->output.total) { size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ ? "alcd blks" : "allocated blocks")); if (have_seg_crr) { if (state->info.allctr_prv_crr[state->trace_info.segment_ix]) size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ ? "mpd segs" : "mapped segments")); if (state->info.allctr_usd_crr[state->trace_info.segment_ix]) size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ ? "chd segs" : "cached segments")); } } for (i = 0; i < state->output.no_allctrs; i++) { size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ ? "alcd blks" : "allocated blocks")); if (state->info.allctr_prv_crr[state->output.allctrs[i].ix]) size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ ? "prvd crrs" : "provided carriers")); if (state->info.allctr_usd_crr[state->output.allctrs[i].ix]) size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ ? "usd crrs" : "used carriers")); } for (i = 0; i < state->output.no_btypes; i++) size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ ? "alcd blks" : "allocated blocks")); size += write_str(pp, HEADER_EOL_STR); overflow = 0; size += write_title(pp, ofp, EM_TIME_FIELD_WIDTH, ""); if (state->output.total) { size += write_obj_sub_titles(state, pp, ofp); if (have_seg_crr) { if (state->info.allctr_prv_crr[state->trace_info.segment_ix]) size += write_obj_sub_titles(state, pp, ofp); if (state->info.allctr_usd_crr[state->trace_info.segment_ix]) size += write_obj_sub_titles(state, pp, ofp); } } for (i = 0; i < state->output.no_allctrs; i++) { size += write_obj_sub_titles(state, pp, ofp); if (state->info.allctr_prv_crr[state->output.allctrs[i].ix]) size += write_obj_sub_titles(state, pp, ofp); if (state->info.allctr_usd_crr[state->output.allctrs[i].ix]) size += write_obj_sub_titles(state, pp, ofp); } for (i = 0; i < state->output.no_btypes; i++) size += write_obj_sub_titles(state, pp, ofp); size += write_str(pp, HEADER_EOL_STR);#undef MIN_LTEXT_SZ#undef HEADER_EOL_STR return size;}static INLINE voidwrite_mem_info(em_state *state, usgnd_int_8 **p, em_mem_info *mi){ int fw = state->output.field_width - 1; *p += sprintf(*p, "%*" USGND_INT_MAX_FSTR " ", fw, mi->size); if (state->output.max_min_values) *p += sprintf(*p, "%*" USGND_INT_MAX_FSTR " %*" USGND_INT_MAX_FSTR " ", fw, mi->min_size, fw, mi->max_size); if (state->output.block_counts) { *p += sprintf(*p, "%*" USGND_INT_MAX_FSTR " ", fw, mi->no); if (state->output.max_min_values) *p += sprintf(*p, "%*" USGND_INT_MAX_FSTR " %*" USGND_INT_MAX_FSTR " ", fw, mi->min_no, fw, mi->max_no); } if (state->output.op_counts) *p += sprintf(*p, "%*" USGND_INT_MAX_FSTR " %*" USGND_INT_MAX_FSTR " %*" USGND_INT_MAX_FSTR " ", fw, mi->allocs, fw, mi->reallocs, fw, mi->frees); /* Update max ever values */ if (mi->max_ever_size < mi->max_size) mi->max_ever_size = mi->max_size; if (mi->max_ever_no < mi->max_no) mi->max_ever_no = mi->max_no; /* Reset max/min values */ mi->max_size = mi->min_size = mi->size; mi->max_no = mi->min_no = mi->no;}static INLINE voidwrite_max_ever_mem_info(em_state *state, usgnd_int_8 **p, em_mem_info *mi){ int fw = state->output.field_width - 1; *p += sprintf(*p, "%*" USGND_INT_MAX_FSTR " ", fw, mi->max_ever_size); if (state->output.max_min_values) *p += sprintf(*p, "%*s %*s ", fw, "", fw, ""); if (state->output.block_counts) { *p += sprintf(*p, "%*" USGND_INT_MAX_FSTR " ", fw, mi->max_ever_no); if (state->output.max_min_values) *p += sprintf(*p, "%*s %*s ", fw, "", fw, ""); } if (state->output.op_counts) *p += sprintf(*p, "%*s %*s %*s ", fw, "", fw, "", fw, "");}static voidprint_string(em_state *state, char *str){ em_area area = {NULL, 0}; usgnd_int_8 *p; /* Get area */ get_next_write_area(&area,state,&state->output.queue,write_str(NULL,str)); p = (usgnd_int_8 *) area.ptr; area.size = write_str(&p, str); /* Leave area */ wrote_area(&area, state, &state->output.queue);}static intprint_emu_arg(em_state *state){ em_area area = {NULL, 0}; char hostname[100]; char carg[22]; struct sockaddr_in saddr; struct hostent *hp; struct in_addr iaddr; usgnd_int_16 port; int saddr_size = sizeof(saddr); size_t size; char *format = "> Emulator command line argument: +Mit %s\n"; if (getsockname(state->input.socket, (struct sockaddr *) &saddr, &saddr_size) != 0) goto error; port = ntohs(saddr.sin_port); ASSERT(state->input.listen_port == 0 || state->input.listen_port == port); state->input.listen_port = port; if (gethostname(hostname, sizeof(hostname)) != 0) goto error; hp = gethostbyname(hostname); if (!hp) goto error; if (hp->h_addr_list) { (void) memcpy(&iaddr.s_addr, *hp->h_addr_list, sizeof(iaddr.s_addr)); (void) sprintf(carg, "%s:%d", inet_ntoa(iaddr), (int) port); } else (void) sprintf(carg, "127.0.0.1:%d", (int) port);#if EMEM_d_SWITCH if (state->output.erl_cmd_file) { fprintf(state->output.erl_cmd_file, "+Mit %s\n", carg); fclose(state->output.erl_cmd_file); state->output.erl_cmd_file = NULL; }#endif size = strlen(format) + strlen(carg); /* Get area */ get_next_write_area(&area, state, &state->output.queue, size); area.size = sprintf(area.ptr, format, carg); /* Leave area */ wrote_area(&area, state, &state->output.queue); return 0; error: return GET_SOCK_ERRNO();}static size_twrite_allocator_info(em_state *state, usgnd_int_8 *ptr){ usgnd_int_32 aix, i, j; char *header = "> Allocator information:\n"; char *allctr_str = "> * Allocator:"; char *crr_prv_str = "> * Carrier providers:"; char *blk_tp_str = "> * Block types:"; char *line_prefix = "> "; size_t size = 0; char **strings; size_t strings_size; size_t max_line_size = 80; usgnd_int_8 *p = ptr; usgnd_int_8 **pp = ptr ? &p : NULL; strings_size = state->trace_info.max_block_type_ix + 1; if (strings_size < state->trace_info.max_allocator_ix + 1) strings_size = state->trace_info.max_allocator_ix + 1; strings = (char **) (*state->alloc)((strings_size + 1)*sizeof(char *)); if (!strings) error(ENOMEM); size += write_str(pp, header); for (aix = 0; aix <= state->trace_info.max_allocator_ix; aix++) { emtp_allocator *allctr = state->trace_info.allocator[aix]; if (!allctr->valid) continue; strings[0] = allctr->name; strings[1] = NULL; size += write_strings(pp,strings,allctr_str,line_prefix,max_line_size); i = 0; if (allctr->carrier.provider) for (j = 0; j < allctr->carrier.no_providers; j++) { usgnd_int_32 cpix = allctr->carrier.provider[j];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -