diff options
Diffstat (limited to 'erts')
32 files changed, 315 insertions, 1242 deletions
diff --git a/erts/doc/src/erl_tracer.xml b/erts/doc/src/erl_tracer.xml index 63feebb0b5..fd3c17f337 100644 --- a/erts/doc/src/erl_tracer.xml +++ b/erts/doc/src/erl_tracer.xml @@ -653,7 +653,7 @@ ok <0.37.0> 3> erlang:trace(new, true, [send,{tracer, erl_msg_tracer, Tracer}]). 0 -{<0.39.0>,<0.27.0>} +{trace,<0.39.0>,<0.27.0>} 4> {ok, D} = file:open("/tmp/tmp.data",[write]). {trace,#Port<0.486>,<0.40.0>} {trace,<0.40.0>,<0.21.0>} @@ -758,18 +758,21 @@ static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) /* * argv[0]: TraceTag, should only be 'send' - * argv[1]: TracerState, process to send {argv[2], argv[4]} to + * argv[1]: TracerState, process to send {Tracee, Recipient} to * argv[2]: Tracee - * argv[3]: Recipient - * argv[4]: Options, ignored + * argv[3]: Message + * argv[4]: Options, map containing Recipient */ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifPid to_pid; + ERL_NIF_TERM recipient, msg; if (enif_get_local_pid(env, argv[1], &to_pid)) { - ERL_NIF_TERM msg = enif_make_tuple3(env, enif_make_atom(env, "trace"), argv[2], argv[4]); + if (enif_get_map_value(env, argv[4], enif_make_atom(env, "extra"), &recipient)) { + msg = enif_make_tuple3(env, enif_make_atom(env, "trace"), argv[2], recipient); enif_send(env, &to_pid, NULL, msg); + } } return enif_make_atom(env, "ok"); diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index d0fa170e66..8ae87ac280 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -32,559 +32,20 @@ <p>This document describes the changes made to the ERTS application.</p> -<section><title>Erts 9.0</title> +<section><title>Erts 8.3.4</title> <section><title>Fixed Bugs and Malfunctions</title> <list> <item> - <p>Fix various bugs regarding loading, upgrade and purge - of HiPE compiled code:</p> <list> <item>The native code - memory for a purged module was never deallocated.</item> - <item>Wrong functions could in some cases be called after - a module upgrade.</item> - <item><c>erlang:check_process_code</c> did not check for - recursive calls made from native code.</item> </list> <p> - Own Id: OTP-13968</p> - </item> - <item> - <p> - Hipe optional LLVM backend does require LLVM version 3.9 - or later as older versions forced strong dependencies on - erts internals structures.</p> - <p> - Own Id: OTP-14238</p> - </item> - <item> - <p>When an exception such as '<c>throw(HugeTerm)</c>' was - caught, <c>HugeTerm</c> term would be kept in the process - until the next exception occurred, potentially increasing - the heap size for the process. That has been - corrected.</p> - <p> - Own Id: OTP-14255 Aux Id: OTP-14400, OTP-14401 </p> - </item> - <item> - <p> - Slogans in crash dumps have been extended to print more - complex terms.</p> - <p> - Own Id: OTP-14303</p> - </item> - <item> - <p> - Fixed bug when using <c>enif_inspect_binary</c> in - combination with <c>enif_copy</c>. In some circumstances - the inspected binary could be realloced by the - <c>enif_copy</c> call when it shouldn't have been.</p> - <p> - Own Id: OTP-14304</p> - </item> - <item> - <p> - The address family <c>local</c> (AF_UNIX / AF_LOCAL) now - does not ensure zero termination of Linux Abstract - Addresses so they can use all bytes.</p> - <p> - Own Id: OTP-14305</p> - </item> - <item> - <p> - Use <c>-fno-PIE</c> for Gentoo Hardened and others that - don't accept linker flag <c>-no-pie</c>.</p> - <p> - Own Id: OTP-14307 Aux Id: PR-1379 </p> - </item> - <item> - <p> - Disable hipe for <c>ppc64le</c> architecture (little - endian) as it is not, and has never been, supported. It - was earlier equated with <c>ppc64</c> (big endian) which - lead to broken build without <c>--disable-hipe</c>.</p> - <p> - Own Id: OTP-14314 Aux Id: ERL-369, PR-1394 </p> - </item> - <item> - <p> - Fix 'epmd -kill' to return a failure exit status code if - epmd was not killed because of some error.</p> - <p> - Own Id: OTP-14324</p> - </item> - <item> - <p>Fixed the following dirty scheduler related bugs:</p> - <list> <item><p>the <c>+SDPcpu</c> command line argument - could cause the amount of dirty CPU schedulers to be set - to zero</p></item> - <item><p><c>erlang:system_flag(multi_scheduling, _)</c> - failed when only one normal scheduler was used together - with dirty scheduler support</p></item> </list> - <p> - Own Id: OTP-14335</p> - </item> - <item> - <p> - Fix erlexec to handle mismatch in sysconf and proc fs - when figuring out the cpu topology. This behaviour has - been seen when using docker together with - <c>--cpuset-cpus</c>.</p> - <p> - Own Id: OTP-14352</p> - </item> - <item> - <p> - Fixed memory segment cache used for multiblock carriers. - Huge (> 2GB) memory segments could cause a VM crash. - Creation of such huge memory segments used for multiblock - carriers is however very uncommon.</p> - <p> - Own Id: OTP-14360 Aux Id: ERL-401, PR-1417 </p> - </item> - <item> - <p> - Fix bug causing <c>code:is_module_native</c> to falsely - return true when <c>local</c> call trace is enabled for - the module.</p> - <p> - Own Id: OTP-14390</p> - </item> - <item> - <p> - Fix emulator crash when receive tracing on a - <c>trace_delivered</c> message.</p> - <p> - Own Id: OTP-14411</p> - </item> - <item> - <p> - <c>escript</c> did not handle paths with spaces correct.</p> - <p> - Own Id: OTP-14433</p> - </item> - <item> - <p> - Fix erroneous lock check assertion when <c>wx</c> is run - on MacOS X.</p> - <p> - Own Id: OTP-14437 Aux Id: ERL-360 </p> - </item> - </list> - </section> - - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - Added <c>erlang:garbage_collect/2</c> that takes an - option list as the last argument that can be used to - control whether a minor or a major garbage collection is - to be done. Doing a minor collection only collects terms - that have recently died, but is cheaper than a mjor - collection.</p> - <p> - Own Id: OTP-11695</p> - </item> - <item> - <p> - Optimized test for tuples with an atom as first element.</p> - <p> - Own Id: OTP-12148</p> - </item> - <item> - <p> - Erlang literals are no longer copied during process to - process messaging.</p> - <p> - Own Id: OTP-13529</p> - </item> - <item> - <p>Add support in the <c>erl_nif</c> API for asynchronous - message notifications when sockets or other file - descriptors are ready to accept read or write operations. - The following functions have been added:</p> <list> - <item><p>enif_select</p></item> - <item><p>enif_monitor_process</p></item> - <item><p>enif_demonitor_process</p></item> - <item><p>enif_compare_monitors</p></item> - <item><p>enif_open_resource_type_x</p></item> </list> - <p> - Own Id: OTP-13684</p> - </item> - <item> - <p>There are two new guard BIFs '<c>floor/1</c>' and - '<c>ceil/1</c>'. They both return integers. In the - '<c>math</c>' module, there are two new BIFs with the - same names that return floating point values.</p> - <p> - Own Id: OTP-13692</p> - </item> - <item> - <p> - Remove deprecated <c>erlang:hash/2</c>.</p> - <p> - *** POTENTIAL INCOMPATIBILITY ***</p> - <p> - Own Id: OTP-13827</p> - </item> - <item> - <p>Replaced usage of deprecated symbolic <seealso - marker="erts:erlang#type-time_unit"><c>time - unit</c></seealso> representations.</p> - <p> - Own Id: OTP-13831 Aux Id: OTP-13735 </p> - </item> - <item> - <p> - Added support in zlib for extraction of the inflation - dictionary.</p> - <p> - Own Id: OTP-13842</p> - </item> - <item> - <p> - The previously used purge strategy has been removed. The - optional purge strategy introduced in ERTS version 8.1 is - now the only strategy available.</p> - <p> - The new purge strategy is slightly incompatible with the - old strategy. Previously processes holding <c>fun</c>s - that referred to the module being purged either failed a - soft purge, or was killed during a hard purge. The new - strategy completely ignores <c>fun</c>s. If <c>fun</c>s - referring to the code being purged exist, and are used - after a purge, an exception will be raised upon usage. - That is, the behavior will be exactly the same as the - case when a <c>fun</c> is received by a process after the - purge.</p> - <p> - For more information see the documentation of <seealso - marker="erts:erlang#check_process_code/3"><c>erlang:check_process_code/3</c></seealso>.</p> - <p> - *** POTENTIAL INCOMPATIBILITY ***</p> - <p> - Own Id: OTP-13844 Aux Id: OTP-13833 </p> - </item> - <item> - <p> - Dirty schedulers are now enabled by default when the - runtime system is built with SMP support.</p> - <p> - Own Id: OTP-13860</p> - </item> - <item> - <p> - Improved ETS lookup/insert/delete speed for large - <c>set</c>, <c>bag</c> and <c>duplicate_bag</c> by a - significant reduction of the hash load factor. This speed - improvement comes at the expense of less than one word - per table entry. Tables with less than 256 entries are - not affected at all.</p> - <p> - Own Id: OTP-13903</p> - </item> - <item> - <p> - The NIF library <c>reload</c> feature is not supported - anymore. It has been marked as deprecated since OTP R15B. - This means that you are only allowed to do one successful - call to <c>erlang:load_nif/2</c> for each module - instance. A second call to <c>erlang:load_nif/2</c> will - return <c>{error, {reload, _}}</c> even if the NIF - library imlements the <c>reload</c> callback.</p> - <p> - Runtime upgrade of a NIF library is still supported by - using the Erlang module upgrade mechanics with a current - and an old module instance existing at the same time with - their corresponding NIF libraries.</p> - <p> - *** POTENTIAL INCOMPATIBILITY ***</p> - <p> - Own Id: OTP-13908</p> - </item> - <item> - <p> - Add <c>erlang:system_info(atom_count)</c> and - <c>erlang:system_info(atom_limit)</c> to provide a way to - retrieve the current and maximum number of atoms.</p> - <p> - Own Id: OTP-13976</p> - </item> - <item> - <p>The function <c>fmod/2</c> has been added to the - <c>math</c> module.</p> - <p> - Own Id: OTP-14000</p> - </item> - <item> - <p> - <c>erlang:load_nif/2</c> returns new error type - <c>notsup</c> when called for a HiPE compiled module, - which is not supported.</p> - <p> - Own Id: OTP-14002</p> - </item> - <item> - <p> - Add driver and nif lock instrumentation to lcnt</p> - <p> - Own Id: OTP-14069</p> - </item> - <item> - <p> - Reduce memory pressure by converting sub-binaries to - heap-binaries when possible. This is done during garbage - collection.</p> - <p> - Own Id: OTP-14149</p> - </item> - <item> - <p> - Dirty schedulers are now enabled and supported on Erlang - runtime systems with SMP support.</p> - <p> - Besides support for dirty NIFs also support for dirty - BIFs and dirty garbage collection have been introduced. - All garbage collections that potentially will take a long - time to complete are now performed on dirty schedulers if - enabled.</p> - <p> - <seealso - marker="erts:erlang#statistics/1"><c>erlang:statistics/1</c></seealso> - with arguments inspecting scheduler and run queue states - have been changed due to the dirty scheduler support. - Code using this functionality may have to be rewritten - taking these incompatibilities into consideration. - Examples of such uses are calls to <seealso - marker="erts:erlang#statistics_scheduler_wall_time"><c>erlang:statistics(scheduler_wall_time)</c></seealso>, - <seealso - marker="erts:erlang#statistics_total_run_queue_lengths"><c>statistics(total_run_queue_lengths)</c></seealso>, - <seealso - marker="erts:erlang#statistics_total_active_tasks"><c>statistics(total_active_tasks)</c></seealso>, - etc.</p> - <p> - *** POTENTIAL INCOMPATIBILITY ***</p> - <p> - Own Id: OTP-14152</p> - </item> - <item> - <p>Atoms may now contain arbitrary Unicode - characters.</p> - <p> - Own Id: OTP-14178</p> - </item> - <item> - <p> - Introduce an event manager in Erlang to handle OS - signals. A subset of OS signals may be subscribed to and - those are described in the Kernel application.</p> - <p> - Own Id: OTP-14186</p> - </item> - <item> - <p> - The <c>escript</c> program now handles symbolic links to - escripts.</p> - <p> - This is useful for standalone systems with - <c>escript</c>s residing on a bin directory not included - in the execution path (as it may cause their <c>erl</c> - program(s) to override the desired one). Instead the - <c>escript</c>s can be referred to via symbolic links - from a bin directory in the path.</p> - <p> - Own Id: OTP-14201 Aux Id: PR-1293 </p> - </item> - <item> - <p> - All uses of the magic binary kludge has been replaced by - uses of erlang references.</p> - <p> - A magic binary was presented as an empty binary, but - actually referred other data internally in the Erlang VM. - Since they were presented as empty binaries, different - magic binaries compared as equal, and also lost their - internal data when passed out of an erlang node.</p> - <p> - The new usage of references has not got any of these - strange semantic issues, and the usage of these - references has been optimized to give the same - performance benefits as well as memory usage benefits as - magic binaries had.</p> - <p> - A couple of examples of previous uses of magic binaries - are match specifications and NIF resources.</p> - <p> - Own Id: OTP-14205</p> - </item> - <item> - <p> - The non-smp emulators have been deprecated and are - scheduled for removal in OTP-21.</p> - <p> - In preperations for this, the threaded non-smp emulator - is no longer built by default and has to be enabled using - the --enable-plain-emulator to configure.</p> - <p> - *** POTENTIAL INCOMPATIBILITY ***</p> - <p> - Own Id: OTP-14272</p> - </item> - <item> - <p> - Allow HiPE to run on VM built with - <c>--enable-m32-build</c>.</p> - <p> - Own Id: OTP-14330 Aux Id: PR-1397 </p> - </item> - <item> - <p> - Upgraded the OTP internal PCRE library from version 8.33 - to version 8.40. This library is used for implementation - of the <seealso marker="stdlib:re"><c>re</c></seealso> - regular expressions module.</p> - <p> - Besides various bug fixes, the new version allows for - better stack protection. In order to utilize this - feature, the stack size of normal scheduler threads is - now by default set to 128 kilo words on all platforms. - The stack size of normal scheduler threads can be set - upon system start by passing the <seealso - marker="erts:erl#sched_thread_stack_size"><c>+sss</c></seealso> - command line argument to the <seealso - marker="erts:erl"><c>erl</c></seealso> command.</p> - <p> - See <url - href="http://pcre.org/original/changelog.txt"><c>http://pcre.org/original/changelog.txt</c></url> - for information about changes made to PCRE between the - versions 8.33 and 8.40.</p> - <p> - *** POTENTIAL INCOMPATIBILITY ***</p> - <p> - Own Id: OTP-14331 Aux Id: ERL-208 </p> - </item> - <item> - <p> - Remove generation of atoms in old latin1 external format. - The old latin1 format can still be decoded but is never - generated by <c>term_to_binary</c> or sent on a - distribution channel. The new utf8 format for atoms was - introduced in OTP R16. An OTP 20 node can therefore not - connect to nodes older than R16.</p> - <p> - Own Id: OTP-14337</p> - </item> - <item> - <p> - Added function <c>re:version/0</c> which returns - information about the OTP internal PCRE version used for - implementation of the <c>re</c> module.</p> - <p> - Own Id: OTP-14347 Aux Id: PR-1412 </p> - </item> - <item> - <p> - Added new debug bif <c>erlang:list_to_port/1</c>.</p> - <p> - Own Id: OTP-14348</p> - </item> - <item> - <p> - Various improvements of timer management internally in - the VM. These improvements both reduced memory - consumption of timer wheels as well as reduce the amount - of work that has to be performed in order to handle - timers.</p> - <p> - Own Id: OTP-14356</p> - </item> - <item> - <p> Sockets can now be bound to device (SO_BINDTODEVICE) - on platforms where it is supported. </p> <p> This has - been implemented e.g to support VRF-Lite under Linux; see - <url - href="https://www.kernel.org/doc/Documentation/networking/vrf.txt"> - VRF </url>, and GitHub pull request <url - href="https://github.com/erlang/otp/pull/1326">#1326</url>. - </p> - <p> - Own Id: OTP-14357 Aux Id: PR-1326 </p> - </item> - <item> - <p>Added the following <seealso - marker="erl"><c>erl</c></seealso> command line arguments - with which you can set suggested stack for dirty - schedulers:</p> <taglist> <tag><seealso - marker="erl#dcpu_sched_thread_stack_size"><c>+sssdcpu</c></seealso></tag> - <item><p>for dirty CPU schedulers</p></item> - <tag><seealso - marker="erl#dio_sched_thread_stack_size"><c>+sssdio</c></seealso></tag> - <item><p>for dirty IO schedulers</p></item> </taglist> - <p>The default suggested stack size for dirty schedulers - is 40 kilo words.</p> - <p> - Own Id: OTP-14380</p> - </item> - <item> - <p> - Changed erts startup program name, argv 0, to use the - environment variable <c>ESCRIPT_NAME</c> so that - <c>erlc</c>, <c>dialyzer</c>, <c>typer</c>, - <c>ct_run</c>, or the escript name can be seen with - external programs, such as ps and htop (depending on - options), on unix.</p> - <p> - Own Id: OTP-14381</p> - </item> - <item> - <p> - Improvements of <c>escript</c> documentation.</p> - <p> - Own Id: OTP-14384 Aux Id: OTP-14201 </p> - </item> - <item> - <p> - Add function <c>enif_hash</c> for NIFs to calculate hash - values of arbitrary terms.</p> - <p> - Own Id: OTP-14385 Aux Id: PR-1413 </p> - </item> - <item> - <p>'<c>./configure --enable-lock-counter</c>' will - enabling building of an additional emulator that has - support for lock counting. (The option previously - existed, but would turn on lock counting in the default - emulator being built.) To start the lock-counting - emulator, use '<c>erl -emu_type lcnt</c>'.</p> - <p>On Windows, <c>erl</c> recognized the undocumented - option <c>-debug</c> for starting a debug-compiled - emulator. That option has been removed. Use '<c>erl - -emu_type debug</c>' instead.</p> - <p> - Own Id: OTP-14407</p> - </item> - <item> - <p> - Warnings have been added to the relevant documentation - about not using un-secure distributed nodes in exposed - environments.</p> - <p> - Own Id: OTP-14425</p> - </item> - <item> - <p> - Improvement of the documentation of the environment - variable <c>ERL_CRASH_DUMP_SECONDS</c> as well as the - default behavior when it is not set.</p> - <p> - Own Id: OTP-14434</p> - </item> - <item> - <p> - Enabled off-heap message queue for some system processes - that might receive large amounts of messages.</p> + Add option to make SIGTERM trigger the OS default + behaviour instead of doing a gracefull shutdown. To + activate this bahviour the environment variable + ERL_ZZ_SIGTERM_KILL should be set to "true". This option + only works in OTP 19 as OTP 20 will have a different way + to deal with SIGTERM.</p> <p> - Own Id: OTP-14438</p> + Own Id: OTP-14418 Aux Id: ERIERL-15 </p> </item> </list> </section> diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index 254e59f2c7..61c1e14741 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -149,6 +149,8 @@ endif LIBS += $(TYPE_LIBS) +ORIG_LIBS:= $(LIBS) + comma:=, space:= space+= @@ -965,7 +967,7 @@ $(OBJDIR)/%.o: hipe/%.c $(V_CC) $(subst O2,O3, $(CFLAGS)) $(INCLUDES) -c $< -o $@ $(BINDIR)/hipe_mkliterals$(TF_MARKER): $(OBJDIR)/hipe_mkliterals.o - $(ld_verbose)$(CC) $(LDFLAGS) -o $@ $< $(TYPE_LIBS) + $(ld_verbose)$(CC) $(LDFLAGS) -o $@ $< $(ORIG_LIBS) $(OBJDIR)/hipe_mkliterals.o: $(HIPE_ASM) $(TTF_DIR)/erl_alloc_types.h $(DTRACE_HEADERS) \ $(TTF_DIR)/OPCODES-GENERATED $(TTF_DIR)/TABLES-GENERATED diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 7134d2da56..40dd4129d2 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -2047,8 +2047,6 @@ ebif_bang_2(BIF_ALIST_2) #define SEND_YIELD_CONTINUE (-8) -Sint do_send(Process *p, Eterm to, Eterm msg, Eterm *refp, ErtsSendContext*); - static Sint remote_send(Process *p, DistEntry *dep, Eterm to, Eterm full_to, Eterm msg, ErtsSendContext* ctx) @@ -2102,8 +2100,8 @@ static Sint remote_send(Process *p, DistEntry *dep, return res; } -Sint -do_send(Process *p, Eterm to, Eterm msg, Eterm *refp, ErtsSendContext* ctx) +static Sint +do_send(Process *p, Eterm to, Eterm msg, Eterm *refp, ErtsSendContext *ctx) { Eterm portid; Port *pt; diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c index 4889fac923..6fddba4b34 100644 --- a/erts/emulator/beam/erl_alloc_util.c +++ b/erts/emulator/beam/erl_alloc_util.c @@ -821,7 +821,7 @@ static void clear_literal_range(void* start, Uint size) #if HAVE_ERTS_MSEG -void* +static void* erts_alcu_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags) { void *res; @@ -832,7 +832,7 @@ erts_alcu_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags) return res; } -void* +static void* erts_alcu_mseg_realloc(Allctr_t *allctr, void *seg, Uint old_size, Uint *new_size_p) { @@ -845,7 +845,7 @@ erts_alcu_mseg_realloc(Allctr_t *allctr, void *seg, return res; } -void +static void erts_alcu_mseg_dealloc(Allctr_t *allctr, void *seg, Uint size, Uint flags) { erts_mseg_dealloc_opt(allctr->alloc_no, seg, (UWord) size, flags, &allctr->mseg_opt); @@ -996,7 +996,7 @@ erts_alcu_exec_mseg_dealloc(Allctr_t *allctr, void *seg, Uint size, Uint flags) #endif /* HAVE_ERTS_MSEG */ -void* +static void* erts_alcu_sys_alloc(Allctr_t *allctr, Uint* size_p, int superalign) { void *res; @@ -1013,7 +1013,7 @@ erts_alcu_sys_alloc(Allctr_t *allctr, Uint* size_p, int superalign) return res; } -void* +static void* erts_alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint *size_p, Uint old_size, int superalign) { void *res; @@ -1035,7 +1035,7 @@ erts_alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint *size_p, Uint old_size, return res; } -void +static void erts_alcu_sys_dealloc(Allctr_t *allctr, void *ptr, Uint size, int superalign) { #if ERTS_SA_MB_CARRIERS && ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h index f570703f25..7a96bd0319 100644 --- a/erts/emulator/beam/erl_alloc_util.h +++ b/erts/emulator/beam/erl_alloc_util.h @@ -195,10 +195,6 @@ extern UWord erts_literal_vspace_map[]; # define ERTS_VSPACE_WORD_BITS (sizeof(UWord)*8) #endif -void* erts_alcu_mseg_alloc(Allctr_t*, Uint *size_p, Uint flags); -void* erts_alcu_mseg_realloc(Allctr_t*, void *seg, Uint old_size, Uint *new_size_p); -void erts_alcu_mseg_dealloc(Allctr_t*, void *seg, Uint size, Uint flags); - #if HAVE_ERTS_MSEG # if defined(ARCH_32) void* erts_alcu_literal_32_mseg_alloc(Allctr_t*, Uint *size_p, Uint flags); @@ -218,9 +214,6 @@ void erts_alcu_exec_mseg_dealloc(Allctr_t*, void *seg, Uint size, Uint flags); # endif #endif /* HAVE_ERTS_MSEG */ -void* erts_alcu_sys_alloc(Allctr_t*, Uint *size_p, int superalign); -void* erts_alcu_sys_realloc(Allctr_t*, void *ptr, Uint *size_p, Uint old_size, int superalign); -void erts_alcu_sys_dealloc(Allctr_t*, void *ptr, Uint size, int superalign); #ifdef ARCH_32 void* erts_alcu_literal_32_sys_alloc(Allctr_t*, Uint *size_p, int superalign); void* erts_alcu_literal_32_sys_realloc(Allctr_t*, void *ptr, Uint *size_p, Uint old_size, int superalign); diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c index eea55b3239..71c64997c1 100644 --- a/erts/emulator/beam/erl_bits.c +++ b/erts/emulator/beam/erl_bits.c @@ -1636,7 +1636,7 @@ erts_bs_get_unaligned_uint32(ErlBinMatchBuffer* mb) return LSB[0] | (LSB[1]<<8) | (LSB[2]<<16) | (LSB[3]<<24); } -void +static void erts_align_utf8_bytes(ErlBinMatchBuffer* mb, byte* buf) { Uint bits = mb->size - mb->offset; diff --git a/erts/emulator/beam/erl_bits.h b/erts/emulator/beam/erl_bits.h index 632855255e..5da2b28a89 100644 --- a/erts/emulator/beam/erl_bits.h +++ b/erts/emulator/beam/erl_bits.h @@ -202,7 +202,6 @@ void erts_new_bs_put_string(ERL_BITS_PROTO_2(byte* iptr, Uint num_bytes)); Uint erts_bits_bufs_size(void); Uint32 erts_bs_get_unaligned_uint32(ErlBinMatchBuffer* mb); -void erts_align_utf8_bytes(ErlBinMatchBuffer* mb, byte* buf); Eterm erts_bs_get_utf8(ErlBinMatchBuffer* mb); Eterm erts_bs_get_utf16(ErlBinMatchBuffer* mb, Uint flags); Eterm erts_bs_append(Process* p, Eterm* reg, Uint live, Eterm build_size_term, diff --git a/erts/emulator/beam/erl_cpu_topology.c b/erts/emulator/beam/erl_cpu_topology.c index 4347f9f2b7..d0fd763798 100644 --- a/erts/emulator/beam/erl_cpu_topology.c +++ b/erts/emulator/beam/erl_cpu_topology.c @@ -2243,45 +2243,6 @@ add_cpu_groups(int groups, return cgm; } -static void -remove_cpu_groups(erts_cpu_groups_callback_t callback, void *arg) -{ - erts_cpu_groups_map_t *prev_cgm, *cgm; - erts_cpu_groups_callback_list_t *prev_cgcl, *cgcl; - - ERTS_SMP_LC_ASSERT(erts_lc_rwmtx_is_rwlocked(&cpuinfo_rwmtx)); - - no_cpu_groups_callbacks--; - - prev_cgm = NULL; - for (cgm = cpu_groups_maps; cgm; cgm = cgm->next) { - prev_cgcl = NULL; - for (cgcl = cgm->callback_list; cgcl; cgcl = cgcl->next) { - if (cgcl->callback == callback && cgcl->arg == arg) { - if (prev_cgcl) - prev_cgcl->next = cgcl->next; - else - cgm->callback_list = cgcl->next; - erts_free(ERTS_ALC_T_CPU_GRPS_MAP, cgcl); - if (!cgm->callback_list) { - if (prev_cgm) - prev_cgm->next = cgm->next; - else - cpu_groups_maps = cgm->next; - if (cgm->array) - erts_free(ERTS_ALC_T_CPU_GRPS_MAP, cgm->array); - erts_free(ERTS_ALC_T_CPU_GRPS_MAP, cgm); - } - return; - } - prev_cgcl = cgcl; - } - prev_cgm = cgm; - } - - erts_exit(ERTS_ABORT_EXIT, "Cpu groups not found\n"); -} - static int cpu_groups_lookup(erts_cpu_groups_map_t *map, ErtsSchedulerData *esdp) @@ -2321,21 +2282,3 @@ update_cpu_groups_maps(void) for (cgm = cpu_groups_maps; cgm; cgm = cgm->next) make_cpu_groups_map(cgm, 0); } - -void -erts_add_cpu_groups(int groups, - erts_cpu_groups_callback_t callback, - void *arg) -{ - erts_smp_rwmtx_rwlock(&cpuinfo_rwmtx); - add_cpu_groups(groups, callback, arg); - erts_smp_rwmtx_rwunlock(&cpuinfo_rwmtx); -} - -void erts_remove_cpu_groups(erts_cpu_groups_callback_t callback, - void *arg) -{ - erts_smp_rwmtx_rwlock(&cpuinfo_rwmtx); - remove_cpu_groups(callback, arg); - erts_smp_rwmtx_rwunlock(&cpuinfo_rwmtx); -} diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c index 08a0f0e83b..0addfaa3c7 100644 --- a/erts/emulator/beam/erl_db_hash.c +++ b/erts/emulator/beam/erl_db_hash.c @@ -676,7 +676,7 @@ int db_create_hash(Process *p, DbTable *tbl) sizeof(DbTableHashFineLocks)); for (i=0; i<DB_HASH_LOCK_CNT; ++i) { erts_smp_rwmtx_init_opt_x(&tb->locks->lck_vec[i].lck, &rwmtx_opt, - "db_hash_slot", make_small(i)); + "db_hash_slot", tb->common.the_name); } /* This important property is needed to guarantee the two buckets * involved in a grow/shrink operation it protected by the same lock: diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 00fc6116e5..fc2b34e70f 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -13933,7 +13933,11 @@ erts_continue_exit_process(Process *p) erts_set_gc_state(p, 1); state = erts_smp_atomic32_read_acqb(&p->state); - if (state & ERTS_PSFLG_ACTIVE_SYS) { + if (state & ERTS_PSFLG_ACTIVE_SYS +#ifdef ERTS_DIRTY_SCHEDULERS + || p->dirty_sys_tasks +#endif + ) { if (cleanup_sys_tasks(p, state, CONTEXT_REDS) >= CONTEXT_REDS/2) goto yield; } diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index 0acc2432a7..f8341f788a 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -969,17 +969,21 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, fdrec.sfv_len = SENDFILE_CHUNK_SIZE; else fdrec.sfv_len = *nbytes; + retval = sendfilev(out_fd, &fdrec, 1, &len); - /* Sometimes sendfilev can return -1 and still send data. - When that happens we just pretend that no error happend. */ - if (retval != -1 || errno == EAGAIN || errno == EINTR || - len != 0) { + if (retval == -1 && errno == EINVAL) { + /* On some solaris versions (I've seen it on SunOS 5.10), + using a sfv_len larger then a filesize will result in + a -1 && errno == EINVAL return. We translate this so + a successful send of the data.*/ + retval = len; + } + + if (retval != -1 || errno == EAGAIN || errno == EINTR) { *offset += len; *nbytes -= len; written += len; - if (errno != EAGAIN && errno != EINTR && len != 0) - retval = len; } } while (len == SENDFILE_CHUNK_SIZE); #elif defined(__DARWIN__) diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 2479ccc01f..fcd7244ae9 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -117,7 +117,6 @@ MODULES= \ tracer_SUITE \ tracer_test \ scheduler_SUITE \ - old_scheduler_SUITE \ port_trace_SUITE \ unique_SUITE \ z_SUITE \ diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl index 355be7a36d..4d17276e5c 100644 --- a/erts/emulator/test/binary_SUITE.erl +++ b/erts/emulator/test/binary_SUITE.erl @@ -1358,17 +1358,19 @@ do_trapping(N, Bif, ArgFun) -> io:format("N=~p: Do ~p ~s gc.\n", [N, Bif, case N rem 2 of 0 -> "with"; 1 -> "without" end]), Pid = spawn(?MODULE,trapping_loop,[Bif, ArgFun, 1000, self()]), receive ok -> ok end, - receive after 100 -> ok end, Ref = make_ref(), case N rem 2 of - 0 -> erlang:garbage_collect(Pid, [{async,Ref}]), - receive after 100 -> ok end; + 0 -> + erlang:garbage_collect(Pid, [{async,Ref}]), + receive after 1 -> ok end; 1 -> void end, - exit(Pid,kill), + exit(Pid, kill), case N rem 2 of - 0 -> receive {garbage_collect, Ref, _} -> ok end; - 1 -> void + 0 -> + receive {garbage_collect, Ref, _} -> ok end; + 1 -> + void end, receive after 1 -> ok end, do_trapping(N-1, Bif, ArgFun). diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl index ed03284a5b..779d81daa5 100644 --- a/erts/emulator/test/bs_construct_SUITE.erl +++ b/erts/emulator/test/bs_construct_SUITE.erl @@ -35,7 +35,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 10}}]. + {timetrap, {minutes, 1}}]. all() -> [test1, test2, test3, test4, test5, testf, not_used, diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl index 95171d04ce..1251d644ae 100644 --- a/erts/emulator/test/call_trace_SUITE.erl +++ b/erts/emulator/test/call_trace_SUITE.erl @@ -43,7 +43,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 30}}]. + {timetrap, {minutes, 2}}]. all() -> Common = [errors, on_load], diff --git a/erts/emulator/test/ddll_SUITE.erl b/erts/emulator/test/ddll_SUITE.erl index 0b9f76a892..031b05790d 100644 --- a/erts/emulator/test/ddll_SUITE.erl +++ b/erts/emulator/test/ddll_SUITE.erl @@ -55,7 +55,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 10}}]. + {timetrap, {minutes, 1}}]. all() -> [ddll_test, errors, reference_count, kill_port, diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index 434e729310..dc7afa381b 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -62,8 +62,7 @@ -export([sender/3, receiver2/2, dummy_waiter/0, dead_process/0, roundtrip/1, bounce/1, do_dist_auto_connect/1, inet_rpc_server/1, dist_parallel_sender/3, dist_parallel_receiver/0, - dist_evil_parallel_receiver/0, - sendersender/4, sendersender2/4]). + dist_evil_parallel_receiver/0]). %% epmd_module exports -export([start_link/0, register_node/2, register_node/3, port_please/2]). @@ -129,52 +128,53 @@ bulk_send_small(Config) when is_list(Config) -> bulk_send_big(Config) when is_list(Config) -> bulk_send(32, 64). -bulk_send_bigbig(Config) when is_list(Config) -> - bulk_sendsend(32*5, 4). - bulk_send(Terms, BinSize) -> ct:timetrap({seconds, 30}), io:format("Sending ~w binaries, each of size ~w K", [Terms, BinSize]), {ok, Node} = start_node(bulk_receiver), Recv = spawn(Node, erlang, apply, [fun receiver/2, [0, 0]]), - Bin = list_to_binary(lists:duplicate(BinSize*1024, 253)), + Bin = binary:copy(<<253>>, BinSize*1024), Size = Terms*size(Bin), {Elapsed, {Terms, Size}} = test_server:timecall(?MODULE, sender, [Recv, Bin, Terms]), stop_node(Node), - {comment, integer_to_list(trunc(Size/1024/max(1,Elapsed)+0.5)) ++ " K/s"}. + {comment, integer_to_list(round(Size/1024/max(1,Elapsed))) ++ " K/s"}. -bulk_sendsend(Terms, BinSize) -> +sender(To, _Bin, 0) -> + To ! {done, self()}, + receive + Any -> + Any + end; +sender(To, Bin, Left) -> + To ! {term, Bin}, + sender(To, Bin, Left-1). + +bulk_send_bigbig(Config) when is_list(Config) -> + Terms = 32*5, + BinSize = 4, {Rate1, MonitorCount1} = bulk_sendsend2(Terms, BinSize, 5), {Rate2, MonitorCount2} = bulk_sendsend2(Terms, BinSize, 995), Ratio = if MonitorCount2 == 0 -> MonitorCount1 / 1.0; true -> MonitorCount1 / MonitorCount2 end, - Comment = integer_to_list(Rate1) ++ " K/s, " ++ - integer_to_list(Rate2) ++ " K/s, " ++ - integer_to_list(MonitorCount1) ++ " monitor msgs, " ++ - integer_to_list(MonitorCount2) ++ " monitor msgs, " ++ - float_to_list(Ratio) ++ " monitor ratio", - if - %% A somewhat arbitrary ratio, but hopefully one that will - %% accommodate a wide range of CPU speeds. - Ratio > 8.0 -> - {comment,Comment}; - true -> - io:put_chars(Comment), - ct:fail(ratio_too_low) - end. + Comment0 = io_lib:format("~p K/s, ~p K/s, " + "~p monitor msgs, ~p monitor msgs, " + "~.1f monitor ratio", + [Rate1,Rate2,MonitorCount1, + MonitorCount2,Ratio]), + Comment = lists:flatten(Comment0), + {comment,Comment}. bulk_sendsend2(Terms, BinSize, BusyBufSize) -> ct:timetrap({seconds, 30}), - io:format("Sending ~w binaries, each of size ~w K", + io:format("\nSending ~w binaries, each of size ~w K", [Terms, BinSize]), {ok, NodeRecv} = start_node(bulk_receiver), Recv = spawn(NodeRecv, erlang, apply, [fun receiver/2, [0, 0]]), - Bin = list_to_binary(lists:duplicate(BinSize*1024, 253)), - %%Size = Terms*size(Bin), + Bin = binary:copy(<<253>>, BinSize*1024), %% SLF LEFT OFF HERE. %% When the caller uses small hunks, like 4k via @@ -185,74 +185,62 @@ bulk_sendsend2(Terms, BinSize, BusyBufSize) -> %% default busy size and "+zdbbl 5", and if the 5 case gets %% "many many more" monitor messages, then we know we're working. - {ok, NodeSend} = start_node(bulk_sender, "+zdbbl " ++ integer_to_list(BusyBufSize)), - _Send = spawn(NodeSend, erlang, apply, [fun sendersender/4, [self(), Recv, Bin, Terms]]), + {ok, NodeSend} = start_node(bulk_sender, "+zdbbl " ++ + integer_to_list(BusyBufSize)), + _Send = spawn(NodeSend, erlang, apply, + [fun sendersender/4, [self(), Recv, Bin, Terms]]), {Elapsed, {_TermsN, SizeN}, MonitorCount} = - receive - %% On some platforms (windows), the time taken is 0 so we - %% simulate that some little time has passed. - {sendersender, {0.0,T,MC}} -> - {0.0015, T, MC}; - {sendersender, BigRes} -> - BigRes - end, + receive + %% On some platforms (Windows), the time taken is 0 so we + %% simulate that some little time has passed. + {sendersender, {0.0,T,MC}} -> + {0.0015, T, MC}; + {sendersender, BigRes} -> + BigRes + end, stop_node(NodeRecv), stop_node(NodeSend), - {trunc(SizeN/1024/Elapsed+0.5), MonitorCount}. - -sender(To, _Bin, 0) -> - To ! {done, self()}, - receive - Any -> - Any - end; -sender(To, Bin, Left) -> - To ! {term, Bin}, - sender(To, Bin, Left-1). + {round(SizeN/1024/Elapsed), MonitorCount}. %% Sender process to be run on a slave node sendersender(Parent, To, Bin, Left) -> erlang:system_monitor(self(), [busy_dist_port]), - [spawn(fun() -> sendersender2(To, Bin, Left, false) end) || - _ <- lists:seq(1,1)], + _ = spawn(fun() -> + sendersender_send(To, Bin, Left), + exit(normal) + end), {USec, {Res, MonitorCount}} = - timer:tc(?MODULE, sendersender2, [To, Bin, Left, true]), + timer:tc(fun() -> + sendersender_send(To, Bin, Left), + To ! {done, self()}, + count_monitors(0) + end), Parent ! {sendersender, {USec/1000000, Res, MonitorCount}}. -sendersender2(To, Bin, Left, SendDone) -> - sendersender3(To, Bin, Left, SendDone, 0). +sendersender_send(_To, _Bin, 0) -> + ok; +sendersender_send(To, Bin, Left) -> + To ! {term, Bin}, + sendersender_send(To, Bin, Left-1). -sendersender3(To, _Bin, 0, SendDone, MonitorCount) -> - if SendDone -> - To ! {done, self()}; - true -> - ok - end, +count_monitors(MonitorCount) -> receive {monitor, _Pid, _Type, _Info} -> - sendersender3(To, _Bin, 0, SendDone, MonitorCount + 1) + count_monitors(MonitorCount + 1) after 0 -> - if SendDone -> - receive - Any when is_tuple(Any), size(Any) == 2 -> - {Any, MonitorCount} - end; - true -> - exit(normal) - end - end; -sendersender3(To, Bin, Left, SendDone, MonitorCount) -> - To ! {term, Bin}, - %%timer:sleep(50), - sendersender3(To, Bin, Left-1, SendDone, MonitorCount). + receive + {_,_}=Any -> + {Any,MonitorCount} + end + end. %% Receiver process to be run on a slave node. receiver(Terms, Size) -> receive {term, Bin} -> - receiver(Terms+1, Size+size(Bin)); + receiver(Terms+1, Size+byte_size(Bin)); {done, ReplyTo} -> ReplyTo ! {Terms, Size} end. diff --git a/erts/emulator/test/evil_SUITE.erl b/erts/emulator/test/evil_SUITE.erl index 9416ac7a02..fb1954ce37 100644 --- a/erts/emulator/test/evil_SUITE.erl +++ b/erts/emulator/test/evil_SUITE.erl @@ -34,7 +34,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 30}}]. + {timetrap, {minutes, 1}}]. all() -> [heap_frag, encode_decode_ext, decode_integer_ext, diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl index 76e3556bc4..ad6d8c890f 100644 --- a/erts/emulator/test/exception_SUITE.erl +++ b/erts/emulator/test/exception_SUITE.erl @@ -33,7 +33,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 10}}]. + {timetrap, {minutes, 1}}]. all() -> [badmatch, pending_errors, nil_arith, stacktrace, diff --git a/erts/emulator/test/gc_SUITE.erl b/erts/emulator/test/gc_SUITE.erl index 35dd147550..2c2cb9c32d 100644 --- a/erts/emulator/test/gc_SUITE.erl +++ b/erts/emulator/test/gc_SUITE.erl @@ -203,89 +203,90 @@ long_receive() -> end. minor_major_gc_option_self(_Config) -> - Endless = fun Endless() -> - receive - {gc, Type} -> erlang:garbage_collect(self(), [{type, Type}]) - after 100 -> ok end, - Endless() - end, - - %% Try as major, a test process will self-trigger GC - P1 = spawn(Endless), - erlang:garbage_collect(P1, []), - erlang:trace(P1, true, [garbage_collection]), - P1 ! {gc, major}, - expect_trace_messages(P1, [gc_major_start, gc_major_end]), - erlang:trace(P1, false, [garbage_collection]), - erlang:exit(P1, kill), - - %% Try as minor, a test process will self-trigger GC - P2 = spawn(Endless), - erlang:garbage_collect(P2, []), - erlang:trace(P2, true, [garbage_collection]), - P2 ! {gc, minor}, - expect_trace_messages(P2, [gc_minor_start, gc_minor_end]), - erlang:trace(P2, false, [garbage_collection]), - erlang:exit(P2, kill). + %% Try as major, the test process will self-trigger GC + check_gc_tracing_around( + fun(Pid, Ref) -> + Pid ! {gc, Ref, major} + end, [gc_major_start, gc_major_end]), + + %% Try as minor, the test process will self-trigger GC + check_gc_tracing_around( + fun(Pid, Ref) -> + Pid ! {gc, Ref, minor} + end, [gc_minor_start, gc_minor_end]). minor_major_gc_option_async(_Config) -> - Endless = fun Endless() -> - receive after 100 -> ok end, - Endless() - end, - - %% Try with default option, must be major gc - P1 = spawn(Endless), - erlang:garbage_collect(P1, []), - erlang:trace(P1, true, [garbage_collection]), - erlang:garbage_collect(P1, []), - expect_trace_messages(P1, [gc_major_start, gc_major_end]), - erlang:trace(P1, false, [garbage_collection]), - erlang:exit(P1, kill), + %% Try with default option, must be major GC + check_gc_tracing_around( + fun(Pid, _Ref) -> + erlang:garbage_collect(Pid, []) + end, [gc_major_start, gc_major_end]), %% Try with the 'major' type - P2 = spawn(Endless), - erlang:garbage_collect(P2, []), - erlang:trace(P2, true, [garbage_collection]), - erlang:garbage_collect(P2, [{type, major}]), - expect_trace_messages(P2, [gc_major_start, gc_major_end]), - erlang:trace(P2, false, [garbage_collection]), - erlang:exit(P2, kill), + check_gc_tracing_around( + fun(Pid, _Ref) -> + erlang:garbage_collect(Pid, [{type, major}]) + end, [gc_major_start, gc_major_end]), %% Try with 'minor' option, once - P3 = spawn(Endless), - erlang:garbage_collect(P3, []), - erlang:trace(P3, true, [garbage_collection]), - erlang:garbage_collect(P3, [{type, minor}]), - expect_trace_messages(P3, [gc_minor_start, gc_minor_end]), - erlang:trace(P3, false, [garbage_collection]), - erlang:exit(P3, kill), + check_gc_tracing_around( + fun(Pid, _Ref) -> + erlang:garbage_collect(Pid, [{type, minor}]) + end, [gc_minor_start, gc_minor_end]), %% Try with 'minor' option, once, async - P4 = spawn(Endless), + check_gc_tracing_around( + fun(Pid, Ref) -> + ?assertEqual(async, + erlang:garbage_collect(Pid, [{type, minor}, {async, Ref}])), + + receive + {garbage_collect, Ref, true} -> + ok + after 10000 -> + ct:fail("Did not receive a completion notification on async GC") + end + end, [gc_minor_start, gc_minor_end]). + +%% Traces garbage collection around the given operation, and fails the test if +%% it results in any unexpected messages or if the expected trace tags are not +%% received. +check_gc_tracing_around(Fun, ExpectedTraceTags) -> Ref = erlang:make_ref(), - erlang:garbage_collect(P4, []), - erlang:trace(P4, true, [garbage_collection]), - ?assertEqual(async, - erlang:garbage_collect(P4, [{type, minor}, {async, Ref}])), - expect_trace_messages(P4, [gc_minor_start, gc_minor_end]), - erlang:trace(P4, false, [garbage_collection]), - receive {garbage_collect, Ref, true} -> ok; - Other4 -> ct:pal("Unexpected message: ~p~n" - ++ "while waiting for async gc result", [Other4]) - after 2000 -> ?assert(false) - end, - erlang:exit(P4, kill). - -%% Given a list of atoms, trace tags - receives messages and checks if they are -%% trace events, and if the tag matches. Else will crash failing the test. -expect_trace_messages(_Pid, []) -> ok; + Pid = spawn( + fun Endless() -> + receive + {gc, Ref, Type} -> + erlang:garbage_collect(self(), [{type, Type}]) + after 100 -> + ok + end, + Endless() + end), + erlang:garbage_collect(Pid, []), + erlang:trace(Pid, true, [garbage_collection]), + Fun(Pid, Ref), + expect_trace_messages(Pid, ExpectedTraceTags), + erlang:trace(Pid, false, [garbage_collection]), + erlang:exit(Pid, kill), + check_no_unexpected_messages(). + +%% Ensures that trace messages with the provided tags have all been received +%% within a reasonable timeframe. +expect_trace_messages(_Pid, []) -> + ok; expect_trace_messages(Pid, [Tag | TraceTags]) -> receive - {trace, Pid, Tag, _Data} -> ok; - AnythingElse -> - ct:pal("Unexpected message: ~p~nWhile expected {trace, _, ~p, _}", - [AnythingElse, Tag]), - ?assert(false) - end, - expect_trace_messages(Pid, TraceTags). + {trace, Pid, Tag, _Data} -> + expect_trace_messages(Pid, TraceTags) + after 4000 -> + ct:fail("Didn't receive tag ~p within 4000ms", [Tag]) + end. + +check_no_unexpected_messages() -> + receive + Anything -> + ct:fail("Unexpected message: ~p", [Anything]) + after 0 -> + ok + end. diff --git a/erts/emulator/test/lttng_SUITE.erl b/erts/emulator/test/lttng_SUITE.erl index c12f63706a..1c1952f912 100644 --- a/erts/emulator/test/lttng_SUITE.erl +++ b/erts/emulator/test/lttng_SUITE.erl @@ -40,7 +40,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 10}}]. + {timetrap, {minutes, 1}}]. all() -> [t_lttng_list, diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl index eb189c2c33..92ddc23592 100644 --- a/erts/emulator/test/match_spec_SUITE.erl +++ b/erts/emulator/test/match_spec_SUITE.erl @@ -42,7 +42,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 30}}]. + {timetrap, {minutes, 1}}]. all() -> case test_server:is_native(match_spec_SUITE) of diff --git a/erts/emulator/test/nested_SUITE.erl b/erts/emulator/test/nested_SUITE.erl index 7af2873ce2..5059317172 100644 --- a/erts/emulator/test/nested_SUITE.erl +++ b/erts/emulator/test/nested_SUITE.erl @@ -27,7 +27,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 10}}]. + {timetrap, {minutes, 1}}]. all() -> [case_in_case, case_in_after, catch_in_catch, diff --git a/erts/emulator/test/old_scheduler_SUITE.erl b/erts/emulator/test/old_scheduler_SUITE.erl deleted file mode 100644 index 8515a87df8..0000000000 --- a/erts/emulator/test/old_scheduler_SUITE.erl +++ /dev/null @@ -1,384 +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% -%% - --module(old_scheduler_SUITE). - --include_lib("common_test/include/ct.hrl"). - --export([all/0, suite/0, - init_per_testcase/2, end_per_testcase/2]). --export([equal/1, many_low/1, few_low/1, max/1, high/1]). - -suite() -> - [{ct_hooks,[ts_install_cth]}, - {timetrap, {minutes, 11}}]. - -all() -> - case catch erlang:system_info(modified_timing_level) of - Level when is_integer(Level) -> - {skipped, - "Modified timing (level " ++ - integer_to_list(Level) ++ - ") is enabled. Testcases gets messed " - "up by modfied timing."}; - _ -> [equal, many_low, few_low, max, high] - end. - - -%%----------------------------------------------------------------------------------- -%% TEST SUITE DESCRIPTION -%% -%% The test case function spawns two controlling processes: Starter and Receiver. -%% Starter spawns a number of prio A and a number of prio B test processes. Each -%% test process loops for a number of times, sends a report to the Receiver, then -%% loops again. For each report, the Receiver increases a counter that corresponds -%% to the priority of the sender. After a certain amount of time, the Receiver -%% sends the collected data to the main test process and waits for the test case -%% to terminate. From this data, it's possible to calculate the average run time -%% relationship between the prio A and B test processes. -%% -%% Note that in order to be able to run tests with high or max prio test processes, -%% the main test process and the Receiver needs to run at max prio, or they will -%% be starved by the test processes. The controlling processes must not wait for -%% messages from a normal (or low) prio process while max or high prio test processes -%% are running (which happens e.g. if an io function is called). -%%----------------------------------------------------------------------------------- - -init_per_testcase(_Case, Config) -> - %% main test process needs max prio - Prio = process_flag(priority, max), - MS = erlang:system_flag(multi_scheduling, block_normal), - [{prio,Prio},{multi_scheduling, MS}|Config]. - -end_per_testcase(_Case, Config) -> - erlang:system_flag(multi_scheduling, unblock_normal), - Prio=proplists:get_value(prio, Config), - process_flag(priority, Prio), - ok. - -ok(Config) when is_list(Config) -> - case proplists:get_value(multi_scheduling, Config) of - blocked -> - {comment, - "Multi-scheduling blocked during test. This testcase was not " - "written to work with multiple schedulers."}; - _ -> ok - end. - -%% Run equal number of low and normal prio processes. - -equal(Config) when is_list(Config) -> - Self = self(), - - %% specify number of test processes to run - Normal = {normal,500}, - Low = {low,500}, - - %% specify time of test (in seconds) - Time = 30, - - %% start controllers - Receiver = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Normal, Low) end), - Starter = - spawn(fun() -> starter(Normal, Low, Receiver) end), - - %% receive test data from Receiver - {NRs,NAvg,LRs,LAvg,Ratio} = - receive - {Receiver,Res} -> Res - end, - - %% stop controllers and test processes - exit(Starter, kill), - exit(Receiver, kill), - - io:format("Reports: ~w normal (~w/proc), ~w low (~w/proc). Ratio: ~w~n", - [NRs,NAvg,LRs,LAvg,Ratio]), - - %% runtime ratio between normal and low should be ~8 - if Ratio < 7.5 ; Ratio > 8.5 -> - ct:fail({bad_ratio,Ratio}); - true -> - ok(Config) - end. - - -%% Run many low and few normal prio processes. - -many_low(Config) when is_list(Config) -> - Self = self(), - Normal = {normal,1}, - Low = {low,1000}, - - %% specify time of test (in seconds) - Time = 30, - - Receiver = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Normal, Low) end), - Starter = - spawn(fun() -> starter(Normal, Low, Receiver) end), - {NRs,NAvg,LRs,LAvg,Ratio} = - receive - {Receiver,Res} -> Res - end, - exit(Starter, kill), - exit(Receiver, kill), - io:format("Reports: ~w normal (~w/proc), ~w low (~w/proc). Ratio: ~w~n", - [NRs,NAvg,LRs,LAvg,Ratio]), - if Ratio < 7.5 ; Ratio > 8.5 -> - ct:fail({bad_ratio,Ratio}); - true -> - ok(Config) - end. - - -%% Run few low and many normal prio processes. - -few_low(Config) when is_list(Config) -> - Self = self(), - Normal = {normal,1000}, - Low = {low,1}, - - %% specify time of test (in seconds) - Time = 30, - - Receiver = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Normal, Low) end), - Starter = - spawn(fun() -> starter(Normal, Low, Receiver) end), - {NRs,NAvg,LRs,LAvg,Ratio} = - receive - {Receiver,Res} -> Res - end, - exit(Starter, kill), - exit(Receiver, kill), - io:format("Reports: ~w normal (~w/proc), ~w low (~w/proc). Ratio: ~w~n", - [NRs,NAvg,LRs,LAvg,Ratio]), - if Ratio < 7.0 ; Ratio > 8.5 -> - ct:fail({bad_ratio,Ratio}); - true -> - ok(Config) - end. - - -%% Run max prio processes and verify they get at least as much -%% runtime as high, normal and low. - -max(Config) when is_list(Config) -> - max = process_flag(priority, max), % should already be max (init_per_tc) - Self = self(), - Max = {max,2}, - High = {high,2}, - Normal = {normal,100}, - Low = {low,100}, - - %% specify time of test (in seconds) - Time = 30, - - Receiver1 = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Max, High) end), - Starter1 = - spawn(fun() -> starter(Max, High, Receiver1) end), - {M1Rs,M1Avg,HRs,HAvg,Ratio1} = - receive - {Receiver1,Res1} -> Res1 - end, - exit(Starter1, kill), - exit(Receiver1, kill), - io:format("Reports: ~w max (~w/proc), ~w high (~w/proc). Ratio: ~w~n", - [M1Rs,M1Avg,HRs,HAvg,Ratio1]), - if Ratio1 < 1.0 -> - ct:fail({bad_ratio,Ratio1}); - true -> - ok(Config) - end, - - Receiver2 = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Max, Normal) end), - Starter2 = - spawn(fun() -> starter(Max, Normal, Receiver2) end), - {M2Rs,M2Avg,NRs,NAvg,Ratio2} = - receive - {Receiver2,Res2} -> Res2 - end, - exit(Starter2, kill), - exit(Receiver2, kill), - io:format("Reports: ~w max (~w/proc), ~w normal (~w/proc). Ratio: ~w~n", - [M2Rs,M2Avg,NRs,NAvg,Ratio2]), - if Ratio2 < 1.0 -> - ct:fail({bad_ratio,Ratio2}); - true -> - ok - end, - - Receiver3 = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Max, Low) end), - Starter3 = - spawn(fun() -> starter(Max, Low, Receiver3) end), - {M3Rs,M3Avg,LRs,LAvg,Ratio3} = - receive - {Receiver3,Res3} -> Res3 - end, - exit(Starter3, kill), - exit(Receiver3, kill), - io:format("Reports: ~w max (~w/proc), ~w low (~w/proc). Ratio: ~w~n", - [M3Rs,M3Avg,LRs,LAvg,Ratio3]), - if Ratio3 < 1.0 -> - ct:fail({bad_ratio,Ratio3}); - true -> - ok(Config) - end. - - -%% Run high prio processes and verify they get at least as much -%% runtime as normal and low. - -high(Config) when is_list(Config) -> - max = process_flag(priority, max), % should already be max (init_per_tc) - Self = self(), - High = {high,2}, - Normal = {normal,100}, - Low = {low,100}, - - %% specify time of test (in seconds) - Time = 30, - - Receiver1 = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, High, Normal) end), - Starter1 = - spawn(fun() -> starter(High, Normal, Receiver1) end), - {H1Rs,H1Avg,NRs,NAvg,Ratio1} = - receive - {Receiver1,Res1} -> Res1 - end, - exit(Starter1, kill), - exit(Receiver1, kill), - io:format("Reports: ~w high (~w/proc), ~w normal (~w/proc). Ratio: ~w~n", - [H1Rs,H1Avg,NRs,NAvg,Ratio1]), - if Ratio1 < 1.0 -> - ct:fail({bad_ratio,Ratio1}); - true -> - ok - end, - - Receiver2 = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, High, Low) end), - Starter2 = - spawn(fun() -> starter(High, Low, Receiver2) end), - {H2Rs,H2Avg,LRs,LAvg,Ratio2} = - receive - {Receiver2,Res2} -> Res2 - end, - exit(Starter2, kill), - exit(Receiver2, kill), - io:format("Reports: ~w high (~w/proc), ~w low (~w/proc). Ratio: ~w~n", - [H2Rs,H2Avg,LRs,LAvg,Ratio2]), - if Ratio2 < 1.0 -> - ct:fail({bad_ratio,Ratio2}); - true -> - ok(Config) - end. - - -%%----------------------------------------------------------------------------------- -%% Controller processes and help functions -%%----------------------------------------------------------------------------------- - -receiver(T0, TimeSec, Main, {P1,P1N}, {P2,P2N}) -> - %% prio should be max so that mailbox doesn't overflow - process_flag(priority, max), - receiver(T0, TimeSec*1000, Main, P1,P1N,0, P2,P2N,0, 100000). - -%% uncomment lines below to get life sign (debug) -receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, 0) -> - % T = erlang:convert_time_unit(erlang:monotonic_time() - T0, native, millisecond), - % erlang:display({round(T/1000),P1Rs,P2Rs}), - receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, 100000); - -receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, C) -> - Remain = Time - erlang:convert_time_unit(erlang:monotonic_time() - T0, - native, millisecond), % test time remaining - Remain1 = if Remain < 0 -> - 0; - true -> - Remain - end, - {P1Rs1,P2Rs1} = - receive - {_Pid,P1} -> % report from a P1 process - {P1Rs+1,P2Rs}; - {_Pid,P2} -> % report from a P2 process - {P1Rs,P2Rs+1} - after Remain1 -> - {P1Rs,P2Rs} - end, - if Remain > 0 -> % keep going - receiver(T0, Time, Main, P1,P1N,P1Rs1, P2,P2N,P2Rs1, C-1); - true -> % finish - %% calculate results and send to main test process - P1Avg = P1Rs1/P1N, - P2Avg = P2Rs1/P2N, - Ratio = if P2Avg < 1.0 -> P1Avg; - true -> P1Avg/P2Avg - end, - Main ! {self(),{P1Rs1,round(P1Avg),P2Rs1,round(P2Avg),Ratio}}, - flush_loop() - end. - -starter({P1,P1N}, {P2,P2N}, Receiver) -> - %% start N1 processes with prio P1 - start_p(P1, P1N, Receiver), - %% start N2 processes with prio P2 - start_p(P2, P2N, Receiver), - erlang:display({started,P1N+P2N}), - flush_loop(). - -start_p(_, 0, _) -> - ok; -start_p(Prio, N, Receiver) -> - spawn_link(fun() -> p(Prio, Receiver) end), - start_p(Prio, N-1, Receiver). - -p(Prio, Receiver) -> - %% set process priority - process_flag(priority, Prio), - p_loop(0, Prio, Receiver). - -p_loop(100, Prio, Receiver) -> - receive after 0 -> ok end, - %% if Receiver gone, we're done - case is_process_alive(Receiver) of - false -> exit(bye); - true -> ok - end, - %% send report - Receiver ! {self(),Prio}, - p_loop(0, Prio, Receiver); - -p_loop(N, Prio, Receiver) -> - p_loop(N+1, Prio, Receiver). - - -flush_loop() -> - receive _ -> - ok - end, - flush_loop(). diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 94ee9851dd..fccbaf13ee 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -153,7 +153,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 10}}]. + {timetrap, {minutes, 1}}]. all() -> [otp_6224, {group, stream}, basic_ping, slow_writes, diff --git a/erts/emulator/test/port_trace_SUITE.erl b/erts/emulator/test/port_trace_SUITE.erl index 03efdc15db..bfc3c8cb51 100644 --- a/erts/emulator/test/port_trace_SUITE.erl +++ b/erts/emulator/test/port_trace_SUITE.erl @@ -52,7 +52,7 @@ -define(ECHO_DRV_REMOTE_SEND_TERM, 15). suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 30}}]. + {timetrap, {minutes, 2}}]. all() -> [port_specs, ports, open_close, diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index e14185e881..4204d12eb3 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -134,6 +134,11 @@ init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> [{testcase, Func}|Config]. end_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + %% Restore max_heap_size to default value. + erlang:system_flag(max_heap_size, + #{size => 0, + kill => true, + error_logger => true}), ok. fun_spawn(Fun) -> @@ -1024,36 +1029,48 @@ bump_big(Prev, Limit) -> %% Priority 'low' should be mixed with 'normal' using a factor of %% about 8. (OTP-2644) low_prio(Config) when is_list(Config) -> - case erlang:system_info(schedulers_online) of - 1 -> - ok = low_prio_test(Config); - _ -> - erlang:system_flag(multi_scheduling, block_normal), - ok = low_prio_test(Config), - erlang:system_flag(multi_scheduling, unblock_normal), - {comment, - "Test not written for SMP runtime system. " - "Multi scheduling blocked during test."} - end. + erlang:system_flag(multi_scheduling, block_normal), + Prop = low_prio_test(Config), + erlang:system_flag(multi_scheduling, unblock_normal), + Str = lists:flatten(io_lib:format("Low/high proportion is ~.3f", + [Prop])), + {comment,Str}. low_prio_test(Config) when is_list(Config) -> process_flag(trap_exit, true), - S = spawn_link(?MODULE, prio_server, [0, 0]), + + %% Spawn the server running with high priority. The server must + %% not run at normal priority as that would skew the results for + %% two reasons: + %% + %% 1. There would be one more normal-priority processes than + %% low-priority processes. + %% + %% 2. The receive queue would grow faster than the server process + %% could process it. That would in turn trigger the reduction + %% punishment for the clients. + S = spawn_opt(?MODULE, prio_server, [0, 0], [link,{priority,high}]), + + %% Spawn the clients and let them run for a while. PCs = spawn_prio_clients(S, erlang:system_info(schedulers_online)), - ct:sleep({seconds,3}), + ct:sleep({seconds,2}), lists:foreach(fun (P) -> exit(P, kill) end, PCs), + + %% Stop the server and retrieve the result. S ! exit, - receive {'EXIT', S, {A, B}} -> check_prio(A, B) end, - ok. + receive + {'EXIT', S, {A, B}} -> + check_prio(A, B) + end. check_prio(A, B) -> Prop = A/B, ok = io:format("Low=~p, High=~p, Prop=~p\n", [A, B, Prop]), - %% It isn't 1/8, it's more like 0.3, but let's check that - %% the low-prio processes get some little chance to run at all. - true = (Prop < 1.0), - true = (Prop > 1/32). + %% Prop is expected to be appr. 1/8. Allow a reasonable margin. + true = Prop < 1/4, + true = Prop > 1/16, + Prop. prio_server(A, B) -> receive @@ -2057,6 +2074,7 @@ max_heap_size_test(Option, Size, Kill, ErrorLogger) -> end, if ErrorLogger -> receive + %% There must be at least one error message. {error, _, {emulator, _, [Pid|_]}} -> ok end; @@ -2069,22 +2087,33 @@ max_heap_size_test(Option, Size, Kill, ErrorLogger) -> {'DOWN', Ref, process, Pid, die} -> ok end, - flush(); + %% If the process was not killed, the limit may have + %% been reached more than once and there may be + %% more {error, ...} messages left. + receive_error_messages(Pid); true -> ok end, + + %% Make sure that there are no unexpected messages. + receive_unexpected(). + +receive_error_messages(Pid) -> receive - M -> - ct:fail({unexpected_message, M}) - after 10 -> + {error, _, {emulator, _, [Pid|_]}} -> + receive_error_messages(Pid) + after 1000 -> ok end. -flush() -> +receive_unexpected() -> receive - _M -> - flush() - after 1000 -> + {info_report, _, _} -> + %% May be an alarm message from os_mon. Ignore. + receive_unexpected(); + M -> + ct:fail({unexpected_message, M}) + after 10 -> ok end. diff --git a/erts/emulator/test/receive_SUITE.erl b/erts/emulator/test/receive_SUITE.erl index 83653a7a36..c7d5a3f5a0 100644 --- a/erts/emulator/test/receive_SUITE.erl +++ b/erts/emulator/test/receive_SUITE.erl @@ -39,25 +39,43 @@ groups() -> call_with_huge_message_queue(Config) when is_list(Config) -> Pid = spawn_link(fun echo_loop/0), - - {Time,ok} = tc(fun() -> calls(10, Pid) end), - - [self() ! {msg,N} || N <- lists:seq(1, 500000)], + _WarmUpTime = time_calls(Pid), + Time = time_calls(Pid), + _ = [self() ! {msg,N} || N <- lists:seq(1, 500000)], + io:format("Time for empty message queue: ~p", [Time]), erlang:garbage_collect(), - {NewTime1,ok} = tc(fun() -> calls(10, Pid) end), - {NewTime2,ok} = tc(fun() -> calls(10, Pid) end), + call_with_huge_message_queue_1(Pid, Time, 5). + +call_with_huge_message_queue_1(_Pid, _Time, 0) -> + ct:fail(bad_ratio); +call_with_huge_message_queue_1(Pid, Time, NumTries) -> + HugeTime = time_calls(Pid), + io:format("Time for huge message queue: ~p", [HugeTime]), + + case (HugeTime+1) / (Time+1) of + Q when Q < 10 -> + ok; + Q -> + io:format("Too high ratio: ~p\n", [Q]), + call_with_huge_message_queue_1(Pid, Time, NumTries-1) + end. - io:format("Time for empty message queue: ~p", [Time]), - io:format("Time1 for huge message queue: ~p", [NewTime1]), - io:format("Time2 for huge message queue: ~p", [NewTime2]), - - case hd(lists:sort([(NewTime1+1) / (Time+1), (NewTime2+1) / (Time+1)])) of - Q when Q < 10 -> - ok; - Q -> - ct:fail("Best Q = ~p", [Q]) - end, - ok. +%% Time a number calls. Try to avoid returning a zero time. +time_calls(Pid) -> + time_calls(Pid, 10). + +time_calls(_Pid, 0) -> + 0; +time_calls(Pid, NumTries) -> + case timer:tc(fun() -> calls(Pid) end) of + {0,ok} -> + time_calls(Pid, NumTries-1); + {Time,ok} -> + Time + end. + +calls(Pid) -> + calls(100, Pid). calls(0, _) -> ok; calls(N, Pid) -> @@ -108,6 +126,3 @@ echo_loop() -> Pid ! {Ref,Msg}, echo_loop() end. - -tc(Fun) -> - timer:tc(erlang, apply, [Fun,[]]). diff --git a/erts/emulator/test/timer_bif_SUITE.erl b/erts/emulator/test/timer_bif_SUITE.erl index 7cbd93a0f3..a977eb41c4 100644 --- a/erts/emulator/test/timer_bif_SUITE.erl +++ b/erts/emulator/test/timer_bif_SUITE.erl @@ -488,24 +488,40 @@ registered_process(Config) when is_list(Config) -> same_time_yielding(Config) when is_list(Config) -> Mem = mem(), + Ref = make_ref(), SchdlrsOnln = erlang:system_info(schedulers_online), Tmo = erlang:monotonic_time(millisecond) + 3000, Tmrs = lists:map(fun (I) -> process_flag(scheduler, (I rem SchdlrsOnln) + 1), - erlang:start_timer(Tmo, self(), hej, [{abs, true}]) + erlang:start_timer(Tmo, self(), Ref, [{abs, true}]) end, lists:seq(1, (?TIMEOUT_YIELD_LIMIT*3+1)*SchdlrsOnln)), true = mem_larger_than(Mem), - lists:foreach(fun (Tmr) -> receive {timeout, Tmr, hej} -> ok end end, Tmrs), + receive_all_timeouts(length(Tmrs), Ref), Done = erlang:monotonic_time(millisecond), true = Done >= Tmo, + MsAfterTmo = Done - Tmo, + io:format("Done ~p ms after Tmo\n", [MsAfterTmo]), case erlang:system_info(build_type) of - opt -> true = Done < Tmo + 200; - _ -> true = Done < Tmo + 1000 + opt -> + true = MsAfterTmo < 200; + _ -> + true = MsAfterTmo < 1000 end, Mem = mem(), ok. +%% Read out all timeouts in receive queue order. This is efficient +%% even if there are very many messages. + +receive_all_timeouts(0, _Ref) -> + ok; +receive_all_timeouts(N, Ref) -> + receive + {timeout, _Tmr, Ref} -> + receive_all_timeouts(N-1, Ref) + end. + same_time_yielding_with_cancel(Config) when is_list(Config) -> same_time_yielding_with_cancel_test(false, false). diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl index 643c2e0472..bd0ea22de9 100644 --- a/erts/emulator/test/trace_SUITE.erl +++ b/erts/emulator/test/trace_SUITE.erl @@ -46,7 +46,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 5}}]. + {timetrap, {minutes, 1}}]. all() -> [cpu_timestamp, receive_trace, link_receive_call_correlation, @@ -184,10 +184,10 @@ receive_trace(Config) when is_list(Config) -> {'EXIT', Intruder, {badarg, _}} = receive_first(), %% Untrace the process; we should not receive anything. - ?line 1 = erlang:trace(Receiver, false, ['receive']), - ?line Receiver ! {hello, there}, - ?line Receiver ! any_garbage, - ?line receive_nothing(), + 1 = erlang:trace(Receiver, false, ['receive']), + Receiver ! {hello, there}, + Receiver ! any_garbage, + receive_nothing(), %% Verify restrictions in matchspec for 'receive' F3 = fun (Pat) -> {'EXIT', {badarg,_}} = (catch erlang:trace_pattern('receive', Pat, [])) end, diff --git a/erts/emulator/test/trace_port_SUITE.erl b/erts/emulator/test/trace_port_SUITE.erl index e4db368ea1..5eb27a7b68 100644 --- a/erts/emulator/test/trace_port_SUITE.erl +++ b/erts/emulator/test/trace_port_SUITE.erl @@ -37,7 +37,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 30}}]. + {timetrap, {minutes, 2}}]. all() -> [call_trace, return_trace, send, receive_trace, |