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