Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
3021-erts-tools-remove-emem-completely.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 3021-erts-tools-remove-emem-completely.patch of Package erlang
From 69994d56e1c454134cbc83fafe673a605daffbe2 Mon Sep 17 00:00:00 2001 From: Maxim Fedorov <maximfca@gmail.com> Date: Fri, 7 Jan 2022 10:37:03 -0800 Subject: [PATCH 1/3] [erts, tools] remove "emem" completely Test suites for the tool were lost long ago. Removing "liberts.a" library as well, for it is now empty and AR on MacOS/Windows does not like empty libraries. --- .gitignore | 3 - HOWTO/INSTALL-IOS.md | 3 +- erts/configure | 3 +- erts/configure.ac | 1 - erts/doc/src/erts_alloc.xml | 4 - erts/emulator/Makefile.in | 3 +- erts/emulator/beam/erl_alloc.c | 42 - erts/emulator/beam/erl_alloc_util.c | 11 - erts/emulator/beam/erl_bif_info.c | 4 - erts/emulator/beam/erl_init.c | 4 - erts/emulator/beam/erl_lock_check.c | 2 - erts/emulator/beam/erl_mtrace.c | 1268 ------- erts/emulator/beam/erl_mtrace.h | 52 - erts/emulator/beam/erl_sock.h | 45 - erts/emulator/drivers/common/inet_drv.c | 73 - erts/emulator/sys/common/erl_mseg.c | 18 - .../emulator/sys/common/erl_mtrace_sys_wrap.c | 246 -- erts/etc/common/erlexec.c | 1 - erts/include/erl_memory_trace_parser.h | 157 - .../internal/erl_memory_trace_protocol.h | 246 -- erts/lib_src/Makefile.in | 54 +- erts/lib_src/common/erl_memory_trace_parser.c | 1962 ----------- lib/reltool/doc/src/reltool_examples.xml | 11 +- lib/tools/Makefile | 2 +- lib/tools/bin/.gitignore | 0 lib/tools/c_src/Makefile | 6 - lib/tools/c_src/Makefile.in | 221 -- lib/tools/c_src/depend.mk | 17 - lib/tools/c_src/erl_memory.c | 2947 ----------------- .../c_src/erl_memory_trace_block_table.c | 762 ----- .../c_src/erl_memory_trace_block_table.h | 74 - lib/tools/obj/.gitignore | 0 lib/tools/test/Makefile | 1 - lib/tools/test/emem_SUITE.erl | 654 ---- lib/tools/test/tools.spec.win | 1 - 35 files changed, 14 insertions(+), 8884 deletions(-) delete mode 100644 erts/emulator/beam/erl_mtrace.c delete mode 100644 erts/emulator/beam/erl_mtrace.h delete mode 100644 erts/emulator/beam/erl_sock.h delete mode 100644 erts/emulator/sys/common/erl_mtrace_sys_wrap.c delete mode 100644 erts/include/erl_memory_trace_parser.h delete mode 100644 erts/include/internal/erl_memory_trace_protocol.h delete mode 100644 erts/lib_src/common/erl_memory_trace_parser.c delete mode 100644 lib/tools/bin/.gitignore delete mode 100644 lib/tools/c_src/Makefile delete mode 100644 lib/tools/c_src/Makefile.in delete mode 100644 lib/tools/c_src/depend.mk delete mode 100644 lib/tools/c_src/erl_memory.c delete mode 100644 lib/tools/c_src/erl_memory_trace_block_table.c delete mode 100644 lib/tools/c_src/erl_memory_trace_block_table.h delete mode 100644 lib/tools/obj/.gitignore delete mode 100644 lib/tools/test/emem_SUITE.erl diff --git a/HOWTO/INSTALL-IOS.md b/HOWTO/INSTALL-IOS.md index cdb0bab137..3ec368ecc7 100644 --- a/HOWTO/INSTALL-IOS.md +++ b/HOWTO/INSTALL-IOS.md @@ -41,7 +41,6 @@ To build with OpenSSL statically linked, run `configure` like this (note that 1. To use the resulting `libbeam.a` it needs to be packaged into a Xcode `.xcframework` package together with all other required `.a` files. These include: * `libbeam.a` -* `liberts.a` * `libz.a` * `libcrypto.a` @@ -49,7 +48,7 @@ Basically all .a files that have been generated by the build. One way of creating a combined archive out of all of these is to use `libtool`: - $ libtool -static -o liberlang.a /Path/to/libbeam.a /Path/to/liberts.a /Path/to/....a + $ libtool -static -o liberlang.a /Path/to/libbeam.a /Path/to/....a This list should also include static nifs you want to include: diff --git a/erts/configure b/erts/configure index 7d0aa2d1eb..d3e168c6f5 100755 --- a/erts/configure +++ b/erts/configure @@ -25296,7 +25296,7 @@ ac_config_files="$ac_config_files emulator/$host/Makefile:emulator/Makefile.in e ac_config_files="$ac_config_files ../make/make_emakefile:../make/make_emakefile.in" -ac_config_files="$ac_config_files ../lib/os_mon/c_src/$host/Makefile:../lib/os_mon/c_src/Makefile.in ../lib/runtime_tools/c_src/$host/Makefile:../lib/runtime_tools/c_src/Makefile.in ../lib/tools/c_src/$host/Makefile:../lib/tools/c_src/Makefile.in" +ac_config_files="$ac_config_files ../lib/os_mon/c_src/$host/Makefile:../lib/os_mon/c_src/Makefile.in ../lib/runtime_tools/c_src/$host/Makefile:../lib/runtime_tools/c_src/Makefile.in" ac_config_files="$ac_config_files ../make/install_dir_data.sh:../make/install_dir_data.sh.in" @@ -26002,7 +26002,6 @@ do "../make/make_emakefile") CONFIG_FILES="$CONFIG_FILES ../make/make_emakefile:../make/make_emakefile.in" ;; "../lib/os_mon/c_src/$host/Makefile") CONFIG_FILES="$CONFIG_FILES ../lib/os_mon/c_src/$host/Makefile:../lib/os_mon/c_src/Makefile.in" ;; "../lib/runtime_tools/c_src/$host/Makefile") CONFIG_FILES="$CONFIG_FILES ../lib/runtime_tools/c_src/$host/Makefile:../lib/runtime_tools/c_src/Makefile.in" ;; - "../lib/tools/c_src/$host/Makefile") CONFIG_FILES="$CONFIG_FILES ../lib/tools/c_src/$host/Makefile:../lib/tools/c_src/Makefile.in" ;; "../make/install_dir_data.sh") CONFIG_FILES="$CONFIG_FILES ../make/install_dir_data.sh:../make/install_dir_data.sh.in" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; diff --git a/erts/configure.in b/erts/configure.in index e3b368e2b8..368058d2a2 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -3608,7 +3608,6 @@ dnl AC_CONFIG_FILES([ ../lib/os_mon/c_src/$host/Makefile:../lib/os_mon/c_src/Makefile.in ../lib/runtime_tools/c_src/$host/Makefile:../lib/runtime_tools/c_src/Makefile.in - ../lib/tools/c_src/$host/Makefile:../lib/tools/c_src/Makefile.in ]) AC_CONFIG_FILES([../make/install_dir_data.sh:../make/install_dir_data.sh.in], [chmod +x ../make/install_dir_data.sh]) diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml index 9dca046307..579e8f91e9 100644 --- a/erts/doc/src/erts_alloc.xml +++ b/erts/doc/src/erts_alloc.xml @@ -781,10 +781,6 @@ <seecref marker="#M_atags"><c>+M<S>atags</c></seecref> for a more complete description.</p> </item> - <tag><marker id="Mit"/><c>+Mit X</c></tag> - <item> - <p>Reserved for future use. Do <em>not</em> use this flag.</p> - </item> </taglist> <note> diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index 72018c0b81..1f4651d07a 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -1100,7 +1100,7 @@ endif RUN_OBJS += \ - $(OBJDIR)/erl_alloc.o $(OBJDIR)/erl_mtrace.o \ + $(OBJDIR)/erl_alloc.o \ $(OBJDIR)/erl_alloc_util.o $(OBJDIR)/erl_goodfit_alloc.o \ $(OBJDIR)/erl_bestfit_alloc.o $(OBJDIR)/erl_afit_alloc.o \ $(OBJDIR)/erl_init.o \ @@ -1226,7 +1226,6 @@ OS_OBJS += $(OBJDIR)/erl_poll.o \ $(OBJDIR)/erl_mmap.o \ $(OBJDIR)/erl_osenv.o \ $(OBJDIR)/erl_$(ERLANG_OSTYPE)_sys_ddll.o \ - $(OBJDIR)/erl_mtrace_sys_wrap.o \ $(OBJDIR)/erl_sys_common_misc.o \ $(OBJDIR)/erl_os_monotonic_time_extender.o diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index 0f77e8b60e..08f825312a 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -38,7 +38,6 @@ #include "erl_db.h" #include "erl_binary.h" #include "erl_bits.h" -#include "erl_mtrace.h" #include "erl_mseg.h" #include "erl_monitor_link.h" #include "erl_hl_timer.h" @@ -191,10 +190,6 @@ typedef struct { int top_pad; int dirty_alloc_insts; AlcUInit_t alloc_util; - struct { - char *mtrace; - char *nodename; - } instr; struct au_init sl_alloc; struct au_init std_alloc; struct au_init ll_alloc; @@ -772,7 +767,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) if (!init.temp_alloc.thr_spec) refuse_af_strategy(&init.temp_alloc); - erts_mtrace_pre_init(); #if HAVE_ERTS_MSEG init.mseg.nos = erts_no_schedulers; init.mseg.ndai = init.dirty_alloc_insts; @@ -828,8 +822,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) sys_alloc_opt(SYS_ALLOC_OPT_TRIM_THRESHOLD, init.trim_threshold); sys_alloc_opt(SYS_ALLOC_OPT_TOP_PAD, init.top_pad); - erts_mtrace_init(init.instr.mtrace, init.instr.nodename); - start_au_allocator(ERTS_ALC_A_TEMPORARY, &init.temp_alloc, &temp_alloc_state); @@ -871,8 +863,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) &init.test_alloc, &test_alloc_state); - erts_mtrace_install_wrapper_functions(); - init_aireq_alloc(); #ifdef DEBUG @@ -1740,15 +1730,6 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init) bad_param(param, param+1); } break; - case 'i': - switch (argv[i][3]) { - case 't': - init->instr.mtrace = get_value(argv[i]+4, argv, &i); - break; - default: - bad_param(param, param+2); - } - break; case 'l': if (has_prefix("pm", param+2)) { arg = get_value(argv[i]+5, argv, &i); @@ -1818,18 +1799,6 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init) case '-': if (argv[i][2] == '\0') { /* End of system flags reached */ - if (init->instr.mtrace) { - while (i < *argc) { - if(sys_strcmp(argv[i], "-sname") == 0 - || sys_strcmp(argv[i], "-name") == 0) { - if (i + 1 <*argc) { - init->instr.nodename = argv[i+1]; - break; - } - } - i++; - } - } goto args_parsed; } break; @@ -2871,9 +2840,6 @@ erts_allocator_info(fmtfn_t to, void *arg) erts_print(to, arg, "=allocator:instr\n"); - erts_print(to, arg, "option t: %s\n", - erts_mtrace_enabled ? "true" : "false"); - } Eterm @@ -2975,14 +2941,6 @@ erts_allocator_options(void *proc) terms[length++] = erts_mmap_info_options(&erts_dflt_mmapper, NULL, NULL, NULL, hpp, szp); #endif - { - Eterm o[1], v[1]; - o[0] = ERTS_MAKE_AM("t"); - v[0] = erts_mtrace_enabled ? am_true : am_false; - - atoms[length] = ERTS_MAKE_AM("instr"); - terms[length++] = erts_bld_2tup_list(hpp, szp, 1, o, v); - } atoms[length] = ERTS_MAKE_AM("lock_physical_memory"); terms[length++] = (lock_all_physical_memory ? am_all : am_no); diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c index 4315bb67ab..9c32308a7c 100644 --- a/erts/emulator/beam/erl_alloc_util.c +++ b/erts/emulator/beam/erl_alloc_util.c @@ -43,7 +43,6 @@ #include "global.h" #include "big.h" #include "erl_mmap.h" -#include "erl_mtrace.h" #define GET_ERL_ALLOC_UTIL_IMPL #include "erl_alloc_util.h" #include "erl_mseg.h" @@ -1091,8 +1090,6 @@ erts_alcu_sys_alloc(Allctr_t *allctr, Uint* size_p, int superalign) #endif res = erts_sys_alloc(0, NULL, size); INC_CC(allctr->calls.sys_alloc); - if (erts_mtrace_enabled) - erts_mtrace_crr_alloc(res, allctr->alloc_no, ERTS_ALC_A_SYSTEM, size); return res; } @@ -1109,12 +1106,6 @@ erts_alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint *size_p, Uint old_size, #endif res = erts_sys_realloc(0, NULL, ptr, size); INC_CC(allctr->calls.sys_realloc); - if (erts_mtrace_enabled) - erts_mtrace_crr_realloc(res, - allctr->alloc_no, - ERTS_ALC_A_SYSTEM, - ptr, - size); return res; } @@ -1128,8 +1119,6 @@ erts_alcu_sys_dealloc(Allctr_t *allctr, void *ptr, Uint size, int superalign) #endif erts_sys_free(0, NULL, ptr); INC_CC(allctr->calls.sys_free); - if (erts_mtrace_enabled) - erts_mtrace_crr_free(allctr->alloc_no, ERTS_ALC_A_SYSTEM, ptr); } #ifdef ARCH_32 diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index d0de83ce8e..01f8e76916 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -38,7 +38,6 @@ #include "erl_message.h" #include "erl_binary.h" #include "erl_db.h" -#include "erl_mtrace.h" #include "dist.h" #include "erl_gc.h" #include "erl_cpu_topology.h" @@ -3060,9 +3059,6 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1) if (sz) hp = HAlloc(BIF_P, sz); BIF_RET(c_compiler_used(&hp, NULL)); - } else if (ERTS_IS_ATOM_STR("stop_memory_trace", BIF_ARG_1)) { - erts_mtrace_stop(); - BIF_RET(am_true); } else if (ERTS_IS_ATOM_STR("context_reductions", BIF_ARG_1)) { BIF_RET(make_small(CONTEXT_REDS)); } else if (ERTS_IS_ATOM_STR("kernel_poll", BIF_ARG_1)) { diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 09d6a895f2..8a37e7634e 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -37,7 +37,6 @@ #include "erl_mseg.h" #include "erl_threads.h" #include "erl_hl_timer.h" -#include "erl_mtrace.h" #include "erl_printf_term.h" #include "erl_misc_utils.h" #include "packet_parser.h" @@ -2591,9 +2590,6 @@ erts_exit_vv(int n, int flush_async, const char *fmt, va_list args1, va_list arg { system_cleanup(flush_async); - if (erts_mtrace_enabled) - erts_mtrace_exit((Uint32) n); - if (fmt != NULL && *fmt != '\0') erl_error(fmt, args2); /* Print error message. */ diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c index 347719075c..91385f8276 100644 --- a/erts/emulator/beam/erl_lock_check.c +++ b/erts/emulator/beam/erl_lock_check.c @@ -144,7 +144,6 @@ static erts_lc_lock_order_t erts_lock_order[] = { { "port_table", NULL }, { "magic_ref_table", "address" }, { "pid_ref_table", "address" }, - { "mtrace_op", NULL }, { "instr_x", NULL }, { "instr", NULL }, { "dyn_lock_check", NULL }, @@ -162,7 +161,6 @@ static erts_lc_lock_order_t erts_lock_order[] = { { "save_ops_lock", NULL }, #endif #endif - { "mtrace_buf", NULL }, { "os_monotonic_time", NULL }, { "erts_alloc_hard_debug", NULL }, { "hard_dbg_mseg", NULL }, diff --git a/erts/emulator/beam/erl_mtrace.c b/erts/emulator/beam/erl_mtrace.c deleted file mode 100644 index 6e0a0dcff7..0000000000 --- a/erts/emulator/beam/erl_mtrace.c +++ /dev/null @@ -1,1268 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2003-2018. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -/* - * Description: Memory allocation trace. The trace is sent over a - * tcp/ip connection. - * - * The trace format is not intended to be documented. - * Instead a library for parsing the trace will be - * distributed. This in order to more easily be able - * to make changes in the trace format. The library - * for parsing the trace is currently not included in - * the OTP distribution, but will be in the future. - * - * Author: Rickard Green - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "sys.h" -#include "global.h" -#include "erl_sock.h" -#include "erl_threads.h" -#include "erl_memory_trace_protocol.h" -#include "erl_mtrace.h" - -#if defined(MAXHOSTNAMELEN) && MAXHOSTNAMELEN > 255 -# undef MAXHOSTNAMELEN -#endif - -#ifndef MAXHOSTNAMELEN -# define MAXHOSTNAMELEN 255 -#endif - -#define TRACE_PRINTOUTS 0 -#ifdef TRACE_PRINTOUTS -#define MSB2BITS(X) ((((unsigned)(X))+1)*8) -#endif - -static erts_mtx_t mtrace_op_mutex; -static erts_mtx_t mtrace_buf_mutex; - -#define TRACE_BUF_SZ (16*1024) - - -#define UI8_MSB_EHF_SZ ERTS_MT_UI8_MSB_EHDR_FLD_SZ -#define UI16_MSB_EHF_SZ ERTS_MT_UI16_MSB_EHDR_FLD_SZ -#define UI32_MSB_EHF_SZ ERTS_MT_UI32_MSB_EHDR_FLD_SZ -#define UI64_MSB_EHF_SZ ERTS_MT_UI64_MSB_EHDR_FLD_SZ -#define UI_MSB_EHF_SZ ERTS_MT_UI64_MSB_EHDR_FLD_SZ -#define TAG_EHF_SZ ERTS_MT_TAG_EHDR_FLD_SZ - -#define UI8_MSB_EHF_MSK ERTS_MT_UI8_MSB_EHDR_FLD_MSK -#define UI16_MSB_EHF_MSK ERTS_MT_UI16_MSB_EHDR_FLD_MSK -#define UI32_MSB_EHF_MSK ERTS_MT_UI32_MSB_EHDR_FLD_MSK -#define UI_MSB_EHF_MSK ERTS_MT_UI64_MSB_EHDR_FLD_MSK -#define UI64_MSB_EHF_MSK ERTS_MT_UI64_MSB_EHDR_FLD_MSK -#define TAG_EHF_MSK ERTS_MT_TAG_EHDR_FLD_MSK - -#define UI8_SZ (1) -#define UI16_SZ (2) -#define UI32_SZ (4) -#define UI64_SZ (8) -#ifdef ARCH_64 /* XXX:PaN Halfword? (whole file...) */ -# define UI_SZ UI64_SZ -#else -# define UI_SZ UI32_SZ -#endif - -#define WRITE_UI8(P, V) (*(P) = (byte) ((V) & 0xff)) - -#define WRITE_UI16(P, V) \ - ((P)[0] = (byte) (((V) >> 8) & 0xff), \ - (P)[1] = (byte) ( (V) & 0xff)) - -#define WRITE_UI32(P, V) \ - ((P)[0] = (byte) (((V) >> 24) & 0xff), \ - (P)[1] = (byte) (((V) >> 16) & 0xff), \ - (P)[2] = (byte) (((V) >> 8) & 0xff), \ - (P)[3] = (byte) ( (V) & 0xff)) - -#define WRITE_UI64(P, V) \ - ((P)[0] = (byte) (((V) >> 56) & 0xff), \ - (P)[1] = (byte) (((V) >> 48) & 0xff), \ - (P)[2] = (byte) (((V) >> 40) & 0xff), \ - (P)[3] = (byte) (((V) >> 32) & 0xff), \ - (P)[4] = (byte) (((V) >> 24) & 0xff), \ - (P)[5] = (byte) (((V) >> 16) & 0xff), \ - (P)[6] = (byte) (((V) >> 8) & 0xff), \ - (P)[7] = (byte) ( (V) & 0xff)) - -#define PUT_UI8(P, V) (WRITE_UI8((P), (V)), (P) += UI8_SZ) -#define PUT_UI16(P, V) (WRITE_UI16((P), (V)), (P) += UI16_SZ) -#define PUT_UI32(P, V) (WRITE_UI32((P), (V)), (P) += UI32_SZ) -#define PUT_UI64(P, V) (WRITE_UI64((P), (V)), (P) += UI64_SZ) - -#define PUT_VSZ_UI16(P, M, V) \ -do { \ - Uint16 v__ = (Uint16) (V); \ - if (v__ >= (((Uint16) 1) << 8)) (M) = 1; else (M) = 0; \ - switch ((M)) { \ - case 1: *((P)++) = (byte) ((v__ >> 8) & 0xff); \ - case 0: *((P)++) = (byte) ( v__ & 0xff); \ - } \ -} while (0) - -#define PUT_VSZ_UI32(P, M, V) \ -do { \ - Uint32 v__ = (Uint32) (V); \ - if (v__ >= (((Uint32) 1) << 16)) { \ - if (v__ >= (((Uint32) 1) << 24)) (M) = 3; else (M) = 2; \ - } else { \ - if (v__ >= (((Uint32) 1) << 8)) (M) = 1; else (M) = 0; \ - } \ - switch ((M)) { \ - case 3: *((P)++) = (byte) ((v__ >> 24) & 0xff); \ - case 2: *((P)++) = (byte) ((v__ >> 16) & 0xff); \ - case 1: *((P)++) = (byte) ((v__ >> 8) & 0xff); \ - case 0: *((P)++) = (byte) ( v__ & 0xff); \ - } \ -} while (0) - -#ifdef ARCH_64 - -#define PUT_VSZ_UI64(P, M, V) \ -do { \ - Uint64 v__ = (Uint64) (V); \ - if (v__ >= (((Uint64) 1) << 32)) { \ - if (v__ >= (((Uint64) 1) << 48)) { \ - if (v__ >= (((Uint64) 1) << 56)) (M) = 7; else (M) = 6; \ - } else { \ - if (v__ >= (((Uint64) 1) << 40)) (M) = 5; else (M) = 4; \ - } \ - } else { \ - if (v__ >= (((Uint64) 1) << 16)) { \ - if (v__ >= (((Uint64) 1) << 24)) (M) = 3; else (M) = 2; \ - } else { \ - if (v__ >= (((Uint64) 1) << 8)) (M) = 1; else (M) = 0; \ - } \ - } \ - switch ((M)) { \ - case 7: *((P)++) = (byte) ((v__ >> 56) & 0xff); \ - case 6: *((P)++) = (byte) ((v__ >> 48) & 0xff); \ - case 5: *((P)++) = (byte) ((v__ >> 40) & 0xff); \ - case 4: *((P)++) = (byte) ((v__ >> 32) & 0xff); \ - case 3: *((P)++) = (byte) ((v__ >> 24) & 0xff); \ - case 2: *((P)++) = (byte) ((v__ >> 16) & 0xff); \ - case 1: *((P)++) = (byte) ((v__ >> 8) & 0xff); \ - case 0: *((P)++) = (byte) ( v__ & 0xff); \ - } \ -} while (0) - -#define PUT_VSZ_UI PUT_VSZ_UI64 -#else /* #ifdef ARCH_64 */ -#define PUT_VSZ_UI PUT_VSZ_UI32 -#endif /* #ifdef ARCH_64 */ - -#define MAKE_TBUF_SZ(SZ) \ - (TRACE_BUF_SZ < (SZ) \ - ? (disable_trace(1, "Internal buffer overflow", 0), 0) \ - : (endp - tracep < (SZ) ? send_trace_buffer() : 1)) - - -static void disable_trace(int error, char *reason, int eno); -static int send_trace_buffer(void); - -#ifdef DEBUG -void -check_alloc_entry(byte *sp, byte *ep, - byte tag, - Uint16 ct_no, int ct_no_n, - Uint16 type, int type_n, - UWord res, int res_n, - Uint size, int size_n, - Uint32 ti,int ti_n); -void -check_realloc_entry(byte *sp, byte *ep, - byte tag, - Uint16 ct_no, int ct_no_n, - Uint16 type, int type_n, - UWord res, int res_n, - UWord ptr, int ptr_n, - Uint size, int size_n, - Uint32 ti,int ti_n); -void -check_free_entry(byte *sp, byte *ep, - byte tag, - Uint16 ct_no, int ct_no_n, - Uint16 t_no, int t_no_n, - UWord ptr, int ptr_n, - Uint32 ti,int ti_n); -void -check_time_inc_entry(byte *sp, byte *ep, - Uint32 secs, int secs_n, - Uint32 usecs, int usecs_n); -#endif - - - -int erts_mtrace_enabled; -static erts_sock_t socket_desc; -static byte trace_buffer[TRACE_BUF_SZ]; -static byte *tracep; -static byte *endp; -static SysTimeval last_tv; - -static ErtsAllocatorWrapper_t mtrace_wrapper; - -#if ERTS_MTRACE_SEGMENT_ID >= ERTS_ALC_A_MIN || ERTS_MTRACE_SEGMENT_ID < 0 -#error ERTS_MTRACE_SEGMENT_ID >= ERTS_ALC_A_MIN || ERTS_MTRACE_SEGMENT_ID < 0 -#endif - -char* erl_errno_id(int error); - -#define INVALID_TIME_INC (0xffffffff) - -static ERTS_INLINE Uint32 -get_time_inc(void) -{ - Sint32 secs; - Sint32 usecs; - Uint32 res; - SysTimeval tv; - sys_gettimeofday(&tv); - - secs = tv.tv_sec - last_tv.tv_sec; - if (tv.tv_usec >= last_tv.tv_usec) - usecs = tv.tv_usec - last_tv.tv_usec; - else { - secs--; - usecs = 1000000 + tv.tv_usec - last_tv.tv_usec; - } - - ASSERT(0 <= usecs); - ASSERT(usecs < 1000000); - - if (secs < 0) { - /* Clock stepped backwards; we pretend that no time has past. */ - res = 0; - } - else if (secs < ERTS_MT_TIME_INC_SECS_MASK) { - res = ((((Uint32) secs) << ERTS_MT_TIME_INC_SECS_SHIFT) - | (((Uint32) usecs) << ERTS_MT_TIME_INC_USECS_SHIFT)); - } - else { - /* Increment too large to fit in a 32-bit integer; - put a time inc entry in trace ... */ - if (MAKE_TBUF_SZ(UI8_SZ + UI16_SZ + 2*UI32_SZ)) { - byte *hdrp; - Uint16 hdr; - int secs_n, usecs_n; - - *(tracep++) = ERTS_MT_TIME_INC_BDY_TAG; - - hdrp = tracep; - tracep += 2; - - PUT_VSZ_UI32(tracep, secs_n, secs); - PUT_VSZ_UI32(tracep, usecs_n, usecs); - - hdr = usecs_n; - - hdr <<= UI32_MSB_EHF_SZ; - hdr |= secs_n; - - WRITE_UI16(hdrp, hdr); -#ifdef DEBUG - check_time_inc_entry(hdrp-1, tracep, - (Uint32) secs, secs_n, - (Uint32) usecs, usecs_n); -#endif - res = 0; - } - else { - res = INVALID_TIME_INC; - } - } - - last_tv = tv; - return res; -} - - -static void -disable_trace(int error, char *reason, int eno) -{ - char *mt_dis = "Memory trace disabled"; - char *eno_str; - - erts_mtrace_enabled = 0; - erts_sock_close(socket_desc); - socket_desc = ERTS_SOCK_INVALID_SOCKET; - - if (eno == 0) - erts_fprintf(stderr, "%s: %s\n", mt_dis, reason); - else { - eno_str = erl_errno_id(eno); - if (sys_strcmp(eno_str, "unknown") == 0) - erts_fprintf(stderr, "%s: %s: %d\n", mt_dis, reason, eno); - else - erts_fprintf(stderr, "%s: %s: %s\n", mt_dis, reason, eno_str); - } -} - -static int -send_trace_buffer(void) -{ - ssize_t ssz; - size_t sz; - - sz = tracep - trace_buffer; - tracep = trace_buffer; - - do { - ssz = erts_sock_send(socket_desc, (void *) tracep, sz); - if (ssz < 0) { - int socket_errno = erts_sock_errno(); - -#ifdef EINTR - if (socket_errno == EINTR) - continue; -#endif - disable_trace(0, "Connection lost", socket_errno); - return 0; - } - if (ssz > sz) { - disable_trace(1, "Unexpected error", 0); - return 0; - } - tracep += ssz; - sz -= ssz; - } while (sz); - - tracep = trace_buffer; - return 1; -} - -#if ERTS_ALC_N_MAX >= (1 << 16) -#error "Excessively large type numbers" -#endif - - -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 = sys_strlen(nodename); - h_len = sys_strlen(hostname); - p_len = sys_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); - sys_memcpy((void *) tracep, (void *) nodename, n_len); - tracep += n_len; - - PUT_UI8(tracep, (byte) h_len); - sys_memcpy((void *) tracep, (void *) hostname, h_len); - tracep += h_len; - - PUT_UI8(tracep, (byte) p_len); - sys_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 = sys_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); - sys_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 = sys_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); - sys_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; -} - -static void mtrace_pre_lock(void); -static void mtrace_pre_unlock(void); -static void *mtrace_alloc(ErtsAlcType_t, void *, Uint); -static void *mtrace_realloc(ErtsAlcType_t, void *, void *, Uint); -static void mtrace_free(ErtsAlcType_t, void *, void *); - -static ErtsAllocatorFunctions_t real_allctrs[ERTS_ALC_A_MAX+1]; - -void erts_mtrace_pre_init(void) -{ -} - -void erts_mtrace_init(char *receiver, char *nodename) -{ - char hostname[MAXHOSTNAMELEN + 1]; - char pid[21]; /* enough for a 64 bit number */ - - socket_desc = ERTS_SOCK_INVALID_SOCKET; - erts_mtrace_enabled = receiver != NULL; - - if (erts_mtrace_enabled) { - unsigned a, b, c, d, p; - byte ip_addr[4]; - Uint16 port; - - erts_mtx_init(&mtrace_buf_mutex, "mtrace_buf", NIL, - ERTS_LOCK_FLAGS_PROPERTY_STATIC | ERTS_LOCK_FLAGS_CATEGORY_DEBUG); - erts_mtx_init(&mtrace_op_mutex, "mtrace_op", NIL, - ERTS_LOCK_FLAGS_PROPERTY_STATIC | ERTS_LOCK_FLAGS_CATEGORY_DEBUG); - - socket_desc = erts_sock_open(); - if (socket_desc == ERTS_SOCK_INVALID_SOCKET) { - disable_trace(1, "Failed to open socket", erts_sock_errno()); - return; - } - - if (5 != sscanf(receiver, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &p) - || a >= (1 << 8) || b >= (1 << 8)|| c >= (1 << 8) || d >= (1 << 8) - || p >= (1 << 16)) { - disable_trace(1, "Invalid receiver address", 0); - return; - } - - ip_addr[0] = (byte) a; - ip_addr[1] = (byte) b; - ip_addr[2] = (byte) c; - ip_addr[3] = (byte) d; - - port = (Uint16) p; - - if (!erts_sock_connect(socket_desc, ip_addr, 4, port)) { - disable_trace(1, "Failed to connect to receiver", - erts_sock_errno()); - return; - } - tracep = trace_buffer; - endp = trace_buffer + TRACE_BUF_SZ; - /* gethostname requires that the len is max(hostname) + 1 */ - if (erts_sock_gethostname(hostname, MAXHOSTNAMELEN + 1) != 0) - hostname[0] = '\0'; - hostname[MAXHOSTNAMELEN] = '\0'; - sys_get_pid(pid, sizeof(pid)); - write_trace_header(nodename ? nodename : "", pid, hostname); - erts_mtrace_update_heap_size(); - } -} - -void -erts_mtrace_install_wrapper_functions(void) -{ - if (erts_mtrace_enabled) { - int i; - /* Install trace functions */ - ERTS_CT_ASSERT(sizeof(erts_allctrs) == sizeof(real_allctrs)); - - sys_memcpy((void *) real_allctrs, - (void *) erts_allctrs, - sizeof(erts_allctrs)); - - for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) { - erts_allctrs[i].alloc = mtrace_alloc; - erts_allctrs[i].realloc = mtrace_realloc; - erts_allctrs[i].free = mtrace_free; - erts_allctrs[i].extra = (void *) &real_allctrs[i]; - } - mtrace_wrapper.lock = mtrace_pre_lock; - mtrace_wrapper.unlock = mtrace_pre_unlock; - erts_allctr_wrapper_prelock_init(&mtrace_wrapper); - } -} - -void -erts_mtrace_stop(void) -{ - ASSERT(!erts_is_allctr_wrapper_prelocked()); - erts_mtx_lock(&mtrace_op_mutex); - erts_mtx_lock(&mtrace_buf_mutex); - if (erts_mtrace_enabled) { - Uint32 ti = get_time_inc(); - - if (ti != INVALID_TIME_INC - && MAKE_TBUF_SZ(UI8_SZ + UI16_SZ + UI32_SZ)) { - byte *hdrp; - Uint16 hdr; - int ti_n; - - *(tracep++) = ERTS_MT_STOP_BDY_TAG; - - hdrp = tracep; - tracep += 2; - - PUT_VSZ_UI32(tracep, ti_n, ti); - - hdr = ti_n; - - WRITE_UI16(hdrp, hdr); - - if(send_trace_buffer()) { - erts_mtrace_enabled = 0; - erts_sock_close(socket_desc); - socket_desc = ERTS_SOCK_INVALID_SOCKET; - } - } - } - erts_mtx_unlock(&mtrace_buf_mutex); - erts_mtx_unlock(&mtrace_op_mutex); -} - -void -erts_mtrace_exit(Uint32 exit_value) -{ - ASSERT(!erts_is_allctr_wrapper_prelocked()); - erts_mtx_lock(&mtrace_op_mutex); - erts_mtx_lock(&mtrace_buf_mutex); - if (erts_mtrace_enabled) { - Uint32 ti = get_time_inc(); - - if (ti != INVALID_TIME_INC - && MAKE_TBUF_SZ(UI8_SZ + UI16_SZ + 2*UI32_SZ)) { - byte *hdrp; - Uint16 hdr; - int ti_n, exit_value_n; - - *(tracep++) = ERTS_MT_EXIT_BDY_TAG; - - hdrp = tracep; - tracep += 2; - - PUT_VSZ_UI32(tracep, exit_value_n, exit_value); - PUT_VSZ_UI32(tracep, ti_n, ti); - - hdr = ti_n; - - hdr <<= UI32_MSB_EHF_SZ; - hdr |= exit_value_n; - - WRITE_UI16(hdrp, hdr); - - if(send_trace_buffer()) { - erts_mtrace_enabled = 0; - erts_sock_close(socket_desc); - socket_desc = ERTS_SOCK_INVALID_SOCKET; - } - } - } - erts_mtx_unlock(&mtrace_buf_mutex); - erts_mtx_unlock(&mtrace_op_mutex); -} - -static ERTS_INLINE void -write_alloc_entry(byte tag, - void *res, - ErtsAlcType_t x, - ErtsAlcType_t y, - Uint size) -{ - erts_mtx_lock(&mtrace_buf_mutex); - if (erts_mtrace_enabled) { - Uint32 ti = get_time_inc(); - - if (ti != INVALID_TIME_INC - && MAKE_TBUF_SZ(UI8_SZ + 2*UI16_SZ + 2*UI_SZ + UI32_SZ)) { - Uint16 hdr, t_no = (Uint16) x, ct_no = (Uint16) y; - byte *hdrp; - int t_no_n, ct_no_n = 0, res_n, size_n, ti_n; - - *(tracep++) = tag; - - hdrp = tracep; - tracep += 2; - - if (tag == ERTS_MT_CRR_ALLOC_BDY_TAG) { - PUT_VSZ_UI16(tracep, ct_no_n, ct_no); - } - PUT_VSZ_UI16(tracep, t_no_n, t_no); - PUT_VSZ_UI( tracep, res_n, res); - PUT_VSZ_UI( tracep, size_n, size); - PUT_VSZ_UI32(tracep, ti_n, ti); - - hdr = ti_n; - - hdr <<= UI_MSB_EHF_SZ; - hdr |= size_n; - - hdr <<= UI_MSB_EHF_SZ; - hdr |= res_n; - - hdr <<= UI16_MSB_EHF_SZ; - hdr |= t_no_n; - - if (tag == ERTS_MT_CRR_ALLOC_BDY_TAG) { - hdr <<= UI16_MSB_EHF_SZ; - hdr |= ct_no_n; - } - - WRITE_UI16(hdrp, hdr); - -#if TRACE_PRINTOUTS - print_trace_entry(tag, - ct_no, ct_no_n, - t_no, t_no_n, - (Uint) res, res_n, - 0, 0, - size, size_n, - ti, ti_n); -#endif - -#ifdef DEBUG - check_alloc_entry(hdrp-1, tracep, - tag, - ct_no, ct_no_n, - t_no, t_no_n, - (UWord) res, res_n, - size, size_n, - ti, ti_n); -#endif - - } - - } - erts_mtx_unlock(&mtrace_buf_mutex); - -} - -static ERTS_INLINE void -write_realloc_entry(byte tag, - void *res, - ErtsAlcType_t x, - ErtsAlcType_t y, - void *ptr, - Uint size) -{ - erts_mtx_lock(&mtrace_buf_mutex); - if (erts_mtrace_enabled) { - Uint32 ti = get_time_inc(); - - if (ti != INVALID_TIME_INC - && MAKE_TBUF_SZ(UI8_SZ + 2*UI16_SZ + 3*UI_SZ + UI32_SZ)) { - Uint16 hdr, t_no = (Uint16) x, ct_no = (Uint16) y; - byte *hdrp; - int t_no_n, ct_no_n = 0, res_n, ptr_n, size_n, ti_n; - - *(tracep++) = tag; - - hdrp = tracep; - tracep += 2; - - if (tag == ERTS_MT_CRR_REALLOC_BDY_TAG) { - PUT_VSZ_UI16(tracep, ct_no_n, ct_no); - } - PUT_VSZ_UI16(tracep, t_no_n, t_no); - PUT_VSZ_UI( tracep, res_n, res); - PUT_VSZ_UI( tracep, ptr_n, ptr); - PUT_VSZ_UI( tracep, size_n, size); - PUT_VSZ_UI32(tracep, ti_n, ti); - - hdr = ti_n; - - hdr <<= UI_MSB_EHF_SZ; - hdr |= size_n; - - hdr <<= UI_MSB_EHF_SZ; - hdr |= ptr_n; - - hdr <<= UI_MSB_EHF_SZ; - hdr |= res_n; - - hdr <<= UI16_MSB_EHF_SZ; - hdr |= t_no_n; - - if (tag == ERTS_MT_CRR_REALLOC_BDY_TAG) { - hdr <<= UI16_MSB_EHF_SZ; - hdr |= ct_no_n; - } - - WRITE_UI16(hdrp, hdr); - -#if TRACE_PRINTOUTS - print_trace_entry(tag, - ct_no, ct_no_n, - t_no, t_no_n, - (Uint) res, res_n, - (Uint) ptr, ptr_n, - size, size_n, - ti, ti_n); -#endif - -#ifdef DEBUG - check_realloc_entry(hdrp-1, tracep, - tag, - ct_no, ct_no_n, - t_no, t_no_n, - (UWord) res, res_n, - (UWord) ptr, ptr_n, - size, size_n, - ti, ti_n); -#endif - - } - } - erts_mtx_unlock(&mtrace_buf_mutex); -} - -static ERTS_INLINE void -write_free_entry(byte tag, - ErtsAlcType_t x, - ErtsAlcType_t y, - void *ptr) -{ - erts_mtx_lock(&mtrace_buf_mutex); - if (erts_mtrace_enabled) { - Uint32 ti = get_time_inc(); - - if (ti != INVALID_TIME_INC - && MAKE_TBUF_SZ(UI8_SZ + 2*UI16_SZ + UI_SZ + UI32_SZ)) { - Uint16 hdr, t_no = (Uint16) x, ct_no = (Uint16) y; - byte *hdrp; - int t_no_n, ct_no_n = 0, ptr_n, ti_n; - - *(tracep++) = tag; - - hdrp = tracep; - tracep += 2; - - if (tag == ERTS_MT_CRR_FREE_BDY_TAG) { - PUT_VSZ_UI16(tracep, ct_no_n, ct_no); - } - PUT_VSZ_UI16(tracep, t_no_n, t_no); - PUT_VSZ_UI( tracep, ptr_n, ptr); - PUT_VSZ_UI32(tracep, ti_n, ti); - - hdr = ti_n; - - hdr <<= UI_MSB_EHF_SZ; - hdr |= ptr_n; - - hdr <<= UI16_MSB_EHF_SZ; - hdr |= t_no_n; - - if (tag == ERTS_MT_CRR_FREE_BDY_TAG) { - hdr <<= UI16_MSB_EHF_SZ; - hdr |= ct_no_n; - } - - WRITE_UI16(hdrp, hdr); - -#if TRACE_PRINTOUTS - print_trace_entry(tag, - ct_no, ct_no_n, - t_no, t_no_n, - (Uint) 0, 0, - (Uint) ptr, ptr_n, - 0, 0, - ti, ti_n); -#endif - -#ifdef DEBUG - check_free_entry(hdrp-1, tracep, - tag, - ct_no, ct_no_n, - t_no, t_no_n, - (UWord) ptr, ptr_n, - ti, ti_n); -#endif - } - - } - erts_mtx_unlock(&mtrace_buf_mutex); -} - -static void mtrace_pre_lock(void) -{ - erts_mtx_lock(&mtrace_op_mutex); -} - -static void mtrace_pre_unlock(void) -{ - erts_mtx_unlock(&mtrace_op_mutex); -} - - -static void * -mtrace_alloc(ErtsAlcType_t n, void *extra, Uint size) -{ - ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra; - void *res; - - if (!erts_is_allctr_wrapper_prelocked()) { - erts_mtx_lock(&mtrace_op_mutex); - } - - res = (*real_af->alloc)(n, real_af->extra, size); - write_alloc_entry(ERTS_MT_ALLOC_BDY_TAG, res, n, 0, size); - - if (!erts_is_allctr_wrapper_prelocked()) { - erts_mtx_unlock(&mtrace_op_mutex); - } - - return res; -} - -static void * -mtrace_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size) -{ - ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra; - void *res; - - if (!erts_is_allctr_wrapper_prelocked()) { - erts_mtx_lock(&mtrace_op_mutex); - } - - res = (*real_af->realloc)(n, real_af->extra, ptr, size); - write_realloc_entry(ERTS_MT_REALLOC_BDY_TAG, res, n, 0, ptr, size); - - if (!erts_is_allctr_wrapper_prelocked()) { - erts_mtx_unlock(&mtrace_op_mutex); - } - - return res; - -} - -static void -mtrace_free(ErtsAlcType_t n, void *extra, void *ptr) -{ - ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra; - - if (!erts_is_allctr_wrapper_prelocked()) { - erts_mtx_lock(&mtrace_op_mutex); - } - - (*real_af->free)(n, real_af->extra, ptr); - if (!erts_is_allctr_wrapper_prelocked()) { - write_free_entry(ERTS_MT_FREE_BDY_TAG, n, 0, ptr); - } - - erts_mtx_unlock(&mtrace_op_mutex); -} - - -void -erts_mtrace_crr_alloc(void *res, ErtsAlcType_t n, ErtsAlcType_t m, Uint size) -{ - write_alloc_entry(ERTS_MT_CRR_ALLOC_BDY_TAG, res, n, m, size); -} - -void -erts_mtrace_crr_realloc(void *res, ErtsAlcType_t n, ErtsAlcType_t m, void *ptr, - Uint size) -{ - write_realloc_entry(ERTS_MT_CRR_REALLOC_BDY_TAG, res, n, m, ptr, size); -} - -void -erts_mtrace_crr_free(ErtsAlcType_t n, ErtsAlcType_t m, void *ptr) -{ - write_free_entry(ERTS_MT_CRR_FREE_BDY_TAG, n, m, ptr); -} - - -#if TRACE_PRINTOUTS -static void -print_trace_entry(byte tag, - Uint16 t_no, int t_no_n, - Uint16 ct_no, int ct_no_n, - Uint res, int res_n, - Uint ptr, int ptr_n, - Uint size, int size_n, - Uint32 ti,int ti_n) -{ - switch (tag) { - case ERTS_MT_ALLOC_BDY_TAG: - fprintf(stderr, - "{alloc, {%lu, %lu, %lu}, {%u, %u, %u, %u}}\n\r", - - (unsigned long) t_no, (unsigned long) res, - (unsigned long) size, - - MSB2BITS(t_no_n), MSB2BITS(res_n), - MSB2BITS(size_n), MSB2BITS(ti_n)); - break; - case ERTS_MT_REALLOC_BDY_TAG: - fprintf(stderr, - "{realloc, {%lu, %lu, %lu, %lu}, {%u, %u, %u, %u, %u}}\n\r", - - (unsigned long) t_no, (unsigned long) res, - (unsigned long) ptr, (unsigned long) size, - - MSB2BITS(t_no_n), MSB2BITS(res_n), - MSB2BITS(ptr_n), MSB2BITS(size_n), MSB2BITS(ti_n)); - break; - case ERTS_MT_FREE_BDY_TAG: - fprintf(stderr, - "{free, {%lu, %lu}, {%u, %u, %u, %u, %u}}\n\r", - - (unsigned long) t_no, (unsigned long) ptr, - - MSB2BITS(t_no_n), MSB2BITS(ptr_n), MSB2BITS(ti_n)); - break; - case ERTS_MT_CRR_ALLOC_BDY_TAG: - fprintf(stderr, - "{crr_alloc, {%lu, %lu, %lu, %lu}, {%u, %u, %u, %u, %u}}\n\r", - - (unsigned long) ct_no, (unsigned long) t_no, - (unsigned long) res, (unsigned long) size, - - MSB2BITS(ct_no_n), MSB2BITS(t_no_n), - MSB2BITS(res_n), MSB2BITS(size_n), - MSB2BITS(ti_n)); - break; - case ERTS_MT_CRR_REALLOC_BDY_TAG: - fprintf(stderr, - "{crr_realloc, {%lu, %lu, %lu, %lu, %lu}, " - "{%u, %u, %u, %u, %u, %u}}\n\r", - - (unsigned long) ct_no, (unsigned long) t_no, - (unsigned long) res, (unsigned long) ptr, - (unsigned long) size, - - MSB2BITS(ct_no_n), MSB2BITS(t_no_n), - MSB2BITS(res_n), MSB2BITS(ptr_n), - MSB2BITS(size_n), MSB2BITS(ti_n)); - break; - case ERTS_MT_CRR_FREE_BDY_TAG: - fprintf(stderr, - "{crr_free, {%lu, %lu, %lu}, {%u, %u, %u, %u}}\n\r", - - (unsigned long) ct_no, (unsigned long) t_no, - (unsigned long) ptr, - - MSB2BITS(ct_no_n), MSB2BITS(t_no_n), - MSB2BITS(ptr_n), MSB2BITS(ti_n)); - break; - default: - fprintf(stderr, "{'\?\?\?'}\n\r"); - break; - } -} - -#endif /* #if TRACE_PRINTOUTS */ - -#ifdef DEBUG - -#define GET_UI16(P) ((P) += UI16_SZ, \ - (((Uint16) (*((P) - 2) << 8)) | ((Uint16) (*((P) - 1))))) - -static void -check_ui(Uint16 *hdrp, byte **pp, Uint ui, int msb, - Uint16 f_mask, Uint16 f_size) -{ - Uint x; - int n; - - ASSERT((msb & ~f_mask) == 0); - - n = (int) (*hdrp & f_mask); - - ASSERT(n == msb); - - *hdrp >>= f_size; - - x = 0; - switch (n) { -#ifdef ARCH_64 - case 7: x |= *((*pp)++); x <<= 8; - case 6: x |= *((*pp)++); x <<= 8; - case 5: x |= *((*pp)++); x <<= 8; - case 4: x |= *((*pp)++); x <<= 8; -#endif - case 3: x |= *((*pp)++); x <<= 8; - case 2: x |= *((*pp)++); x <<= 8; - case 1: x |= *((*pp)++); x <<= 8; - case 0: x |= *((*pp)++); break; - default: ASSERT(0); - } - - ASSERT(x == ui); -} - - -void -check_alloc_entry(byte *sp, byte *ep, - byte tag, - Uint16 ct_no, int ct_no_n, - Uint16 t_no, int t_no_n, - UWord res, int res_n, - Uint size, int size_n, - Uint32 ti,int ti_n) -{ - byte *p = sp; - Uint16 hdr; - - ASSERT(*p == tag); - p++; - - hdr = GET_UI16(p); - - if (tag == ERTS_MT_CRR_ALLOC_BDY_TAG) - check_ui(&hdr, &p, ct_no, ct_no_n, UI16_MSB_EHF_MSK, UI16_MSB_EHF_SZ); - check_ui(&hdr, &p, t_no, t_no_n, UI16_MSB_EHF_MSK, UI16_MSB_EHF_SZ); - check_ui(&hdr, &p, res, res_n, UI_MSB_EHF_MSK, UI_MSB_EHF_SZ); - check_ui(&hdr, &p, size, size_n, UI_MSB_EHF_MSK, UI_MSB_EHF_SZ); - check_ui(&hdr, &p, ti, ti_n, UI32_MSB_EHF_MSK, UI32_MSB_EHF_SZ); - - ASSERT(hdr == 0); - ASSERT(p == ep); -} - -void -check_realloc_entry(byte *sp, byte *ep, - byte tag, - Uint16 ct_no, int ct_no_n, - Uint16 t_no, int t_no_n, - UWord res, int res_n, - UWord ptr, int ptr_n, - Uint size, int size_n, - Uint32 ti,int ti_n) -{ - byte *p = sp; - Uint16 hdr; - - ASSERT(*p == tag); - p++; - - hdr = GET_UI16(p); - - if (tag == ERTS_MT_CRR_REALLOC_BDY_TAG) - check_ui(&hdr, &p, ct_no, ct_no_n, UI16_MSB_EHF_MSK, UI16_MSB_EHF_SZ); - check_ui(&hdr, &p, t_no, t_no_n, UI16_MSB_EHF_MSK, UI16_MSB_EHF_SZ); - check_ui(&hdr, &p, res, res_n, UI_MSB_EHF_MSK, UI_MSB_EHF_SZ); - check_ui(&hdr, &p, ptr, ptr_n, UI_MSB_EHF_MSK, UI_MSB_EHF_SZ); - check_ui(&hdr, &p, size, size_n, UI_MSB_EHF_MSK, UI_MSB_EHF_SZ); - check_ui(&hdr, &p, ti, ti_n, UI32_MSB_EHF_MSK, UI32_MSB_EHF_SZ); - - ASSERT(hdr == 0); - ASSERT(p == ep); -} - -void -check_free_entry(byte *sp, byte *ep, - byte tag, - Uint16 ct_no, int ct_no_n, - Uint16 t_no, int t_no_n, - UWord ptr, int ptr_n, - Uint32 ti,int ti_n) -{ - byte *p = sp; - Uint16 hdr; - - ASSERT(*p == tag); - p++; - - hdr = GET_UI16(p); - - if (tag == ERTS_MT_CRR_FREE_BDY_TAG) - check_ui(&hdr, &p, ct_no, ct_no_n, UI16_MSB_EHF_MSK, UI16_MSB_EHF_SZ); - check_ui(&hdr, &p, t_no, t_no_n, UI16_MSB_EHF_MSK, UI16_MSB_EHF_SZ); - check_ui(&hdr, &p, ptr, ptr_n, UI_MSB_EHF_MSK, UI_MSB_EHF_SZ); - check_ui(&hdr, &p, ti, ti_n, UI32_MSB_EHF_MSK, UI32_MSB_EHF_SZ); - - ASSERT(hdr == 0); - ASSERT(p == ep); - -} - -void -check_time_inc_entry(byte *sp, byte *ep, - Uint32 secs, int secs_n, - Uint32 usecs, int usecs_n) -{ - byte *p = sp; - Uint16 hdr; - - ASSERT(*p == ERTS_MT_TIME_INC_BDY_TAG); - p++; - - hdr = GET_UI16(p); - - check_ui(&hdr, &p, secs, secs_n, UI32_MSB_EHF_MSK, UI32_MSB_EHF_SZ); - check_ui(&hdr, &p, usecs, usecs_n, UI32_MSB_EHF_MSK, UI32_MSB_EHF_SZ); - - ASSERT(hdr == 0); - ASSERT(p == ep); - -} - -#endif /* #ifdef DEBUG */ - diff --git a/erts/emulator/beam/erl_mtrace.h b/erts/emulator/beam/erl_mtrace.h deleted file mode 100644 index 776c70a819..0000000000 --- a/erts/emulator/beam/erl_mtrace.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2003-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -#ifndef ERL_MTRACE_H__ -#define ERL_MTRACE_H__ - -#include "erl_alloc_types.h" - -#if (defined(ERTS___AFTER_MORECORE_HOOK_CAN_TRACK_MALLOC) \ - || defined(ERTS_BRK_WRAPPERS_CAN_TRACK_MALLOC)) -#undef ERTS_CAN_TRACK_MALLOC -#define ERTS_CAN_TRACK_MALLOC -#endif - -#define ERTS_MTRACE_SEGMENT_ID ERTS_ALC_A_INVALID - -extern int erts_mtrace_enabled; - -void erts_mtrace_pre_init(void); -void erts_mtrace_init(char *receiver, char *nodename); -void erts_mtrace_install_wrapper_functions(void); -void erts_mtrace_stop(void); -void erts_mtrace_exit(Uint32 exit_value); - -void erts_mtrace_crr_alloc(void*, ErtsAlcType_t, ErtsAlcType_t, Uint); -void erts_mtrace_crr_realloc(void*, ErtsAlcType_t, ErtsAlcType_t, void*, Uint); -void erts_mtrace_crr_free(ErtsAlcType_t, ErtsAlcType_t, void*); - - -void erts_mtrace_update_heap_size(void); /* Implemented in - * ../sys/common/erl_mtrace_sys_wrap.c - */ - -#endif /* #ifndef ERL_MTRACE_H__ */ - diff --git a/erts/emulator/beam/erl_sock.h b/erts/emulator/beam/erl_sock.h deleted file mode 100644 index 3429a52d7e..0000000000 --- a/erts/emulator/beam/erl_sock.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2003-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -/* - * A *very* limited socket interface exported by inet_drv.c. - * Used by the erl_mtrace.c. - */ - -#ifndef ERL_SOCK_H_ -#define ERL_SOCK_H_ - -#ifdef __WIN32__ -#include <winsock2.h> -typedef SOCKET erts_sock_t; -#else -typedef int erts_sock_t; -#endif - -#define ERTS_SOCK_INVALID_SOCKET -1 - -erts_sock_t erts_sock_open(void); -void erts_sock_close(erts_sock_t); -int erts_sock_connect(erts_sock_t, byte *, int, Uint16); -Sint erts_sock_send(erts_sock_t, const void *, Sint); -int erts_sock_gethostname(char *, int); -int erts_sock_errno(void); - -#endif diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index e2d578f76e..04a1f70bf4 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -13549,76 +13549,3 @@ static void send_to_subscribers } } - -/* - * A *very* limited socket interface. Used by the memory tracer - * (erl_mtrace.c). - */ -#include "erl_sock.h" - -erts_sock_t erts_sock_open(void) -{ - SOCKET s; - - if(!sock_init()) - return ERTS_SOCK_INVALID_SOCKET; - - s = sock_open(AF_INET, SOCK_STREAM, 0); - - if (s == INVALID_SOCKET) - return ERTS_SOCK_INVALID_SOCKET; - - return (erts_sock_t) s; -} - -void erts_sock_close(erts_sock_t socket) -{ - if (socket != ERTS_SOCK_INVALID_SOCKET) - sock_close((SOCKET) socket); -} - - -int erts_sock_connect(erts_sock_t socket, byte *ip_addr, int len, Uint16 port) -{ - SOCKET s = (SOCKET) socket; - char buf[2 + 4], *p; - ErlDrvSizeT blen = 6; - inet_address addr; - - if (socket == ERTS_SOCK_INVALID_SOCKET || len != 4) - return 0; - - put_int16(port, buf); - memcpy((void *) (buf + 2), (void *) ip_addr, 4); - - p = buf; - if (inet_set_address(AF_INET, &addr, &p, &blen) != NULL) - return 0; - - if (IS_SOCKET_ERROR - (sock_connect(s, (struct sockaddr *) &addr, blen))) - return 0; - return 1; -} - -Sint erts_sock_send(erts_sock_t socket, const void *buf, Sint len) -{ - Sint result = (Sint) sock_send((SOCKET) socket, buf, (size_t) len, 0); - if (IS_SOCKET_ERROR(result)) - return SOCKET_ERROR; - return result; -} - - -int erts_sock_gethostname(char *buf, int bufsz) -{ - if (IS_SOCKET_ERROR(sock_hostname(buf, bufsz))) - return SOCKET_ERROR; - return 0; -} - - -int erts_sock_errno() -{ - return sock_errno(); -} diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c index 42c4879a0e..42ebd3eddc 100644 --- a/erts/emulator/sys/common/erl_mseg.c +++ b/erts/emulator/sys/common/erl_mseg.c @@ -36,7 +36,6 @@ #include "erl_mseg.h" #include "global.h" #include "erl_threads.h" -#include "erl_mtrace.h" #include "erl_time.h" #include "erl_alloc.h" #include "big.h" @@ -45,8 +44,6 @@ #if HAVE_ERTS_MSEG -#define SEGTYPE ERTS_MTRACE_SEGMENT_ID - #ifndef HAVE_GETPAGESIZE #define HAVE_GETPAGESIZE 0 #endif @@ -570,9 +567,6 @@ static ERTS_INLINE Uint mseg_drop_one_cache_size(ErtsMsegAllctr_t *ma, Uint flag c = erts_circleq_tail(head); erts_circleq_remove(c); - if (erts_mtrace_enabled) - erts_mtrace_crr_free(SEGTYPE, SEGTYPE, c->seg); - mseg_destroy(ma, flags, c->seg, c->size); mseg_cache_clear_node(c); erts_circleq_push_head(&(ma->cache_free), c); @@ -593,9 +587,6 @@ static ERTS_INLINE Uint mseg_drop_cache_size(ErtsMsegAllctr_t *ma, Uint flags, c c = erts_circleq_tail(head); erts_circleq_remove(c); - if (erts_mtrace_enabled) - erts_mtrace_crr_free(SEGTYPE, SEGTYPE, c->seg); - mseg_destroy(ma, flags, c->seg, c->size); mseg_cache_clear_node(c); @@ -732,9 +723,6 @@ mseg_alloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, UWord *size_p, else { done: *size_p = size; - if (erts_mtrace_enabled) - erts_mtrace_crr_alloc(seg, atype, ERTS_MTRACE_SEGMENT_ID, size); - ERTS_MSEG_ALLOC_STAT(ma,size); } @@ -753,9 +741,6 @@ mseg_dealloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg, UWord size, goto done; } - if (erts_mtrace_enabled) - erts_mtrace_crr_free(atype, SEGTYPE, seg); - mseg_destroy(ma, flags, seg, size); done: @@ -825,9 +810,6 @@ mseg_realloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg, } } - if (erts_mtrace_enabled) - erts_mtrace_crr_realloc(new_seg, atype, SEGTYPE, seg, new_size); - INC_CC(ma, realloc); ASSERT(!MSEG_FLG_IS_2POW(flags) || IS_2POW(new_size)); diff --git a/erts/emulator/sys/common/erl_mtrace_sys_wrap.c b/erts/emulator/sys/common/erl_mtrace_sys_wrap.c deleted file mode 100644 index fc871f94f1..0000000000 --- a/erts/emulator/sys/common/erl_mtrace_sys_wrap.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2004-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "sys.h" -#include "erl_mtrace.h" - -#ifdef ERTS_CAN_TRACK_MALLOC -#if defined(HAVE_END_SYMBOL) -extern char end; -#elif defined(HAVE__END_SYMBOL) -extern char _end; -#endif - -static int inited = 0; -static int init(void); - -static volatile char *heap_start = NULL; -static volatile char *heap_end = NULL; - -#if defined(ERTS___AFTER_MORECORE_HOOK_CAN_TRACK_MALLOC) /* ----------------- */ - -#ifdef HAVE_MALLOC_H -# include <malloc.h> -#endif - -#undef SBRK_0 -#define SBRK_0 sbrk(0) - -static void -init_hook(void) -{ - __after_morecore_hook = erts_mtrace_update_heap_size; - if (inited) - return; - heap_end = NULL; -#if defined(HAVE_END_SYMBOL) - heap_start = &end; -#elif defined(HAVE__END_SYMBOL) - heap_start = &_end; -#else - heap_start = SBRK_0; - if (heap_start == (SBRK_RET_TYPE) -1) { - heap_start = NULL; - return; - } -#endif - inited = 1; -} - -static int -init(void) -{ - init_hook(); - return inited; -} - -void (*__malloc_initialize_hook)(void) = init_hook; - -#elif defined(ERTS_BRK_WRAPPERS_CAN_TRACK_MALLOC) /* ------------------------ */ -#ifdef HAVE_DLFCN_H -# include <dlfcn.h> -#endif - -#undef SBRK_0 -#define SBRK_0 (*real_sbrk)(0) - -#ifndef HAVE_SBRK -# error no sbrk() -#endif -#if !defined(HAVE_END_SYMBOL) && !defined(HAVE__END_SYMBOL) -# error no 'end' nor '_end' -#endif - -static void update_heap_size(char *new_end); - -#define SBRK_IMPL(RET_TYPE, FUNC, ARG_TYPE) \ -RET_TYPE FUNC (ARG_TYPE); \ -static RET_TYPE (*real_ ## FUNC)(ARG_TYPE) = NULL; \ -RET_TYPE FUNC (ARG_TYPE arg) \ -{ \ - RET_TYPE res; \ - if (!inited && !init()) \ - return (RET_TYPE) -1; \ - res = (*real_ ## FUNC)(arg); \ - if (erts_mtrace_enabled && res != ((RET_TYPE) -1)) \ - update_heap_size((char *) (*real_ ## FUNC)(0)); \ - return res; \ -} - -#define BRK_IMPL(RET_TYPE, FUNC, ARG_TYPE) \ -RET_TYPE FUNC (ARG_TYPE); \ -static RET_TYPE (*real_ ## FUNC)(ARG_TYPE) = NULL; \ -RET_TYPE FUNC (ARG_TYPE arg) \ -{ \ - RET_TYPE res; \ - if (!inited && !init()) \ - return (RET_TYPE) -1; \ - res = (*real_ ## FUNC)(arg); \ - if (erts_mtrace_enabled && res != ((RET_TYPE) -1)) \ - update_heap_size((char *) arg); \ - return res; \ -} - -SBRK_IMPL(SBRK_RET_TYPE, sbrk, SBRK_ARG_TYPE) -#ifdef HAVE_BRK - BRK_IMPL(BRK_RET_TYPE, brk, BRK_ARG_TYPE) -#endif - -#ifdef HAVE__SBRK - SBRK_IMPL(SBRK_RET_TYPE, _sbrk, SBRK_ARG_TYPE) -#endif -#ifdef HAVE__BRK - BRK_IMPL(BRK_RET_TYPE, _brk, BRK_ARG_TYPE) -#endif - -#ifdef HAVE___SBRK - SBRK_IMPL(SBRK_RET_TYPE, __sbrk, SBRK_ARG_TYPE) -#endif -#ifdef HAVE___BRK - BRK_IMPL(BRK_RET_TYPE, __brk, BRK_ARG_TYPE) -#endif - -static int -init(void) -{ - if (inited) - return 1; - -#define INIT_XBRK_SYM(SYM) \ -do { \ - if (!real_ ## SYM) { \ - real_ ## SYM = dlsym(RTLD_NEXT, #SYM); \ - if (!real_ ## SYM) { \ - errno = ENOMEM; \ - return 0; \ - } \ - } \ -} while (0) - - heap_end = NULL; -#if defined(HAVE_END_SYMBOL) - heap_start = &end; -#elif defined(HAVE__END_SYMBOL) - heap_start = &_end; -#endif - - INIT_XBRK_SYM(sbrk); -#ifdef HAVE_BRK - INIT_XBRK_SYM(brk); -#endif -#ifdef HAVE__SBRK - INIT_XBRK_SYM(_sbrk); -#endif -#ifdef HAVE__BRK - INIT_XBRK_SYM(_brk); -#endif -#ifdef HAVE___SBRK - INIT_XBRK_SYM(__sbrk); -#endif -#ifdef HAVE___BRK - INIT_XBRK_SYM(__brk); -#endif - - return inited = 1; -#undef INIT_XBRK_SYM -} - -#endif /* #elif defined(ERTS_BRK_WRAPPERS_CAN_TRACK_MALLOC) */ /* ----------- */ - -static void -update_heap_size(char *new_end) -{ - volatile char *new_start, *old_start, *old_end; - Uint size; - - if (new_end == ((char *) -1)) - return; - - new_start = (old_start = heap_start); - old_end = heap_end; - heap_end = new_end; - if (new_end < old_start || !old_start) - heap_start = (new_start = new_end); - - size = (Uint) (new_end - new_start); - - if (!old_end) { - if (size) - erts_mtrace_crr_alloc((void *) new_start, - ERTS_ALC_A_SYSTEM, - ERTS_MTRACE_SEGMENT_ID, - size); - else - heap_end = NULL; - } - else { - if (old_end != new_end || old_start != new_start) { - - if (size) - erts_mtrace_crr_realloc((void *) new_start, - ERTS_ALC_A_SYSTEM, - ERTS_MTRACE_SEGMENT_ID, - (void *) old_start, - size); - else { - if (old_start) - erts_mtrace_crr_free(ERTS_ALC_A_SYSTEM, - ERTS_MTRACE_SEGMENT_ID, - (void *) old_start); - heap_end = NULL; - } - } - } -} - -#endif /* #ifdef ERTS_CAN_TRACK_MALLOC */ - -void -erts_mtrace_update_heap_size(void) -{ -#ifdef ERTS_CAN_TRACK_MALLOC - if (erts_mtrace_enabled && (inited || init())) - update_heap_size((char *) SBRK_0); -#endif -} - diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c index a842ba18e6..aa4aca9488 100644 --- a/erts/etc/common/erlexec.c +++ b/erts/etc/common/erlexec.c @@ -104,7 +104,6 @@ static char *plusM_other_switches[] = { "usac", "im", "is", - "it", "lpm", "Mamcbf", "Mrmcbf", diff --git a/erts/include/erl_memory_trace_parser.h b/erts/include/erl_memory_trace_parser.h deleted file mode 100644 index 3170ebc0d0..0000000000 --- a/erts/include/erl_memory_trace_parser.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2004-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - - -/* - * Description: - * - * Author: Rickard Green - */ - -#ifndef ERL_MTRACE_PARSER_H__ -#define ERL_MTRACE_PARSER_H__ - -#include <stdlib.h> -#include "erl_fixed_size_int_types.h" - -/* emtp_parse() return values */ -#define EMTP_MIN_ERROR EMTP_NO_TRACE_ERROR - -#define EMTP_NO_TRACE_ERROR (-11) -#define EMTP_HEADER_TAG_IN_BODY_ERROR (-10) -#define EMTP_BODY_TAG_IN_HEADER_ERROR ( -9) -#define EMTP_NOT_SUPPORTED_MTRACE_VERSION_ERROR ( -8) -#define EMTP_NOT_AN_ERL_MTRACE_ERROR ( -7) -#define EMTP_NO_MEMORY_ERROR ( -6) -#define EMTP_BAD_OP_SIZE_ERROR ( -5) -#define EMTP_NO_OPERATIONS_ERROR ( -4) -#define EMTP_NOT_SUPPORTED_64_BITS_TRACE_ERROR ( -3) -#define EMTP_PARSE_ERROR ( -2) -#define EMTP_UNKNOWN_TAG_ERROR ( -1) -#define EMTP_END_OF_TRACE ( 0) -#define EMTP_END_OF_TRACE_GARBAGE_FOLLOWS ( 1) -#define EMTP_ALL_OPS_FILLED ( 2) -#define EMTP_NEED_MORE_TRACE ( 3) -#define EMTP_HEADER_PARSED ( 4) - -/* Allocator flags */ -#define EMTP_ALLOCATOR_FLAG_HAVE_USED_CARRIERS_INFO (1 << 0) - -/* Block type flags */ -/* #define EMTP_BLOCK_TYPE_FLAG_X */ - - -typedef struct { - usgnd_int_32 major; - usgnd_int_32 minor; -} emtp_version; - -typedef struct { - emtp_version parser; - emtp_version trace; -} emtp_versions; - -typedef struct { - int valid; - usgnd_int_32 flags; - char * name; - struct { - usgnd_int_16 no_providers; - usgnd_int_16 * provider; - } carrier; -} emtp_allocator; - -typedef struct { - int valid; - usgnd_int_32 flags; - char * name; - sgnd_int_32 allocator; -} emtp_block_type; - -typedef struct { - emtp_versions version; - int bits; - char * nodename; - char * hostname; - char * pid; - struct { - usgnd_int_32 year; - usgnd_int_32 month; - usgnd_int_32 day; - usgnd_int_32 hour; - usgnd_int_32 minute; - usgnd_int_32 second; - usgnd_int_32 micro_second; - } start_time; - usgnd_int_16 segment_ix; - usgnd_int_16 max_allocator_ix; - emtp_allocator ** allocator; - usgnd_int_16 max_block_type_ix; - emtp_block_type ** block_type; - int have_carrier_info; - int have_segment_carrier_info; -} emtp_info; - -typedef struct emtp_state_ emtp_state; - -enum emtp_op_type_ { - EMTP_UNDEF = 0, - EMTP_ALLOC = 1, - EMTP_REALLOC = 2, - EMTP_FREE = 3, - EMTP_CARRIER_ALLOC = 4, - EMTP_CARRIER_REALLOC = 5, - EMTP_CARRIER_FREE = 6, - EMTP_STOP = 7, - EMTP_EXIT = 8 -}; - -typedef enum emtp_op_type_ emtp_op_type; - -typedef struct { - usgnd_int_16 type; - usgnd_int_16 carrier_type; - usgnd_int_max new_ptr; - usgnd_int_max prev_ptr; - usgnd_int_max new_size; -} emtp_block_op; - -typedef struct { - emtp_op_type type; - struct { - usgnd_int_32 secs; - usgnd_int_32 usecs; - } time; - union { - emtp_block_op block; - usgnd_int_32 exit_status; - } u; -} emtp_operation; - -const char *emtp_error_string(int); -int emtp_get_info(emtp_info *ip, size_t *isz, emtp_state *sp); -emtp_state *emtp_state_new(void * (*alloc)(size_t), - void * (*realloc)(void *, size_t), - void (*free)(void *)); -void emtp_state_destroy(emtp_state *sp); -int emtp_parse(emtp_state *sp, - usgnd_int_8 **tracepp, size_t *trace_lenp, - emtp_operation *op_start, size_t op_size, size_t *op_lenp); -#endif diff --git a/erts/include/internal/erl_memory_trace_protocol.h b/erts/include/internal/erl_memory_trace_protocol.h deleted file mode 100644 index d3e0bcc1f4..0000000000 --- a/erts/include/internal/erl_memory_trace_protocol.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2004-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - - -/* - * Description: - * - * Author: Rickard Green - */ - -#ifndef ERL_MEMORY_TRACE_PROTOCOL_H__ -#define ERL_MEMORY_TRACE_PROTOCOL_H__ - -/* - * Increase ERTS_MT_MAJOR_VSN and set ERTS_MT_MINOR_VSN to 0 - * when backward incompatible changes are made in the protocol. - * - * Increase ERTS_MT_MINOR_VSN when backward compatible changes are - * made in the protocol. - */ -#define ERTS_MT_MAJOR_VSN (2) -#define ERTS_MT_MINOR_VSN (0) - -/* Trace flags */ - -#define ERTS_MT_64_BIT_FLAG (1 << 0) -#define ERTS_MT_CRR_INFO (1 << 1) -#define ERTS_MT_SEG_CRR_INFO (1 << 2) - -/* Header flags */ -/* Allocator flags */ - -#define ERTS_MT_ALLCTR_USD_CRR_INFO (1 << 0) - -/* Block type flags */ - - - -/* Entry tags */ - -#define ERTS_MT_V1_ALLOCATOR_TAG (1) -#define ERTS_MT_V1_BLOCK_TYPE_TAG (2) -#define ERTS_MT_V1_ALLOC_TAG (3) -#define ERTS_MT_V1_REALLOC_NPB_TAG (4) -#define ERTS_MT_V1_REALLOC_MV_TAG (5) -#define ERTS_MT_V1_REALLOC_NMV_TAG (6) -#define ERTS_MT_V1_FREE_TAG (7) -#define ERTS_MT_V1_TIME_INC_TAG (8) -#define ERTS_MT_V1_STOP_TAG (9) -#define ERTS_MT_V1_EXIT_TAG (10) - -#define ERTS_MT_END_OF_HDR_TAG (0) -#define ERTS_MT_ALLOCATOR_HDR_TAG (1) -#define ERTS_MT_BLOCK_TYPE_HDR_TAG (2) - -#define ERTS_MT_EXIT_BDY_TAG (0) -#define ERTS_MT_STOP_BDY_TAG (1) -#define ERTS_MT_ALLOC_BDY_TAG (2) -#define ERTS_MT_REALLOC_BDY_TAG (3) -#define ERTS_MT_FREE_BDY_TAG (4) -#define ERTS_MT_CRR_ALLOC_BDY_TAG (5) -#define ERTS_MT_CRR_REALLOC_BDY_TAG (6) -#define ERTS_MT_CRR_FREE_BDY_TAG (7) -#define ERTS_MT_TIME_INC_BDY_TAG (8) -#define ERTS_MT_X_BDY_TAG (9) - -/* X subtags */ -#if 0 -#define ERTS_MT_X_ _BDY_TAG (0) -#endif - -#define ERTS_MT_START_WORD (0xfff04711) -/* Entry header fields */ - -#define ERTS_MT_UI8_MSB_EHDR_FLD_SZ (0) -#define ERTS_MT_UI16_MSB_EHDR_FLD_SZ (1) -#define ERTS_MT_UI32_MSB_EHDR_FLD_SZ (2) -#define ERTS_MT_UI64_MSB_EHDR_FLD_SZ (3) -#define ERTS_MT_UI_MSB_EHDR_FLD_SZ ERTS_MT_UI64_MSB_EHDR_FLD_SZ -#define ERTS_MT_TAG_EHDR_FLD_SZ (4) - -#define ERTS_MT_UI8_MSB_EHDR_FLD_MSK ((1 << ERTS_MT_UI8_MSB_EHDR_FLD_SZ)-1) -#define ERTS_MT_UI16_MSB_EHDR_FLD_MSK ((1 << ERTS_MT_UI16_MSB_EHDR_FLD_SZ)-1) -#define ERTS_MT_UI32_MSB_EHDR_FLD_MSK ((1 << ERTS_MT_UI32_MSB_EHDR_FLD_SZ)-1) -#define ERTS_MT_UI64_MSB_EHDR_FLD_MSK ((1 << ERTS_MT_UI64_MSB_EHDR_FLD_SZ)-1) -#define ERTS_MT_UI_MSB_EHDR_FLD_MSK ERTS_MT_UI64_MSB_EHDR_FLD_MSK -#define ERTS_MT_TAG_EHDR_FLD_MSK ((1 << ERTS_MT_TAG_EHDR_FLD_SZ)-1) - -/* Time increment word */ -#define ERTS_MT_TIME_INC_SECS_SHIFT 20 -#define ERTS_MT_TIME_INC_USECS_SHIFT 0 - -#define ERTS_MT_TIME_INC_SECS_MASK ((1 << 12) - 1) -#define ERTS_MT_TIME_INC_USECS_MASK ((1 << 20) - 1) - - -#define ERTS_MT_MAX_V1_HEADER_ENTRY_SIZE (2 + 2 + 1 + 255 + 2) -/* Largest v1 header entry is block type entry (ERTS_MT_V1_BLOCK_TYPE_TAG) */ -#define ERTS_MT_MAX_V1_BODY_ENTRY_SIZE (2 + 8 + 8 + 8 + 4) -/* Largest body entry is realloc moved entry (ERTS_MT_V1_REALLOC_MV_TAG) */ - - -#define ERTS_MT_MAX_HEADER_ENTRY_SIZE (1 + 2 + 2 + 1 + 255 + 2) -/* Largest header entry is block type entry (ERTS_MT_BLOCK_TYPE_TAG) */ -#define ERTS_MT_MAX_BODY_ENTRY_SIZE ERTS_MT_MAX_CRR_REALLOC_SIZE -/* Largest body entry is carrier realloc entry (ERTS_MT_CRR_REALLOC_BDY_TAG) */ - -/* - * - * Entry header: - * - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | ... |MSB2|MSB1| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Time inc entry field: - * - * 31 23 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Seconds | Micro Seconds | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define ERTS_MT_MAX_CRR_ALLOC_SIZE (1 + 2 + 2 + 2 + 8 + 8 + 4) - -/* - * ERTS_MT_CRR_ALLOC_BDY_TAG: - * N 1 2 3 4 5 - * MSB 1-0 1-0 7|3-0 7|3-0 3-0 - * SZ 1 2 2-1 2-1 8|4-1 8|4-1 4-1 - * UIT UI8 UI16 UI16 UI16 UI64|UI32 UI64|UI32 UI32 - * +---+----+...--+...--+...-------+...-------+...-------+ - * |Tag| Hdr|CType| Type| Out ptr | In size | Time inc | - * +---+----+...--+...--+...-------+...-------+...-------+ - * - */ - -#define ERTS_MT_MAX_ALLOC_SIZE (1 + 2 + 2 + 8 + 8 + 4) -/* - * ERTS_MT_ALLOC_BDY_TAG: - * N 1 2 3 4 - * MSB 1-0 7|3-0 7|3-0 3-0 - * SZ 1 2 2-1 8|4-1 8|4-1 4-1 - * UIT UI8 UI16 UI16 UI64|UI32 UI64|UI32 UI32 - * +---+----+...--+...-------+...-------+...-------+ - * |Tag| Hdr| Type| Out ptr | In size | Time inc | - * +---+----+...--+...-------+...-------+...-------+ - * - */ - -#define ERTS_MT_MAX_CRR_REALLOC_SIZE (1 + 2 + 2 + 2 + 8 + 8 + 8 + 4) -/* - * ERTS_MT_CRR_REALLOC_BDY_TAG: - * N 1 2 3 4 5 6 - * MSB 1-0 1-0 7|3-0 7|3-0 7|3-0 3-0 - * SZ 1 2 2-1 2-1 8|4-1 8|4-1 8|4-1 4-1 - * UIT UI8 UI16 UI16 UI16 UI64|UI32 UI64|UI32 UI64|UI32 UI32 - * +---+----+...--+...--+...-------+...-------+...-------+...-------+ - * |Tag| Hdr|CType| Type| Out ptr | In ptr | In size | Time inc | - * +---+----+...--+...--+...-------+...-------+...-------+...-------+ - * - */ - -#define ERTS_MT_MAX_REALLOC_SIZE (1 + 2 + 2 + 8 + 8 + 8 + 4) -/* - * ERTS_MT_REALLOC_BDY_TAG: - * N 1 2 3 4 5 - * MSB 1-0 7|3-0 7|3-0 7|3-0 3-0 - * SZ 1 2 2-1 8|4-1 8|4-1 8|4-1 4-1 - * UIT UI8 UI16 UI16 UI64|UI32 UI64|UI32 UI64|UI32 UI32 - * +---+----+...--+...-------+...-------+...-------+...-------+ - * |Tag| Hdr| Type| Out ptr | In ptr | In size | Time inc | - * +---+----+...--+...-------+...-------+...-------+...-------+ - * - */ - -#define ERTS_MT_MAX_CRR_FREE_SIZE (1 + 2 + 2 + 2 + 8 + 4) -/* - * ERTS_MT_CRR_FREE_BDY_TAG: - * N 1 2 3 4 - * MSB 1-0 1-0 7|3-0 3-0 - * SZ 1 2 2-1 2-1 8|4-1 4-1 - * UIT UI8 UI16 UI16 UI16 UI64|UI32 UI32 - * +---+----+...--+...--+...-------+...-------+ - * |Tag| Hdr|CType| Type| In ptr | Time inc | - * +---+----+...--+...--+...-------+...-------+ - * - */ - -#define ERTS_MT_MAX_FREE_SIZE (1 + 2 + 2 + 8 + 4) -/* - * ERTS_MT_FREE_BDY_TAG: - * N 1 2 3 - * MSB 1-0 7|3-0 3-0 - * SZ 1 2 2-1 8|4-1 4-1 - * UIT UI8 UI16 UI16 UI64|UI32 UI32 - * +---+----+...--+...-------+...-------+ - * |Tag| Hdr| Type| In ptr | Time inc | - * +---+----+...--+...-------+...-------+ - * - */ - -/* - * ERTS_MT_X_BDY_TAG: - * N - * MSB - * SZ 1 2 1 - * UIT UI8 UI16 UI8 - * +---+-----+------+... ...+ - * |Tag|TotSz|SubTag| | - * +---+-----+------+... ...+ - * - * ^ ^ - * | | - * +------ TotSz bytes -----+ - * - * X for extension - * - * * Tag equals ERTS_MT_X_BDY_TAG. - * * TotSz contains the total size of the entry. - * * SubTag is used to distinguish between different sub entries - * passed in X entries. - * - */ - - - -#endif /* #ifndef ERL_MEMORY_TRACE_PROTOCOL_H__ */ - diff --git a/erts/lib_src/Makefile.in b/erts/lib_src/Makefile.in index d5a5fd0f4d..ae97b7c139 100644 --- a/erts/lib_src/Makefile.in +++ b/erts/lib_src/Makefile.in @@ -170,15 +170,6 @@ else THR_DEFS = $(filter-out -D_GNU_SOURCE%, $(ETHR_DEFS)) endif -# -# erts (public) library -# - -ERTS_LIB_SRCS = common/erl_memory_trace_parser.c - -ERTS_LIB_DIR=../lib/$(TARGET) -CREATE_DIRS += $(ERTS_LIB_DIR) - ifeq ($(USING_VC),yes) # Windows obj dir MD_OBJ_DIR=$(OBJ_DIR)/MD @@ -191,10 +182,10 @@ CREATE_DIRS += $(MD_OBJ_DIR) \ $(MT_OBJ_DIR) \ $(MTd_OBJ_DIR) -ERTS_MD_LIB_OBJS=$(addprefix $(MD_OBJ_DIR)/,$(notdir $(ERTS_LIB_SRCS:.c=.o))) -ERTS_MDd_LIB_OBJS=$(addprefix $(MDd_OBJ_DIR)/,$(notdir $(ERTS_LIB_SRCS:.c=.o))) -ERTS_MT_LIB_OBJS=$(addprefix $(MT_OBJ_DIR)/,$(notdir $(ERTS_LIB_SRCS:.c=.o))) -ERTS_MTd_LIB_OBJS=$(addprefix $(MTd_OBJ_DIR)/,$(notdir $(ERTS_LIB_SRCS:.c=.o))) +ERTS_MD_LIB_OBJS=$(addprefix $(MD_OBJ_DIR)/,$(notdir $(.c=.o))) +ERTS_MDd_LIB_OBJS=$(addprefix $(MDd_OBJ_DIR)/,$(notdir $(.c=.o))) +ERTS_MT_LIB_OBJS=$(addprefix $(MT_OBJ_DIR)/,$(notdir $(.c=.o))) +ERTS_MTd_LIB_OBJS=$(addprefix $(MTd_OBJ_DIR)/,$(notdir $(.c=.o))) else # --- Not windows --- @@ -202,31 +193,9 @@ else # --- Not windows --- ifneq ($(strip $(ETHR_LIB_NAME)),) r_OBJ_DIR = $(OBJ_DIR)/r CREATE_DIRS += $(r_OBJ_DIR) -ERTS_r_LIB_OBJS=$(addprefix $(r_OBJ_DIR)/,$(notdir $(ERTS_LIB_SRCS:.c=.o))) -endif -ERTS_LIB_OBJS=$(addprefix $(OBJ_DIR)/,$(notdir $(ERTS_LIB_SRCS:.c=.o))) - -endif - -ifeq ($(USING_VC),yes) -ERTS_MD_LIB=$(ERTS_LIB_DIR)/$(LIB_PREFIX)erts_MD$(TYPE_SUFFIX)$(LIB_SUFFIX) -ERTS_MDd_LIB=$(ERTS_LIB_DIR)/$(LIB_PREFIX)erts_MDd$(TYPE_SUFFIX)$(LIB_SUFFIX) -ERTS_MT_LIB=$(ERTS_LIB_DIR)/$(LIB_PREFIX)erts_MT$(TYPE_SUFFIX)$(LIB_SUFFIX) -ERTS_MTd_LIB=$(ERTS_LIB_DIR)/$(LIB_PREFIX)erts_MTd$(TYPE_SUFFIX)$(LIB_SUFFIX) -ERTS_LIBS += \ - $(ERTS_MD_LIB) \ - $(ERTS_MDd_LIB) \ - $(ERTS_MT_LIB) \ - $(ERTS_MTd_LIB) -else - -ERTS_LIB = $(ERTS_LIB_DIR)/$(LIB_PREFIX)erts$(TYPE_SUFFIX)$(LIB_SUFFIX) -ERTS_LIBS += $(ERTS_LIB) - -ifneq ($(strip $(ETHR_LIB_NAME)),) -ERTS_r_LIB = $(ERTS_LIB_DIR)/$(LIB_PREFIX)erts_r$(TYPE_SUFFIX)$(LIB_SUFFIX) -ERTS_LIBS += $(ERTS_r_LIB) +ERTS_r_LIB_OBJS=$(addprefix $(r_OBJ_DIR)/,$(notdir $(.c=.o))) endif +ERTS_LIB_OBJS=$(addprefix $(OBJ_DIR)/,$(notdir $(.c=.o))) endif @@ -340,7 +309,7 @@ YCF_SOURCE_DIR=$(ERL_TOP)/erts/lib_src/yielding_c_fun include $(YCF_SOURCE_DIR)/main_target.mk -$(OBJ_DIR)/MADE: $(YCF_EXECUTABLE) $(ETHREAD_LIB) $(ERTS_LIBS) $(ERTS_INTERNAL_LIBS) +$(OBJ_DIR)/MADE: $(YCF_EXECUTABLE) $(ETHREAD_LIB) $(ERTS_INTERNAL_LIBS) $(gen_verbose) ifeq ($(OMIT_OMIT_FP),yes) @echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *' @@ -462,10 +431,8 @@ include ../vsn.mk RELSYSDIR = $(RELEASE_PATH)/erts-$(VSN) RELEASE_INCLUDES= \ - $(ERTS_INCL)/erl_memory_trace_parser.h \ $(ERTS_INCL)/$(TARGET)/erl_int_sizes_config.h \ $(ERTS_INCL)/erl_fixed_size_int_types.h -RELEASE_LIBS=$(ERTS_LIBS) INTERNAL_RELEASE_INCLUDES= \ $(ERTS_INCL_INT)/README \ @@ -479,7 +446,6 @@ INTERNAL_RELEASE_INCLUDES= \ $(ERTS_INCL_INT)/$(TARGET)/ethread_header_config.h \ $(ERTS_INCL_INT)/erl_printf.h \ $(ERTS_INCL_INT)/erl_printf_format.h \ - $(ERTS_INCL_INT)/erl_memory_trace_protocol.h \ $(ERTS_INCL_INT)/erl_misc_utils.h \ $(ERTS_INCL_INT)/erl_errno.h @@ -511,12 +477,6 @@ ifneq ($(strip $(INTERNAL_X_RELEASE_INCLUDE_DIRS)),) "$(RELSYSDIR)/include/internal/$$xdir"; \ done endif -ifneq ($(strip $(RELEASE_LIBS)),) - $(INSTALL_DIR) "$(RELSYSDIR)/lib" - $(INSTALL_DIR) "$(RELEASE_PATH)/usr/lib" - $(INSTALL_DATA) $(RELEASE_LIBS) "$(RELSYSDIR)/lib" - $(INSTALL_DATA) $(RELEASE_LIBS) "$(RELEASE_PATH)/usr/lib" -endif ifneq ($(strip $(INTERNAL_RELEASE_LIBS)),) $(INSTALL_DIR) "$(RELSYSDIR)/lib/internal" $(INSTALL_DATA) $(INTERNAL_RELEASE_LIBS) "$(RELSYSDIR)/lib/internal" diff --git a/erts/lib_src/common/erl_memory_trace_parser.c b/erts/lib_src/common/erl_memory_trace_parser.c deleted file mode 100644 index 1ac3c6b4a8..0000000000 --- a/erts/lib_src/common/erl_memory_trace_parser.c +++ /dev/null @@ -1,1962 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2004-2021. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - - -/* - * Description: - * - * Author: Rickard Green - */ - -#include "erl_memory_trace_parser.h" -#include "erl_memory_trace_protocol.h" -#include <string.h> /* For memcpy */ - -#ifdef DEBUG -#include <assert.h> -#define ASSERT assert -#define PRINT_ERROR_ORIGIN 1 -#if PRINT_ERROR_ORIGIN -#include <stdio.h> -#endif -#define PRINT_PARSED_OP 0 -#if PRINT_PARSED_OP -#include <stdio.h> -static void print_op(emtp_operation *op_p); -#endif -static void hexdump(void *start, void *end); -#else -#define PRINT_ERROR_ORIGIN 0 -#define PRINT_PARSED_OP 0 -#define ASSERT(B) -#endif - - -#if ERTS_MT_MAJOR_VSN != 2 || ERTS_MT_MINOR_VSN != 0 -#error trace version mismatch (expected version 2.0) -/* Make sure that older versions are supported when implementing - support for newer versions! */ -#endif - - -#if defined(__GNUC__) -# define EMTP_CAN_INLINE 1 -# define EMTP_INLINE __inline__ -#elif defined(__WIN32__) -# define EMTP_CAN_INLINE 1 -# define EMTP_INLINE __forceinline -#else -# define EMTP_CAN_INLINE 0 -# define EMTP_INLINE -#endif - - -#define UI8_SZ 1 -#define UI16_SZ 2 -#define UI32_SZ 4 -#define UI64_SZ 8 - -#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) -#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) - -#define DEFAULT_OVERFLOW_BUF_SZ 128 - -#define UNKNOWN_BLOCK_TYPE_IX (-1) -#define UNKNOWN_ALLOCATOR_IX (-1) - -#define INVALID_SIZE (((sgnd_int_32) 1) << 31) -#define INVALID_RESULT ((int) INVALID_SIZE) - -typedef enum { - EMTP_PROGRESS_PARSE_HDR_VSN, - EMTP_PROGRESS_PARSE_HDR_PROLOG, - EMTP_PROGRESS_ALLOC_HDR_INFO, - EMTP_PROGRESS_PARSE_TAGGED_HDR, - EMTP_PROGRESS_PARSE_BODY, - EMTP_PROGRESS_ENDED -} emtp_progress; - -struct emtp_state_ { - - /* Trace version */ - emtp_version version; - - /* Flags */ - usgnd_int_32 flags; - - /* Progress */ - emtp_progress progress; - - /* Name, host, and pid as strings */ - char nodename[256]; - char hostname[256]; - char pid[256]; - - /* Local time on the traced node when the node started */ - struct { - usgnd_int_32 year; - usgnd_int_32 month; - usgnd_int_32 day; - usgnd_int_32 hour; - usgnd_int_32 minute; - usgnd_int_32 second; - usgnd_int_32 micro_second; - } start_time; - - /* Function to parse body with */ - int (*parse_body_func)(emtp_state *, - usgnd_int_8 **, - usgnd_int_8 *, - emtp_operation **, - emtp_operation *, - size_t); - /* Current time elapsed */ - struct { - usgnd_int_32 secs; - usgnd_int_32 usecs; - } time; - - /* */ - - int force_return; - - /* Overflow buffer */ - size_t overflow_size; - size_t overflow_buf_size; - usgnd_int_8 * overflow; - sgnd_int_32 fetch_size; - int known_need; - - usgnd_int_16 segment_ix; - usgnd_int_16 max_allocator_ix; - emtp_allocator ** allocator; - usgnd_int_16 max_block_type_ix; - emtp_block_type ** block_type; - - /* Memory allocation functions */ - void * (*alloc)(size_t); - void * (*realloc)(void *, size_t); - void (*free)(void *); - -}; - -static char unknown_allocator[] = "unknown_allocator"; -static char unknown_block_type[] = "unknown_block_type"; - -const char * __attribute__((externally_visible)) -emtp_error_string(int res) -{ - switch (res) { - case EMTP_NO_TRACE_ERROR: - return "no trace error"; - case EMTP_HEADER_TAG_IN_BODY_ERROR: - return "header tag in body error"; - case EMTP_BODY_TAG_IN_HEADER_ERROR: - return "body tag in header error"; - case EMTP_NOT_SUPPORTED_MTRACE_VERSION_ERROR: - return "not supported mtrace version error"; - case EMTP_NOT_AN_ERL_MTRACE_ERROR: - return "not an erl mtrace error"; - case EMTP_NO_MEMORY_ERROR: - return "no memory error"; - case EMTP_BAD_OP_SIZE_ERROR: - return "bad op size error"; - case EMTP_NO_OPERATIONS_ERROR: - return "no operations error"; - case EMTP_NOT_SUPPORTED_64_BITS_TRACE_ERROR: - return "not supported 64 bits trace error"; - case EMTP_PARSE_ERROR: - return "parse error"; - case EMTP_UNKNOWN_TAG_ERROR: - return "unknown tag error"; - case EMTP_END_OF_TRACE: - return "end of trace"; - case EMTP_END_OF_TRACE_GARBAGE_FOLLOWS: - return "end of trace; garbage follows"; - case EMTP_ALL_OPS_FILLED: - return "all operations filled"; - case EMTP_NEED_MORE_TRACE: - return "need more trace"; - case EMTP_HEADER_PARSED: - return "header parsed"; - default: - return NULL; - } - -} - -int __attribute__((externally_visible)) -emtp_get_info(emtp_info *infop, size_t *info_szp, emtp_state *statep) -{ - if (!infop || !info_szp || *info_szp < sizeof(emtp_info)) - return 0; - - infop->version.parser.major = ERTS_MT_MAJOR_VSN; - infop->version.parser.minor = ERTS_MT_MINOR_VSN; - - *info_szp = sizeof(emtp_version); - - if (!statep || statep->version.major == 0) - return 1; - - infop->version.trace.major = statep->version.major; - infop->version.trace.minor = statep->version.minor; - - *info_szp = sizeof(emtp_versions); - - if (statep->progress != EMTP_PROGRESS_PARSE_BODY - && statep->progress != EMTP_PROGRESS_ENDED) - return 1; - - infop->bits = (statep->flags & ERTS_MT_64_BIT_FLAG - ? 64 - : 32); - - infop->nodename = statep->nodename; - infop->hostname = statep->hostname; - infop->pid = statep->pid; - - infop->start_time.year = statep->start_time.year; - infop->start_time.month = statep->start_time.month; - infop->start_time.day = statep->start_time.day; - infop->start_time.hour = statep->start_time.hour; - infop->start_time.minute = statep->start_time.minute; - infop->start_time.second = statep->start_time.second; - infop->start_time.micro_second = statep->start_time.micro_second; - - infop->have_carrier_info = statep->flags & ERTS_MT_CRR_INFO; - infop->have_segment_carrier_info = statep->flags & ERTS_MT_SEG_CRR_INFO; - infop->segment_ix = statep->segment_ix; - infop->max_allocator_ix = statep->max_allocator_ix; - infop->allocator = statep->allocator; - infop->max_block_type_ix = statep->max_block_type_ix; - infop->block_type = statep->block_type; - - *info_szp = sizeof(emtp_info); - - return 1; -} - -emtp_state * __attribute__((externally_visible)) -emtp_state_new(void * (*alloc)(size_t), - void * (*realloc)(void *, size_t), - void (*free)(void *)) -{ - emtp_state *statep; - - if (!alloc || !realloc || !free) - return NULL; - - statep = (emtp_state *) (*alloc)(sizeof(emtp_state)); - if (!statep) - return NULL; - - statep->version.major = 0; - statep->version.minor = 0; - statep->flags = 0; - statep->progress = EMTP_PROGRESS_PARSE_HDR_VSN; - - statep->nodename[0] = '\0'; - statep->hostname[0] = '\0'; - statep->pid[0] = '\0'; - - statep->start_time.year = 0; - statep->start_time.month = 0; - statep->start_time.day = 0; - statep->start_time.hour = 0; - statep->start_time.minute = 0; - statep->start_time.second = 0; - statep->start_time.micro_second = 0; - - statep->parse_body_func = NULL; - statep->time.secs = 0; - statep->time.usecs = 0; - statep->force_return = 0; - statep->overflow_size = 0; - statep->overflow_buf_size = DEFAULT_OVERFLOW_BUF_SZ; - statep->overflow = - (usgnd_int_8 *) (*alloc)(DEFAULT_OVERFLOW_BUF_SZ*sizeof(usgnd_int_8)); - statep->fetch_size = 0; - statep->known_need = 0; - statep->segment_ix = 0; - statep->max_allocator_ix = 0; - statep->allocator = NULL; - statep->max_block_type_ix = 0; - statep->block_type = NULL; - statep->alloc = alloc; - statep->realloc = realloc; - statep->free = free; - - return statep; -} - -void __attribute__((externally_visible)) -emtp_state_destroy(emtp_state *statep) -{ - void (*freep)(void *); - int i; - - if (!statep) - return; - - freep = statep->free; - - if (statep->overflow) - (*freep)((void *) statep->overflow); - - if (statep->allocator) { - for (i = -1; i <= statep->max_allocator_ix; i++) { - if (statep->allocator[i]) { - if (statep->allocator[i]->name - && statep->allocator[i]->name != unknown_allocator) - (*freep)((void *) statep->allocator[i]->name); - if (statep->allocator[i]->carrier.provider) - (*freep)((void *) statep->allocator[i]->carrier.provider); - (*freep)((void *) statep->allocator[i]); - } - } - statep->allocator--; - (*freep)((void *) statep->allocator); - } - - if (statep->block_type) { - for (i = -1; i <= statep->max_block_type_ix; i++) { - if (statep->block_type[i]) { - if (statep->block_type[i]->name - && statep->block_type[i]->name != unknown_block_type) - (*freep)((void *) statep->block_type[i]->name); - (*freep)((void *) statep->block_type[i]); - } - } - statep->block_type--; - (*freep)((void *) statep->block_type); - } - - (*freep)((void *) statep); -} - -/* - * The following macros are for use in emtp_parse(), parse_vX_body, - * and parse_header. - * - * Note that some of them depend on function local variable names - * and labels: - * - * Variables: - * * result -> the result to return - * * statep -> pointer to the state - * - * Labels: - * * restore_return -> restore then return result - */ - - -#define GET_UI8(UI, BP) ((UI) = *((BP)++)) -#define SKIP_UI8(BP) ((BP)++) - -#define GET_UI16(UI, BP) \ - do { \ - (UI) = ((( (usgnd_int_16) (BP)[0]) << 8) \ - | ((usgnd_int_16) (BP)[1])); \ - (BP) += UI16_SZ; \ -} while(0) -#define SKIP_UI16(BP) ((BP) += UI16_SZ) - - -#define GET_UI32(UI, BP) \ - do { \ - (UI) = ((( (usgnd_int_32) (BP)[0]) << 24) \ - | (((usgnd_int_32) (BP)[1]) << 16) \ - | (((usgnd_int_32) (BP)[2]) << 8) \ - | ( (usgnd_int_32) (BP)[3])); \ - (BP) += UI32_SZ; \ -} while(0) -#define SKIP_UI32(BP) ((BP) += UI32_SZ) - -#define GET_UI64(UI, BP) \ - do { \ - (UI) = ((( (usgnd_int_64) (BP)[0]) << 56) \ - | (((usgnd_int_64) (BP)[1]) << 48) \ - | (((usgnd_int_64) (BP)[2]) << 40) \ - | (((usgnd_int_64) (BP)[3]) << 32) \ - | (((usgnd_int_64) (BP)[4]) << 24) \ - | (((usgnd_int_64) (BP)[5]) << 16) \ - | (((usgnd_int_64) (BP)[6]) << 8) \ - | ( (usgnd_int_64) (BP)[7])); \ - (BP) += UI64_SZ; \ -} while(0) -#define SKIP_UI64(BP) ((BP) += UI64_SZ) - -#define GET_VSZ_UI16(UI, BP, MSB) \ -do { \ - usgnd_int_16 ui_ = 0; \ - switch ((MSB)) { \ - case 1: ui_ |= (usgnd_int_16) *((BP)++); ui_ <<= 8; \ - case 0: ui_ |= (usgnd_int_16) *((BP)++); break; \ - default: ERROR(EMTP_PARSE_ERROR); \ - } \ - (UI) = ui_; \ -} while (0) - -#define GET_VSZ_UI32(UI, BP, MSB) \ -do { \ - usgnd_int_32 ui_ = 0; \ - switch ((MSB)) { \ - case 3: ui_ |= (usgnd_int_32) *((BP)++); ui_ <<= 8; \ - case 2: ui_ |= (usgnd_int_32) *((BP)++); ui_ <<= 8; \ - case 1: ui_ |= (usgnd_int_32) *((BP)++); ui_ <<= 8; \ - case 0: ui_ |= (usgnd_int_32) *((BP)++); break; \ - default: ERROR(EMTP_PARSE_ERROR); \ - } \ - (UI) = ui_; \ -} while (0) - -#define GET_VSZ_UI64(UI, BP, MSB) \ -do { \ - usgnd_int_64 ui_ = 0; \ - switch ((MSB)) { \ - case 7: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \ - case 6: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \ - case 5: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \ - case 4: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \ - case 3: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \ - case 2: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \ - case 1: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \ - case 0: ui_ |= (usgnd_int_64) *((BP)++); break; \ - default: ERROR(EMTP_PARSE_ERROR); \ - } \ - (UI) = ui_; \ -} while (0) - - -#if HAVE_INT_64 -#define GET_VSZ_UIMAX(UI, BP, MSB) \ -do { \ - usgnd_int_64 ui64_; \ - GET_VSZ_UI64(ui64_, (BP), (MSB)); \ - (UI) = (usgnd_int_max) ui64_; \ -} while (0) -#else -#define GET_VSZ_UIMAX(UI, BP, MSB) \ -do { \ - usgnd_int_32 ui32_; \ - GET_VSZ_UI32(ui32_, (BP), (MSB)); \ - (UI) = (usgnd_int_max) ui32_; \ -} while (0) -#endif - - - -#define INC_TIME(C_SECS, C_USECS, SECS, USECS) \ -do { \ - if ((USECS) >= 1000000) \ - ERROR(EMTP_PARSE_ERROR); \ - (C_SECS) += (SECS); \ - (C_USECS) += (USECS); \ - if ((C_USECS) >= 1000000) { \ - (C_USECS) -= 1000000; \ - (C_SECS)++; \ - } \ -} while (0) - -#if PRINT_ERROR_ORIGIN -#include <stdio.h> -#define ERROR(E) \ -do { \ - result = (E); \ - fprintf(stderr,"ERROR:%s:%d: result=%d\n",__FILE__,__LINE__,result);\ - statep->force_return = 1; abort(); \ - goto restore_return; \ -} while (0) -#else -#define ERROR(E) do { \ - result = (E); \ - statep->force_return = 1; \ - goto restore_return; \ -} while (0) -#endif - -#define NEED(NSZ, TSZ) \ -do { \ - sgnd_int_32 need_ = (NSZ); \ - if (need_ > (TSZ)) { \ - statep->known_need = 1; \ - statep->fetch_size = need_; \ - result = EMTP_NEED_MORE_TRACE; \ - goto restore_return; \ - } \ -} while (0) - -#define NEED_AT_LEAST(NSZ, FSZ, TSZ) \ -do { \ - sgnd_int_32 need_ = (NSZ); \ - ASSERT(need_ <= (FSZ)); \ - if (need_ > (TSZ)) { \ - statep->known_need = 0; \ - statep->fetch_size = (FSZ); \ - result = EMTP_NEED_MORE_TRACE; \ - goto restore_return; \ - } \ -} while (0) - - -#define SECS_PER_DAY (60*60*24) -#define IS_LEAP_YEAR(X) (((X) % 4 == 0 && (X) % 100 != 0) || (X) % 400 == 0) - -static void -set_start_time(emtp_state *state, - usgnd_int_32 giga_seconds, - usgnd_int_32 seconds, - usgnd_int_32 micro_seconds) -{ - /* Input is elapsed time since 1970-01-01 00:00.000000 (UTC) */ - - usgnd_int_32 year, days_of_this_year, days, secs, month; - usgnd_int_32 days_of_month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; - - days = 1000000000 / SECS_PER_DAY; - secs = 1000000000 % SECS_PER_DAY; - days *= giga_seconds; - secs *= giga_seconds; - secs += seconds; - days += secs / SECS_PER_DAY; - secs %= SECS_PER_DAY; - days++; - - year = 1969; - days_of_this_year = 0; - while (days > days_of_this_year) { - days -= days_of_this_year; - year++; - days_of_this_year = 365 + (IS_LEAP_YEAR(year) ? 1 : 0); - } - - for (month = 1; month <= 12; month++) { - usgnd_int_32 days_of_this_month = days_of_month[month]; - if (month == 2 && IS_LEAP_YEAR(year)) - days_of_this_month++; - if (days <= days_of_this_month) - break; - days -= days_of_this_month; - } - - state->start_time.year = year; - state->start_time.month = month; - state->start_time.day = days; - state->start_time.hour = secs / (60*60); - secs %= 60*60; - state->start_time.minute = secs / 60; - state->start_time.second = secs % 60; - state->start_time.micro_second = micro_seconds; -} - -static int -parse_v1_body(emtp_state *statep, - usgnd_int_8 **tracepp, usgnd_int_8 *trace_endp, - emtp_operation **op_pp, emtp_operation *op_endp, size_t op_size) -{ - /* "cache" some frequently used values */ - register usgnd_int_8 *c_p = *tracepp; - register emtp_operation *op_p = *op_pp; - register usgnd_int_32 current_secs = statep->time.secs; - register usgnd_int_32 current_usecs = statep->time.usecs; - - sgnd_int_32 trace_size = trace_endp - c_p; - usgnd_int_8 *tracep = c_p; - int result = 0; - - usgnd_int_16 max_block_type = statep->max_block_type_ix; - - while (trace_size >= UI16_SZ) { - usgnd_int_16 ehdr, tag; - unsigned time_inc_msb; - - GET_UI16(ehdr, c_p); - tag = ehdr & ERTS_MT_TAG_EHDR_FLD_MSK; - switch (tag) { - case ERTS_MT_V1_ALLOC_TAG: - - op_p->type = EMTP_ALLOC; - - alloc_common: { - usgnd_int_16 block_type; - unsigned block_type_msb, new_ptr_msb, new_size_msb; - - ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ; - block_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ; - new_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - new_size_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - NEED(UI16_SZ - + 4 - + block_type_msb - + new_ptr_msb - + new_size_msb - + time_inc_msb, - trace_size); - - GET_VSZ_UI16(block_type, c_p, block_type_msb); - if (block_type > max_block_type) - ERROR(EMTP_PARSE_ERROR); - op_p->u.block.type = (int) block_type; - - GET_VSZ_UIMAX(op_p->u.block.new_ptr, c_p, new_ptr_msb); - GET_VSZ_UIMAX(op_p->u.block.new_size, c_p, new_size_msb); - - op_p->u.block.prev_ptr = 0; - } - - read_time_inc: { - usgnd_int_32 secs, usecs, time_inc; - - GET_VSZ_UI32(time_inc, c_p, time_inc_msb); - - secs = ((time_inc >> ERTS_MT_TIME_INC_SECS_SHIFT) - & ERTS_MT_TIME_INC_SECS_MASK); - usecs = ((time_inc >> ERTS_MT_TIME_INC_USECS_SHIFT) - & ERTS_MT_TIME_INC_USECS_MASK); - - INC_TIME(current_secs, current_usecs, secs, usecs); - - op_p->time.secs = current_secs; - op_p->time.usecs = current_usecs; - -#if PRINT_PARSED_OP - print_op(op_p); -#endif - - op_p = (emtp_operation *) (((char *) op_p) + op_size); - break; - } - - case ERTS_MT_V1_REALLOC_NPB_TAG: - op_p->type = EMTP_REALLOC; - goto alloc_common; - - case ERTS_MT_V1_REALLOC_MV_TAG: { - unsigned new_ptr_msb, prev_ptr_msb, new_size_msb; - - op_p->type = EMTP_REALLOC; - - ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ; - new_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - prev_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - new_size_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - NEED(UI16_SZ - + 4 - + new_ptr_msb - + prev_ptr_msb - + new_size_msb - + time_inc_msb, - trace_size); - - GET_VSZ_UIMAX(op_p->u.block.new_ptr, c_p, new_ptr_msb); - GET_VSZ_UIMAX(op_p->u.block.prev_ptr, c_p, prev_ptr_msb); - GET_VSZ_UIMAX(op_p->u.block.new_size, c_p, new_size_msb); - - op_p->u.block.type = UNKNOWN_BLOCK_TYPE_IX; - goto read_time_inc; - } - - case ERTS_MT_V1_REALLOC_NMV_TAG: { - usgnd_int_max new_ptr; - unsigned new_ptr_msb, new_size_msb; - - op_p->type = EMTP_REALLOC; - - ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ; - new_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - new_size_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - NEED(UI16_SZ - + 3 - + new_ptr_msb - + new_size_msb - + time_inc_msb, - trace_size); - - GET_VSZ_UIMAX(new_ptr, c_p, new_ptr_msb); - GET_VSZ_UIMAX(op_p->u.block.new_size, c_p, new_size_msb); - - op_p->u.block.new_ptr = new_ptr; - op_p->u.block.prev_ptr = new_ptr; - - op_p->u.block.type = UNKNOWN_BLOCK_TYPE_IX; - goto read_time_inc; - } - - case ERTS_MT_V1_FREE_TAG: { - unsigned prev_ptr_msb; - - op_p->type = EMTP_FREE; - - ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ; - prev_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - NEED(UI16_SZ - + 2 - + prev_ptr_msb - + time_inc_msb, - trace_size); - - GET_VSZ_UIMAX(op_p->u.block.prev_ptr, c_p, prev_ptr_msb); - - op_p->u.block.new_ptr = 0; - op_p->u.block.new_size = 0; - - op_p->u.block.type = UNKNOWN_BLOCK_TYPE_IX; - goto read_time_inc; - } - - case ERTS_MT_V1_TIME_INC_TAG: { - unsigned secs_msb, usecs_msb; - usgnd_int_32 secs, usecs; - - ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ; - - secs_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI32_MSB_EHDR_FLD_SZ; - - usecs_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - NEED(UI16_SZ + 2 + secs_msb + usecs_msb, trace_size); - - GET_VSZ_UI32(secs, c_p, secs_msb); - GET_VSZ_UI32(usecs, c_p, usecs_msb); - - INC_TIME(current_secs, current_usecs, secs, usecs); - - break; - } - - case ERTS_MT_V1_STOP_TAG: - - op_p->type = EMTP_STOP; - - ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ; - - time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - NEED(UI16_SZ + 1 + time_inc_msb, trace_size); - - goto read_ending_time_inc; - - case ERTS_MT_V1_EXIT_TAG: { - unsigned exit_status_msb; - - op_p->type = EMTP_EXIT; - - ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ; - exit_status_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI32_MSB_EHDR_FLD_SZ; - time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - NEED(UI16_SZ + 2 + exit_status_msb + time_inc_msb, - trace_size); - - GET_VSZ_UI32(op_p->u.exit_status, c_p, exit_status_msb); - - read_ending_time_inc: { - usgnd_int_32 secs, usecs, time_inc; - - GET_VSZ_UI32(time_inc, c_p, time_inc_msb); - - secs = ((time_inc >> ERTS_MT_TIME_INC_SECS_SHIFT) - & ERTS_MT_TIME_INC_SECS_MASK); - usecs = ((time_inc >> ERTS_MT_TIME_INC_USECS_SHIFT) - & ERTS_MT_TIME_INC_USECS_MASK); - - INC_TIME(current_secs, current_usecs, secs, usecs); - - op_p->time.secs = current_secs; - op_p->time.usecs = current_usecs; - -#if PRINT_PARSED_OP - print_op(op_p); -#endif - - op_p = (emtp_operation *) (((char *) op_p) + op_size); - statep->force_return = 1; - statep->progress = EMTP_PROGRESS_ENDED; - - tracep = c_p; - trace_size = trace_endp - tracep; - result = (trace_size - ? EMTP_END_OF_TRACE_GARBAGE_FOLLOWS - : EMTP_END_OF_TRACE); - goto restore_return; - } - } - - case ERTS_MT_V1_ALLOCATOR_TAG: - case ERTS_MT_V1_BLOCK_TYPE_TAG: - -#ifdef DEBUG - hexdump(tracep, trace_endp); -#endif - ERROR(EMTP_HEADER_TAG_IN_BODY_ERROR); - - default: - -#ifdef DEBUG - hexdump(tracep, trace_endp); -#endif - ERROR(EMTP_UNKNOWN_TAG_ERROR); - } - - tracep = c_p; - trace_size = trace_endp - tracep; - - if (op_p >= op_endp) { - statep->force_return = 1; - result = EMTP_ALL_OPS_FILLED; - goto restore_return; - } - } - - statep->known_need = 0; - statep->fetch_size = ERTS_MT_MAX_V1_BODY_ENTRY_SIZE; - - result = EMTP_NEED_MORE_TRACE; - - restore_return: - *tracepp = tracep; - *op_pp = op_p; - statep->time.secs = current_secs; - statep->time.usecs = current_usecs; - - return result; -} - -#define GET_ALLOC_MSBS(EHDR, BT, NP, NS, TI) \ -do { \ - (BT) = (EHDR) & ERTS_MT_UI16_MSB_EHDR_FLD_MSK; \ - (EHDR) >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ; \ - (NP) = (EHDR) & ERTS_MT_UI_MSB_EHDR_FLD_MSK; \ - (EHDR) >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; \ - (NS) = (EHDR) & ERTS_MT_UI_MSB_EHDR_FLD_MSK; \ - (EHDR) >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; \ - (TI) = (EHDR) & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; \ -} while (0) - - -static EMTP_INLINE int -parse_v2_body(emtp_state *statep, - usgnd_int_8 **tracepp, usgnd_int_8 *trace_endp, - emtp_operation **op_pp, emtp_operation *op_endp, size_t op_size) -{ - /* "cache" some frequently used values */ - register usgnd_int_8 *c_p = *tracepp; - register emtp_operation *op_p = *op_pp; - register usgnd_int_32 current_secs = statep->time.secs; - register usgnd_int_32 current_usecs = statep->time.usecs; - - sgnd_int_32 trace_size = trace_endp - c_p; - usgnd_int_8 *tracep = c_p; - int result = 0; - - while (trace_size >= UI8_SZ + UI16_SZ) { - usgnd_int_8 tag; - usgnd_int_16 ehdr; - unsigned time_inc_msb; - - tag = *(c_p++); - - GET_UI16(ehdr, c_p); - - switch (tag) { - - case ERTS_MT_CRR_ALLOC_BDY_TAG: { - usgnd_int_16 type; - unsigned carrier_bytes, carrier_type_msb, block_type_msb, - new_ptr_msb, new_size_msb; - - op_p->type = EMTP_CARRIER_ALLOC; - - carrier_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ; - - if (trace_size < ERTS_MT_MAX_CRR_ALLOC_SIZE) - NEED_AT_LEAST(UI8_SZ + UI16_SZ + 1 + carrier_type_msb, - ERTS_MT_MAX_CRR_ALLOC_SIZE, - trace_size); - - GET_VSZ_UI16(type, c_p, carrier_type_msb); - op_p->u.block.carrier_type = (int) type; - - carrier_bytes = carrier_type_msb + 1; - goto alloc_common; - - case ERTS_MT_ALLOC_BDY_TAG: - - op_p->type = EMTP_ALLOC; - carrier_bytes = 0; - - alloc_common: - block_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ; - new_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - new_size_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - if (trace_size < ERTS_MT_MAX_CRR_ALLOC_SIZE) - NEED(UI8_SZ - + UI16_SZ - + 4 - + carrier_bytes - + block_type_msb - + new_ptr_msb - + new_size_msb - + time_inc_msb, - trace_size); - - GET_VSZ_UI16(type, c_p, block_type_msb); - op_p->u.block.type = (int) type; - - GET_VSZ_UIMAX(op_p->u.block.new_ptr, c_p, new_ptr_msb); - GET_VSZ_UIMAX(op_p->u.block.new_size, c_p, new_size_msb); - - op_p->u.block.prev_ptr = 0; - } - - read_time_inc: { - usgnd_int_32 secs, usecs, time_inc; - - GET_VSZ_UI32(time_inc, c_p, time_inc_msb); - - secs = ((time_inc >> ERTS_MT_TIME_INC_SECS_SHIFT) - & ERTS_MT_TIME_INC_SECS_MASK); - usecs = ((time_inc >> ERTS_MT_TIME_INC_USECS_SHIFT) - & ERTS_MT_TIME_INC_USECS_MASK); - - INC_TIME(current_secs, current_usecs, secs, usecs); - - op_p->time.secs = current_secs; - op_p->time.usecs = current_usecs; - -#if PRINT_PARSED_OP - print_op(op_p); -#endif - - op_p = (emtp_operation *) (((char *) op_p) + op_size); - break; - } - - case ERTS_MT_CRR_REALLOC_BDY_TAG: { - usgnd_int_16 type; - unsigned carrier_bytes, carrier_type_msb, block_type_msb, - new_ptr_msb, prev_ptr_msb, new_size_msb; - - op_p->type = EMTP_CARRIER_REALLOC; - - carrier_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ; - - if (trace_size < ERTS_MT_MAX_CRR_REALLOC_SIZE) - NEED_AT_LEAST(UI8_SZ + UI16_SZ + 1 + carrier_type_msb, - ERTS_MT_MAX_CRR_REALLOC_SIZE, - trace_size); - - GET_VSZ_UI16(type, c_p, carrier_type_msb); - op_p->u.block.carrier_type = (int) type; - - carrier_bytes = carrier_type_msb + 1; - goto realloc_common; - - case ERTS_MT_REALLOC_BDY_TAG: - - op_p->type = EMTP_REALLOC; - carrier_bytes = 0; - - realloc_common: - - block_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ; - new_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - prev_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - new_size_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - if (trace_size < ERTS_MT_MAX_CRR_REALLOC_SIZE) - NEED(UI8_SZ - + UI16_SZ - + 5 - + carrier_bytes - + block_type_msb - + new_ptr_msb - + prev_ptr_msb - + new_size_msb - + time_inc_msb, - trace_size); - - GET_VSZ_UI16(op_p->u.block.type, c_p, block_type_msb); - GET_VSZ_UIMAX(op_p->u.block.new_ptr, c_p, new_ptr_msb); - GET_VSZ_UIMAX(op_p->u.block.prev_ptr, c_p, prev_ptr_msb); - GET_VSZ_UIMAX(op_p->u.block.new_size, c_p, new_size_msb); - - goto read_time_inc; - } - - case ERTS_MT_CRR_FREE_BDY_TAG: { - usgnd_int_16 type; - unsigned carrier_bytes, carrier_type_msb, block_type_msb, - prev_ptr_msb; - - op_p->type = EMTP_CARRIER_FREE; - - carrier_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ; - - if (trace_size < ERTS_MT_MAX_CRR_FREE_SIZE) - NEED_AT_LEAST(UI8_SZ + UI16_SZ + 1 + carrier_type_msb, - ERTS_MT_MAX_CRR_FREE_SIZE, - trace_size); - - GET_VSZ_UI16(type, c_p, carrier_type_msb); - op_p->u.block.carrier_type = (int) type; - - carrier_bytes = carrier_type_msb + 1; - goto free_common; - - case ERTS_MT_FREE_BDY_TAG: - - op_p->type = EMTP_FREE; - carrier_bytes = 0; - - free_common: - - block_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ; - prev_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; - time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - if (trace_size < ERTS_MT_MAX_CRR_FREE_SIZE) - NEED(UI8_SZ - + UI16_SZ - + 3 - + carrier_bytes - + block_type_msb - + prev_ptr_msb - + time_inc_msb, - trace_size); - - GET_VSZ_UI16(op_p->u.block.type, c_p, block_type_msb); - GET_VSZ_UIMAX(op_p->u.block.prev_ptr, c_p, prev_ptr_msb); - - op_p->u.block.new_ptr = 0; - op_p->u.block.new_size = 0; - - goto read_time_inc; - } - - case ERTS_MT_TIME_INC_BDY_TAG: { - unsigned secs_msb, usecs_msb; - usgnd_int_32 secs, usecs; - - secs_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI32_MSB_EHDR_FLD_SZ; - usecs_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - NEED(UI8_SZ + UI16_SZ + 2 + secs_msb + usecs_msb, trace_size); - - GET_VSZ_UI32(secs, c_p, secs_msb); - GET_VSZ_UI32(usecs, c_p, usecs_msb); - - INC_TIME(current_secs, current_usecs, secs, usecs); - - break; - } - - case ERTS_MT_STOP_BDY_TAG: - - op_p->type = EMTP_STOP; - - time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - NEED(UI16_SZ + 1 + time_inc_msb, trace_size); - - goto read_ending_time_inc; - - case ERTS_MT_EXIT_BDY_TAG: { - unsigned exit_status_msb; - - op_p->type = EMTP_EXIT; - - exit_status_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - ehdr >>= ERTS_MT_UI32_MSB_EHDR_FLD_SZ; - time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; - - NEED(UI16_SZ + 2 + exit_status_msb + time_inc_msb, trace_size); - - GET_VSZ_UI32(op_p->u.exit_status, c_p, exit_status_msb); - - read_ending_time_inc: { - usgnd_int_32 secs, usecs, time_inc; - - GET_VSZ_UI32(time_inc, c_p, time_inc_msb); - - secs = ((time_inc >> ERTS_MT_TIME_INC_SECS_SHIFT) - & ERTS_MT_TIME_INC_SECS_MASK); - usecs = ((time_inc >> ERTS_MT_TIME_INC_USECS_SHIFT) - & ERTS_MT_TIME_INC_USECS_MASK); - - INC_TIME(current_secs, current_usecs, secs, usecs); - - op_p->time.secs = current_secs; - op_p->time.usecs = current_usecs; - -#if PRINT_PARSED_OP - print_op(op_p); -#endif - - op_p = (emtp_operation *) (((char *) op_p) + op_size); - statep->force_return = 1; - statep->progress = EMTP_PROGRESS_ENDED; - - tracep = c_p; - trace_size = trace_endp - tracep; - result = (trace_size - ? EMTP_END_OF_TRACE_GARBAGE_FOLLOWS - : EMTP_END_OF_TRACE); - goto restore_return; - } - } - - case ERTS_MT_X_BDY_TAG: { - /* X for extension - * ehdr contains total size of entry - * - * Entry should at least consist of tag (1 byte), - * total size (2 bytes) and subtag (1 byte). - */ - if (ehdr < UI8_SZ + UI16_SZ + UI8_SZ) - ERROR(EMTP_PARSE_ERROR); - NEED(ehdr, trace_size); - c_p = tracep + ehdr; /* No subtags known yet skip entry... */ - break; - } - - default: -#ifdef DEBUG - hexdump(c_p-2, trace_endp); -#endif - ERROR(EMTP_UNKNOWN_TAG_ERROR); - } - - tracep = c_p; - trace_size = trace_endp - tracep; - - if (op_p >= op_endp) { - statep->force_return = 1; - result = EMTP_ALL_OPS_FILLED; - goto restore_return; - } - } - - statep->known_need = 0; - statep->fetch_size = ERTS_MT_MAX_BODY_ENTRY_SIZE; - - result = EMTP_NEED_MORE_TRACE; - - restore_return: - *tracepp = tracep; - *op_pp = op_p; - statep->time.secs = current_secs; - statep->time.usecs = current_usecs; - - return result; -} - -static void -remove_unused_allocators(emtp_state *statep) -{ - emtp_allocator *allctr; - sgnd_int_32 i, j, k; - for (i = -1; i <= statep->max_block_type_ix; i++) { - if (statep->block_type[i]->valid) { - allctr = statep->allocator[statep->block_type[i]->allocator]; - if (allctr->name != unknown_allocator) - allctr->valid = 1; - } - } - for (i = -1; i <= statep->max_allocator_ix; i++) { - allctr = statep->allocator[i]; - if (allctr->valid && allctr->carrier.provider) { - for (j = 0; j < allctr->carrier.no_providers; j++) { - k = allctr->carrier.provider[j]; - if (statep->allocator[k]->name != unknown_allocator) - statep->allocator[k]->valid = 1; - } - } - } - for (i = -1; i <= statep->max_allocator_ix; i++) { - allctr = statep->allocator[i]; - if (!allctr->valid) { - allctr->flags = 0; - if (allctr->name != unknown_allocator) { - (*statep->free)((void *) allctr->name); - allctr->name = unknown_allocator; - } - allctr->carrier.no_providers = 0; - if (allctr->carrier.provider) { - (*statep->free)((void *) allctr->carrier.provider); - } - } - } -} - -static int -parse_header(emtp_state *statep, - usgnd_int_8 **tracepp, usgnd_int_8 *trace_endp) -{ - sgnd_int_32 trace_size; - usgnd_int_8 *tracep; - int i, result; - - tracep = *tracepp; - - switch (statep->progress) { - case EMTP_PROGRESS_PARSE_HDR_VSN: { - usgnd_int_32 start_word; - - trace_size = trace_endp - tracep; - NEED(3*UI32_SZ, trace_size); - - GET_UI32(start_word, tracep); - if (start_word != ERTS_MT_START_WORD) - return EMTP_NOT_AN_ERL_MTRACE_ERROR; - - GET_UI32(statep->version.major, tracep); - GET_UI32(statep->version.minor, tracep); - - statep->progress = EMTP_PROGRESS_PARSE_HDR_PROLOG; - } - case EMTP_PROGRESS_PARSE_HDR_PROLOG: - - trace_size = trace_endp - tracep; - - switch (statep->version.major) { - case 1: { - NEED(2*UI32_SZ + 2*UI16_SZ, trace_size); - - GET_UI32(statep->flags, tracep); - SKIP_UI32(tracep); /* ignore this; may contain garbage! */ - GET_UI16(statep->max_allocator_ix, tracep); - GET_UI16(statep->max_block_type_ix, tracep); - - statep->parse_body_func = parse_v1_body; - - break; - } - case 2: { - usgnd_int_32 giga_seconds; - usgnd_int_32 seconds; - usgnd_int_32 micro_seconds; - usgnd_int_8 len; - usgnd_int_8 *hdr_prolog_start; - usgnd_int_32 hdr_prolog_sz; - NEED(UI32_SZ, trace_size); - hdr_prolog_start = tracep; - GET_UI32(hdr_prolog_sz, tracep); - NEED(hdr_prolog_sz - UI32_SZ, trace_size); - - GET_UI32(statep->flags, tracep); - GET_UI16(statep->segment_ix, tracep); - GET_UI16(statep->max_allocator_ix, tracep); - GET_UI16(statep->max_block_type_ix, tracep); - - GET_UI32(giga_seconds, tracep); - GET_UI32(seconds, tracep); - GET_UI32(micro_seconds, tracep); - - set_start_time(statep, giga_seconds, seconds, micro_seconds); - - GET_UI8(len, tracep); - memcpy((void *) statep->nodename, (void *) tracep, (size_t) len); - statep->nodename[len] = '\0'; - tracep += len; - - GET_UI8(len, tracep); - memcpy((void *) statep->hostname, (void *) tracep, (size_t) len); - statep->hostname[len] = '\0'; - tracep += len; - - GET_UI8(len, tracep); - memcpy((void *) statep->pid, (void *) tracep, (size_t) len); - statep->pid[len] = '\0'; - tracep += len; - - - - /* Skip things in header prolog we dont know about */ - tracep = hdr_prolog_start + hdr_prolog_sz; - -#if EMTP_CAN_INLINE - statep->parse_body_func = NULL; -#else - statep->parse_body_func = parse_v2_body; -#endif - - break; - } - default: - return EMTP_NOT_SUPPORTED_MTRACE_VERSION_ERROR; - } - - statep->progress = EMTP_PROGRESS_ALLOC_HDR_INFO; - - case EMTP_PROGRESS_ALLOC_HDR_INFO: - - /* Allocator info */ - if (!statep->allocator) { - statep->allocator = (emtp_allocator **) - (*statep->alloc)((statep->max_allocator_ix + 2) - * sizeof(emtp_allocator *)); - if (!statep->allocator) - ERROR(EMTP_NO_MEMORY_ERROR); - statep->allocator++; - for (i = -1; i <= statep->max_allocator_ix; i++) - statep->allocator[i] = NULL; - for (i = -1; i <= statep->max_allocator_ix; i++) { - statep->allocator[i] = (emtp_allocator *) - (*statep->alloc)(sizeof(emtp_allocator)); - if (!statep->allocator[i]) - ERROR(EMTP_NO_MEMORY_ERROR); - statep->allocator[i]->valid = 0; - statep->allocator[i]->flags = 0; - statep->allocator[i]->name = unknown_allocator; - statep->allocator[i]->carrier.no_providers = 0; - statep->allocator[i]->carrier.provider = NULL; - } - - } - - /* Block type info */ - if (!statep->block_type) { - statep->block_type = (emtp_block_type **) - (*statep->alloc)((statep->max_block_type_ix + 2) - * sizeof(emtp_block_type *)); - if (!statep->block_type) - ERROR(EMTP_NO_MEMORY_ERROR); - statep->block_type++; - for (i = -1; i <= statep->max_block_type_ix; i++) - statep->block_type[i] = NULL; - for (i = -1; i <= statep->max_block_type_ix; i++) { - statep->block_type[i] = (emtp_block_type *) - (*statep->alloc)(sizeof(emtp_block_type)); - if (!statep->block_type[i]) - ERROR(EMTP_NO_MEMORY_ERROR); - statep->block_type[i]->valid = 0; - statep->block_type[i]->flags = 0; - statep->block_type[i]->name = unknown_block_type; - statep->block_type[i]->allocator = UNKNOWN_ALLOCATOR_IX; - } - - } - - statep->progress = EMTP_PROGRESS_PARSE_TAGGED_HDR; - - case EMTP_PROGRESS_PARSE_TAGGED_HDR: { - usgnd_int_8 *c_p = tracep; - trace_size = trace_endp - tracep; - - switch (statep->version.major) { - case 1: /* Version 1.X ---------------------------------------------- */ - - while (trace_size >= UI16_SZ) { - size_t str_len; - usgnd_int_16 ehdr; - - GET_UI16(ehdr, c_p); - - switch (ehdr & ERTS_MT_TAG_EHDR_FLD_MSK) { - case ERTS_MT_V1_ALLOCATOR_TAG: { - usgnd_int_16 a_ix; - - NEED_AT_LEAST(2*UI16_SZ + UI8_SZ, - ERTS_MT_MAX_HEADER_ENTRY_SIZE, - trace_size); - - GET_UI16(a_ix, c_p); - if (a_ix > statep->max_allocator_ix) - ERROR(EMTP_PARSE_ERROR); - - GET_UI8(str_len, c_p); - - NEED(2*UI16_SZ + UI8_SZ + str_len, trace_size); - - statep->allocator[a_ix]->name - = (char *) (*statep->alloc)(str_len + 1); - if (!statep->allocator[a_ix]->name) - ERROR(EMTP_NO_MEMORY_ERROR); - - memcpy((void *) statep->allocator[a_ix]->name, - (void *) c_p, - str_len); - c_p += str_len; - - statep->allocator[a_ix]->name[str_len] = '\0'; - break; - } - case ERTS_MT_V1_BLOCK_TYPE_TAG: { - usgnd_int_16 bt_ix, a_ix; - - NEED_AT_LEAST(2*UI16_SZ + UI8_SZ, - ERTS_MT_MAX_HEADER_ENTRY_SIZE, - trace_size); - - GET_UI16(bt_ix, c_p); - if (bt_ix > statep->max_block_type_ix) - ERROR(EMTP_PARSE_ERROR); - - GET_UI8(str_len, c_p); - - NEED(2*UI16_SZ + UI8_SZ + str_len + UI16_SZ, trace_size); - - statep->block_type[bt_ix]->name - = (char *) (*statep->alloc)(str_len + 1); - - if (!statep->block_type[bt_ix]->name) - ERROR(EMTP_NO_MEMORY_ERROR); - - memcpy((void *) statep->block_type[bt_ix]->name, - (void *) c_p, - str_len); - c_p += str_len; - - statep->block_type[bt_ix]->name[str_len] = '\0'; - - GET_UI16(a_ix, c_p); - - if (a_ix > statep->max_allocator_ix) - ERROR(EMTP_PARSE_ERROR); - - statep->block_type[bt_ix]->allocator = (sgnd_int_32) a_ix; - statep->block_type[bt_ix]->valid = 1; - break; - } - - case ERTS_MT_V1_ALLOC_TAG: - case ERTS_MT_V1_REALLOC_NPB_TAG: - case ERTS_MT_V1_REALLOC_MV_TAG: - case ERTS_MT_V1_REALLOC_NMV_TAG: - case ERTS_MT_V1_FREE_TAG: - case ERTS_MT_V1_TIME_INC_TAG: - case ERTS_MT_V1_STOP_TAG: - case ERTS_MT_V1_EXIT_TAG: - remove_unused_allocators(statep); - statep->progress = EMTP_PROGRESS_PARSE_BODY; - result = EMTP_HEADER_PARSED; - statep->force_return = 1; - goto restore_return; - default: - ERROR(EMTP_UNKNOWN_TAG_ERROR); - } - - tracep = c_p; - trace_size = trace_endp - tracep; - } - - statep->fetch_size = ERTS_MT_MAX_V1_HEADER_ENTRY_SIZE; - break; - - case 2: /* Version 2.X ---------------------------------------------- */ - - while (trace_size >= UI8_SZ + UI16_SZ) { - usgnd_int_16 entry_sz; - size_t str_len; - usgnd_int_8 tag; - - GET_UI8(tag, c_p); - GET_UI16(entry_sz, c_p); - NEED(entry_sz, trace_size); - - switch (tag) { - case ERTS_MT_ALLOCATOR_HDR_TAG: { - usgnd_int_8 crr_prvds; - usgnd_int_16 a_ix, aflgs; - - if (entry_sz - < UI8_SZ + 3*UI16_SZ + UI8_SZ + 0 + UI8_SZ) - ERROR(EMTP_PARSE_ERROR); - - GET_UI16(aflgs, c_p); - GET_UI16(a_ix, c_p); - if (a_ix > statep->max_allocator_ix) - ERROR(EMTP_PARSE_ERROR); - - if (aflgs & ERTS_MT_ALLCTR_USD_CRR_INFO) - statep->allocator[a_ix]->flags - |= EMTP_ALLOCATOR_FLAG_HAVE_USED_CARRIERS_INFO; - - GET_UI8(str_len, c_p); - - if (entry_sz - < UI8_SZ + 3*UI16_SZ + UI8_SZ + str_len + UI8_SZ) - ERROR(EMTP_PARSE_ERROR); - - statep->allocator[a_ix]->name - = (char *) (*statep->alloc)(str_len + 1); - if (!statep->allocator[a_ix]->name) - ERROR(EMTP_NO_MEMORY_ERROR); - - memcpy((void *) statep->allocator[a_ix]->name, - (void *) c_p, - str_len); - c_p += str_len; - - statep->allocator[a_ix]->name[str_len] = '\0'; - - GET_UI8(crr_prvds, c_p); - if (entry_sz < (UI8_SZ - + 3*UI16_SZ - + UI8_SZ - + str_len - + UI8_SZ - + crr_prvds*UI16_SZ)) - ERROR(EMTP_PARSE_ERROR); - statep->allocator[a_ix]->carrier.no_providers - = (usgnd_int_16) crr_prvds; - statep->allocator[a_ix]->carrier.provider = (usgnd_int_16 *) - (*statep->alloc)(crr_prvds*sizeof(usgnd_int_16)); - if (!statep->allocator[a_ix]->carrier.provider) - ERROR(EMTP_NO_MEMORY_ERROR); - for (i = 0; i < crr_prvds; i++) { - usgnd_int_16 cp_ix; - GET_UI16(cp_ix, c_p); - if (cp_ix > statep->max_allocator_ix) - ERROR(EMTP_PARSE_ERROR); - statep->allocator[a_ix]->carrier.provider[i] = cp_ix; - } - - break; - } - - case ERTS_MT_BLOCK_TYPE_HDR_TAG: { - usgnd_int_16 bt_ix, a_ix; - - if (entry_sz - < UI8_SZ + 3*UI16_SZ + UI8_SZ + 0 + UI16_SZ) - ERROR(EMTP_PARSE_ERROR); - - SKIP_UI16(c_p); /* bitflags */ - GET_UI16(bt_ix, c_p); - if (bt_ix > statep->max_block_type_ix) - ERROR(EMTP_PARSE_ERROR); - - GET_UI8(str_len, c_p); - - if (entry_sz - < UI8_SZ + 3*UI16_SZ + UI8_SZ + str_len + UI16_SZ) - ERROR(EMTP_PARSE_ERROR); - - statep->block_type[bt_ix]->name - = (char *) (*statep->alloc)(str_len + 1); - - if (!statep->block_type[bt_ix]->name) - ERROR(EMTP_NO_MEMORY_ERROR); - - memcpy((void *) statep->block_type[bt_ix]->name, - (void *) c_p, - str_len); - c_p += str_len; - - statep->block_type[bt_ix]->name[str_len] = '\0'; - - GET_UI16(a_ix, c_p); - - if (a_ix > statep->max_allocator_ix) - ERROR(EMTP_PARSE_ERROR); - - statep->block_type[bt_ix]->allocator = (sgnd_int_32) a_ix; - statep->block_type[bt_ix]->valid = 1; - break; - } - - case ERTS_MT_END_OF_HDR_TAG: - tracep = tracep + ((size_t) entry_sz); - remove_unused_allocators(statep); - statep->progress = EMTP_PROGRESS_PARSE_BODY; - result = EMTP_HEADER_PARSED; - statep->force_return = 1; - goto restore_return; - - default: - /* Skip tags that we do not understand. */ - break; - } - - tracep = tracep + ((size_t) entry_sz); - ASSERT(c_p <= tracep); - c_p = tracep; - trace_size = trace_endp - tracep; - } - - statep->fetch_size = UI8_SZ + UI16_SZ; - break; - default: /* Not supported version --------------------------------- */ - ASSERT(0); - } - - break; - } - default: - ASSERT(0); - } - - statep->known_need = 0; - result = EMTP_NEED_MORE_TRACE; - - restore_return: - - *tracepp = tracep; - - return result; - -} - - -int __attribute__((externally_visible)) -emtp_parse(emtp_state *statep, - usgnd_int_8 **tracepp, size_t *trace_lenp, - emtp_operation *op_start, size_t op_size, size_t *op_lenp) -{ - int result, have_all_in_overflow; - usgnd_int_8 *tracep, *trace_endp; - emtp_operation *op_p, *op_endp; - - - have_all_in_overflow = 0; - - op_p = op_start; - - if (!statep) - return EMTP_NO_MEMORY_ERROR; - - if (!tracepp || !trace_lenp) - return EMTP_NO_TRACE_ERROR; - - if (*trace_lenp <= 0) { - if (op_lenp) - *op_lenp = 0; - return EMTP_NEED_MORE_TRACE; - } - - statep->force_return = 0; - - if (statep->overflow_size) { /* Overflow from previous parse */ - sgnd_int_32 tsz; - sgnd_int_32 sz; - - fetch_for_overflow: - sz = statep->fetch_size - statep->overflow_size; - ASSERT(sz > 0); - - if (*trace_lenp <= sz) { - have_all_in_overflow = 1; - sz = *trace_lenp; - } - - if (sz > statep->overflow_buf_size) { - size_t buf_sz = statep->overflow_size + sz; - void *buf = (*statep->realloc)((void *) statep->overflow, buf_sz); - if (!buf) - return EMTP_NO_MEMORY_ERROR; - statep->overflow_buf_size = buf_sz; - statep->overflow = (usgnd_int_8 *) buf; - } - - memcpy((void *) (statep->overflow + statep->overflow_size), - (void *) *tracepp, - sz); - - tsz = statep->overflow_size + sz; - - tracep = statep->overflow; - trace_endp = statep->overflow + tsz; - - if (tsz < statep->fetch_size && statep->known_need) { - ASSERT(have_all_in_overflow); - statep->overflow_size = tsz; - op_endp = NULL; - result = EMTP_NEED_MORE_TRACE; - goto restore_return; - } - } - else { - tracep = *tracepp; - trace_endp = tracep + *trace_lenp; - } - - if (statep->progress == EMTP_PROGRESS_PARSE_BODY) { - -#if !HAVE_INT_64 - if (statep->flags & ERTS_MT_64_BIT_FLAG) - return EMTP_NOT_SUPPORTED_64_BITS_TRACE_ERROR; -#endif - - if (op_size < sizeof(emtp_operation)) - return EMTP_BAD_OP_SIZE_ERROR; - if (!op_start || !op_lenp || *op_lenp < 1) - return EMTP_NO_OPERATIONS_ERROR; - op_endp = (emtp_operation *) (((char *) op_start) + (*op_lenp)*op_size); - - restart_parse_body: -#if EMTP_CAN_INLINE - if (statep->parse_body_func) -#endif - result = (*statep->parse_body_func)(statep, - &tracep, trace_endp, - &op_p, op_endp, op_size); -#if EMTP_CAN_INLINE - else - result = parse_v2_body(statep, - &tracep, trace_endp, - &op_p, op_endp, op_size); -#endif - } - else { - restart_parse_header: - op_endp = NULL; - if (statep->progress == EMTP_PROGRESS_ENDED) { - result = EMTP_END_OF_TRACE; - goto restore_return; - } - result = parse_header(statep, &tracep, trace_endp); - } - - /* Check overflow */ - if (statep->overflow_size) { - if (tracep == statep->overflow) { - /* Nothing parsed, i.e. less new input than 1 entry :( */ - if (!have_all_in_overflow) - goto fetch_for_overflow; - statep->overflow_size = trace_endp - tracep; - trace_endp = tracep = *tracepp + *trace_lenp; - } - else { - size_t sz = tracep - (statep->overflow + statep->overflow_size); - - ASSERT(sz > 0); - - statep->overflow_size = 0; - - tracep = *tracepp + sz; - trace_endp = *tracepp + *trace_lenp; - ASSERT(trace_endp >= tracep); - if (!statep->force_return && (trace_endp - tracep)) { - if (statep->progress == EMTP_PROGRESS_PARSE_BODY) - goto restart_parse_body; - else - goto restart_parse_header; - } - /* else: got it all in the overflow buffer */ - } - } - else { - size_t sz = trace_endp - tracep; - if (!statep->force_return && sz) { - if (sz >= statep->fetch_size) { - ASSERT(0); - ERROR(EMTP_PARSE_ERROR); - } - if (sz > statep->overflow_buf_size) { - (*statep->free)((void *) statep->overflow); - statep->overflow = (usgnd_int_8 *) (*statep->alloc)(sz); - if (!statep->overflow) { - statep->overflow_buf_size = 0; - return EMTP_NO_MEMORY_ERROR; - } - statep->overflow_buf_size = sz; - } - memcpy((void *) statep->overflow, tracep, sz); - statep->overflow_size = sz; - ASSERT(tracep + sz == trace_endp); - tracep = trace_endp; - } - } - - restore_return: - ASSERT(trace_endp >= tracep); - - *tracepp = tracep; - *trace_lenp = trace_endp - tracep; - - if (op_lenp && op_size > 0) - *op_lenp = (int) (((char *) op_p) - ((char *) op_start))/op_size; - - return result; -} - -#ifdef DEBUG -static void -hexdump(void *start, void *end) -{ - unsigned char *p = (unsigned char *) start; - - fprintf(stderr, "hexdump: "); - while ((void *) p < end) { - fprintf(stderr, "%x", (unsigned) *p); - p++; - } - fprintf(stderr, "\n"); -} - -#if PRINT_PARSED_OP -static void -print_op(emtp_operation *op_p) -{ - switch (op_p->type) { - case EMTP_ALLOC: - fprintf(stderr, - "alloc: " - "type=%" USGND_INT_16_FSTR ", " - "ptr=%" USGND_INT_MAX_FSTR ", " - "sz=%" USGND_INT_MAX_FSTR ", " - "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")" - "\n", - op_p->u.block.type, - op_p->u.block.new_ptr, - op_p->u.block.new_size, - op_p->time.secs, - op_p->time.usecs); - break; - case EMTP_REALLOC: - fprintf(stderr, - "realloc: " - "type=%" USGND_INT_16_FSTR ", " - "ptr=%" USGND_INT_MAX_FSTR ", " - "prev_ptr=%" USGND_INT_MAX_FSTR ", " - "sz=%" USGND_INT_MAX_FSTR ", " - "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")" - "\n", - op_p->u.block.type, - op_p->u.block.new_ptr, - op_p->u.block.prev_ptr, - op_p->u.block.new_size, - op_p->time.secs, - op_p->time.usecs); - break; - case EMTP_FREE: - fprintf(stderr, - "free: " - "type=%" USGND_INT_16_FSTR ", " - "ptr=%" USGND_INT_MAX_FSTR ", " - "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")" - "\n", - op_p->u.block.type, - op_p->u.block.prev_ptr, - op_p->time.secs, - op_p->time.usecs); - break; - case EMTP_CARRIER_ALLOC: - fprintf(stderr, - "carrier_alloc: " - "type=%" USGND_INT_16_FSTR ", " - "carrier_type=%" USGND_INT_16_FSTR ", " - "ptr=%" USGND_INT_MAX_FSTR ", " - "sz=%" USGND_INT_MAX_FSTR ", " - "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")" - "\n", - op_p->u.block.type, - op_p->u.block.carrier_type, - op_p->u.block.new_ptr, - op_p->u.block.new_size, - op_p->time.secs, - op_p->time.usecs); - break; - case EMTP_CARRIER_REALLOC: - fprintf(stderr, - "carrier_realloc: " - "type=%" USGND_INT_16_FSTR ", " - "carrier_type=%" USGND_INT_16_FSTR ", " - "ptr=%" USGND_INT_MAX_FSTR ", " - "prev_ptr=%" USGND_INT_MAX_FSTR ", " - "sz=%" USGND_INT_MAX_FSTR ", " - "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")" - "\n", - op_p->u.block.type, - op_p->u.block.carrier_type, - op_p->u.block.new_ptr, - op_p->u.block.prev_ptr, - op_p->u.block.new_size, - op_p->time.secs, - op_p->time.usecs); - break; - case EMTP_CARRIER_FREE: - fprintf(stderr, - "carrier_free: " - "type=%" USGND_INT_16_FSTR ", " - "carrier_type=%" USGND_INT_16_FSTR ", " - "ptr=%" USGND_INT_MAX_FSTR ", " - "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")" - "\n", - op_p->u.block.type, - op_p->u.block.carrier_type, - op_p->u.block.prev_ptr, - op_p->time.secs, - op_p->time.usecs); - break; - case EMTP_STOP: - fprintf(stderr, - "stop: " - "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")" - "\n", - op_p->time.secs, - op_p->time.usecs); - break; - case EMTP_EXIT: - fprintf(stderr, - "exit: " - "status=%" USGND_INT_32_FSTR ", " - "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")" - "\n", - op_p->u.exit_status, - op_p->time.secs, - op_p->time.usecs); - break; - default: - fprintf(stderr, "Unknown op type: %d\n", op_p->type); - break; - } -} - -#endif -#endif diff --git a/lib/reltool/doc/src/reltool_examples.xml b/lib/reltool/doc/src/reltool_examples.xml index b77217dbf7..e270213c9d 100644 --- a/lib/reltool/doc/src/reltool_examples.xml +++ b/lib/reltool/doc/src/reltool_examples.xml @@ -432,16 +432,13 @@ Eshell V10.0 (abort with ^G) [{copy_file,"format_man_pages"}]}, {create_dir,"usr", [{create_dir,"lib", - [{copy_file,"liberts.a"}, - {copy_file,"liberl_interface_st.a"}, - {copy_file,"liberts_r.a"}, + [{copy_file,"liberl_interface_st.a"}, {copy_file,"libic.a"}, {copy_file,"liberl_interface.a"}, {copy_file,"libei_st.a"}, {copy_file,"libei.a"}]}, {create_dir,"include", - [{copy_file,"erl_memory_trace_parser.h"}, - {copy_file,"driver_int.h"}, + [{copy_file,"driver_int.h"}, {copy_file,"ei_connect.h"}, {copy_file,"ei.h"}, {copy_file,"erl_nif_api_funcs.h"}, @@ -476,8 +473,7 @@ Eshell V10.0 (abort with ^G) {copy_file,"liberts_internal_r.a"}, {copy_file,"libethread.a"}, {copy_file,"README"}]}, - {copy_file,"liberts.a"}, - {copy_file,"liberts_r.a"}]}, + ]}, {create_dir,"src",[{copy_file,"setuid_socket_wrap.c"}]}, {create_dir,"doc",[]}, {create_dir,"man",[]}, @@ -488,7 +484,6 @@ Eshell V10.0 (abort with ^G) {copy_file,[...]}, {copy_file,...}, {...}|...]}, - {copy_file,"erl_memory_trace_parser.h"}, {copy_file,"driver_int.h"}, {copy_file,"erl_nif_api_funcs.h"}, {copy_file,"erl_fixed_size_int_types.h"}, diff --git a/lib/tools/Makefile b/lib/tools/Makefile index b8625d8074..1dd9eeb03a 100644 --- a/lib/tools/Makefile +++ b/lib/tools/Makefile @@ -24,7 +24,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk # Macros # ---------------------------------------------------- -SUB_DIRECTORIES = c_src src doc/src examples emacs +SUB_DIRECTORIES = src doc/src examples emacs include vsn.mk VSN = $(TOOLS_VSN) diff --git a/lib/tools/c_src/Makefile b/lib/tools/c_src/Makefile deleted file mode 100644 index 0cdc50e6f5..0000000000 --- a/lib/tools/c_src/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Invoke with GNU make or clearmake -C gnu. -# - -include $(ERL_TOP)/make/run_make.mk - diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in deleted file mode 100644 index 878aa2cde6..0000000000 --- a/lib/tools/c_src/Makefile.in +++ /dev/null @@ -1,221 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2009-2020. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -include $(ERL_TOP)/make/output.mk -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/erts/include/internal/$(TARGET)/ethread.mk - -USING_VC=@MIXED_VC@ - -CC=@CC@ -LD=@LD@ -AR=@AR@ -RANLIB=@RANLIB@ -MKDIR=@MKDIR@ -INSTALL=@INSTALL@ -INSTALL_DIR=@INSTALL_DIR@ -INSTALL_DATA=@INSTALL_DATA@ -INSTALL_PROGRAM=@INSTALL_PROGRAM@ -LDFLAGS=@LDFLAGS@ - -ifeq ($(TYPE),debug) -CFLAGS = @DEBUG_CFLAGS@ -DDEBUG -TYPEMARKER=.debug -PRE_LD = -ifeq ($(TARGET),win32) -LDFLAGS += -g -endif -else -override TYPE=opt -CFLAGS = @CFLAGS@ -PRE_LD = -TYPEMARKER = -endif - -ifeq ($(findstring -D_GNU_SOURCE,$(CFLAGS)),) -THR_DEFS = $(ETHR_DEFS) -else -# Remove duplicate -D_GNU_SOURCE -THR_DEFS = $(filter-out -D_GNU_SOURCE%, $(ETHR_DEFS)) -endif - -LIBS=@LIBS@ -CREATE_DIRS= - -TT_DIR=$(TARGET)/$(TYPE) - -BIN_DIR=../bin/$(TARGET) -OBJ_DIR=../obj/$(TT_DIR) - -CREATE_DIRS += $(BIN_DIR) $(OBJ_DIR) - -PROGS= -DRIVERS= - - -# -# emem sources, objects, includes, libs, etc... -# - - -ifneq ($(strip $(ETHR_LIB_NAME)),) -# Need ethread package for emem -PROGS += $(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@ -endif - -EMEM_OBJ_DIR=$(OBJ_DIR)/emem -CREATE_DIRS += $(EMEM_OBJ_DIR) - -EMEM_INCLUDES = -I$(ERL_TOP)/erts/include \ - -I$(ERL_TOP)/erts/include/$(TARGET) \ - -I$(ERL_TOP)/erts/include/internal \ - -I$(ERL_TOP)/erts/include/internal/$(TARGET) - -EMEM_HEADERS = erl_memory_trace_block_table.h -EMEM_SRCS = erl_memory.c erl_memory_trace_block_table.c - -EMEM_CFLAGS = $(THR_DEFS) $(CFLAGS) $(EMEM_INCLUDES) -EMEM_LDFLAGS = $(LDFLAGS) - -ifeq ($(USING_VC), yes) -ifeq ($(TYPE),debug) -MT_LIB=MDd -else -MT_LIB=MD -endif - -EMEM_CFLAGS += -$(MT_LIB) -EMEM_LDFLAGS += -$(MT_LIB) -EMEM_ERTS_LIB=erts_$(MT_LIB)$(TYPEMARKER) - -else - -EMEM_ERTS_LIB=erts_r$(TYPEMARKER) - -endif - -EMEM_ETHR_LIBS=$(subst -l$(ETHR_LIB_NAME),-l$(ETHR_LIB_NAME)$(TYPEMARKER),$(subst -lerts_internal_r,-lerts_internal_r$(TYPEMARKER),$(ETHR_LIBS))) - -EMEM_LIBS = $(LIBS) \ - -L$(ERL_TOP)/erts/lib/$(TARGET) \ - -L$(ERL_TOP)/erts/lib/internal/$(TARGET) \ - -l$(EMEM_ERTS_LIB) \ - $(EMEM_ETHR_LIBS) - -EMEM_OBJS = $(addprefix $(EMEM_OBJ_DIR)/,$(notdir $(EMEM_SRCS:.c=.o))) - -ERTS_LIB = $(ERL_TOP/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE - -# -# Misc targets -# - -_create_dirs := $(shell mkdir -p $(CREATE_DIRS)) - -all: $(PROGS) $(DRIVERS) - -$(ERTS_LIB): - $(make_verbose)cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE) - - -docs: - -clean: - $(RM) -r ../obj/* - $(RM) -r ../bin/* - $(RM) ./*~ - -.PHONY: all erts_lib docs clean - -# -# Object targets -# - -$(EMEM_OBJ_DIR)/%.o: %.c - $(V_CC) $(EMEM_CFLAGS) -o $@ -c $< - -# -# Driver targets -# - -# -# Program targets -# - -$(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@: $(EMEM_OBJS) $(ERTS_LIB) - $(ld_verbose)$(PRE_LD) $(LD) $(EMEM_LDFLAGS) -o $@ $(EMEM_OBJS) $(EMEM_LIBS) - -# -# Release targets -# -include $(ERL_TOP)/make/otp_release_targets.mk -include ../vsn.mk -RELSYSDIR = $(RELEASE_PATH)/lib/tools-$(TOOLS_VSN) - -release_spec: all - $(INSTALL_DIR) "$(RELSYSDIR)/c_src" - $(INSTALL_DATA) $(EMEM_SRCS) $(EMEM_HEADERS) "$(RELSYSDIR)/c_src" -ifneq ($(PROGS),) - $(INSTALL_DIR) "$(RELSYSDIR)/bin" - $(INSTALL_PROGRAM) $(PROGS) "$(RELSYSDIR)/bin" -endif - -release_docs_spec: - -.PHONY: release_spec release_docs_spec - -# -# Make dependencies -# - -ifeq ($(USING_VC), yes) -DEP_CC=@EMU_CC@ -else -DEP_CC=$(CC) -endif - -SED_REPL_EMEM_OBJ_DIR=s|^\([^:]*\)\.o:|$$(EMEM_OBJ_DIR)/\1.o:|g -SED_REPL_OBJ_DIR=s|^\([^:]*\)\.o:|$$(OBJ_DIR)/\1.o:|g -SED_REPL_TT_DIR=s|$(TT_DIR)/|$$(TT_DIR)/|g -SED_REPL_TARGET=s|$(TARGET)/|$$(TARGET)/|g -SED_REPL_ERL_TOP=s|$(ERL_TOP)/|$$(ERL_TOP)/|g - -SED_EMEM_DEPEND=sed '$(SED_REPL_EMEM_OBJ_DIR);$(SED_REPL_TT_DIR);$(SED_REPL_TARGET);$(SED_REPL_ERL_TOP)' -SED_DEPEND=sed '$(SED_REPL_OBJ_DIR);$(SED_REPL_TT_DIR);$(SED_REPL_TARGET);$(SED_REPL_ERL_TOP)' - -DEPEND_MK=depend.mk - -dep depend: - [ $(v_p) == 0 ] && echo " GEN "$(DEPEND_MK) - $(V_colon)@echo "Generating dependency file $(DEPEND_MK)..." - @echo "# Generated dependency rules." > $(DEPEND_MK); - @echo "# Do *not* edit this file; instead, run 'make depend'." \ - >> $(DEPEND_MK); - @echo "# " >> $(DEPEND_MK); - @echo "# emem objects..." >> $(DEPEND_MK); - $(DEP_CC) -MM $(EMEM_CFLAGS) $(EMEM_SRCS) \ - | $(SED_EMEM_DEPEND) >> $(DEPEND_MK) - @echo "# EOF" >> $(DEPEND_MK); - -.PHONY: dep depend - -include $(DEPEND_MK) - -# eof diff --git a/lib/tools/c_src/depend.mk b/lib/tools/c_src/depend.mk deleted file mode 100644 index 01da30e7c6..0000000000 --- a/lib/tools/c_src/depend.mk +++ /dev/null @@ -1,17 +0,0 @@ -# Generated dependency rules. -# Do *not* edit this file; instead, run 'make depend'. -# -# emem objects... -$(EMEM_OBJ_DIR)/erl_memory.o: erl_memory.c \ - $(ERL_TOP)/erts/include/erl_fixed_size_int_types.h \ - $(ERL_TOP)/erts/include/$(TARGET)/erl_int_sizes_config.h \ - $(ERL_TOP)/erts/include/erl_memory_trace_parser.h \ - erl_memory_trace_block_table.h \ - $(ERL_TOP)/erts/include/internal/ethread.h \ - $(ERL_TOP)/erts/include/internal/$(TARGET)/ethread_header_config.h -$(EMEM_OBJ_DIR)/erl_memory_trace_block_table.o: erl_memory_trace_block_table.c \ - erl_memory_trace_block_table.h \ - $(ERL_TOP)/erts/include/erl_fixed_size_int_types.h \ - $(ERL_TOP)/erts/include/$(TARGET)/erl_int_sizes_config.h \ - $(ERL_TOP)/erts/include/erl_memory_trace_parser.h -# EOF diff --git a/lib/tools/c_src/erl_memory.c b/lib/tools/c_src/erl_memory.c deleted file mode 100644 index 78f3cc9caa..0000000000 --- a/lib/tools/c_src/erl_memory.c +++ /dev/null @@ -1,2947 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2003-2021. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -/* - * Description: - * - * Author: Rickard Green - */ - -/* Headers to include ... */ - -#ifdef __WIN32__ -# include <winsock2.h> -# undef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# include <windows.h> -typedef int socklen_t; -#else -# if defined(__linux__) && defined(__GNUC__) -# define _GNU_SOURCE 1 -# endif -# include <unistd.h> -# include <sys/types.h> -# include <sys/socket.h> -# include <netinet/in.h> -# include <fcntl.h> -# include <netdb.h> -# include <arpa/inet.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <limits.h> -#include <string.h> - -#include "erl_fixed_size_int_types.h" -#include "erl_memory_trace_parser.h" -#include "erl_memory_trace_block_table.h" -#include "ethread.h" - -/* Increment when changes are made */ -#define EMEM_VSN_STR "0.9" - -/* Features not fully implemented yet */ -#define EMEM_A_SWITCH 0 -#define EMEM_C_SWITCH 0 -#define EMEM_c_SWITCH 0 -#define EMEM_d_SWITCH 0 - -/* Some system specific defines ... */ -#ifdef __WIN32__ -# define ssize_t int -# define GET_SOCK_ERRNO() (WSAGetLastError() - WSABASEERR) -# define IS_INVALID_SOCKET(X) ((X) == INVALID_SOCKET) -# ifdef __GNUC__ -# define INLINE __inline__ -# else -# define INLINE __forceinline -# endif -# define DIR_SEP_CHAR '\\' -#else -# define SOCKET int -# define closesocket close -# define GET_SOCK_ERRNO() (errno ? errno : INT_MAX) -# define INVALID_SOCKET (-1) -# define IS_INVALID_SOCKET(X) ((X) < 0) -# ifdef __GNUC__ -# define INLINE __inline__ -# else -# define INLINE -# endif -# define DIR_SEP_CHAR '/' -#endif - -#define EM_ERL_CMD_FILE_NAME "erl_cmd.txt" -#define EM_OUTPUT_FILE_SUFFIX ".emem" - -#define PRINT_OPERATIONS 0 - -/* In VC++, noreturn is a declspec that has to be before the types, - * but in GNUC it is an attribute to be placed between return type - * and function name, hence __decl_noreturn <types> __noreturn <function name> - * - * at some platforms (e.g. Android) __noreturn is defined at sys/cdef.h - */ -#if __GNUC__ -# define __decl_noreturn -# ifndef __noreturn -# define __noreturn __attribute__((noreturn)) -# endif -#else -# if defined(__WIN32__) && defined(_MSC_VER) -# define __noreturn -# define __decl_noreturn __declspec(noreturn) -# else -# define __noreturn -# define __decl_noreturn -# endif -#endif - -/* Our own assert() ... */ -#ifdef DEBUG -#define ASSERT(A) ((A) ? (void)1 : assert_failed(__FILE__, __LINE__, #A)) -#include <stdio.h> -__decl_noreturn static void __noreturn assert_failed(char *f, int l, char *a) -{ - fprintf(stderr, "%s:%d: Assertion failed: %s\n", f, l, a); - abort(); -} - -#else -#define ASSERT(A) ((void) 1) -#endif - -#define ERR_RET(X) return (X) -#if 1 -# undef ERR_RET -# define ERR_RET(X) abort() -#endif - -/* #define HARD_DEBUG */ - - -#define EM_EXIT_RESULT (EMTBT_MIN_ERROR - 1) -#define EM_TRUNCATED_TRACE_ERROR (EMTBT_MIN_ERROR - 2) -#define EM_INTERNAL_ERROR (EMTBT_MIN_ERROR - 3) - -#define EM_DEFAULT_BUF_SZ 8192 - -#define EM_LINES_UNTIL_HEADER 20 -#define EM_NO_OF_OPS 400 -#define EM_MAX_CONSECUTIVE_TRACE_READS 10 -#define EM_MAX_NO_OF_TRACE_BUFS 1280 -#define EM_MIN_TRACE_READ_SIZE (EM_DEFAULT_BUF_SZ/20) -#define EM_TIME_FIELD_WIDTH 11 - -__decl_noreturn static void __noreturn error(int res); -__decl_noreturn static void __noreturn error_msg(int res, char *msg); - -typedef struct { - usgnd_int_max size; - usgnd_int_max min_size; - usgnd_int_max max_size; - usgnd_int_max max_ever_size; - usgnd_int_max no; - usgnd_int_max min_no; - usgnd_int_max max_no; - usgnd_int_max max_ever_no; - usgnd_int_max allocs; - usgnd_int_max reallocs; - usgnd_int_max frees; -} em_mem_info; - -typedef struct em_buffer_ { - struct em_buffer_ *next; - int write; - char *data; - char *data_end; - char *end; - size_t size; - char start[EM_DEFAULT_BUF_SZ]; -} em_buffer; - -typedef struct { - int no_writer; - int no_reader; - size_t tot_buf_size; - size_t max_buf_size; - char *name; - em_buffer *first; - em_buffer *last; - ethr_mutex mutex; - ethr_cond cond; - int used_def_buf_a; - em_buffer def_buf_a; - int used_def_buf_b; - em_buffer def_buf_b; -} em_buf_queue; - -typedef struct { - char *ptr; - size_t size; -} em_area; - -typedef struct { - char *name; - int ix; -} em_output_types; - -typedef struct { - - /* Memory allocation functions */ - void * (*alloc)(size_t); - void * (*realloc)(void *, size_t); - void (*free)(void *); - - emtbt_table *block_table; - emtbt_table **carrier_table; - - struct { - em_mem_info total; - em_mem_info *btype; - em_mem_info *allctr; - em_mem_info **allctr_prv_crr; - em_mem_info **allctr_usd_crr; - - struct { - usgnd_int_32 secs; - usgnd_int_32 usecs; - } stop_time; - emtp_op_type stop_reason; - usgnd_int_32 exit_status; - } info; - - /* Input ... */ - struct { - usgnd_int_16 listen_port; - SOCKET socket; - usgnd_int_max total_trace_size; - int error; - char *error_descr; - em_buf_queue queue; - } input; - - /* Output ... */ - struct { - usgnd_int_32 next_print; - usgnd_int_32 next_print_inc; - char *header; - size_t header_size; - size_t values_per_object; - size_t values_per_line; - size_t field_width; - int verbose; - int total; - int all_allctrs; - int no_allctrs; - em_output_types *allctrs; - int all_btypes; - int no_btypes; - em_output_types *btypes; - int max_min_values; - int block_counts; - int op_counts; - int lines_until_header; - FILE *stream; - char *file_name; -#if EMEM_d_SWITCH - char *dir_name; - FILE *erl_cmd_file; - struct { - ethr_mutex *mutex; - ethr_cond *cond; - } go; -#endif - em_buf_queue queue; - } output; - - /* Trace info */ - emtp_state *trace_state; - emtp_info trace_info; - -} em_state; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ - * Threads... * - * * -\* */ - -static INLINE void -mutex_init(ethr_mutex *mtx) -{ - int res = ethr_mutex_init(mtx); - if (res) - error_msg(res, "Mutex init"); -} - -static INLINE void -mutex_destroy(ethr_mutex *mtx) -{ - int res = ethr_mutex_destroy(mtx); - if (res) - error_msg(res, "Mutex destroy"); -} - -static INLINE void -mutex_lock(ethr_mutex *mtx) -{ - ethr_mutex_lock(mtx); -} - -static INLINE void -mutex_unlock(ethr_mutex *mtx) -{ - ethr_mutex_unlock(mtx); -} - -static INLINE void -cond_init(ethr_cond *cnd) -{ - int res = ethr_cond_init(cnd); - if (res) - error_msg(res, "Cond init"); -} - -static INLINE void -cond_destroy(ethr_cond *cnd) -{ - int res = ethr_cond_destroy(cnd); - if (res) - error_msg(res, "Cond destroy"); -} - -static INLINE void -cond_wait(ethr_cond *cnd, ethr_mutex *mtx) -{ - int res = ethr_cond_wait(cnd, mtx); - if (res != 0 && res != EINTR) - error_msg(res, "Cond wait"); -} - -static INLINE void -cond_signal(ethr_cond *cnd) -{ - ethr_cond_signal(cnd); -} - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ - * Buffer queues * - * * -\* */ - -static INLINE void -reset_buffer(em_buffer *b, size_t size) -{ - b->write = 1; - b->next = NULL; - if (size) { - b->size = size; - b->end = b->start + size; - } - b->data_end = b->data = b->start; -} - -static void -init_queue(em_state *state, em_buf_queue *queue) -{ - reset_buffer(&queue->def_buf_a, EM_DEFAULT_BUF_SZ); - reset_buffer(&queue->def_buf_b, EM_DEFAULT_BUF_SZ); - queue->first = NULL; - queue->last = NULL; - queue->no_writer = 0; - queue->no_reader = 0; - queue->tot_buf_size = 0; - queue->max_buf_size = ~0; - queue->name = ""; - queue->used_def_buf_a = 0; - queue->used_def_buf_b = 0; - mutex_init(&queue->mutex); - cond_init(&queue->cond); -} - -static void -destroy_queue(em_state *state, em_buf_queue *queue) -{ - while (queue->first) { - em_buffer *buf = queue->first; - queue->first = queue->first->next; - if (buf != &queue->def_buf_a && buf != &queue->def_buf_b) - (*state->free)((void *) buf); - } - mutex_destroy(&queue->mutex); - cond_destroy(&queue->cond); -} - -static void -disconnect_queue_writer(em_buf_queue *queue) -{ - mutex_lock(&queue->mutex); - queue->no_writer = 1; - cond_signal(&queue->cond); - mutex_unlock(&queue->mutex); -} - -static void -disconnect_queue_reader(em_buf_queue *queue) -{ - mutex_lock(&queue->mutex); - queue->no_reader = 1; - cond_signal(&queue->cond); - mutex_unlock(&queue->mutex); -} - -static int -is_queue_writer_disconnected(em_buf_queue *queue) -{ - int res; - mutex_lock(&queue->mutex); - res = queue->no_writer; - mutex_unlock(&queue->mutex); - return res; -} - -static int -is_queue_reader_disconnected(em_buf_queue *queue) -{ - int res; - mutex_lock(&queue->mutex); - res = queue->no_reader; - mutex_unlock(&queue->mutex); - return res; -} - -static INLINE void -dequeue(em_state *state, em_buf_queue *queue) -{ - em_buffer *buf; - - ASSERT(queue->first); - ASSERT(queue->tot_buf_size > 0); - - buf = queue->first; - queue->first = buf->next; - if (!queue->first) - queue->last = NULL; - - ASSERT(queue->tot_buf_size >= buf->size); - queue->tot_buf_size -= buf->size; - - if (buf == &queue->def_buf_a) - queue->used_def_buf_a = 0; - else if (buf == &queue->def_buf_b) - queue->used_def_buf_b = 0; - else - (*state->free)((void *) buf); - -} - - -static INLINE em_buffer * -enqueue(em_state *state, em_buf_queue *queue, size_t min_size) -{ - em_buffer *buf; - - if (min_size > EM_DEFAULT_BUF_SZ) - goto alloc_buf; - - if (!queue->used_def_buf_a) { - buf = &queue->def_buf_a; - queue->used_def_buf_a = 1; - reset_buffer(buf, 0); - } - else if (!queue->used_def_buf_b) { - buf = &queue->def_buf_b; - queue->used_def_buf_b = 1; - reset_buffer(buf, 0); - } - else { - size_t bsize; - alloc_buf: - - bsize = EM_DEFAULT_BUF_SZ; - if (bsize < min_size) - bsize = min_size; - - buf = (em_buffer *) (*state->alloc)(sizeof(em_buffer) - + (sizeof(char) - * (bsize-EM_DEFAULT_BUF_SZ))); - if (!buf) - error(ENOMEM); - buf->size = bsize; - reset_buffer(buf, bsize); - } - - if (queue->last) { - ASSERT(queue->first); - queue->last->write = 0; - queue->last->next = buf; - } - else { - ASSERT(!queue->first); - queue->first = buf; - } - - queue->tot_buf_size += buf->size; - queue->last = buf; - - return buf; -} - -static void -get_next_read_area(em_area *area, em_state *state, em_buf_queue *queue) -{ - mutex_lock(&queue->mutex); - - while (!queue->first || queue->first->data == queue->first->data_end) { - if (queue->first && (!queue->first->write - || queue->first->data == queue->first->end)) { - dequeue(state, queue); - continue; - } - - if (queue->no_writer) { - area->ptr = NULL; - area->size = 0; - mutex_unlock(&queue->mutex); - return; - } - cond_wait(&queue->cond, &queue->mutex); - } - - ASSERT(queue->first->data < queue->first->data_end); - - area->ptr = queue->first->data; - area->size = queue->first->data_end - queue->first->data; - - queue->first->data = queue->first->data_end; - - mutex_unlock(&queue->mutex); -} - -static INLINE void -wrote_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 void -wrote_area(em_area *area, em_state *state, em_buf_queue *queue) -{ - wrote_area_aux(area, state, queue, 1); -} - -static void -get_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)); - - ASSERT(buf); - ASSERT(buf->end - buf->data_end >= size); - area->ptr = buf->data_end; - area->size = buf->end - buf->data_end; - - 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_t -write_str(char **dstpp, char *srcp) -{ - size_t i = 0; - if (dstpp) - while (srcp[i]) - *((*dstpp)++) = srcp[i++]; - else - while (srcp[i]) i++; - return i; -} - - -static size_t -write_strings(char **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_t -write_title(char **bufp, size_t *overflow, size_t width, char *str) -{ - size_t i, sz, ws; - char *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 truncated; 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++) = ' '; - } - - i = 0; - while (str[i] && (overflow || p < endp)) - *(p++) = str[i++]; - - while (ws) { - ws--; - *(p++) = ' '; - } - - ASSERT(overflow || p == endp); - ASSERT(sz == (size_t) (p - *bufp)); - *bufp = p; - return sz; -} - -static size_t -write_obj_sub_titles(em_state *state, char **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_t -write_header(em_state *state, char *ptr, int trunc) -{ -#define MIN_LTEXT_SZ 18 -#define HEADER_EOL_STR "|\n" - char *p; - char **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 void -write_mem_info(em_state *state, char **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 void -write_max_ever_mem_info(em_state *state, char **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 void -print_string(em_state *state, char *str) -{ - em_area area = {NULL, 0}; - char *p; - - /* Get area */ - - get_next_write_area(&area,state,&state->output.queue,write_str(NULL,str)); - - p = area.ptr; - area.size = write_str(&p, str); - - /* Leave area */ - - wrote_area(&area, state, &state->output.queue); - -} - -static int -print_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; - socklen_t saddr_size = sizeof(saddr); - size_t size; - char *format = "> Emulator command line argument: +Mit %s\n"; - -#ifdef __clang_analyzer__ - /* CodeChecker does not seem to understand getsockname writes to saddr */ - memset(&saddr, 0, sizeof(saddr)); -#endif - 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_t -write_allocator_info(em_state *state, char *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; - char *p = ptr; - char **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]; - if (cpix == state->trace_info.segment_ix) - strings[i++] = "segment"; - else - strings[i++] = state->trace_info.allocator[cpix]->name; - } - strings[i] = NULL; - size += write_strings(pp,strings,crr_prv_str,line_prefix,max_line_size); - - i = 0; - for (j = 0; j <= state->trace_info.max_block_type_ix; j++) - if (state->trace_info.block_type[j]->allocator == aix) - strings[i++] = state->trace_info.block_type[j]->name; - strings[i] = NULL; - size += write_strings(pp,strings,blk_tp_str,line_prefix,max_line_size); - } - - (*state->free)((void *) strings); - - return size; -} - -static void -print_main_header(em_state *state) -{ -#if HAVE_INT_64 -#define MAX_WORD_SZ_STR "64" -#else -#define MAX_WORD_SZ_STR "32" -#endif - em_area area = {NULL, 0}; - char *format1 = - "> emem version: " EMEM_VSN_STR "\n" - "> Nodename: %s\n" - "> Hostname: %s\n" - "> Pid: %s\n" - "> Start time (UTC): "; - char *format2 = "%4.4" USGND_INT_32_FSTR - "-%2.2" USGND_INT_32_FSTR "-%2.2" USGND_INT_32_FSTR - " %2.2" USGND_INT_32_FSTR ":%2.2" USGND_INT_32_FSTR - ":%2.2" USGND_INT_32_FSTR ".%6.6" USGND_INT_32_FSTR "\n"; - char *format3 = - "> Trace parser version: %" USGND_INT_32_FSTR ".%" USGND_INT_32_FSTR - "\n" - "> Actual trace version: %" USGND_INT_32_FSTR ".%" USGND_INT_32_FSTR - "\n" - "> Maximum trace word size: " MAX_WORD_SZ_STR " bits\n" - "> Actual trace word size: %d bits\n"; - size_t size = (strlen(format1) + - (state->trace_info.start_time.month - ? (strlen(format2) + 7*10) - : 1) - + strlen(format3) - + strlen(state->trace_info.nodename) - + strlen(state->trace_info.hostname) - + strlen(state->trace_info.pid) - + 5*10 + 1); - - if (state->output.verbose) { - size += write_allocator_info(state, NULL); - } - - size += write_header(state, NULL, 0); - - /* Get area */ - get_next_write_area(&area, state, &state->output.queue, size); - - area.size = sprintf(area.ptr, - format1, - state->trace_info.nodename, - state->trace_info.hostname, - state->trace_info.pid); - if (state->trace_info.start_time.month) - area.size += sprintf(area.ptr + area.size, - format2, - state->trace_info.start_time.year, - state->trace_info.start_time.month, - state->trace_info.start_time.day, - state->trace_info.start_time.hour, - state->trace_info.start_time.minute, - state->trace_info.start_time.second, - state->trace_info.start_time.micro_second); - else - *(area.ptr + area.size++) = '\n'; - area.size += sprintf(area.ptr + area.size, - format3, - state->trace_info.version.parser.major, - state->trace_info.version.parser.minor, - state->trace_info.version.trace.major, - state->trace_info.version.trace.minor, - state->trace_info.bits); - - if (state->output.verbose) { - area.size += write_allocator_info(state, area.ptr + area.size); - } - - area.size += write_header(state, area.ptr + area.size, 0); - - /* Leave area */ - wrote_area(&area, state, &state->output.queue); -#undef MAX_WORD_SZ_STR -} - -static void -print_main_footer(em_state *state) -{ - em_area area = {NULL, 0}; - char *p; - int i; - char *stop_str = - "> Trace stopped\n"; - char *exit_str = - "> Emulator exited with code: %" USGND_INT_32_FSTR "\n"; - char *format = - "> Total trace size: %" USGND_INT_MAX_FSTR " bytes\n" - "> Average band width used: %" USGND_INT_MAX_FSTR " Kbit/s\n"; - size_t size; - usgnd_int_max tsz = state->input.total_trace_size; - usgnd_int_32 secs = state->info.stop_time.secs; - usgnd_int_32 usecs = state->info.stop_time.usecs; - usgnd_int_max bw; - - /* Max size of the max value line. Each value can at most use 21 - characters: largest possible usgnd_int_64 (20 digits) and one - white space. */ - size = state->output.values_per_line*21 + 1; - - switch (state->info.stop_reason) { - case EMTP_STOP: - size += strlen(stop_str) + 1; - break; - case EMTP_EXIT: - size += strlen(exit_str); - size += 10; /* Enough for one unsgn_int_32 */ - size++; - break; - default: - break; - } - size += strlen(format); - size += 2*20; /* Enough for two unsgn_int_64 */ - size += 2; - - bw = (tsz + 1023)/1024; - bw *= 1000; - bw /= secs*1000 + usecs/1000; - bw *= 8; - - /* Get area */ - - get_next_write_area(&area, state, &state->output.queue, size); - - p = area.ptr; - - p += sprintf(p, "> %-*s", EM_TIME_FIELD_WIDTH - 2, "Maximum:"); - - if (state->output.total) { - int six = state->trace_info.segment_ix; - write_max_ever_mem_info(state, &p, &state->info.total); - if (state->trace_info.have_segment_carrier_info) { - if (state->info.allctr_prv_crr[six]) - write_max_ever_mem_info(state, - &p, - state->info.allctr_prv_crr[six]); - if (state->info.allctr_usd_crr[six]) - write_max_ever_mem_info(state, - &p, - state->info.allctr_usd_crr[six]); - } - } - for (i = 0; i < state->output.no_allctrs; i++) { - int ix = state->output.allctrs[i].ix; - write_max_ever_mem_info(state, &p, &state->info.allctr[ix]); - if (state->info.allctr_prv_crr[ix]) - write_max_ever_mem_info(state, - &p, - state->info.allctr_prv_crr[ix]); - if (state->info.allctr_usd_crr[ix]) - write_max_ever_mem_info(state, - &p, - state->info.allctr_usd_crr[ix]); - } - for (i = 0; i < state->output.no_btypes; i++) - write_max_ever_mem_info(state, - &p, - &state->info.btype[state->output.btypes[i].ix]); - - p += sprintf(p, "\n"); - - switch (state->info.stop_reason) { - case EMTP_STOP: - p += sprintf(p, "%s", stop_str); - break; - case EMTP_EXIT: - p += sprintf(p, exit_str, state->info.exit_status); - break; - default: - break; - } - - p += sprintf(p, format, tsz, bw); - - area.size = p - area.ptr; - - ASSERT(area.size <= size); - - /* Leave area */ - - wrote_area(&area, state, &state->output.queue); - -} - -static void -print_info(em_state *state, usgnd_int_32 secs, char *extra) -{ - char *p; - int i; - size_t size; - em_area area = {NULL, 0}; - - /* Get area */ - - size = 0; - if (!state->output.lines_until_header) - size += state->output.header_size; - - /* Max size of one line of values. Each value can at most use 21 - characters: largest possible usgnd_int_64 (20 digits) and one white - space. */ - size += state->output.values_per_line*21 + 1; - - if (extra) - size += write_str(NULL, extra); - - get_next_write_area(&area, state, &state->output.queue, size); - - /* Write to area */ - - p = area.ptr; - - if (!state->output.lines_until_header) { - memcpy((void *) area.ptr, - (void *) state->output.header, - state->output.header_size); - p += state->output.header_size; - state->output.lines_until_header = EM_LINES_UNTIL_HEADER; - } - else - state->output.lines_until_header--; - - p += sprintf(p, "%*" USGND_INT_32_FSTR " ", EM_TIME_FIELD_WIDTH - 1, secs); - - if (state->output.total) { - int six = state->trace_info.segment_ix; - write_mem_info(state, &p, &state->info.total); - if (state->trace_info.have_segment_carrier_info) { - if (state->info.allctr_prv_crr[six]) - write_mem_info(state, &p, state->info.allctr_prv_crr[six]); - if (state->info.allctr_usd_crr[six]) - write_mem_info(state, &p, state->info.allctr_usd_crr[six]); - } - } - for (i = 0; i < state->output.no_allctrs; i++) { - int ix = state->output.allctrs[i].ix; - write_mem_info(state, &p, &state->info.allctr[ix]); - if (state->info.allctr_prv_crr[ix]) - write_mem_info(state, &p, state->info.allctr_prv_crr[ix]); - if (state->info.allctr_usd_crr[ix]) - write_mem_info(state, &p, state->info.allctr_usd_crr[ix]); - } - for (i = 0; i < state->output.no_btypes; i++) - write_mem_info(state, - &p, - &state->info.btype[state->output.btypes[i].ix]); - - p += sprintf(p, "\n"); - - if (extra) - p += write_str(&p, extra); - - ASSERT(area.size >= p - area.ptr); - area.size = p - area.ptr; - - /* Leave area */ - - wrote_area(&area, state, &state->output.queue); -} - -static void -reset_mem_info(em_mem_info *mi) -{ - mi->size = 0; - mi->min_size = 0; - mi->max_size = 0; - mi->max_ever_size = 0; - mi->no = 0; - mi->min_no = 0; - mi->max_no = 0; - mi->max_ever_no = 0; - mi->allocs = 0; - mi->reallocs = 0; - mi->frees = 0; -} - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ - * State creation and destruction * - * * -\* */ - -static void -destroy_state(em_state *state) -{ - int i; - void (*freep)(void *); - - freep = state->free; - - if (state->block_table) - emtbt_destroy_table(state->block_table); - - if (state->carrier_table) { - for (i = -1; i <= state->trace_info.max_allocator_ix; i++) - if (state->carrier_table[i]) - emtbt_destroy_table(state->carrier_table[i]); - state->carrier_table--; - (*freep)((void *) state->carrier_table); - } - - if (state->info.btype) { - state->info.btype--; - (*freep)((void *) state->info.btype); - } - - if (state->info.allctr) { - state->info.allctr--; - (*freep)((void *) state->info.allctr); - } - - if (state->info.allctr_prv_crr) { - for (i = -1; i <= state->trace_info.max_allocator_ix; i++) - if (state->info.allctr_prv_crr[i]) - (*freep)((void *) state->info.allctr_prv_crr[i]); - state->info.allctr_prv_crr--; - (*freep)((void *) state->info.allctr_prv_crr); - } - - - if (state->info.allctr_usd_crr) { - for (i = -1; i <= state->trace_info.max_allocator_ix; i++) - if (state->info.allctr_usd_crr[i]) - (*freep)((void *) state->info.allctr_usd_crr[i]); - state->info.allctr_usd_crr--; - (*freep)((void *) state->info.allctr_usd_crr); - } - - emtp_state_destroy(state->trace_state); - destroy_queue(state, &state->input.queue); - - if (state->output.btypes) - (*freep)((void *) state->output.btypes); - if (state->output.allctrs) - (*freep)((void *) state->output.allctrs); - destroy_queue(state, &state->output.queue); - -#if EMEM_d_SWITCH - - if (state->output.go.mutex) { - mutex_destroy(state->output.go.mutex); - (*state->free)((void *) state->output.go.mutex); - state->output.go.mutex = NULL; - } - if (state->output.go.cond) { - cond_destroy(state->output.go.cond); - (*state->free)((void *) state->output.go.cond); - state->output.go.cond = NULL; - } - -#endif - - if (!IS_INVALID_SOCKET(state->input.socket)) { - closesocket(state->input.socket); - state->input.socket = INVALID_SOCKET; - } - - (*freep)((void *) state); -} - -static em_state * -new_state(void * (*alloc)(size_t), - void * (*realloc)(void *, size_t), - void (*free)(void *)) -{ - em_state *state = NULL; - - state = (*alloc)(sizeof(em_state)); - if (!state) - goto error; - - /* Stuff that might fail (used after the error label) */ - - state->trace_state = NULL; - - /* Init state ... */ - - state->alloc = alloc; - state->realloc = realloc; - state->free = free; - - state->block_table = NULL; - state->carrier_table = NULL; - - reset_mem_info(&state->info.total); - state->info.btype = NULL; - state->info.allctr = NULL; - - state->info.allctr_prv_crr = NULL; - state->info.allctr_usd_crr = NULL; - - state->info.stop_time.secs = 0; - state->info.stop_time.usecs = 0; - state->info.stop_reason = EMTP_UNDEF; - state->info.exit_status = 0; - - state->output.next_print = 0; - state->output.next_print_inc = 10; - state->output.header = NULL; - state->output.header_size = 0; - state->output.values_per_object = 0; - state->output.values_per_line = 0; - state->output.field_width = 11; - state->output.verbose = 0; - state->output.total = 0; - state->output.all_allctrs = 0; - state->output.no_allctrs = 0; - state->output.allctrs = NULL; - state->output.all_btypes = 0; - state->output.no_btypes = 0; - state->output.btypes = NULL; - state->output.max_min_values = 0; - state->output.block_counts = 0; - state->output.op_counts = 0; - state->output.lines_until_header = EM_LINES_UNTIL_HEADER; - -#if PRINT_OPERATIONS - state->output.stream = stderr; -#else - state->output.stream = stdout; -#endif - state->output.file_name = NULL; -#if EMEM_d_SWITCH - state->output.dir_name = NULL; - state->output.erl_cmd_file = NULL; - state->output.go.mutex = NULL; - state->output.go.cond = NULL; -#endif - - init_queue(state, &state->output.queue); - state->output.queue.max_buf_size = 10*1024*1024; - state->output.queue.name = "output"; - - state->trace_state = emtp_state_new(alloc, realloc, free); - if (!state->trace_state) - goto error; - - state->trace_info.version.parser.major = 0; - state->trace_info.version.parser.minor = 0; - state->trace_info.version.trace.major = 0; - state->trace_info.version.trace.minor = 0; - state->trace_info.bits = 0; - state->trace_info.max_allocator_ix = 0; - state->trace_info.allocator = NULL; - state->trace_info.max_block_type_ix = 0; - state->trace_info.block_type = NULL; - - state->input.listen_port = 0; - state->input.socket = INVALID_SOCKET; - state->input.total_trace_size = 0; - state->input.error = 0; - state->input.error_descr = NULL; - - init_queue(state, &state->input.queue); - state->input.queue.max_buf_size = 10*1024*1024; - state->input.queue.name = "input"; - - return state; - - error: - if (state) { - if (state->trace_state) - emtp_state_destroy(state->trace_state); - (*free)(state); - } - return NULL; -} - - -static emtbt_table * -mk_block_table(em_state *state) -{ - return emtbt_new_table(state->trace_info.bits == 64, - state->alloc, - state->realloc, - state->free); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ - * * - * * -\* */ -#if PRINT_OPERATIONS -void print_op(em_state *state, emtp_operation *op); -#endif - -static INLINE void -update_max_values(em_mem_info *mi) -{ - if (mi->max_size < mi->size) - mi->max_size = mi->size; - if (mi->max_no < mi->no) - mi->max_no = mi->no; -} - -static INLINE void -update_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 void -update_alloc_op(em_mem_info *mi, usgnd_int_max size) -{ - mi->allocs++; - mi->size += size; - mi->no++; - update_max_values(mi); -} - -static INLINE void -update_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 void -update_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 int -insert_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) { - const 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; -} - -__decl_noreturn static void __noreturn -error(int res) -{ - error_msg(res, NULL); -} - -__decl_noreturn static void __noreturn -error_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_SWITCH - -static size_t -write_output_filename(char *ptr, - char *dirname, - char *nodename, - char *hostname, - char *datetime, - char *pid) -{ - size_t sz = 0; - char *p = ptr; - char **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; -} - -#endif - -static int -complete_state(em_state *state) -{ - int i, j, vpo, vpl; - void * (*allocp)(size_t); - void * (*reallocp)(void *, size_t); - 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; - - 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) { - 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 int -process_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, - (usgnd_int_8 **)&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, - (usgnd_int_8 **)&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 void -usage(char *sw, char *error) -{ - FILE *filep = stdout; -#ifdef __WIN32__ -#define SW_CHAR "/" -#else -#define SW_CHAR "-" -#endif - - if (error) { - ASSERT(sw); - 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 { - fprintf(filep, - "\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"); - exit(0); - } - -#undef SW_CHAR -} - - -static void -parse_args(em_state *state, int argc, char *argv[]) -{ - int port; - int i; - - 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 int -init_connection(em_state *state) -{ - int res; - SOCKET lsock; - SOCKET sock = INVALID_SOCKET; - struct sockaddr_in my_addr; - socklen_t 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) - goto do_listen; - goto error; - } - - lsock = sock; - state->input.socket = sock; - - res = print_emu_arg(state); - if (res != 0) - goto error; - - print_string(state, "> Waiting for emulator to connect... "); - - do_accept: - oth_addr_len = sizeof(oth_addr); - sock = accept(lsock, (struct sockaddr *) &oth_addr, &oth_addr_len); - if (IS_INVALID_SOCKET(sock)) { - res = GET_SOCK_ERRNO(); - if (res == EINTR) - goto do_accept; - sock = lsock; - goto error; - } - - print_string(state, "connected\n"); - - closesocket(lsock); - state->input.socket = sock; - - return 0; - - error: - if (!IS_INVALID_SOCKET(sock)) { - closesocket(sock); - state->input.socket = INVALID_SOCKET; - } - return res; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ - * IO threads * - * * -\* */ - -/* - * The input thread reads from a socket and puts the received data - * in the input buffer queue. - * - * Note: There is intentionally no flow control. If the emem program - * cannot process data as fast as it arrives, it is supposed - * to crash when hitting the maximum buffersize; otherwise, - * the traced emulator would be slowed down. - */ -static void * -input_thread_func(void *arg) -{ - int res; - char *edescr = NULL; - ssize_t recv_sz; - usgnd_int_max total_trace_size = 0; - em_state *state = (em_state *) arg; - em_area area = {NULL, 0}; - SOCKET sock = state->input.socket; - em_buf_queue *queue = &state->input.queue; - - while(1) { - get_next_write_area(&area, - state, - queue, - EM_MIN_TRACE_READ_SIZE); - - if (!area.ptr) { - res = ENOMEM; - edescr = "Input alloc"; - goto stop; - } - - do_recv: - if (is_queue_reader_disconnected(queue)) { - res = 0; - edescr = "Input"; - goto stop; - } - recv_sz = recv(sock, (void *) area.ptr, area.size, 0); - if (recv_sz <= 0) { - res = GET_SOCK_ERRNO(); - if (res == EINTR) - goto do_recv; - edescr = "Input recv"; - goto stop; - } - area.size = (size_t) recv_sz; - total_trace_size += (usgnd_int_max) recv_sz; - } - - stop: - state->input.error = res; - state->input.error_descr = edescr; - state->input.total_trace_size = total_trace_size; - disconnect_queue_writer(queue); - if (!IS_INVALID_SOCKET(state->input.socket)) { - closesocket(sock); - state->input.socket = INVALID_SOCKET; - } - return NULL; -} - - -static void * -output_thread_func(void *arg) -{ - em_state *state = (em_state *) arg; - em_area area = {NULL, 0}; - -#if EMEM_d_SWITCH - - if (state->output.go.mutex) { - mutex_lock(state->output.go.mutex); - while (!state->output.stream - && !is_queue_writer_disconnected(&state->output.queue)) - cond_wait(state->output.go.cond, state->output.go.mutex); - mutex_unlock(state->output.go.mutex); - - mutex_destroy(state->output.go.mutex); - (*state->free)((void *) state->output.go.mutex); - state->output.go.mutex = NULL; - cond_destroy(state->output.go.cond); - (*state->free)((void *) state->output.go.cond); - state->output.go.cond = NULL; - } - -#endif - - while (1) { - get_next_read_area(&area, state, &state->output.queue); - if (!area.size) { - disconnect_queue_reader(&state->output.queue); - if (is_queue_writer_disconnected(&state->output.queue)) - goto stop; - else - error_msg(EIO, "Output queue"); - } - if (fwrite((void *) area.ptr, - sizeof(char), - area.size, - state->output.stream) != area.size) { - disconnect_queue_reader(&state->output.queue); - error_msg(0, "Write"); - } - } - - stop: - if (state->output.stream != stdout && state->output.stream != stderr) - fclose(state->output.stream); - return NULL; -} - - -int -main(int argc, char *argv[]) -{ - int res, ires, jres; - ethr_tid input_tid; - ethr_tid output_tid; - em_state *state; - - /* set stdout in unbuffered mode */ - if (setvbuf(stdout, NULL, _IONBF, 0) != 0) { - fprintf(stderr, "emem: failed to set stdout in unbuffered mode\n"); - exit(1); - } - - if (ethr_init(NULL) != 0 || ethr_late_init(NULL) != 0) { - fprintf(stderr, "emem: failed to initialize thread package\n"); - exit(1); - } - - state = new_state(malloc, realloc, free); - if (!state) - error(ENOMEM); - - parse_args(state, argc, argv); - - res = ethr_thr_create(&output_tid, - output_thread_func, - (void *) state, - NULL); - if (res != 0) - error_msg(res, "Output thread create"); - -#ifdef DEBUG - print_string(state, "> [debug]\n"); -#endif - - res = init_connection(state); - if (res != 0) - error_msg(res, "Initialize connection"); - - res = ethr_thr_create(&input_tid, - input_thread_func, - (void *) state, - NULL); - if (res != 0) - error_msg(res, "Input thread create"); - - res = process_trace(state); - - disconnect_queue_reader(&state->input.queue); - - jres = ethr_thr_join(input_tid, NULL); - if (jres != 0) - error_msg(jres, "Input thread join"); - - if (res == EM_EXIT_RESULT) - print_main_footer(state); - disconnect_queue_writer(&state->output.queue); - - jres = ethr_thr_join(output_tid, NULL); - if (jres != 0) - error_msg(jres, "Output thread join"); - - ires = state->input.error; - - destroy_state(state); - -#ifdef __WIN32__ - WSACleanup(); -#endif - - switch (res) { - case EM_EXIT_RESULT: - break; - case EM_TRUNCATED_TRACE_ERROR: - error_msg(ires, state->input.error_descr); - break; - default: - error(res); - break; - } - - return 0; -} - - -#if PRINT_OPERATIONS -void -print_op(em_state *state, emtp_operation *op) -{ - -#if 0 - printf("%5" USGND_INT_32_FSTR ":%6.6" USGND_INT_32_FSTR " ", - op->time.secs, op->time.usecs); -#endif - if (state->trace_info.version.parser.major >= 2) { - - switch (op->type) { - case EMTP_ALLOC: - printf(" %" USGND_INT_MAX_FSTR " = alloc(%" USGND_INT_16_FSTR - ", %" USGND_INT_MAX_FSTR ")\n", - op->u.block.new_ptr, - op->u.block.type, - op->u.block.new_size); - break; - case EMTP_REALLOC: - printf(" %" USGND_INT_MAX_FSTR " = realloc(%" USGND_INT_16_FSTR - ", %" USGND_INT_MAX_FSTR ", %" USGND_INT_MAX_FSTR ")\n", - op->u.block.new_ptr, - op->u.block.type, - op->u.block.prev_ptr, - op->u.block.new_size); - break; - case EMTP_FREE: - printf(" free(%" USGND_INT_16_FSTR ", %" USGND_INT_MAX_FSTR ")" - "\n", - op->u.block.type, - op->u.block.prev_ptr); - break; - case EMTP_CARRIER_ALLOC: - printf(" %" USGND_INT_MAX_FSTR " = carrier_alloc(%" - USGND_INT_16_FSTR ", %" USGND_INT_16_FSTR ", %" - USGND_INT_MAX_FSTR ")\n", - op->u.block.new_ptr, - op->u.block.carrier_type, - op->u.block.type, - op->u.block.new_size); - break; - case EMTP_CARRIER_REALLOC: - printf(" %" USGND_INT_MAX_FSTR " = carrier_realloc(%" - USGND_INT_16_FSTR ", %" USGND_INT_16_FSTR ", %" - USGND_INT_MAX_FSTR ", %" USGND_INT_MAX_FSTR ")\n", - op->u.block.new_ptr, - op->u.block.carrier_type, - op->u.block.type, - op->u.block.prev_ptr, - op->u.block.new_size); - case EMTP_CARRIER_FREE: - printf(" carrier_free(%" USGND_INT_16_FSTR ", %" USGND_INT_16_FSTR - ", %" USGND_INT_MAX_FSTR ")\n", - op->u.block.carrier_type, - op->u.block.type, - op->u.block.prev_ptr); - break; - default: - printf(" op = %d\n", op->type); - break; - } - - } - else { - - switch (op->type) { - case EMTP_ALLOC: - printf(" %" USGND_INT_MAX_FSTR " = alloc(%" USGND_INT_MAX_FSTR ")" - "\n", - op->u.block.new_ptr, - op->u.block.new_size); - break; - case EMTP_REALLOC: - printf(" %" USGND_INT_MAX_FSTR " = realloc(%" USGND_INT_MAX_FSTR - ", %" USGND_INT_MAX_FSTR ")\n", - op->u.block.new_ptr, - op->u.block.prev_ptr, - op->u.block.new_size); - break; - case EMTP_FREE: - printf(" free(%" USGND_INT_MAX_FSTR ")\n", - op->u.block.prev_ptr); - break; - default: - printf(" op = %d\n", op->type); - break; - } - } - fflush(stdout); -} -#endif diff --git a/lib/tools/c_src/erl_memory_trace_block_table.c b/lib/tools/c_src/erl_memory_trace_block_table.c deleted file mode 100644 index ca7cb45a0e..0000000000 --- a/lib/tools/c_src/erl_memory_trace_block_table.c +++ /dev/null @@ -1,762 +0,0 @@ -/* ``Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * The Initial Developer of the Original Code is Ericsson Utvecklings AB. - * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings - * AB. All Rights Reserved.'' - * - * $Id$ - */ - - -/* - * Description: - * - * Author: Rickard Green - */ - -/* Headers to include ... */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "erl_memory_trace_block_table.h" -#include <errno.h> - -#undef HARD_DEBUG -#undef REALLY_HARD_DEBUG -#ifdef DEBUG -# define HARD_DEBUG 0 -# define REALLY_HARD_DEBUG 0 -#else -# define HARD_DEBUG 0 -# define REALLY_HARD_DEBUG 0 -#endif - -/* Some system specific defines ... */ -#if defined(__WIN32__) && !defined(__GNUC__) -# define INLINE __forceinline -#else -# ifdef __GNUC__ -# define INLINE __inline__ -# else -# define INLINE -# endif -#endif - -/* Our own assert() ... */ -#ifdef DEBUG -#define ASSERT(A) ((void) ((A) ? 1 : assert_failed(__FILE__, __LINE__, #A))) -#include <stdio.h> -static int assert_failed(char *f, int l, char *a) -{ - fprintf(stderr, "%s:%d: Assertion failed: %s\n", f, l, a); - abort(); - return 0; -} - -#else -#define ASSERT(A) ((void) 1) -#endif - - -#define EMTBT_BLOCKS_PER_POOL 1000 - -typedef struct emtbt_block_pool_ { - struct emtbt_block_pool_ *next; - emtbt_block blocks[1]; -} emtbt_block_pool; - -struct emtbt_table_ { - void * (*alloc)(size_t); - void * (*realloc)(void *, size_t); - void (*free)(void *); - int is_64_bit; - int no_blocks; - int no_of_buckets; - int max_used_buckets; - int min_used_buckets; - int used_buckets; - int current_size_index; - emtbt_block *blocks; - emtbt_block ** buckets; - - - /* Fixed size allocation of blocks */ - emtbt_block_pool *block_pools; - emtbt_block *free_blocks; - int blocks_per_pool; - -}; - - -static emtbt_block null_blk = {0}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ - * Block table * - * * -\* */ - -#if HARD_DEBUG -static void check_table(emtbt_table *table); -#endif - -static emtbt_block * -block_alloc_new_pool(emtbt_table *tab) -{ - size_t size; - emtbt_block_pool *poolp; - - size = sizeof(emtbt_block_pool) - sizeof(emtbt_block); - size += tab->blocks_per_pool*sizeof(emtbt_block); - - poolp = (*tab->alloc)(size); - - if (poolp) { - int i; - emtbt_block *blks; - - poolp->next = tab->block_pools; - tab->block_pools = poolp; - - blks = (emtbt_block *) poolp->blocks; - - for (i = 1; i < tab->blocks_per_pool - 1; i++) - blks[i].next = &blks[i + 1]; - blks[tab->blocks_per_pool - 1].next = NULL; - tab->free_blocks = &blks[1]; - - return &blks[0]; - } - return NULL; -} - -static INLINE emtbt_block * -block_alloc(emtbt_table *tab) -{ - emtbt_block *res; -#if HARD_DEBUG - check_table(tab); -#endif - - if (tab->free_blocks) { - res = tab->free_blocks; - tab->free_blocks = tab->free_blocks->next; - } - else { - res = block_alloc_new_pool(tab); - } - -#ifdef DEBUG - res->next = ((emtbt_block *) 0xfffffff0); - res->prev = ((emtbt_block *) 0xfffffff0); - res->bucket = ((emtbt_block **) 0xfffffff0); -#endif - -#if HARD_DEBUG - check_table(tab); -#endif - - return res; -} - -static INLINE void -block_free(emtbt_table *tab, emtbt_block *bp) -{ - -#if HARD_DEBUG - check_table(tab); -#endif - - bp->next = tab->free_blocks; - tab->free_blocks = bp; - -#if HARD_DEBUG - check_table(tab); -#endif - - -} - -#define PRIME0 ((usgnd_int_32) 268438039) -#define PRIME1 ((usgnd_int_32) 268440479) -#define PRIME2 ((usgnd_int_32) 268439161) -#define PRIME3 ((usgnd_int_32) 268437017) - -#define MK_HASH(H, P, IS64) \ -do { \ - (H) = (P) & 0xff; \ - (H) *= PRIME0; \ - (H) += ((P) >> 8) & 0xff; \ - (H) *= PRIME1; \ - (H) += ((P) >> 16) & 0xff; \ - (H) *= PRIME2; \ - (H) += ((P) >> 24) & 0xff; \ - (H) *= PRIME3; \ - if ((IS64)) { \ - (H) += ((P) >> 32) & 0xff; \ - (H) *= PRIME0; \ - (H) += ((P) >> 40) & 0xff; \ - (H) *= PRIME1; \ - (H) += ((P) >> 48) & 0xff; \ - (H) *= PRIME2; \ - (H) += ((P) >> 56) & 0xff; \ - (H) *= PRIME3; \ - } \ -} while (0) - -static const int table_sizes[] = { - 3203, - 4813, - 6421, - 9643, - 12853, - 19289, - 25717, - 51437, - 102877, - 205759, - 411527, - 823117, - 1646237, - 3292489, - 6584983, - 13169977, - 26339969, - 52679969 -}; - -#if HARD_DEBUG - -static void -check_table(emtbt_table *table) -{ - int no_blocks; - emtbt_block *block, *prev_block; - - no_blocks = 0; - block = table->blocks; - ASSERT(!block || !block->prev); - prev_block = NULL; - while (block) { - usgnd_int_32 hash; - MK_HASH(hash, block->pointer, table->is_64_bit); - ASSERT(hash == block->hash); - ASSERT(block->bucket - table->buckets - == hash % table->no_of_buckets); - ASSERT(!prev_block || prev_block == block->prev); - prev_block = block; - block = block->next; - no_blocks++; - ASSERT(table->no_blocks >= no_blocks); - } - - ASSERT(table->no_blocks == no_blocks); - -#if REALLY_HARD_DEBUG - { - int i; - for (i = 0; i < table->no_of_buckets; i++) { - int bucket_end_found; - emtbt_block **bucket; - if (!table->buckets[i]) - continue; - bucket_end_found = 0; - bucket = &table->buckets[i]; - for (block = table->blocks; block; block = block->next) { - if (block->bucket == bucket) { - if (!block->prev || block->prev->bucket != bucket) - ASSERT(*bucket == block); - if (!block->next || block->next->bucket != bucket) - bucket_end_found++; - } - } - ASSERT(bucket_end_found); - } - } -#endif - -} - -#endif - -static INLINE void -link_block(emtbt_table *table, emtbt_block **bucket, emtbt_block *block) -{ - ASSERT(bucket); - - block->bucket = bucket; - if (*bucket) { - block->next = *bucket; - block->prev = (*bucket)->prev; - if (block->prev) - block->prev->next = block; - else - table->blocks = block; - block->next->prev = block; - } - else { - block->next = table->blocks; - block->prev = NULL; - if (table->blocks) - table->blocks->prev = block; - table->blocks = block; - table->used_buckets++; - - } - *bucket = block; - table->no_blocks++; - -#if HARD_DEBUG - check_table(table); -#endif - -} - -static int -resize_table(emtbt_table *table, int new_no_of_buckets) -{ -#ifdef DEBUG - int org_no_blocks; -#endif - int i; - emtbt_block *block; - emtbt_block **buckets; - - if (new_no_of_buckets < table->no_of_buckets) { - /* shrink never fails */ - buckets = (emtbt_block **) (*table->realloc)(table->buckets, - (sizeof(emtbt_block *) - * new_no_of_buckets)); - if (!buckets) - return 1; - } - else if (new_no_of_buckets > table->no_of_buckets) { - (*table->free)((void *) table->buckets); - buckets = (emtbt_block **) (*table->alloc)((sizeof(emtbt_block *) - * new_no_of_buckets)); - if (!buckets) - return 0; - } - else - return 1; - - table->buckets = buckets; - table->no_of_buckets = new_no_of_buckets; - table->max_used_buckets = (4*new_no_of_buckets)/5; - table->min_used_buckets = new_no_of_buckets/5; - table->used_buckets = 0; - -#ifdef DEBUG - org_no_blocks = table->no_blocks; -#endif - - table->no_blocks = 0; - - - for (i = 0; i < new_no_of_buckets; i++) - buckets[i] = NULL; - - block = table->blocks; - table->blocks = NULL; - - while (block) { - emtbt_block *next_block = block->next; - link_block(table,&table->buckets[block->hash%new_no_of_buckets],block); - block = next_block; - } - - ASSERT(org_no_blocks == table->no_blocks); - - return 1; -} - -static INLINE int -grow_table(emtbt_table *table) -{ - if (table->current_size_index < sizeof(table_sizes)/sizeof(int)) { - int new_size; - table->current_size_index++; - new_size = table_sizes[table->current_size_index]; - ASSERT(new_size > 0); - return resize_table(table, new_size); - } - return 1; -} - -static INLINE void -shrink_table(emtbt_table *table) -{ - if (table->current_size_index > 0) { - int new_size; - table->current_size_index--; - new_size = table_sizes[table->current_size_index]; - ASSERT(new_size > 0); - (void) resize_table(table, new_size); - } -} - -static INLINE emtbt_block * -peek_block(emtbt_table *table, usgnd_int_max ptr) -{ - emtbt_block **bucket; - emtbt_block *block; - usgnd_int_32 hash; - - MK_HASH(hash, ptr, table->is_64_bit); - - bucket = &table->buckets[hash % table->no_of_buckets]; - block = *bucket; - if (!block) - return NULL; - - while (block->bucket == bucket) { - ASSERT(block); - if (block->pointer == ptr) - return block; - if (!block->next) - break; - block = block->next; - } - return NULL; -} - -static INLINE int -insert_block(emtbt_table *table, emtbt_block *block) -{ - emtbt_block **bucket; - emtbt_block *tmp_block; - usgnd_int_32 hash; - usgnd_int_max p; - -#if HARD_DEBUG - check_table(table); -#endif - - if (table->used_buckets >= table->max_used_buckets) { - if(!grow_table(table)) - return -1; - } - - p = block->pointer; - - MK_HASH(hash, p, table->is_64_bit); - block->hash = hash; - - bucket = &table->buckets[hash % table->no_of_buckets]; - tmp_block = *bucket; - if (tmp_block) { - while (tmp_block->bucket == bucket) { - if (tmp_block->pointer == p) - return 0; - if (!tmp_block->next) - break; - tmp_block = tmp_block->next; - } - } - - link_block(table, bucket, block); - - ASSERT(block == peek_block(table, p)); - - - return 1; -} - -static INLINE void -delete_block(emtbt_table *table, emtbt_block *block) -{ - emtbt_block **bucket; - - if (!block) - return; - -#if HARD_DEBUG - check_table(table); -#endif - - bucket = block->bucket; - ASSERT(bucket); - - if (block->prev) - block->prev->next = block->next; - else - table->blocks = block->next; - - if (block->next) - block->next->prev = block->prev; - - if (block == *bucket) { - ASSERT(!block->prev || block->prev->bucket != bucket); - if (block->next && block->next->bucket == bucket) - *bucket = block->next; - else { - ASSERT(table->used_buckets > 0); - *bucket = NULL; - table->used_buckets--; - } - } -#ifdef DEBUG - - block->next = ((emtbt_block *) 0xfffffff0); - block->prev = ((emtbt_block *) 0xfffffff0); - block->bucket = ((emtbt_block **) 0xfffffff0); -#endif - - ASSERT(table->no_blocks > 0); - table->no_blocks--; - - if (table->used_buckets < table->min_used_buckets) - shrink_table(table); - -#if HARD_DEBUG - check_table(table); -#endif - -} - -static INLINE emtbt_block * -fetch_block(emtbt_table *table, usgnd_int_max ptr) -{ - emtbt_block *block; - - block = peek_block(table, ptr); - delete_block(table, block); - return block; -} - - -const char *emtbt_error_string(int error) -{ - switch (error) { - case EMTBT_ALLOC_XBLK_ERROR: - return "Allocation to an already existing block"; - case EMTBT_REALLOC_NOBLK_ERROR: - return "Reallocation of non-existing block"; - case EMTBT_REALLOC_XBLK_ERROR: - return "Reallocation to an already existing block"; - case EMTBT_REALLOC_BLK_TYPE_MISMATCH: - return "Block types mismatch when reallocating"; - case EMTBT_FREE_NOBLK_ERROR: - return "Deallocation of non-existing block"; - case EMTBT_FREE_BLK_TYPE_MISMATCH: - return "Block types mismatch when deallocating"; - case EMTBT_INTERNAL_ERROR: - return "Block table internal error"; - default: - return NULL; - } - - -} - - -emtbt_table * -emtbt_new_table(int is_64_bit, - void * (*alloc)(size_t), - void * (*realloc)(void *, size_t), - void (*free)(void *)) -{ - emtbt_table *tab = (*alloc)(sizeof(emtbt_table)); - if (tab) { - tab->alloc = alloc; - tab->realloc = realloc; - tab->free = free; - tab->is_64_bit = is_64_bit; - tab->no_blocks = 0; - tab->no_of_buckets = 0; - tab->max_used_buckets = 0; - tab->min_used_buckets = 0; - tab->used_buckets = 0; - tab->current_size_index = 0; - tab->blocks = NULL; - tab->buckets = NULL; - - tab->block_pools = NULL; - tab->free_blocks = NULL; - tab->blocks_per_pool = EMTBT_BLOCKS_PER_POOL; - - } - return tab; -} - -void -emtbt_destroy_table(emtbt_table *tab) -{ - void (*freep)(void *); - emtbt_block_pool *poolp1, *poolp2; - - freep = tab->free; - - /* Free block pools */ - poolp1 = tab->block_pools; - while (poolp1) { - poolp2 = poolp1; - poolp1 = poolp1->next; - (*freep)((void *) poolp2); - } - - if (tab->buckets) - (*freep)((void *) tab->buckets); - - (*freep)((void *) tab); -} - - -#define CP_BLK(TO, FROM) \ -do { \ - (TO)->time.secs = (FROM)->time.secs; \ - (TO)->time.usecs = (FROM)->time.usecs; \ - (TO)->type = (FROM)->type; \ - (TO)->pointer = (FROM)->pointer; \ - (TO)->size = (FROM)->size; \ -} while (0) - -int -emtbt_alloc_op(emtbt_table *tab, emtp_operation *op) -{ - int res; - emtbt_block *blk; - - blk = block_alloc(tab); - if (!blk) - return ENOMEM; - - blk->time.secs = op->time.secs; - blk->time.usecs = op->time.usecs; - blk->type = op->u.block.type; - blk->pointer = op->u.block.new_ptr; - blk->size = op->u.block.new_size; - - res = insert_block(tab, blk); - if (res < 0) - return ENOMEM; - else if (res == 0) - return EMTBT_ALLOC_XBLK_ERROR; - return 0; -} - -int -emtbt_realloc_op(emtbt_table *tab, emtp_operation *op, emtbt_block *old_blk) -{ - int res; - emtbt_block *blk; - - if (!op->u.block.new_size) { - /* freed block */ - - blk = fetch_block(tab, op->u.block.prev_ptr); - if (!blk) - return EMTBT_REALLOC_NOBLK_ERROR; - - CP_BLK(old_blk, blk); - block_free(tab, blk); - } - else { - - if (!op->u.block.new_ptr) { - /* failed operation */ - if (!op->u.block.prev_ptr) - CP_BLK(old_blk, &null_blk); - else { - blk = peek_block(tab, op->u.block.prev_ptr); - if (!blk) - return EMTBT_REALLOC_NOBLK_ERROR; - CP_BLK(old_blk, blk); -#if 0 - if (blk->type != op->u.block.type) - return EMTBT_REALLOC_BLK_TYPE_MISMATCH; -#endif - } - } - else if (!op->u.block.prev_ptr) { - /* new block */ - - CP_BLK(old_blk, &null_blk); - blk = block_alloc(tab); - if (!blk) - return ENOMEM; - blk->type = op->u.block.type; - blk->pointer = op->u.block.new_ptr; - blk->time.secs = op->time.secs; - blk->time.usecs = op->time.usecs; - blk->size = op->u.block.new_size; - - res = insert_block(tab, blk); - if (res < 0) - return ENOMEM; - else if (res == 0) - return EMTBT_REALLOC_XBLK_ERROR; - } - else if (op->u.block.new_ptr == op->u.block.prev_ptr) { - /* resized block */ - blk = peek_block(tab, op->u.block.prev_ptr); - if (!blk) - return EMTBT_REALLOC_NOBLK_ERROR; - CP_BLK(old_blk, blk); - blk->time.secs = op->time.secs; - blk->time.usecs = op->time.usecs; - blk->size = op->u.block.new_size; -#if 0 - if (blk->type != op->u.block.type) - return EMTBT_REALLOC_BLK_TYPE_MISMATCH; -#endif - } - else { - /* moved block */ - blk = fetch_block(tab, op->u.block.prev_ptr); - if (!blk) - return EMTBT_REALLOC_NOBLK_ERROR; - CP_BLK(old_blk, blk); - blk->time.secs = op->time.secs; - blk->time.usecs = op->time.usecs; - blk->pointer = op->u.block.new_ptr; - blk->size = op->u.block.new_size; - res = insert_block(tab, blk); - if (res < 0) - return ENOMEM; - else if (res == 0) - return EMTBT_REALLOC_XBLK_ERROR; -#if 0 - if (blk->type != op->u.block.type) - return EMTBT_REALLOC_BLK_TYPE_MISMATCH; -#endif - } - } - return 0; - -} - - -int -emtbt_free_op(emtbt_table *tab, emtp_operation *op, emtbt_block *old_blk) -{ - emtbt_block *blk; - - if (!op->u.block.prev_ptr) - CP_BLK(old_blk, &null_blk); - else { - - blk = fetch_block(tab, op->u.block.prev_ptr); - if (!blk) - return EMTBT_FREE_NOBLK_ERROR; - - CP_BLK(old_blk, blk); - block_free(tab, blk); -#if 0 - if (blk->type != op->u.block.type) - return EMTBT_FREE_BLK_TYPE_MISMATCH; -#endif - } - return 0; -} diff --git a/lib/tools/c_src/erl_memory_trace_block_table.h b/lib/tools/c_src/erl_memory_trace_block_table.h deleted file mode 100644 index ead3afc8fb..0000000000 --- a/lib/tools/c_src/erl_memory_trace_block_table.h +++ /dev/null @@ -1,74 +0,0 @@ -/* ``Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * The Initial Developer of the Original Code is Ericsson Utvecklings AB. - * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings - * AB. All Rights Reserved.'' - * - * $Id$ - */ - - -/* - * Description: - * - * Author: Rickard Green - */ - -#ifndef ERL_MEMORY_TRACE_BLOCK_TABLE_H__ -#define ERL_MEMORY_TRACE_BLOCK_TABLE_H__ - -#include <stdlib.h> -#include "erl_fixed_size_int_types.h" -#include "erl_memory_trace_parser.h" - - -#define EMTBT_ALLOC_XBLK_ERROR (EMTP_MIN_ERROR - 1) -#define EMTBT_REALLOC_NOBLK_ERROR (EMTP_MIN_ERROR - 2) -#define EMTBT_REALLOC_XBLK_ERROR (EMTP_MIN_ERROR - 3) -#define EMTBT_REALLOC_BLK_TYPE_MISMATCH (EMTP_MIN_ERROR - 4) -#define EMTBT_FREE_NOBLK_ERROR (EMTP_MIN_ERROR - 5) -#define EMTBT_FREE_BLK_TYPE_MISMATCH (EMTP_MIN_ERROR - 6) -#define EMTBT_INTERNAL_ERROR (EMTP_MIN_ERROR - 7) - -#define EMTBT_MIN_ERROR EMTBT_INTERNAL_ERROR - - -typedef struct emtbt_block_ { - - struct emtbt_block_ * next; - struct emtbt_block_ * prev; - usgnd_int_32 hash; - struct emtbt_block_ ** bucket; - - struct { - usgnd_int_32 secs; - usgnd_int_32 usecs; - } time; - usgnd_int_16 type; - usgnd_int_max pointer; - usgnd_int_max size; -} emtbt_block; - -typedef struct emtbt_table_ emtbt_table; - -const char *emtbt_error_string(int); -emtbt_table *emtbt_new_table(int, - void * (*)(size_t), - void * (*)(void *, size_t), - void (*)(void *)); -void emtbt_destroy_table(emtbt_table *); -int emtbt_alloc_op(emtbt_table *tab, emtp_operation *op); -int emtbt_realloc_op(emtbt_table *, emtp_operation *, emtbt_block *); -int emtbt_free_op(emtbt_table *, emtp_operation *, emtbt_block *); - -#endif diff --git a/lib/tools/test/Makefile b/lib/tools/test/Makefile index 350b936978..c5d0156c2e 100644 --- a/lib/tools/test/Makefile +++ b/lib/tools/test/Makefile @@ -24,7 +24,6 @@ MODULES = \ cover_SUITE \ eprof_SUITE \ emacs_SUITE \ - emem_SUITE \ fprof_SUITE \ cprof_SUITE \ instrument_SUITE \ diff --git a/lib/tools/test/emem_SUITE.erl b/lib/tools/test/emem_SUITE.erl deleted file mode 100644 index 968b360883..0000000000 --- a/lib/tools/test/emem_SUITE.erl +++ /dev/null @@ -1,654 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2005-2021. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% --module(emem_SUITE). - --export([all/0, suite/0, - init_per_testcase/2, end_per_testcase/2, - init_per_suite/1, end_per_suite/1, - receive_and_save_trace/2, send_trace/2]). - --export([live_node/1, - 'sparc_sunos5.8_32b_emt2.0'/1, - 'pc_win2000_32b_emt2.0'/1, - 'pc.smp_linux2.2.19pre17_32b_emt2.0'/1, - 'powerpc_darwin7.7.0_32b_emt2.0'/1, - 'alpha_osf1v5.1_64b_emt2.0'/1, - 'sparc_sunos5.8_64b_emt2.0'/1, - 'sparc_sunos5.8_32b_emt1.0'/1, - 'pc_win2000_32b_emt1.0'/1, - 'powerpc_darwin7.7.0_32b_emt1.0'/1, - 'alpha_osf1v5.1_64b_emt1.0'/1, - 'sparc_sunos5.8_64b_emt1.0'/1]). - --include_lib("kernel/include/file.hrl"). --include_lib("common_test/include/ct.hrl"). - --define(EMEM_64_32_COMMENT, - "64 bit trace; this build of emem can only handle 32 bit traces"). - --record(emem_res, {nodename, - hostname, - pid, - start_time, - trace_version, - max_word_size, - word_size, - last_values, - maximum, - exit_code}). - -%% -%% Exported suite functions -%% - -suite() -> - [{ct_hooks,[ts_install_cth]}, - {timetrap,{minutes,5}}]. - -all() -> - case test_server:is_debug() of - true -> {skip, "Not run when debug compiled"}; - false -> test_cases() - end. - - -test_cases() -> - [live_node, 'sparc_sunos5.8_32b_emt2.0', - 'pc_win2000_32b_emt2.0', - 'pc.smp_linux2.2.19pre17_32b_emt2.0', - 'powerpc_darwin7.7.0_32b_emt2.0', - 'alpha_osf1v5.1_64b_emt2.0', - 'sparc_sunos5.8_64b_emt2.0', - 'sparc_sunos5.8_32b_emt1.0', 'pc_win2000_32b_emt1.0', - 'powerpc_darwin7.7.0_32b_emt1.0', - 'alpha_osf1v5.1_64b_emt1.0', - 'sparc_sunos5.8_64b_emt1.0']. - -init_per_testcase(Case, Config) when is_list(Config) -> - case maybe_skip(Config) of - {skip, _}=Skip -> - Skip; - ok -> - %% Until emem is completely stable we run these tests in a working - %% directory with an ignore_core_files file which will make the - %% search for core files ignore cores generated by this suite. - ignore_cores:setup(?MODULE, Case, [{testcase, Case}|Config]) - end. - -end_per_testcase(_Case, Config) when is_list(Config) -> - ignore_cores:restore(Config), - ok. - -maybe_skip(Config) -> - DataDir = proplists:get_value(data_dir, Config), - case filelib:is_dir(DataDir) of - false -> - {skip, "No data directory"}; - true -> - case proplists:get_value(emem, Config) of - undefined -> - {skip, "emem not found"}; - _ -> - ok - end - end. - -init_per_suite(Config) when is_list(Config) -> - BinDir = filename:join([code:lib_dir(tools), "bin"]), - Target = erlang:system_info(system_architecture), - Res = (catch begin - case check_dir(filename:join([BinDir, Target])) of - not_found -> ok; - TDir -> - check_emem(TDir, debug), - check_emem(TDir, opt) - end, - check_emem(BinDir, opt), - "" - end), - Res ++ ignore_cores:init(Config). - -end_per_suite(Config) when is_list(Config) -> - Config1 = lists:keydelete(emem, 1, Config), - Config2 = lists:keydelete(emem_comment, 1, Config1), - ignore_cores:fini(Config2). - -%% -%% -%% Test cases -%% -%% - -live_node(Config) when is_list(Config) -> - {ok, EmuFlag, Port} = start_emem(Config), - Nodename = mk_nodename(Config), - {ok, Node} = start_node(Nodename, EmuFlag), - NP = spawn(Node, - fun () -> - receive go -> ok end, - I = spawn(fun () -> ignorer end), - GC = fun () -> - GCP = fun (P) -> - garbage_collect(P) - end, - lists:foreach(GCP, processes()) - end, - Seq = fun () -> I ! lists:seq(1, 1000000) end, - spawn_link(Seq), - B1 = <<0:10000000>>, - spawn_link(Seq), - B2 = <<0:10000000>>, - spawn_link(Seq), - B3 = <<0:10000000>>, - I ! {B1, B2, B3}, - GC(), - GC(), - GC() - end), - MRef = erlang:monitor(process, NP), - NP ! go, - receive - {'DOWN', MRef, process, NP, Reason} -> - spawn(Node, fun () -> halt(17) end), - normal = Reason - end, - Res = get_emem_result(Port), - {ok, Hostname} = inet:gethostname(), - ShortHostname = short_hostname(Hostname), - {true, _} = has_prefix(Nodename, Res#emem_res.nodename), - ShortHostname = short_hostname(Res#emem_res.hostname), - Bits = case erlang:system_info(wordsize) of - 4 -> "32 bits"; - 8 -> "64 bits" - end, - Bits = Res#emem_res.word_size, - "17" = Res#emem_res.exit_code, - emem_comment(Config). - -'sparc_sunos5.8_32b_emt2.0'(Config) when is_list(Config) -> - Res = run_emem_on_casefile(Config), - "test_server" = Res#emem_res.nodename, - "gorbag" = Res#emem_res.hostname, - "17074" = Res#emem_res.pid, - "2005-01-14 17:28:37.881980" = Res#emem_res.start_time, - "2.0" = Res#emem_res.trace_version, - "32 bits" = Res#emem_res.word_size, - ["15", "2665739", "8992", "548986", "16131", "539994", - "4334192", "1", "99", "15", "98", - "0", "0", "49", "0", "49"] = Res#emem_res.last_values, - ["5972061", "9662", "7987824", "5", - "2375680", "3"] = Res#emem_res.maximum, - "0" = Res#emem_res.exit_code, - emem_comment(Config). - -'pc_win2000_32b_emt2.0'(Config) when is_list(Config) -> - Res = run_emem_on_casefile(Config), - "test_server" = Res#emem_res.nodename, - "E-788FCF5191B54" = Res#emem_res.hostname, - "504" = Res#emem_res.pid, - "2005-01-24 17:27:28.224000" = Res#emem_res.start_time, - "2.0" = Res#emem_res.trace_version, - "32 bits" = Res#emem_res.word_size, - ["11", "2932575", "8615", "641087", "68924", "632472"] - = Res#emem_res.last_values, - ["5434206", "9285"] = Res#emem_res.maximum, - "0" = Res#emem_res.exit_code, - emem_comment(Config). - -'pc.smp_linux2.2.19pre17_32b_emt2.0'(Config) when is_list(Config) -> - Res = run_emem_on_casefile(Config), - "test_server" = Res#emem_res.nodename, - "four-roses" = Res#emem_res.hostname, - "20689" = Res#emem_res.pid, - "2005-01-20 13:11:26.143077" = Res#emem_res.start_time, - "2.0" = Res#emem_res.trace_version, - "32 bits" = Res#emem_res.word_size, - ["49", "2901817", "9011", "521610", "10875", "512599", - "5392096", "2", "120", "10", "118", - "0", "0", "59", "0", "59"] = Res#emem_res.last_values, - ["6182918", "9681", - "9062112", "6", - "2322432", "3"] = Res#emem_res.maximum, - "0" = Res#emem_res.exit_code, - emem_comment(Config). - - -'powerpc_darwin7.7.0_32b_emt2.0'(Config) when is_list(Config) -> - Res = run_emem_on_casefile(Config), - "test_server" = Res#emem_res.nodename, - "grima" = Res#emem_res.hostname, - "13021" = Res#emem_res.pid, - "2005-01-20 15:08:17.568668" = Res#emem_res.start_time, - "2.0" = Res#emem_res.trace_version, - "32 bits" = Res#emem_res.word_size, - ["9", "2784323", "8641", "531105", "15893", "522464"] - = Res#emem_res.last_values, - ["6150376", "9311"] = Res#emem_res.maximum, - "0" = Res#emem_res.exit_code, - emem_comment(Config). - -'alpha_osf1v5.1_64b_emt2.0'(Config) when is_list(Config) -> - Res = run_emem_on_casefile(Config), - "test_server" = Res#emem_res.nodename, - "thorin" = Res#emem_res.hostname, - "224630" = Res#emem_res.pid, - "2005-01-20 22:38:01.299632" = Res#emem_res.start_time, - "2.0" = Res#emem_res.trace_version, - "64 bits" = Res#emem_res.word_size, - case Res#emem_res.max_word_size of - "32 bits" -> - emem_comment(Config, ?EMEM_64_32_COMMENT); - "64 bits" -> - ["22", - "6591992", "8625", "516785", "14805", "508160", - "11429184", "5", "127", "254", "122", - "0", "0", "61", "0", "61"] = Res#emem_res.last_values, - ["7041775", "9295", - "11593024", "7", - "2097152", "3"] = Res#emem_res.maximum, - "0" = Res#emem_res.exit_code, - emem_comment(Config) - end. - -'sparc_sunos5.8_64b_emt2.0'(Config) when is_list(Config) -> - Res = run_emem_on_casefile(Config), - "test_server" = Res#emem_res.nodename, - "gorbag" = Res#emem_res.hostname, - "10907" = Res#emem_res.pid, - "2005-01-20 13:48:34.677068" = Res#emem_res.start_time, - "2.0" = Res#emem_res.trace_version, - "64 bits" = Res#emem_res.word_size, - case Res#emem_res.max_word_size of - "32 bits" -> - emem_comment(Config, ?EMEM_64_32_COMMENT); - "64 bits" -> - ["16", - "5032887", "8657", "530635", "14316", "521978", - "8627140", "5", "139", "19", "134", - "0", "0", "67", "0", "67"] = Res#emem_res.last_values, - ["11695070", "9324", - "16360388", "10", - "4136960", "3"] = Res#emem_res.maximum, - "0" = Res#emem_res.exit_code, - emem_comment(Config) - end. - -'sparc_sunos5.8_32b_emt1.0'(Config) when is_list(Config) -> - Res = run_emem_on_casefile(Config), - "" = Res#emem_res.nodename, - "" = Res#emem_res.hostname, - "" = Res#emem_res.pid, - "" = Res#emem_res.start_time, - "1.0" = Res#emem_res.trace_version, - "32 bits" = Res#emem_res.word_size, - ["11", "2558261", "8643", "560610", "15325", "551967"] - = Res#emem_res.last_values, - ["2791121", "9317"] = Res#emem_res.maximum, - "0" = Res#emem_res.exit_code, - emem_comment(Config). - -'pc_win2000_32b_emt1.0'(Config) when is_list(Config) -> - Res = run_emem_on_casefile(Config), - "" = Res#emem_res.nodename, - "" = Res#emem_res.hostname, - "" = Res#emem_res.pid, - "" = Res#emem_res.start_time, - "1.0" = Res#emem_res.trace_version, - "32 bits" = Res#emem_res.word_size, - ["6", "2965248", "8614", "640897", "68903", "632283"] - = Res#emem_res.last_values, - ["3147090", "9283"] = Res#emem_res.maximum, - "0" = Res#emem_res.exit_code, - emem_comment(Config). - - -'powerpc_darwin7.7.0_32b_emt1.0'(Config) when is_list(Config) -> - Res = run_emem_on_casefile(Config), - "" = Res#emem_res.nodename, - "" = Res#emem_res.hostname, - "" = Res#emem_res.pid, - "" = Res#emem_res.start_time, - "1.0" = Res#emem_res.trace_version, - "32 bits" = Res#emem_res.word_size, - ["8", "2852991", "8608", "529662", "15875", "521054"] - = Res#emem_res.last_values, - ["3173335", "9278"] = Res#emem_res.maximum, - "0" = Res#emem_res.exit_code, - emem_comment(Config). - -'alpha_osf1v5.1_64b_emt1.0'(Config) when is_list(Config) -> - Res = run_emem_on_casefile(Config), - "" = Res#emem_res.nodename, - "" = Res#emem_res.hostname, - "" = Res#emem_res.pid, - "" = Res#emem_res.start_time, - "1.0" = Res#emem_res.trace_version, - "64 bits" = Res#emem_res.word_size, - case Res#emem_res.max_word_size of - "32 bits" -> - emem_comment(Config, ?EMEM_64_32_COMMENT); - "64 bits" -> - ["22", - "6820094", "8612", "515518", "14812", "506906"] - = Res#emem_res.last_values, - ["7292413", "9282"] = Res#emem_res.maximum, - "0" = Res#emem_res.exit_code, - emem_comment(Config) - end. - -'sparc_sunos5.8_64b_emt1.0'(Config) when is_list(Config) -> - Res = run_emem_on_casefile(Config), - "" = Res#emem_res.nodename, - "" = Res#emem_res.hostname, - "" = Res#emem_res.pid, - "" = Res#emem_res.start_time, - "1.0" = Res#emem_res.trace_version, - "64 bits" = Res#emem_res.word_size, - case Res#emem_res.max_word_size of - "32 bits" -> - emem_comment(Config, ?EMEM_64_32_COMMENT); - "64 bits" -> - ["15", - "4965746", "8234", "543940", "14443", "535706"] - = Res#emem_res.last_values, - ["11697645", "8908"] = Res#emem_res.maximum, - "0" = Res#emem_res.exit_code, - emem_comment(Config) - end. - -%% -%% -%% Auxiliary functions -%% -%% - -receive_and_save_trace(PortNumber, FileName) when is_integer(PortNumber), - is_list(FileName) -> - {ok, F} = file:open(FileName, [write, compressed]), - {ok, LS} = gen_tcp:listen(PortNumber, [inet, {reuseaddr,true}, binary]), - {ok, S} = gen_tcp:accept(LS), - gen_tcp:close(LS), - receive_loop(S,F). - -receive_loop(Socket, File) -> - receive - {tcp, Socket, Data} -> - ok = file:write(File, Data), - receive_loop(Socket, File); - {tcp_closed, Socket} -> - file:close(File), - ok; - {tcp_error, Socket, Reason} -> - file:close(File), - {error, Reason} - end. - -send_trace({Host, PortNumber}, FileName) when is_list(Host), - is_integer(PortNumber), - is_list(FileName) -> - {ok, F} = file:open(FileName, [read, compressed]), - {ok, S} = gen_tcp:connect(Host, PortNumber, [inet,{packet, 0}]), - send_loop(S, F); -send_trace(EmuFlag, FileName) when is_list(EmuFlag), - is_list(FileName) -> - ["+Mit", IpAddrStr, PortNoStr] = string:tokens(EmuFlag, " :"), - send_trace({IpAddrStr, list_to_integer(PortNoStr)}, FileName). - -send_loop(Socket, File) -> - case file:read(File, 128) of - {ok, Data} -> - case gen_tcp:send(Socket, Data) of - ok -> send_loop(Socket, File); - Error -> - gen_tcp:close(Socket), - file:close(File), - Error - end; - eof -> - gen_tcp:close(Socket), - file:close(File), - ok; - Error -> - gen_tcp:close(Socket), - file:close(File), - Error - end. - -check_emem(Dir, Type) when is_atom(Type) -> - ExeSuffix = case os:type() of - {win32, _} -> ".exe"; - _ -> "" - end, - TypeSuffix = case Type of - opt -> ""; - _ -> "." ++ atom_to_list(Type) - end, - Emem = "emem" ++ TypeSuffix ++ ExeSuffix, - case check_file(filename:join([Dir, Emem])) of - not_found -> ok; - File -> - Comment = case Type of - opt -> ""; - _ -> "[emem " ++ atom_to_list(Type) ++ " compiled]" - end, - throw([{emem, File}, {emem_comment, Comment}]) - end. - -check_dir(DirName) -> - case file:read_file_info(DirName) of - {ok, #file_info {type = directory, access = A}} when A == read; - A == read_write -> - DirName; - _ -> - not_found - end. - -check_file(FileName) -> - case file:read_file_info(FileName) of - {ok, #file_info {type = regular, access = A}} when A == read; - A == read_write -> - FileName; - _ -> - not_found - end. - -emem_comment(Config) when is_list(Config) -> - emem_comment(Config, ""). - -emem_comment(Config, ExtraComment) - when is_list(Config), is_list(ExtraComment) -> - case {proplists:get_value(emem_comment, Config), ExtraComment} of - {"", ""} -> ok; - {"", XC} -> {comment, XC}; - {EmemC, ""} -> {comment, EmemC}; - {EmemC, XC} -> {comment, EmemC ++ " " ++ XC} - end. - -run_emem_on_casefile(Config) -> - CaseName = atom_to_list(proplists:get_value(testcase, Config)), - File = filename:join([proplists:get_value(data_dir, Config), CaseName ++ ".gz"]), - case check_file(File) of - not_found -> - ct:fail({error, {filenotfound, File}}); - _ -> - ok - end, - {ok, EmuFlag, Port} = start_emem(Config), - Parent = self(), - Ref = make_ref(), - spawn_link(fun () -> - SRes = send_trace(EmuFlag, File), - Parent ! {Ref, SRes} - end), - Res = get_emem_result(Port), - receive - {Ref, ok} -> - ok; - {Ref, SendError} -> - io:format("Send result: ~p~n", [SendError]) - end, - Res. - -get_emem_result(Port) -> - {Res, LV} = get_emem_result(Port, {#emem_res{}, []}), - Res#emem_res{last_values = string:tokens(LV, " ")}. - -get_emem_result(Port, {_EmemRes, _LastValues} = Res) -> - case get_emem_line(Port) of - eof -> - Res; - Line -> - get_emem_result(Port, parse_emem_line(Line, Res)) - end. - -parse_emem_main_header_footer_line(Line, {ER, LV} = Res) -> - - %% Header - case has_prefix("> Nodename:", Line) of - {true, NN} -> - throw({ER#emem_res{nodename = strip(NN)}, LV}); - false -> ok - end, - case has_prefix("> Hostname:", Line) of - {true, HN} -> - throw({ER#emem_res{hostname = strip(HN)}, LV}); - false -> ok - end, - case has_prefix("> Pid:", Line) of - {true, P} -> - throw({ER#emem_res{pid = strip(P)}, LV}); - false -> ok - end, - case has_prefix("> Start time (UTC):", Line) of - {true, ST} -> - throw({ER#emem_res{start_time = strip(ST)}, LV}); - false -> ok - end, - case has_prefix("> Actual trace version:", Line) of - {true, TV} -> - throw({ER#emem_res{trace_version = strip(TV)}, LV}); - false -> ok - end, - case has_prefix("> Maximum trace word size:", Line) of - {true, MWS} -> - throw({ER#emem_res{max_word_size = strip(MWS)}, LV}); - false -> ok - end, - case has_prefix("> Actual trace word size:", Line) of - {true, WS} -> - throw({ER#emem_res{word_size = strip(WS)}, LV}); - false -> ok - end, - - %% Footer - case has_prefix("> Maximum:", Line) of - {true, M} -> - throw({ER#emem_res{maximum = string:tokens(M," ")}, LV}); - false -> ok - end, - case has_prefix("> Emulator exited with code:", Line) of - {true, EC} -> - throw({ER#emem_res{exit_code = strip(EC)}, LV}); - false -> ok - end, - Res. - -parse_emem_header_line(_Line, {_ER, _LV} = Res) -> - Res. - -parse_emem_value_line(Line, {EmemRes, _OldLastValues}) -> - {EmemRes, Line}. - -parse_emem_line("", Res) -> - Res; -parse_emem_line(Line, Res) -> - [Prefix | _] = Line, - case Prefix of - $> -> catch parse_emem_main_header_footer_line(Line, Res); - $| -> catch parse_emem_header_line(Line, Res); - _ -> catch parse_emem_value_line(Line, Res) - end. - -start_emem(Config) when is_list(Config) -> - Emem = proplists:get_value(emem, Config), - Cd = case ignore_cores:dir(Config) of - false -> []; - Dir -> [{cd, Dir}] - end, - case open_port({spawn, Emem ++ " -t -n -o -i 1"}, - Cd ++ [{line, 1024}, eof]) of - Port when is_port(Port) -> {ok, read_emu_flag(Port), Port}; - Error -> ct:fail(Error) - end. - -read_emu_flag(Port) -> - Line = case get_emem_line(Port) of - eof -> ct:fail(unexpected_end_of_file); - L -> L - end, - case has_prefix("> Emulator command line argument:", Line) of - {true, EmuFlag} -> EmuFlag; - false -> read_emu_flag(Port) - end. - -get_emem_line(Port, Acc) -> - receive - {Port, {data, {eol, Data}}} -> - Res = case Acc of - [] -> Data; - _ -> lists:flatten([Acc|Data]) - end, - io:format("~s", [Res]), - Res; - {Port, {data, {noeol, Data}}} -> - get_emem_line(Port, [Acc|Data]); - {Port, eof} -> - port_close(Port), - eof - end. - -get_emem_line(Port) -> - get_emem_line(Port, []). - -short_hostname([]) -> - []; -short_hostname([$.|_]) -> - []; -short_hostname([C|Cs]) -> - [C | short_hostname(Cs)]. - -has_prefix([], List) when is_list(List) -> - {true, List}; -has_prefix([P|Xs], [P|Ys]) -> - has_prefix(Xs, Ys); -has_prefix(_, _) -> - false. - -strip(Str) -> string:strip(Str). - -mk_nodename(Config) -> - Us = erlang:monotonic_time(), - atom_to_list(?MODULE) - ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) - ++ integer_to_list(Us). - -start_node(Name, Args) -> - Pa = filename:dirname(code:which(?MODULE)), - test_server:start_node(Name, peer, [{args, Args ++ " -pa " ++ Pa}]). diff --git a/lib/tools/test/tools.spec.win b/lib/tools/test/tools.spec.win index b43d542ff1..93d5930472 100644 --- a/lib/tools/test/tools.spec.win +++ b/lib/tools/test/tools.spec.win @@ -1,2 +1 @@ {topcase, {dir, "../tools_test"}}. -{skip, {emem_SUITE, "Not on windows, yet. FIXME!!!"}}. -- 2.31.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor