📄 erl_memory.c
字号:
static INLINE voidupdate_min_values(em_mem_info *mi){ if (mi->min_size > mi->size) mi->min_size = mi->size; if (mi->min_no > mi->no) mi->min_no = mi->no;}static INLINE voidupdate_alloc_op(em_mem_info *mi, usgnd_int_max size){ mi->allocs++; mi->size += size; mi->no++; update_max_values(mi);}static INLINE voidupdate_realloc_op(em_mem_info *mi, usgnd_int_max size, usgnd_int_max prev_size, int no_change){ mi->reallocs++; ASSERT(mi->size >= prev_size); mi->size -= prev_size; mi->size += size; if (no_change) { if (no_change > 0) mi->no++; else { ASSERT(mi->no > 0); mi->no--; } } update_max_values(mi); update_min_values(mi);}static INLINE voidupdate_free_op(em_mem_info *mi, usgnd_int_max prev_size){ mi->frees++; ASSERT(mi->size >= prev_size); mi->size -= prev_size; ASSERT(mi->no > 0); mi->no--; update_min_values(mi);}static intinsert_operations(em_state *state, emtp_operation ops[], size_t len){ emtbt_table *crr_table; emtbt_block old_blk; usgnd_int_32 prev_size; usgnd_int_max size; size_t i; int res; int aix, btix, crrix; for (i = 0; i < len; i++) { while (state->output.next_print <= ops[i].time.secs) { print_info(state, state->output.next_print, NULL); state->output.next_print += state->output.next_print_inc; } switch (ops[i].type) { case EMTP_ALLOC:#if PRINT_OPERATIONS print_op(state, &ops[i]);#endif btix = (int) ops[i].u.block.type; aix = state->trace_info.block_type[btix]->allocator; if (!ops[i].u.block.new_ptr) continue; res = emtbt_alloc_op(state->block_table, &ops[i]); if (res != 0) ERR_RET(res); size = ops[i].u.block.new_size; update_alloc_op(&state->info.btype[btix], size); update_alloc_op(&state->info.allctr[aix], size); update_alloc_op(&state->info.total, size); break; case EMTP_REALLOC: { int no;#if PRINT_OPERATIONS print_op(state, &ops[i]);#endif res = emtbt_realloc_op(state->block_table, &ops[i], &old_blk); if (res != 0) ERR_RET(res); size = ops[i].u.block.new_size; prev_size = old_blk.size; if (!ops[i].u.block.prev_ptr) btix = (int) ops[i].u.block.type; else btix = (int) old_blk.type; aix = state->trace_info.block_type[btix]->allocator; no = ((!old_blk.pointer && ops[i].u.block.new_ptr) ? 1 : ((old_blk.pointer && !ops[i].u.block.new_size) ? -1 : 0)); update_realloc_op(&state->info.btype[btix], size, prev_size, no); update_realloc_op(&state->info.allctr[aix], size, prev_size, no); update_realloc_op(&state->info.total, size, prev_size, no); break; } case EMTP_FREE:#if PRINT_OPERATIONS print_op(state, &ops[i]);#endif if (!ops[i].u.block.prev_ptr) continue; res = emtbt_free_op(state->block_table, &ops[i], &old_blk); if (res != 0) ERR_RET(res); prev_size = old_blk.size; btix = (int) old_blk.type; aix = state->trace_info.block_type[btix]->allocator; update_free_op(&state->info.btype[btix], prev_size); update_free_op(&state->info.allctr[aix], prev_size); update_free_op(&state->info.total, prev_size); break; case EMTP_CARRIER_ALLOC:#if PRINT_OPERATIONS print_op(state, &ops[i]);#endif aix = (int) ops[i].u.block.type; crrix = (int) ops[i].u.block.carrier_type; if (!state->carrier_table[crrix]) { state->carrier_table[crrix] = mk_block_table(state); if (!state->carrier_table[crrix]) ERR_RET(ENOMEM); } crr_table = state->carrier_table[crrix]; if (!ops[i].u.block.new_ptr) continue; res = emtbt_alloc_op(crr_table, &ops[i]); if (res != 0) ERR_RET(res); size = ops[i].u.block.new_size; if (state->info.allctr_usd_crr[aix]) update_alloc_op(state->info.allctr_usd_crr[aix], size); if (state->info.allctr_prv_crr[crrix]) update_alloc_op(state->info.allctr_prv_crr[crrix], size); update_alloc_op(&state->info.allctr[crrix], size); break; case EMTP_CARRIER_REALLOC: { int no;#if PRINT_OPERATIONS print_op(state, &ops[i]);#endif crrix = (int) ops[i].u.block.carrier_type; if (!state->carrier_table[crrix]) { state->carrier_table[crrix] = mk_block_table(state); if (!state->carrier_table[crrix]) ERR_RET(ENOMEM); } crr_table = state->carrier_table[crrix]; res = emtbt_realloc_op(crr_table, &ops[i], &old_blk); if (res != 0) ERR_RET(res); size = ops[i].u.block.new_size; prev_size = old_blk.size; if (!ops[i].u.block.prev_ptr) aix = (int) ops[i].u.block.type; else aix = (int) old_blk.type; no = ((!old_blk.pointer && ops[i].u.block.new_ptr) ? 1 : ((old_blk.pointer && !ops[i].u.block.new_size) ? -1 : 0)); if (state->info.allctr_usd_crr[aix]) update_realloc_op(state->info.allctr_usd_crr[aix], size, prev_size, no); if (state->info.allctr_prv_crr[crrix]) update_realloc_op(state->info.allctr_prv_crr[crrix], size, prev_size, no); update_realloc_op(&state->info.allctr[crrix], size, prev_size, no); break; } case EMTP_CARRIER_FREE:#if PRINT_OPERATIONS print_op(state, &ops[i]);#endif crrix = (int) ops[i].u.block.carrier_type; crr_table = state->carrier_table[crrix]; if (!crr_table) ERR_RET(EMTBT_FREE_NOBLK_ERROR); if (!ops[i].u.block.prev_ptr) continue; res = emtbt_free_op(crr_table, &ops[i], &old_blk); if (res != 0) ERR_RET(res); prev_size = old_blk.size; aix = (int) old_blk.type; if (state->info.allctr_usd_crr[aix]) update_free_op(state->info.allctr_usd_crr[aix], prev_size); if (state->info.allctr_prv_crr[crrix]) update_free_op(state->info.allctr_prv_crr[crrix], prev_size); update_free_op(&state->info.allctr[crrix], prev_size); break; case EMTP_STOP:#if PRINT_OPERATIONS print_op(state, &ops[i]);#endif state->info.stop_reason = EMTP_STOP; state->info.stop_time.secs = ops[i].time.secs; state->info.stop_time.usecs = ops[i].time.usecs; print_info(state, ops[i].time.secs, NULL); return EM_EXIT_RESULT; case EMTP_EXIT:#if PRINT_OPERATIONS print_op(state, &ops[i]);#endif state->info.stop_reason = EMTP_EXIT; state->info.exit_status = ops[i].u.exit_status; state->info.stop_time.secs = ops[i].time.secs; state->info.stop_time.usecs = ops[i].time.usecs; print_info(state, ops[i].time.secs, NULL); return EM_EXIT_RESULT; default:#if PRINT_OPERATIONS print_op(state, &ops[i]);#endif /* Ignore not understood operation */ break; } } return 0;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * * * *\* */static const char *error_string(int error){ const char *str; const char *error_str; static const char unknown_error[] = "Unknown error"; error_str = unknown_error; if (error > 0) { char *str = strerror(error); if (str) error_str = str; } else if (error < 0) { str = emtp_error_string(error); if (!str) { str = emtbt_error_string(error); if (!str) { switch (error) { case EM_TRUNCATED_TRACE_ERROR: error_str = "Truncated trace"; break; case EM_INTERNAL_ERROR: error_str = "emem internal error"; break; default: break; } } } if (str) error_str = str; } return error_str;}static voiderror(int res){ error_msg(res, NULL);}static voiderror_msg(int res, char *msg){ fprintf(stderr, "emem: %s%sFatal error: %s (%d)\n", msg ? msg : "", msg ? ": ": "", error_string(res), res); exit(1);}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * * * *\* */#if EMEM_d_SWITCHstatic size_twrite_output_filename(usgnd_int_8 *ptr, char *dirname, char *nodename, char *hostname, char *datetime, char *pid){ size_t sz = 0; usgnd_int_8 *p = ptr; usgnd_int_8 **pp = ptr ? &p : NULL; sz += write_str(pp, dirname); if (pp) *((*pp)++) = DIR_SEP_CHAR; sz++; sz += write_str(pp, nodename); sz += write_str(pp, "_"); sz += write_str(pp, hostname); sz += write_str(pp, "_"); sz += write_str(pp, datetime); sz += write_str(pp, "_"); sz += write_str(pp, pid); sz += write_str(pp, EM_OUTPUT_FILE_SUFFIX); if (pp) *((*pp)++) = '\0'; sz++; return sz;}static char *make_output_filename(em_state *state){ char *fname; size_t fname_size; char *nodename = state->trace_info.nodename; char *hostname = state->trace_info.hostname; char *pid = state->trace_info.pid; char dt_buf[20]; char *date_time = NULL; if (*nodename == '\0') nodename = "nonode"; if (*hostname == '\0') hostname = "nohost"; if (!state->trace_info.start_time.day) date_time = "notime"; else { sprintf(dt_buf, "%d-%2.2d-%2.2d_%2.2d.%2.2d.%2.2d", state->trace_info.start_time.year % 10000, state->trace_info.start_time.month % 100, state->trace_info.start_time.day % 100, state->trace_info.start_time.hour % 100, state->trace_info.start_time.minute % 100, state->trace_info.start_time.second % 100); date_time = &dt_buf[0]; } if (*pid == '\0') pid = "nopid"; fname = (*state->alloc)(write_output_filename(NULL, state->output.dir_name, nodename, hostname, date_time, pid)); if (!fname) return NULL; (void) write_output_filename(fname, state->output.dir_name, nodename, hostname, date_time, pid); return fname;}#endifstatic intcomplete_state(em_state *state){ int i, j, vpo, vpl; void * (*allocp)(size_t); void * (*reallocp)(void *, size_t); void (*freep)(void *); size_t size = sizeof(emtp_info); if (!emtp_get_info(&state->trace_info, &size, state->trace_state) || size < sizeof(emtp_info)) return EM_INTERNAL_ERROR;#if EMEM_d_SWITCH if (!state->output.stream) { char *fname = make_filename(state); mutex_lock(state->output.go.mutex); state->output.stream = fopen(fname, "w"); if (!state->output.stream) { disconnect_queue_reader(&state->input.queue); disconnect_queue_writer(&state->output.queue); } cond_signal(state->output.go.cond); mutex_unlock(state->output.go.mutex); (*state->free)((void *) fname); if (!state->output.stream) return EIO; }#endif allocp = state->alloc; reallocp = state->realloc; freep = state->free; state->carrier_table = (*allocp)((state->trace_info.max_allocator_ix+2) * sizeof(emtbt_table *)); if (!state->carrier_table) return ENOMEM; state->carrier_table++; for (i = -1; i <= state->trace_info.max_allocator_ix; i++) state->carrier_table[i] = NULL; state->block_table = mk_block_table(state); state->info.btype = (*allocp)((state->trace_info.max_block_type_ix+2) * sizeof(em_mem_info)); state->info.allctr = (*allocp)((state->trace_info.max_allocator_ix+2) * sizeof(em_mem_info)); if (!state->block_table || !state->info.btype || !state->info.allctr) return ENOMEM; state->info.btype++; state->info.allctr++; state->info.allctr_prv_crr = (*allocp)((state->trace_info.max_allocator_ix+2) * sizeof(em_mem_info *)); if (!state->info.allctr_prv_crr) return ENOMEM; state->info.allctr_prv_crr++; for (i = -1; i <= state->trace_info.max_allocator_ix; i++) state->info.allctr_prv_crr[i] = NULL; state->info.allctr_usd_crr = (*allocp)((state->trace_info.max_allocator_ix+2) * sizeof(em_mem_info *)); if (!state->info.allctr_usd_crr) return ENOMEM; state->info.allctr_usd_crr++; for (i = -1; i <= state->trace_info.max_allocator_ix; i++) state->info.allctr_usd_crr[i] = NULL; if (state->output.all_btypes) { if (state->output.btypes) (*state->free)((void *) state->output.btypes); state->output.no_btypes = state->trace_info.max_block_type_ix + 2; state->output.btypes = (*allocp)(state->output.no_btypes * sizeof(em_output_types)); if (!state->output.btypes) return ENOMEM; } if (state->output.all_allctrs) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -