diff options
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/atom.c | 12 | ||||
-rw-r--r-- | erts/emulator/beam/atom.h | 21 | ||||
-rw-r--r-- | erts/emulator/beam/erl_init.c | 22 | ||||
-rw-r--r-- | erts/emulator/beam/erl_port_task.c | 12 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 38 | ||||
-rw-r--r-- | erts/emulator/beam/erl_vm.h | 2 | ||||
-rw-r--r-- | erts/emulator/beam/external.c | 7 |
7 files changed, 88 insertions, 26 deletions
diff --git a/erts/emulator/beam/atom.c b/erts/emulator/beam/atom.c index dfc3cde6a7..e2a79d6e4f 100644 --- a/erts/emulator/beam/atom.c +++ b/erts/emulator/beam/atom.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -322,7 +322,7 @@ init_atom_table(void) text_list = NULL; erts_index_init(ERTS_ALC_T_ATOM_TABLE, &erts_atom_table, - "atom_tab", ATOM_SIZE, ATOM_LIMIT, f); + "atom_tab", ATOM_SIZE, erts_atom_table_size, f); more_atom_space(); /* Ordinary atoms */ diff --git a/erts/emulator/beam/atom.h b/erts/emulator/beam/atom.h index e7e0dc440d..cb245a87b1 100644 --- a/erts/emulator/beam/atom.h +++ b/erts/emulator/beam/atom.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -28,6 +28,17 @@ #define MAX_ATOM_LENGTH 255 #define ATOM_LIMIT (1024*1024) +#define MIN_ATOM_TABLE_SIZE 8192 + +#ifndef ARCH_32 +/* Internal atom cache needs MAX_ATOM_TABLE_SIZE to be less than an + unsigned 32 bit integer. See external.c(erts_encode_ext_dist_header_setup) + for more details. */ +#define MAX_ATOM_TABLE_SIZE ((MAX_ATOM_INDEX + 1 < (1UL << 32)) ? MAX_ATOM_INDEX + 1 : (1UL << 32)) +#else +#define MAX_ATOM_TABLE_SIZE (MAX_ATOM_INDEX + 1) +#endif + /* * Atom entry. diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index bdf888eaff..17cf3b9597 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -119,6 +119,8 @@ int erts_disable_tolerant_timeofday; /* Time correction can be disabled it is * not and/or it is too slow. */ +int erts_atom_table_size = ATOM_LIMIT; /* Maximum number of atoms */ + int erts_modified_timing_level; int erts_no_crash_dump = 0; /* Use -d to suppress crash dump. */ @@ -569,6 +571,10 @@ void erts_usage(void) erts_fprintf(stderr, " schedulers online (n2), valid range for both\n"); erts_fprintf(stderr, " numbers are [1-%d]\n", ERTS_MAX_NO_OF_SCHEDULERS); + erts_fprintf(stderr, "-t size set the maximum number of atoms the " + "emulator can handle\n"); + erts_fprintf(stderr, " valid range is [%d-%d]\n", + MIN_ATOM_TABLE_SIZE, MAX_ATOM_TABLE_SIZE); erts_fprintf(stderr, "-T number set modified timing level,\n"); erts_fprintf(stderr, " valid range is [0-%d]\n", ERTS_MODIFIED_TIMING_LEVELS-1); @@ -1140,6 +1146,22 @@ erl_start(int argc, char **argv) } break; } + case 't': + /* set atom table size */ + arg = get_arg(argv[i]+2, argv[i+1], &i); + errno = 0; + erts_atom_table_size = strtol(arg, NULL, 10); + if (errno != 0 || + erts_atom_table_size < MIN_ATOM_TABLE_SIZE || + erts_atom_table_size > MAX_ATOM_TABLE_SIZE) { + erts_fprintf(stderr, "bad atom table size %s\n", arg); + erts_usage(); + } + VERBOSE(DEBUG_SYSTEM, + ("setting maximum number of atoms to %d\n", + erts_atom_table_size)); + break; + case 'T' : arg = get_arg(argv[i]+2, argv[i+1], &i); errno = 0; diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c index 3cb5a966ac..0b6bb0d8e9 100644 --- a/erts/emulator/beam/erl_port_task.c +++ b/erts/emulator/beam/erl_port_task.c @@ -575,7 +575,7 @@ erts_port_task_schedule(Eterm id, } #endif - ASSERT(!(runq->flags & ERTS_RUNQ_FLG_SUSPENDED)); + ASSERT(!enq_port || !(runq->flags & ERTS_RUNQ_FLG_SUSPENDED)); ASSERT(pp->sched.taskq); ASSERT(ptp); @@ -601,6 +601,15 @@ erts_port_task_schedule(Eterm id, break; } +#ifndef ERTS_SMP + /* + * When (!enq_port && !pp->sched.exe_taskq) is true in the smp case, + * the port might not be in the run queue. If this is the case, another + * thread is in the process of enqueueing the port. This very seldom + * occur, but do occur and is a valid scenario. Debug info showing this + * enqueue in progress must be introduced before we can enable (modified + * versions of these) assertions in the smp case again. + */ #if defined(HARD_DEBUG) if (pp->sched.exe_taskq || enq_port) ERTS_PT_CHK_NOT_IN_PORTQ(runq, pp); @@ -612,6 +621,7 @@ erts_port_task_schedule(Eterm id, ASSERT(pp->sched.prev || runq->ports.start == pp); } #endif +#endif if (!enq_port) { ERTS_PT_CHK_PRES_PORTQ(runq, pp); diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index b519b39d63..2789691c55 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -2765,7 +2765,7 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all) p->flags |= F_HAVE_BLCKD_MSCHED; ASSERT(erts_smp_atomic_read(&schdlr_sspnd.active) == 1); ASSERT(p->scheduler_data->no == 1); - res = 1; + res = ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED; } else { p->flags |= F_HAVE_BLCKD_MSCHED; @@ -2896,12 +2896,16 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all) #endif p->flags &= ~F_HAVE_BLCKD_MSCHED; erts_smp_atomic_set(&schdlr_sspnd.msb.ongoing, 0); - if (schdlr_sspnd.online == 1) - /* No schedulers to resume */; + if (schdlr_sspnd.online == 1) { + /* No schedulers to resume */ + ASSERT(erts_smp_atomic_read(&schdlr_sspnd.active) == 1); + schdlr_sspnd.changing = 0; + } else if (erts_common_run_queue) { for (ix = 1; ix < schdlr_sspnd.online; ix++) erts_smp_atomic_set(&ERTS_SCHEDULER_IX(ix)->suspended, 0); wake_all_schedulers(); + erts_smp_cnd_broadcast(&schdlr_sspnd.cnd); } else { int online = schdlr_sspnd.online; @@ -2933,8 +2937,8 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all) erts_smp_runq_unlock(ERTS_RUNQ_IX(0)); erts_smp_mtx_unlock(&balance_info.update_mtx); erts_smp_mtx_lock(&schdlr_sspnd.mtx); + erts_smp_cnd_broadcast(&schdlr_sspnd.cnd); } - erts_smp_cnd_broadcast(&schdlr_sspnd.cnd); res = ERTS_SCHDLR_SSPND_DONE; } } @@ -8033,11 +8037,6 @@ erts_do_exit_process(Process* p, Eterm reason) if (p->bif_timers) erts_cancel_bif_timers(p, ERTS_PROC_LOCKS_ALL); -#ifdef ERTS_SMP - if (p->flags & F_HAVE_BLCKD_MSCHED) - erts_block_multi_scheduling(p, ERTS_PROC_LOCKS_ALL, 0, 1); -#endif - erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_ALL_MINOR); #ifdef ERTS_SMP @@ -8082,6 +8081,27 @@ continue_exit_process(Process *p erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS); #endif +#ifdef ERTS_SMP + if (p->flags & F_HAVE_BLCKD_MSCHED) { + ErtsSchedSuspendResult ssr; + ssr = erts_block_multi_scheduling(p, ERTS_PROC_LOCK_MAIN, 0, 1); + switch (ssr) { + case ERTS_SCHDLR_SSPND_YIELD_RESTART: + goto yield; + case ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED: + case ERTS_SCHDLR_SSPND_YIELD_DONE_MSCHED_BLOCKED: + case ERTS_SCHDLR_SSPND_DONE: + case ERTS_SCHDLR_SSPND_YIELD_DONE: + p->flags &= ~F_HAVE_BLCKD_MSCHED; + break; + case ERTS_SCHDLR_SSPND_EINVAL: + default: + erl_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error: %d\n", + __FILE__, __LINE__, (int) ssr); + } + } +#endif + if (p->flags & F_USING_DB) { if (erts_db_process_exiting(p, ERTS_PROC_LOCK_MAIN)) goto yield; diff --git a/erts/emulator/beam/erl_vm.h b/erts/emulator/beam/erl_vm.h index 5b0d3c2bfa..50b3e5b61c 100644 --- a/erts/emulator/beam/erl_vm.h +++ b/erts/emulator/beam/erl_vm.h @@ -181,6 +181,8 @@ extern int num_instructions; /* Number of instruction in opc[]. */ extern int H_MIN_SIZE; /* minimum (heap + stack) */ extern int BIN_VH_MIN_SIZE; /* minimum virtual (bin) heap */ +extern int erts_atom_table_size;/* Atom table size */ + #define ORIG_CREATION 0 /* macros for extracting bytes from uint16's */ diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index 24887b3dea..b011d4c0de 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -271,11 +271,8 @@ erts_encode_ext_dist_header_size(ErtsAtomCacheMap *acmp) byte *erts_encode_ext_dist_header_setup(byte *ctl_ext, ErtsAtomCacheMap *acmp) { -#ifndef ARCH_32 -#if ATOM_LIMIT >= (1UL << 32) -#error "ATOM_LIMIT too large for interal atom cache update instructions. New instructions needed." -#endif -#endif + /* Maximum number of atom must be less than the maximum of a 32 bits + unsigned integer. Check is done in erl_init.c, erl_start function. */ if (!acmp) return ctl_ext; else { |