📄 erl_memory.c
字号:
if (state->output.allctrs) (*state->free)((void *) state->output.allctrs); state->output.no_allctrs = state->trace_info.max_allocator_ix + 2; state->output.allctrs = (*allocp)(state->output.no_allctrs * sizeof(em_output_types)); if (!state->output.allctrs) return ENOMEM; } for (i = -1; i <= state->trace_info.max_block_type_ix; i++) { /* Save block type if we should print info about it */ emtp_block_type *btp = state->trace_info.block_type[i]; reset_mem_info(&state->info.btype[i]); if (state->output.no_btypes) { if (state->output.all_btypes) { state->output.btypes[i+1].name = btp->name; state->output.btypes[i+1].ix = btp->valid ? i : -1; } else { for (j = 0; j < state->output.no_btypes; j++) if (strcmp(btp->name, state->output.btypes[j].name) == 0) { state->output.btypes[j].ix = i; break; } } } } /* Remove invalid block types */ if (state->output.no_btypes) { for (i = 0, j = 0; i < state->output.no_btypes; i++) { if (state->output.btypes[i].ix >= 0) { state->output.btypes[j].name = state->output.btypes[i].name; state->output.btypes[j].ix = state->output.btypes[i].ix; j++; } } state->output.no_btypes = j; } for (i = -1; i <= state->trace_info.max_allocator_ix; i++) { /* Save allocator if we should print info about it */ emtp_allocator *ap = state->trace_info.allocator[i]; reset_mem_info(&state->info.allctr[i]); if (state->output.no_allctrs) { if (state->output.all_allctrs) { state->output.allctrs[i+1].name = ap->name; state->output.allctrs[i+1].ix = ap->valid ? i : -1; } else { for (j = 0; j < state->output.no_allctrs; j++) if (strcmp(ap->name, state->output.allctrs[j].name) == 0) { state->output.allctrs[j].ix = i; break; } } } /* Allocate em_mem_info if used carrier info is available */ if (ap->flags & EMTP_ALLOCATOR_FLAG_HAVE_USED_CARRIERS_INFO || (i == state->trace_info.segment_ix && state->trace_info.have_segment_carrier_info)) { state->info.allctr_usd_crr[i] = (em_mem_info *) (*allocp)(sizeof(em_mem_info)); if (!state->info.allctr_usd_crr[i]) return ENOMEM; reset_mem_info(state->info.allctr_usd_crr[i]); } /* Allocate em_mem_info for carrier providers */ if (ap->carrier.provider) { sgnd_int_32 j; for (j = 0; j < ap->carrier.no_providers; j++) { sgnd_int_32 crr_prvdr = ap->carrier.provider[j]; if (!state->info.allctr_prv_crr[crr_prvdr]) { state->info.allctr_prv_crr[crr_prvdr] = (em_mem_info *) (*allocp)(sizeof(em_mem_info)); if (!state->info.allctr_prv_crr[crr_prvdr]) return ENOMEM; reset_mem_info(state->info.allctr_prv_crr[crr_prvdr]); } } } } /* Remove invalid allocators */ if (state->output.no_allctrs) { for (i = 0, j = 0; i < state->output.no_allctrs; i++) { if (state->output.allctrs[i].ix >= 0) { state->output.allctrs[j].name = state->output.allctrs[i].name; state->output.allctrs[j].ix = state->output.allctrs[i].ix; j++; } } state->output.no_allctrs = j; } if (state->output.no_btypes) { state->output.btypes = (*reallocp)(state->output.btypes, sizeof(em_output_types) * state->output.no_btypes); if (!state->output.btypes) return ENOMEM; } if (state->output.no_allctrs) { state->output.allctrs = (*reallocp)(state->output.allctrs, sizeof(em_output_types) * state->output.no_allctrs); if (!state->output.allctrs) return ENOMEM; } vpo = 1; if (state->output.max_min_values) vpo += 2; if (state->output.block_counts) { vpo++; if (state->output.max_min_values) vpo += 2; } if (state->output.op_counts) vpo += 3; state->output.values_per_object = vpo; vpl = 0; vpl++; /* time */ if (state->output.total) { vpl += vpo; /* total allocated */ if (state->trace_info.have_segment_carrier_info) { vpl += vpo; /* total carriers */ vpl += vpo; /* cached carriers */ } } for (i = 0; i < state->output.no_allctrs; i++) { vpl += vpo; /* allocated */ if (state->trace_info.have_carrier_info) { if (state->info.allctr_prv_crr[state->output.allctrs[i].ix]) vpl += vpo; /* provided carriers */ vpl += vpo; /* used carriers */ } } vpl += state->output.no_btypes*vpo; /* allocated */ state->output.values_per_line = vpl; state->output.header_size = write_header(state, NULL, 1); state->output.header = (*state->alloc)(state->output.header_size + 1); if (!state->output.header) return ENOMEM; size = write_header(state, state->output.header, 1); ASSERT(state->output.header_size == size); return 0;}static intprocess_trace(em_state *state){ emtp_operation ops[EM_NO_OF_OPS]; int res; size_t ops_len; em_area area; while (1) { get_next_read_area(&area, state, &state->input.queue); if (!area.size) return EM_TRUNCATED_TRACE_ERROR; res = emtp_parse(state->trace_state, &area.ptr, &area.size, NULL, 0, NULL); if (res == EMTP_HEADER_PARSED) break; if (res == EMTP_NEED_MORE_TRACE) continue; if (res < 0) return res; else return EM_TRUNCATED_TRACE_ERROR; } res = complete_state(state); if (res != 0) return res; print_main_header(state); while (1) { if (!area.size) { get_next_read_area(&area, state, &state->input.queue); if (!area.size) return EM_TRUNCATED_TRACE_ERROR; } while (area.size) { ops_len = EM_NO_OF_OPS; res = emtp_parse(state->trace_state, &area.ptr, &area.size, ops, sizeof(emtp_operation), &ops_len); if (res < 0) return res; res = insert_operations(state, ops, ops_len); if (res != 0) return res; } }}static voidusage(char *sw, char *error){ int status = 0; FILE *filep = stdout;#ifdef __WIN32__#define SW_CHAR "/"#else#define SW_CHAR "-"#endif if (error) { ASSERT(sw); status = 1; filep = stderr; fprintf(filep, "emem: %s: %s\n", sw, error); } fprintf(filep, "Usage: emem "#if EMEM_A_SWITCH "[" SW_CHAR "A <ALLOCATOR>] "#endif "[" SW_CHAR "a <ALLOCATOR>] " "[" SW_CHAR "b <BLOCK TYPE>] "#if EMEM_C_SWITCH "[" SW_CHAR "C <CLASS>] "#endif#if EMEM_c_SWITCH "[" SW_CHAR "c <CLASS>] "#endif "{"#if EMEM_d_SWITCH SW_CHAR "d <DIRNAME>|"#endif SW_CHAR "f <FILENAME>} " "[" SW_CHAR "h] " "[" SW_CHAR "i <SECONDS>] " "[" SW_CHAR "m] " "[" SW_CHAR "n] " "[" SW_CHAR "o] " "{" SW_CHAR "p <PORT>} " "[" SW_CHAR "t] " "[" SW_CHAR "v] " "\n"); if (error) exit(1); else { char *help_str = "\n" " [] - switch is allowed any number of times\n" " {} - switch is allowed at most one time\n"#if EMEM_d_SWITCH " | - exclusive or\n"#endif "\n" " Switches:\n"#if EMEM_A_SWITCH " " SW_CHAR "a <A> - display info about Allocator <A> and all block types using <A>\n"#endif " " SW_CHAR "a <A> - display info about allocator <A>\n" " " SW_CHAR "b <B> - display info about block type <B>\n"#if EMEM_C_SWITCH " " SW_CHAR "C <C> - display info about class <C> and all block types in class <C>\n"#endif#if EMEM_c_SWITCH " " SW_CHAR "b <B> - display info about class <C>\n"#endif#if EMEM_d_SWITCH " " SW_CHAR "d <D> - run as daemon and set output directory to <D>\n"#endif " " SW_CHAR "f <F> - set output file to <F>\n" " " SW_CHAR "h - display help and exit\n" " " SW_CHAR "i <I> - set display interval to <I> seconds\n" " " SW_CHAR "m - display max/min values\n" " " SW_CHAR "n - display block/carrier/segment count values\n" " " SW_CHAR "o - display operation count values\n" " " SW_CHAR "p <P> - set listen port to <P>\n" " " SW_CHAR "t - display info about total values\n" " " SW_CHAR "v - verbose output\n"; fprintf(filep, help_str); exit(0); }#undef SW_CHAR}static voidparse_args(em_state *state, int argc, char *argv[]){ int port; int i; port = -1; i = 1; while (i < argc) { if ((argv[i][0] != '-' && argv[i][0] != '/') || argv[i][2] != '\0') { unknown_switch: usage(argv[i], "unknown switch"); } switch (argv[i][1]) {#if EMEM_A_SWITCH case 'A': /* TODO: Allocator + blocktypes using allocator */#endif case 'a': if (i + 1 >= argc) usage(argv[i], "missing allocator"); i++; if (state->output.all_allctrs || strcmp(argv[i],"all") == 0) { state->output.all_allctrs = 1; break; } if (!state->output.allctrs) state->output.allctrs = (*state->alloc)(sizeof(em_output_types)*argc/2); if (!state->output.allctrs) error(ENOMEM); state->output.allctrs[state->output.no_allctrs].name = argv[i]; state->output.allctrs[state->output.no_allctrs].ix = -1; state->output.no_allctrs++; break; case 'b': if (i + 1 >= argc) usage(argv[i], "missing block type"); i++; if (state->output.all_btypes || strcmp(argv[i],"all") == 0) { state->output.all_btypes = 1; break; } if (!state->output.btypes) state->output.btypes = (*state->alloc)(sizeof(em_output_types)*argc/2); if (!state->output.btypes) error(ENOMEM); state->output.btypes[state->output.no_btypes].name = argv[i]; state->output.btypes[state->output.no_btypes].ix = -1; state->output.no_btypes++; break;#if EMEM_C_SWITCH#endif#if EMEM_c_SWITCH case 'c': break;#endif#if EMEM_d_SWITCH case 'd': { char *p; char *fname; if (state->output.dir_name) usage(argv[i], "directory already set"); if (state->output.file_name) usage(argv[i], "file name already set"); if (i + 1 >= argc) usage(argv[i], "missing directory name"); state->output.dir_name = argv[i+1]; fname = (*state->alloc)(strlen(state->output.dir_name) + 1 + strlen(EM_ERL_CMD_FILE_NAME) + 1); state->output.go.mutex = (*state->alloc)(sizeof(ethr_mutex)); state->output.go.cond = (*state->alloc)(sizeof(ethr_cond)); if (!fname || !state->output.go.mutex || !state->output.go.cond) error(ENOMEM); p = fname; (void) write_str(&p, state->output.dir_name); *(p++) = DIR_SEP_CHAR; (void) write_str(&p, EM_ERL_CMD_FILE_NAME); *(p++) = '\0'; state->output.erl_cmd_file = fopen(fname, "w"); if (!state->output.erl_cmd_file) usage(argv[i], "cannot create files in directory"); (*state->free)((void *) fname); state->output.stream = NULL; mutex_init(state->output.go.mutex); cond_init(state->output.go.cond); i++; break; }#endif case 'f':#if EMEM_d_SWITCH if (state->output.dir_name) usage(argv[i], "directory already set");#endif if (state->output.file_name) usage(argv[i], "file name already set"); if (i + 1 >= argc) usage(argv[i], "missing file name"); state->output.file_name = argv[i+1]; state->output.stream = fopen(state->output.file_name, "w"); if (!state->output.stream) usage(argv[i], "cannot create file"); if (setvbuf(state->output.stream, NULL, _IONBF, 0) != 0) { fprintf(stderr, "emem: failed to set file %s in unbuffered mode\n", state->output.file_name); exit(1); } i++; break; case 'h': usage(NULL, NULL); break; case 'i': { int interval; if (argv[i][2]) goto unknown_switch; if (i + 1 >= argc) usage(argv[i], "missing interval"); interval = atoi(argv[i+1]); if (interval < 1) usage(argv[i], "bad interval"); i++; state->output.next_print_inc = interval; break; } case 'm': state->output.max_min_values = 1; break; case 'n': state->output.block_counts = 1; break; case 'o': state->output.op_counts = 1; break; case 'p': if (state->input.listen_port) usage(argv[i], "port already set"); if (i + 1 >= argc) usage(argv[i], "missing port number"); port = atoi(argv[i+1]); if (port <= 1024 || port >= (1 << 16)) usage(argv[i], "bad port number"); i++; state->input.listen_port = (usgnd_int_16) port; break; case 't': state->output.total = 1; break; case 'v': state->output.verbose = 1; break; default: goto unknown_switch; } i++; } if (!state->output.allctrs && !state->output.btypes) state->output.total = 1;}static intinit_connection(em_state *state){ int res; SOCKET lsock; SOCKET sock = INVALID_SOCKET; struct sockaddr_in my_addr; int oth_addr_len; struct sockaddr_in oth_addr;#ifdef __WIN32__ WORD wVersionRequested = MAKEWORD(2,0); WSADATA wsaData; if (WSAStartup(wVersionRequested, &wsaData) != 0) return EIO; if ((LOBYTE(wsaData.wVersion) != 2) || (HIBYTE(wsaData.wVersion) != 0)) return EIO;#endif do_socket: sock = socket(AF_INET, SOCK_STREAM, 0); if (IS_INVALID_SOCKET(sock)) { res = GET_SOCK_ERRNO(); if (res == EINTR) goto do_socket; goto error; } memset((void *) &my_addr, 0, sizeof(struct sockaddr_in)); my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = htonl(INADDR_ANY); my_addr.sin_port = htons(state->input.listen_port); do_bind: if (bind(sock, (struct sockaddr*) &my_addr, sizeof(my_addr)) < 0) { res = GET_SOCK_ERRNO(); if (res == EINTR) goto do_bind; goto error; } do_listen: if (listen(sock, 1) < 0) { res = GET_SOCK_ERRNO(); if (res == EINTR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -