diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/doc/src/erlang.xml | 20 | ||||
-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/test/port_SUITE.erl | 9 | ||||
-rw-r--r-- | erts/preloaded/ebin/erl_prim_loader.beam | bin | 54792 -> 54768 bytes | |||
-rw-r--r-- | erts/preloaded/ebin/erlang.beam | bin | 98276 -> 98240 bytes | |||
-rw-r--r-- | erts/preloaded/ebin/erts_internal.beam | bin | 4296 -> 4276 bytes | |||
-rw-r--r-- | erts/preloaded/ebin/init.beam | bin | 48816 -> 48796 bytes | |||
-rw-r--r-- | erts/preloaded/ebin/otp_ring0.beam | bin | 1480 -> 1460 bytes | |||
-rw-r--r-- | erts/preloaded/ebin/prim_eval.beam | bin | 1360 -> 1340 bytes | |||
-rw-r--r-- | erts/preloaded/ebin/prim_file.beam | bin | 44916 -> 44892 bytes | |||
-rw-r--r-- | erts/preloaded/ebin/prim_inet.beam | bin | 72932 -> 72912 bytes | |||
-rw-r--r-- | erts/preloaded/ebin/prim_zip.beam | bin | 23448 -> 23424 bytes | |||
-rw-r--r-- | erts/preloaded/ebin/zlib.beam | bin | 13196 -> 13176 bytes | |||
-rw-r--r-- | erts/preloaded/src/erlang.erl | 6 | ||||
-rw-r--r-- | erts/test/otp_SUITE.erl | 80 |
17 files changed, 138 insertions, 46 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 7aaded200c..e7e9b218f2 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -1784,6 +1784,15 @@ os_prompt% </pre> </desc> </func> <func> + <name name="is_map" arity="1"/> + <fsummary>Check whether a term is a map</fsummary> + <desc> + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a map; + otherwise returns <c>false</c>.</p> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> <name name="is_number" arity="1"/> <fsummary>Check whether a term is a number</fsummary> <desc> @@ -2220,6 +2229,17 @@ os_prompt% </pre> </desc> </func> <func> + <name name="map_size" arity="1"/> + <fsummary>Return the size of a map</fsummary> + <desc> + <p>Returns an integer which is the number of key-value pairs in <c><anno>Map</anno></c>.</p> + <pre> +> <input>map_size(#{a=>1, b=>2, c=>3}).</input> +3</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> <name name="max" arity="2"/> <fsummary>Return the largest of two term</fsummary> <desc> 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 8bf0cc9491..b4b97d7df1 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -9207,7 +9207,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; @@ -9269,12 +9268,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; @@ -9284,8 +9277,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/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 202a8b7537..e01b2f253b 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-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 @@ -1698,12 +1698,13 @@ otp_5119(Config) when is_list(Config) -> Path = ?config(data_dir, Config), ok = load_driver(Path, "exit_drv"), PI1 = port_ix(otp_5119_fill_empty_port_tab([])), - PI2 = port_ix(erlang:open_port({spawn, "exit_drv"}, [])), + Port2 = erlang:open_port({spawn, "exit_drv"}, []), + PI2 = port_ix(Port2), {PortIx1, PortIx2} = case PI2 > PI1 of true -> {PI1, PI2}; false -> - {port_ix(otp_5119_fill_empty_port_tab([PI2])), + {port_ix(otp_5119_fill_empty_port_tab([Port2])), port_ix(erlang:open_port({spawn, "exit_drv"}, []))} end, MaxPorts = max_ports(), @@ -2318,7 +2319,7 @@ close_deaf_port(Config) when is_list(Config) -> test_server:timetrap_cancel(Dog), Res. -close_deaf_port_1(1000, _) -> +close_deaf_port_1(200, _) -> ok; close_deaf_port_1(N, Cmd) -> Timeout = integer_to_list(random:uniform(5*1000)), diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam Binary files differindex 26f851fd7a..f1e588320b 100644 --- a/erts/preloaded/ebin/erl_prim_loader.beam +++ b/erts/preloaded/ebin/erl_prim_loader.beam diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex 344176b71b..b4e22f6d74 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam Binary files differindex bd402f9a98..d41c833e05 100644 --- a/erts/preloaded/ebin/erts_internal.beam +++ b/erts/preloaded/ebin/erts_internal.beam diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam Binary files differindex 5d49eed469..7f2d2740e1 100644 --- a/erts/preloaded/ebin/init.beam +++ b/erts/preloaded/ebin/init.beam diff --git a/erts/preloaded/ebin/otp_ring0.beam b/erts/preloaded/ebin/otp_ring0.beam Binary files differindex 2607739d12..4d22d8bace 100644 --- a/erts/preloaded/ebin/otp_ring0.beam +++ b/erts/preloaded/ebin/otp_ring0.beam diff --git a/erts/preloaded/ebin/prim_eval.beam b/erts/preloaded/ebin/prim_eval.beam Binary files differindex d665d35ab1..efc8347b6e 100644 --- a/erts/preloaded/ebin/prim_eval.beam +++ b/erts/preloaded/ebin/prim_eval.beam diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam Binary files differindex 201252de34..6c49b5185e 100644 --- a/erts/preloaded/ebin/prim_file.beam +++ b/erts/preloaded/ebin/prim_file.beam diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam Binary files differindex ff8265414e..fe5431c5ff 100644 --- a/erts/preloaded/ebin/prim_inet.beam +++ b/erts/preloaded/ebin/prim_inet.beam diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam Binary files differindex f80d4a96e5..73be297bbb 100644 --- a/erts/preloaded/ebin/prim_zip.beam +++ b/erts/preloaded/ebin/prim_zip.beam diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam Binary files differindex dba3ec9546..193cebdc31 100644 --- a/erts/preloaded/ebin/zlib.beam +++ b/erts/preloaded/ebin/zlib.beam diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index fbc37bd955..cabbbd191f 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -1745,9 +1745,9 @@ is_pid(_Term) -> erlang:nif_error(undefined). %% Shadowed by erl_bif_types: erlang:is_map/1 --spec is_map(Map) -> boolean() when - Map :: map(). -is_map(_Map) -> +-spec is_map(Term) -> boolean() when + Term :: term(). +is_map(_Term) -> erlang:nif_error(undefined). %% Shadowed by erl_bif_types: erlang:is_port/1 diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl index cd5cfcbab4..229d10ccee 100644 --- a/erts/test/otp_SUITE.erl +++ b/erts/test/otp_SUITE.erl @@ -392,12 +392,18 @@ is_bad_encoding(File) -> end. runtime_dependencies(Config) -> + %% Ignore applications intentionally not declaring dependencies + %% found by xref. + IgnoreApps = [diameter], + + %% Verify that (at least) OTP application runtime dependencies found %% by xref are listed in the runtime_dependencies field of the .app file %% of each application. Server = ?config(xref_server, Config), {ok, AE} = xref:q(Server, "AE"), SAE = lists:keysort(1, AE), + put(ignored_failures, []), {AppDep, AppDeps} = lists:foldl(fun ({App, App}, Acc) -> Acc; ({App, Dep}, {undefined, []}) -> @@ -409,8 +415,45 @@ runtime_dependencies(Config) -> end, {undefined, []}, SAE), - [] = check_apps_deps([AppDep|AppDeps]), - ok. + [] = lists:filter(fun ({missing_runtime_dependency, + AppFile, + common_test}) -> + %% The test_server app is contaminated by + %% common_test when run in a source tree. It + %% should however *not* be contaminated + %% when run in an installation. + case {filename:basename(AppFile), + is_run_in_src_tree()} of + {"test_server.app", true} -> + false; + _ -> + true + end; + (_) -> + true + end, + check_apps_deps([AppDep|AppDeps], IgnoreApps)), + case IgnoreApps of + [] -> + ok; + _ -> + Comment = lists:flatten(io_lib:format("Ignored applications: ~p " + "Ignored failures: ~p", + [IgnoreApps, + get(ignored_failures)])), + {comment, Comment} + end. + +is_run_in_src_tree() -> + %% At least currently run_erl is not present in <code-root>/bin + %% in the source tree, but present in <code-root>/bin of an + %% ordinary installation. + case file:read_file_info(filename:join([code:root_dir(), + "bin", + "run_erl"])) of + {ok, _} -> false; + {error, _} -> true + end. have_rdep(_App, [], _Dep) -> false; @@ -424,28 +467,43 @@ have_rdep(App, [RDep | RDeps], Dep) -> have_rdep(App, RDeps, Dep) end. -check_app_deps(_App, _AppFile, _AFDeps, []) -> +check_app_deps(_App, _AppFile, _AFDeps, [], _IgnoreApps) -> []; -check_app_deps(App, AppFile, AFDeps, [XRDep | XRDeps]) -> - ResOtherDeps = check_app_deps(App, AppFile, AFDeps, XRDeps), +check_app_deps(App, AppFile, AFDeps, [XRDep | XRDeps], IgnoreApps) -> + ResOtherDeps = check_app_deps(App, AppFile, AFDeps, XRDeps, IgnoreApps), case have_rdep(App, AFDeps, XRDep) of true -> ResOtherDeps; false -> - [{missing_runtime_dependency, AppFile, XRDep} | ResOtherDeps] + Failure = {missing_runtime_dependency, AppFile, XRDep}, + case lists:member(App, IgnoreApps) of + true -> + put(ignored_failures, [Failure | get(ignored_failures)]), + ResOtherDeps; + false -> + [Failure | ResOtherDeps] + end end. -check_apps_deps([]) -> +check_apps_deps([], _IgnoreApps) -> []; -check_apps_deps([{App, Deps}|AppDeps]) -> - ResOtherApps = check_apps_deps(AppDeps), +check_apps_deps([{App, Deps}|AppDeps], IgnoreApps) -> + ResOtherApps = check_apps_deps(AppDeps, IgnoreApps), AppFile = code:where_is_file(atom_to_list(App) ++ ".app"), {ok,[{application, App, Info}]} = file:consult(AppFile), case lists:keyfind(runtime_dependencies, 1, Info) of {runtime_dependencies, RDeps} -> - check_app_deps(App, AppFile, RDeps, Deps) ++ ResOtherApps; + check_app_deps(App, AppFile, RDeps, Deps, IgnoreApps) + ++ ResOtherApps; false -> - [{missing_runtime_dependencies_key, AppFile} | ResOtherApps] + Failure = {missing_runtime_dependencies_key, AppFile}, + case lists:member(App, IgnoreApps) of + true -> + put(ignored_failures, [Failure | get(ignored_failures)]), + ResOtherApps; + false -> + [Failure | ResOtherApps] + end end. %%% |