Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions erts/doc/references/erl_cmd.md
Original file line number Diff line number Diff line change
Expand Up @@ -1455,6 +1455,24 @@ behavior of earlier flags.

Since: OTP 27.0

- **`+zmml limit`{: #+zmml }** - Sets the maximum number of entries in the
`module_code` loader index table, that is, the maximum number of modules
that can be loaded into the runtime system. Valid range of this limit is
`[1, 2147483647]` (on 32-bit systems the maximum is `134217727`). Defaults
to 65536.

The current value can be read by Erlang code by calling
[`erlang:system_info(module_limit)`](`m:erlang#system_info_module_limit`).

- **`+zmel limit`{: #+zmel }** - Sets the maximum number of entries in the
`export_list` loader index table, that is, the maximum number of exported
functions that can be loaded into the runtime system. Valid range of this
limit is `[1, 2147483647]` (on 32-bit systems the maximum is `134217727`).
Defaults to 524288.

The current value can be read by Erlang code by calling
[`erlang:system_info(export_limit)`](`m:erlang#system_info_export_limit`).

## Environment Variables

- **`ERL_CRASH_DUMP`** - If the emulator needs to write a crash dump, the value
Expand Down
27 changes: 27 additions & 0 deletions erts/doc/src/erlang_system_info.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ order to make it easier to navigate.
[`atom_limit`](`m:erlang#system_info_atom_limit`),
[`ets_count`](`m:erlang#system_info_ets_count`),
[`ets_limit`](`m:erlang#system_info_ets_limit`),
[`export_count`](`m:erlang#system_info_export_count`),
[`export_limit`](`m:erlang#system_info_export_limit`),
[`module_count`](`m:erlang#system_info_module_count`),
[`module_limit`](`m:erlang#system_info_module_limit`),
[`port_count`](`m:erlang#system_info_port_count`),
[`port_limit`](`m:erlang#system_info_port_limit`),
[`process_count`](`m:erlang#system_info_process_count`),
Expand Down Expand Up @@ -374,6 +378,29 @@ Returns information about the current system (emulator) limits as specified by `

Since: OTP R16B03

- `export_count`{: #system_info_export_count } - Returns the number of exported
functions currently loaded at the local node. The value is given as an
integer.

Since: OTP 30.0

- `export_limit`{: #system_info_export_limit } - Returns the maximum number of
exported functions allowed. This limit can be changed at startup by passing
command-line flag [`+zmel`](erl_cmd.md#+zmel) to `erl(1)`.

Since: OTP 30.0

- `module_count`{: #system_info_module_count } - Returns the number of modules
currently loaded at the local node. The value is given as an integer.

Since: OTP 30.0

- `module_limit`{: #system_info_module_limit } - Returns the maximum number of
modules allowed. This limit can be changed at startup by passing command-line
flag [`+zmml`](erl_cmd.md#+zmml) to `erl(1)`.

Since: OTP 30.0

- `port_count`{: #system_info_port_count } - Returns the number of ports
currently existing at the local node. The value is given as an integer. This
is the same value as returned by `length(erlang:ports())`, but more
Expand Down
12 changes: 12 additions & 0 deletions erts/emulator/beam/erl_bif_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -3521,6 +3521,18 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
else if (ERTS_IS_ATOM_STR("atom_count",BIF_ARG_1)) {
BIF_RET(make_small(atom_table_size()));
}
else if (ERTS_IS_ATOM_STR("module_limit",BIF_ARG_1)) {
BIF_RET(make_small(erts_module_table_limit()));
}
else if (ERTS_IS_ATOM_STR("module_count",BIF_ARG_1)) {
BIF_RET(make_small(module_code_size(erts_active_code_ix())));
}
else if (ERTS_IS_ATOM_STR("export_limit",BIF_ARG_1)) {
BIF_RET(make_small(erts_export_table_limit()));
}
else if (ERTS_IS_ATOM_STR("export_count",BIF_ARG_1)) {
BIF_RET(make_small(export_list_size(erts_active_code_ix())));
}
else if (ERTS_IS_ATOM_STR("tolerant_timeofday",BIF_ARG_1)) {
if (erts_has_time_correction()
&& erts_time_offset_state() == ERTS_TIME_OFFSET_FINAL) {
Expand Down
40 changes: 35 additions & 5 deletions erts/emulator/beam/erl_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ static void erl_init(int ncpu,
int time_correction,
ErtsTimeWarpMode time_warp_mode,
int node_tab_delete_delay,
ErtsDbSpinCount db_spin_count);
ErtsDbSpinCount db_spin_count,
int module_tab_sz,
int export_tab_sz);

static erts_atomic_t exiting;

Expand Down Expand Up @@ -255,7 +257,9 @@ erl_init(int ncpu,
int time_correction,
ErtsTimeWarpMode time_warp_mode,
int node_tab_delete_delay,
ErtsDbSpinCount db_spin_count)
ErtsDbSpinCount db_spin_count,
int module_tab_sz,
int export_tab_sz)
{
init_global_literals();
erts_monitor_link_init();
Expand Down Expand Up @@ -283,9 +287,9 @@ erl_init(int ncpu,
erts_code_ix_init();
erts_init_fun_table();
init_atom_table();
init_export_table();
init_export_table(export_tab_sz);
erts_record_init_table();
init_module_table();
init_module_table(module_tab_sz);
init_register_table();
init_message();
#ifdef BEAMASM
Expand Down Expand Up @@ -1310,6 +1314,8 @@ erl_start(int argc, char **argv)
ErtsTimeWarpMode time_warp_mode;
int node_tab_delete_delay = ERTS_NODE_TAB_DELAY_GC_DEFAULT;
ErtsDbSpinCount db_spin_count = ERTS_DB_SPNCNT_NORMAL;
int module_tab_sz = 0;
int export_tab_sz = 0;

/* Must be set up as early as possible for crash dump encryption to work
* properly. */
Expand Down Expand Up @@ -2446,6 +2452,28 @@ erl_start(int argc, char **argv)
erts_halt_flush_timeout = (ErtsMonotonicTime) val;
}
}
else if (has_prefix("mml", sub_param)) {
long val;
arg = get_arg(sub_param+3, argv[i+1], &i);
errno = 0;
val = strtol(arg, NULL, 10);
if (errno != 0 || val < 1 || MAX_SMALL < val || INT_MAX < val) {
erts_fprintf(stderr, "Invalid module table limit %s\n", arg);
erts_usage();
}
module_tab_sz = (int) val;
}
else if (has_prefix("mel", sub_param)) {
long val;
arg = get_arg(sub_param+3, argv[i+1], &i);
errno = 0;
val = strtol(arg, NULL, 10);
if (errno != 0 || val < 1 || MAX_SMALL < val || INT_MAX < val) {
erts_fprintf(stderr, "Invalid export table limit %s\n", arg);
erts_usage();
}
export_tab_sz = (int) val;
}
else {
erts_fprintf(stderr, "bad -z option %s\n", argv[i]);
erts_usage();
Expand Down Expand Up @@ -2529,7 +2557,9 @@ erl_start(int argc, char **argv)
time_correction,
time_warp_mode,
node_tab_delete_delay,
db_spin_count);
db_spin_count,
module_tab_sz,
export_tab_sz);

load_preloaded();
erts_end_staging_code_ix();
Expand Down
14 changes: 12 additions & 2 deletions erts/emulator/beam/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
#define EXPORT_INITIAL_SIZE 4000
#define EXPORT_LIMIT (512*1024)

static int export_limit = EXPORT_LIMIT;

#ifdef DEBUG
# define IF_DEBUG(x) x
#else
Expand Down Expand Up @@ -115,7 +117,7 @@ static void export_stage(Export *export,
#define ERTS_CODE_STAGED_OBJECT_ALLOC_TYPE ERTS_ALC_T_EXPORT
#define ERTS_CODE_STAGED_TABLE_ALLOC_TYPE ERTS_ALC_T_EXPORT_TABLE
#define ERTS_CODE_STAGED_TABLE_INITIAL_SIZE EXPORT_INITIAL_SIZE
#define ERTS_CODE_STAGED_TABLE_LIMIT EXPORT_LIMIT
#define ERTS_CODE_STAGED_TABLE_LIMIT export_limit

#define ERTS_CODE_STAGED_WANT_GET
#define ERTS_CODE_STAGED_WANT_PUT
Expand All @@ -128,11 +130,19 @@ static void export_stage(Export *export,
#include "erl_code_staged.h"

void
init_export_table(void)
init_export_table(int limit)
{
if (limit > 0) {
export_limit = limit;
}
export_staged_init();
}

int erts_export_table_limit(void)
{
return export_limit;
}

void
export_info(fmtfn_t to, void *to_arg)
{
Expand Down
3 changes: 2 additions & 1 deletion erts/emulator/beam/export.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,9 @@ typedef struct export_
#define DBG_CHECK_EXPORT(EP, CX)
#endif

void init_export_table(void);
void init_export_table(int limit);
void export_info(fmtfn_t, void *);
int erts_export_table_limit(void);

ERTS_GLB_INLINE void erts_activate_export_trampoline(Export *ep, int code_ix);
ERTS_GLB_INLINE int erts_is_export_trampoline_active(const Export * const ep, int code_ix);
Expand Down
17 changes: 14 additions & 3 deletions erts/emulator/beam/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#define MODULE_SIZE 50
#define MODULE_LIMIT (64*1024)

static int module_limit = MODULE_LIMIT;

static IndexTable module_tables[ERTS_NUM_CODE_IX];

erts_rwmtx_t the_old_code_rwlocks[ERTS_NUM_CODE_IX];
Expand Down Expand Up @@ -103,11 +105,15 @@ static void module_free(Module* mod)
erts_atomic_add_nob(&tot_module_bytes, -sizeof(Module));
}

void init_module_table(void)
void init_module_table(int limit)
{
HashFunctions f;
int i;

if (limit > 0) {
module_limit = limit;
}

f.hash = (H_FUN) module_hash;
f.cmp = (HCMP_FUN) module_cmp;
f.alloc = (HALLOC_FUN) module_alloc;
Expand All @@ -117,8 +123,8 @@ void init_module_table(void)
f.meta_print = (HMPRINT_FUN) erts_print;

for (i = 0; i < ERTS_NUM_CODE_IX; i++) {
erts_index_init(ERTS_ALC_T_MODULE_TABLE, &module_tables[i], "module_code",
MODULE_SIZE, MODULE_LIMIT, f);
erts_index_init(ERTS_ALC_T_MODULE_TABLE, &module_tables[i], "module_code",
MODULE_SIZE, module_limit, f);
}

for (i=0; i<ERTS_NUM_CODE_IX; i++) {
Expand Down Expand Up @@ -256,6 +262,11 @@ int module_code_size(ErtsCodeIndex code_ix)
return module_tables[code_ix].entries;
}

int erts_module_table_limit(void)
{
return module_limit;
}

int module_table_sz(void)
{
return erts_atomic_read_nob(&tot_module_bytes);
Expand Down
3 changes: 2 additions & 1 deletion erts/emulator/beam/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,15 @@ void erts_unseal_module(struct erl_module_instance *modi);
* setting up a code barrier. */
void erts_seal_module(struct erl_module_instance *modi);

void init_module_table(void);
void init_module_table(int limit);
void module_start_staging(void);
void module_end_staging(int commit);
void module_info(fmtfn_t, void *);

Module *module_code(int, ErtsCodeIndex);
int module_code_size(ErtsCodeIndex);
int module_table_sz(void);
int erts_module_table_limit(void);

ERTS_GLB_INLINE void erts_rwlock_old_code(ErtsCodeIndex);
ERTS_GLB_INLINE void erts_rwunlock_old_code(ErtsCodeIndex);
Expand Down
Loading