diff options
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/beam_emu.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 52 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 15 | ||||
-rw-r--r-- | erts/emulator/beam/erl_term.h | 12 | ||||
-rw-r--r-- | erts/emulator/beam/erl_trace.c | 4 |
5 files changed, 50 insertions, 35 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 9634faff1d..1026e5f649 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -3525,7 +3525,7 @@ get_map_elements_fail: erts_post_nif(&env); #ifdef ERTS_DIRTY_SCHEDULERS if (is_non_value(nif_bif_result) && c_p->freason == TRAP) { - Export* ep = (Export*) c_p->psd->data[ERTS_PSD_DIRTY_SCHED_TRAP_EXPORT]; + Export* ep = ERTS_PROC_GET_DIRTY_SCHED_TRAP_EXPORT(c_p); ep->code[0] = I[-3]; ep->code[1] = I[-2]; } diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 063dba056e..ff551ea3af 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -1515,26 +1515,35 @@ int enif_consume_timeslice(ErlNifEnv* env, int percent) #ifdef ERTS_DIRTY_SCHEDULERS +/* NIFs exports need one more item than the Export struct provides, the + * erl_module_nif*, so the DirtyNifExport below adds that. The Export + * member must be first in the struct. + */ +typedef struct { + Export exp; + struct erl_module_nif* m; +} DirtyNifExport; + static void -alloc_proc_psd(Process* proc, Export **ep) +alloc_proc_psd(Process* proc, DirtyNifExport **ep) { int i; if (!*ep) { - *ep = erts_alloc(ERTS_ALC_T_PSD, sizeof(Export)); - sys_memset((void*) *ep, 0, sizeof(Export)); + *ep = erts_alloc(ERTS_ALC_T_PSD, sizeof(DirtyNifExport)); + sys_memset((void*) *ep, 0, sizeof(DirtyNifExport)); for (i=0; i<ERTS_NUM_CODE_IX; i++) { - (*ep)->addressv[i] = &(*ep)->code[3]; + (*ep)->exp.addressv[i] = &(*ep)->exp.code[3]; } - (*ep)->code[3] = (BeamInstr) em_call_nif; + (*ep)->exp.code[3] = (BeamInstr) em_call_nif; } - (void) ERTS_PROC_SET_DIRTY_SCHED_TRAP_EXPORT(proc, ERTS_PROC_LOCK_MAIN, *ep); + (void) ERTS_PROC_SET_DIRTY_SCHED_TRAP_EXPORT(proc, ERTS_PROC_LOCK_MAIN, &(*ep)->exp); } static ERL_NIF_TERM execute_dirty_nif_finalizer(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { Eterm* reg = ERTS_PROC_GET_SCHDATA(env->proc)->x_reg_array; - ERL_NIF_TERM result = (ERL_NIF_TERM) reg[0]; + ERL_NIF_TERM result, dirty_result = (ERL_NIF_TERM) reg[0]; typedef ERL_NIF_TERM (*FinalizerFP)(ErlNifEnv*, ERL_NIF_TERM); FinalizerFP fp; #if HAVE_INT64 && SIZEOF_LONG != 8 @@ -1544,7 +1553,11 @@ execute_dirty_nif_finalizer(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ASSERT(sizeof(fp) <= sizeof(unsigned long)); enif_get_ulong(env, reg[1], (unsigned long *) &fp); #endif - return (*fp)(env, result); + result = (*fp)(env, dirty_result); + if (erts_refc_dectest(&env->mod_nif->rt_dtor_cnt, 0) == 0 + && env->mod_nif->mod == NULL) + close_lib(env->mod_nif); + return result; } #endif /* ERTS_DIRTY_SCHEDULERS */ @@ -1560,7 +1573,7 @@ enif_schedule_dirty_nif(ErlNifEnv* env, int flags, erts_aint32_t state, n, a; Process* proc = env->proc; Eterm* reg = ERTS_PROC_GET_SCHDATA(proc)->x_reg_array; - Export* ep = NULL; + DirtyNifExport* ep = NULL; int i; int chkflgs = (flags & (ERL_NIF_DIRTY_JOB_IO_BOUND|ERL_NIF_DIRTY_JOB_CPU_BOUND)); @@ -1585,17 +1598,20 @@ enif_schedule_dirty_nif(ErlNifEnv* env, int flags, if (a == state) break; } - if (!(ep = ERTS_PROC_GET_DIRTY_SCHED_TRAP_EXPORT(proc))) + if (!(ep = (DirtyNifExport*) ERTS_PROC_GET_DIRTY_SCHED_TRAP_EXPORT(proc))) alloc_proc_psd(proc, &ep); ERTS_VBUMP_ALL_REDS(proc); - ep->code[2] = argc; + ep->exp.code[2] = argc; for (i = 0; i < argc; i++) { reg[i] = (Eterm) argv[i]; } - proc->i = (BeamInstr*) ep->addressv[0]; - ep->code[4] = (BeamInstr) fp; + proc->i = (BeamInstr*) ep->exp.addressv[0]; + ep->exp.code[4] = (BeamInstr) fp; + ep->m = env->mod_nif; proc->freason = TRAP; + erts_refc_inc(&env->mod_nif->rt_dtor_cnt, 1); + return THE_NON_VALUE; #else return (*fp)(env, argc, argv); @@ -1609,17 +1625,17 @@ enif_schedule_dirty_nif_finalizer(ErlNifEnv* env, ERL_NIF_TERM result, #ifdef USE_THREADS Process* proc = env->proc; Eterm* reg = ERTS_PROC_GET_SCHDATA(proc)->x_reg_array; - Export* ep; + DirtyNifExport* ep; erts_smp_atomic32_read_band_mb(&proc->state, ~(ERTS_PSFLG_DIRTY_CPU_PROC |ERTS_PSFLG_DIRTY_IO_PROC |ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q |ERTS_PSFLG_DIRTY_IO_PROC_IN_Q)); - if (!(ep = ERTS_PROC_GET_DIRTY_SCHED_TRAP_EXPORT(proc))) + if (!(ep = (DirtyNifExport*) ERTS_PROC_GET_DIRTY_SCHED_TRAP_EXPORT(proc))) alloc_proc_psd(proc, &ep); ERTS_VBUMP_ALL_REDS(proc); - ep->code[2] = 2; + ep->exp.code[2] = 2; reg[0] = (Eterm) result; #if HAVE_INT64 && SIZEOF_LONG != 8 ASSERT(sizeof(fp) <= sizeof(ErlNifUInt64)); @@ -1628,8 +1644,8 @@ enif_schedule_dirty_nif_finalizer(ErlNifEnv* env, ERL_NIF_TERM result, ASSERT(sizeof(fp) <= sizeof(unsigned long)); reg[1] = (Eterm) enif_make_ulong(env, (unsigned long) fp); #endif - proc->i = (BeamInstr*) ep->addressv[0]; - ep->code[4] = (BeamInstr) execute_dirty_nif_finalizer; + proc->i = (BeamInstr*) ep->exp.addressv[0]; + ep->exp.code[4] = (BeamInstr) execute_dirty_nif_finalizer; proc->freason = TRAP; return THE_NON_VALUE; diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index baca73f7f6..3130b207e1 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -9214,7 +9214,6 @@ Process *schedule(Process *p, int calls) */ pick_next_process: { erts_aint32_t psflg_band_mask; - erts_aint32_t running_flag; int prio_q; int qmask; @@ -9276,12 +9275,6 @@ Process *schedule(Process *p, int calls) state = erts_smp_atomic32_read_nob(&p->state); } - - if (state & ERTS_PSFLG_ACTIVE_SYS) - running_flag = ERTS_PSFLG_RUNNING_SYS; - else - running_flag = ERTS_PSFLG_RUNNING; - while (1) { erts_aint32_t exp, new, tmp; tmp = new = exp = state; @@ -9291,8 +9284,12 @@ Process *schedule(Process *p, int calls) tmp = state & (ERTS_PSFLG_SUSPENDED | ERTS_PSFLG_PENDING_EXIT | ERTS_PSFLG_ACTIVE_SYS); - if (tmp != ERTS_PSFLG_SUSPENDED) - new |= running_flag; + if (tmp != ERTS_PSFLG_SUSPENDED) { + if (state & ERTS_PSFLG_ACTIVE_SYS) + new |= ERTS_PSFLG_RUNNING_SYS; + else + new |= ERTS_PSFLG_RUNNING; + } } state = erts_smp_atomic32_cmpxchg_relb(&p->state, new, exp); if (state == exp) { diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h index f10a3a9d38..37014ccf94 100644 --- a/erts/emulator/beam/erl_term.h +++ b/erts/emulator/beam/erl_term.h @@ -112,11 +112,11 @@ struct erl_node_; /* Declared in erl_node_tables.h */ * 1000 REFC_BINARY | | * 1001 HEAP_BINARY | BINARIES | * 1010 SUB_BINARY | | - * 1011 Not used + * 1011 Not used; see comment below * 1100 EXTERNAL_PID | | * 1101 EXTERNAL_PORT | EXTERNAL THINGS | * 1110 EXTERNAL_REF | | - * 1111 Not used + * 1111 MAP * * COMMENTS: * @@ -140,10 +140,11 @@ struct erl_node_; /* Declared in erl_node_tables.h */ #define REFC_BINARY_SUBTAG (0x8 << _TAG_PRIMARY_SIZE) /* BINARY */ #define HEAP_BINARY_SUBTAG (0x9 << _TAG_PRIMARY_SIZE) /* BINARY */ #define SUB_BINARY_SUBTAG (0xA << _TAG_PRIMARY_SIZE) /* BINARY */ -#define MAP_SUBTAG (0xB << _TAG_PRIMARY_SIZE) /* MAP */ +/* _BINARY_XXX_MASK depends on 0xB being unused */ #define EXTERNAL_PID_SUBTAG (0xC << _TAG_PRIMARY_SIZE) /* EXTERNAL_PID */ #define EXTERNAL_PORT_SUBTAG (0xD << _TAG_PRIMARY_SIZE) /* EXTERNAL_PORT */ #define EXTERNAL_REF_SUBTAG (0xE << _TAG_PRIMARY_SIZE) /* EXTERNAL_REF */ +#define MAP_SUBTAG (0xF << _TAG_PRIMARY_SIZE) /* MAP */ #define _TAG_HEADER_ARITYVAL (TAG_PRIMARY_HEADER|ARITYVAL_SUBTAG) @@ -156,11 +157,11 @@ struct erl_node_; /* Declared in erl_node_tables.h */ #define _TAG_HEADER_REFC_BIN (TAG_PRIMARY_HEADER|REFC_BINARY_SUBTAG) #define _TAG_HEADER_HEAP_BIN (TAG_PRIMARY_HEADER|HEAP_BINARY_SUBTAG) #define _TAG_HEADER_SUB_BIN (TAG_PRIMARY_HEADER|SUB_BINARY_SUBTAG) -#define _TAG_HEADER_MAP (TAG_PRIMARY_HEADER|MAP_SUBTAG) #define _TAG_HEADER_EXTERNAL_PID (TAG_PRIMARY_HEADER|EXTERNAL_PID_SUBTAG) #define _TAG_HEADER_EXTERNAL_PORT (TAG_PRIMARY_HEADER|EXTERNAL_PORT_SUBTAG) #define _TAG_HEADER_EXTERNAL_REF (TAG_PRIMARY_HEADER|EXTERNAL_REF_SUBTAG) #define _TAG_HEADER_BIN_MATCHSTATE (TAG_PRIMARY_HEADER|BIN_MATCHSTATE_SUBTAG) +#define _TAG_HEADER_MAP (TAG_PRIMARY_HEADER|MAP_SUBTAG) #define _TAG_HEADER_MASK 0x3F @@ -892,7 +893,8 @@ typedef struct external_thing_ { (((x) & _TAG_HEADER_MASK) == _TAG_HEADER_EXTERNAL_REF) #define is_external_header(x) \ - (((x) & (_TAG_HEADER_MASK-_BINARY_XXX_MASK)) == _TAG_HEADER_EXTERNAL_PID) + (((x) & (_TAG_HEADER_MASK-_BINARY_XXX_MASK)) == _TAG_HEADER_EXTERNAL_PID \ + && ((x) & _TAG_HEADER_MASK) != _TAG_HEADER_MAP) #define is_external(x) (is_boxed((x)) && is_external_header(*boxed_val((x)))) diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index 305058ceff..ea5c850a30 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1999-2013. All Rights Reserved. + * Copyright Ericsson AB 1999-2014. 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 @@ -2524,7 +2524,7 @@ monitor_large_heap(Process *p) { #ifndef ERTS_SMP ASSERT(is_internal_pid(system_monitor)); monitor_p = erts_proc_lookup(system_monitor); - if (monitor_p || p == monitor_p) { + if (!monitor_p || p == monitor_p) { return; } #endif |