diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/doc/src/erlang.xml | 130 | ||||
-rw-r--r-- | erts/doc/src/notes.xml | 43 | ||||
-rw-r--r-- | erts/emulator/beam/beam_bp.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_msacc.h | 32 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 53 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 14 | ||||
-rw-r--r-- | erts/emulator/drivers/common/inet_drv.c | 83 | ||||
-rw-r--r-- | erts/emulator/hipe/hipe_amd64_bifs.m4 | 1 | ||||
-rw-r--r-- | erts/emulator/hipe/hipe_bif0.tab | 2 | ||||
-rw-r--r-- | erts/emulator/hipe/hipe_bif_list.m4 | 2 | ||||
-rw-r--r-- | erts/emulator/hipe/hipe_debug.c | 8 | ||||
-rw-r--r-- | erts/emulator/hipe/hipe_native_bif.c | 9 | ||||
-rw-r--r-- | erts/emulator/hipe/hipe_native_bif.h | 4 | ||||
-rw-r--r-- | erts/emulator/hipe/hipe_primops.h | 2 | ||||
-rw-r--r-- | erts/emulator/nifs/common/zlib_nif.c | 30 | ||||
-rw-r--r-- | erts/emulator/test/process_SUITE.erl | 13 | ||||
-rw-r--r-- | erts/preloaded/ebin/zlib.beam | bin | 19784 -> 19744 bytes | |||
-rw-r--r-- | erts/preloaded/src/zlib.erl | 13 | ||||
-rw-r--r-- | erts/vsn.mk | 2 |
19 files changed, 235 insertions, 208 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index d0588fe3c1..c77f426919 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -4730,11 +4730,11 @@ RealSystem = system + MissedSystem</code> </func> <func> - <name name="process_flag" arity="2" clause_i="3"/> + <name name="process_flag" arity="2" clause_i="3" + anchor="process_flag_min_heap_size"/> <fsummary>Set process flag min_heap_size for the calling process. </fsummary> <desc> - <marker id="process_flag_min_heap_size"/> <p>Changes the minimum heap size for the calling process.</p> <p>Returns the old value of the flag.</p> </desc> @@ -4752,12 +4752,12 @@ RealSystem = system + MissedSystem</code> </func> <func> - <name name="process_flag" arity="2" clause_i="5"/> + <name name="process_flag" arity="2" clause_i="5" + anchor="process_flag_max_heap_size"/> <fsummary>Set process flag max_heap_size for the calling process. </fsummary> <type name="max_heap_size"/> <desc> - <marker id="process_flag_max_heap_size"/> <p>This flag sets the maximum heap size for the calling process. If <c><anno>MaxHeapSize</anno></c> is an integer, the system default values for <c>kill</c> and <c>error_logger</c> are used. @@ -4826,12 +4826,12 @@ RealSystem = system + MissedSystem</code> </func> <func> - <name name="process_flag" arity="2" clause_i="6"/> + <name name="process_flag" arity="2" clause_i="6" + anchor="process_flag_message_queue_data"/> <fsummary>Set process flag message_queue_data for the calling process. </fsummary> <type name="message_queue_data"/> <desc> - <marker id="process_flag_message_queue_data"/> <p>This flag determines how messages in the message queue are stored, as follows:</p> <taglist> @@ -4868,11 +4868,12 @@ RealSystem = system + MissedSystem</code> </func> <func> - <name name="process_flag" arity="2" clause_i="7"/> + <name name="process_flag" arity="2" clause_i="7" + anchor="process_flag_priority"/> <fsummary>Set process flag priority for the calling process.</fsummary> <type name="priority_level"/> <desc> - <p><marker id="process_flag_priority"></marker> + <p> Sets the process priority. <c><anno>Level</anno></c> is an atom. Four priority levels exist: <c>low</c>, <c>normal</c>, <c>high</c>, and <c>max</c>. Default @@ -6347,10 +6348,10 @@ true</pre> </func> <func> - <name name="statistics" arity="1" clause_i="1"/> + <name name="statistics" arity="1" clause_i="1" + anchor="statistics_active_tasks"/> <fsummary>Information about active processes and ports.</fsummary> <desc> - <marker id="statistics_active_tasks"></marker> <p>Returns the same as <seealso marker="#statistics_active_tasks_all"> <c>statistics(active_tasks_all)</c></seealso> @@ -6362,10 +6363,10 @@ true</pre> </func> <func> - <name name="statistics" arity="1" clause_i="2"/> + <name name="statistics" arity="1" clause_i="2" + anchor="statistics_active_tasks_all"/> <fsummary>Information about active processes and ports.</fsummary> <desc> - <marker id="statistics_active_tasks_all"></marker> <p>Returns a list where each element represents the amount of active processes and ports on each run queue and its associated schedulers. That is, the number of processes and @@ -6413,10 +6414,10 @@ true</pre> </func> <func> - <name name="statistics" arity="1" clause_i="4"/> + <name name="statistics" arity="1" clause_i="4" + anchor="statistics_exact_reductions"/> <fsummary>Information about exact reductions.</fsummary> <desc> - <marker id="statistics_exact_reductions"></marker> <p>Returns the number of exact reductions.</p> <note> <p><c>statistics(exact_reductions)</c> is @@ -6451,10 +6452,10 @@ true</pre> </func> <func> - <name name="statistics" arity="1" clause_i="7"/> + <name name="statistics" arity="1" clause_i="7" + anchor="statistics_microstate_accounting"/> <fsummary>Information about microstate accounting.</fsummary> <desc> - <marker id="statistics_microstate_accounting"></marker> <p>Microstate accounting can be used to measure how much time the Erlang runtime system spends doing various tasks. It is designed to be as lightweight as possible, but some overhead exists when this @@ -6594,10 +6595,10 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="8"/> + <name name="statistics" arity="1" clause_i="8" + anchor="statistics_reductions"/> <fsummary>Information about reductions.</fsummary> <desc> - <marker id="statistics_reductions"></marker> <p>Returns information about reductions, for example:</p> <pre> > <input>statistics(reductions).</input> @@ -6613,9 +6614,10 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="9"/> + <name name="statistics" arity="1" clause_i="9" + anchor="statistics_run_queue"/> <fsummary>Information about the run-queues.</fsummary> - <desc><marker id="statistics_run_queue"></marker> + <desc> <p>Returns the total length of all normal run-queues. That is, the number of processes and ports that are ready to run on all available normal run-queues. Dirty run queues are not part of the @@ -6629,9 +6631,10 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="10"/> + <name name="statistics" arity="1" clause_i="10" + anchor="statistics_run_queue_lengths"/> <fsummary>Information about the run-queue lengths.</fsummary> - <desc><marker id="statistics_run_queue_lengths"></marker> + <desc> <p>Returns the same as <seealso marker="#statistics_run_queue_lengths_all"> <c>statistics(run_queue_lengths_all)</c></seealso> @@ -6643,9 +6646,10 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="11"/> + <name name="statistics" arity="1" clause_i="11" + anchor="statistics_run_queue_lengths_all"/> <fsummary>Information about the run-queue lengths.</fsummary> - <desc><marker id="statistics_run_queue_lengths_all"></marker> + <desc> <p>Returns a list where each element represents the amount of processes and ports ready to run for each run queue. Values for normal run queues are located first in the @@ -6703,10 +6707,10 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="13"/> + <name name="statistics" arity="1" clause_i="13" + anchor="statistics_scheduler_wall_time"/> <fsummary>Information about each schedulers work time.</fsummary> <desc> - <marker id="statistics_scheduler_wall_time"></marker> <p>Returns a list of tuples with <c>{<anno>SchedulerId</anno>, <anno>ActiveTime</anno>, <anno>TotalTime</anno>}</c>, where @@ -6824,10 +6828,10 @@ ok </func> <func> - <name name="statistics" arity="1" clause_i="14"/> + <name name="statistics" arity="1" clause_i="14" + anchor="statistics_scheduler_wall_time_all"/> <fsummary>Information about each schedulers work time.</fsummary> <desc> - <marker id="statistics_scheduler_wall_time_all"></marker> <p>The same as <seealso marker="#statistics_scheduler_wall_time"><c>statistics(scheduler_wall_time)</c></seealso>, except that it also include information about all dirty I/O @@ -6849,9 +6853,10 @@ ok </desc> </func> <func> - <name name="statistics" arity="1" clause_i="15"/> + <name name="statistics" arity="1" clause_i="15" + anchor="statistics_total_active_tasks"/> <fsummary>Information about active processes and ports.</fsummary> - <desc><marker id="statistics_total_active_tasks"></marker> + <desc> <p>The same as calling <c>lists:sum(</c><seealso marker="#statistics_active_tasks"><c>statistics(active_tasks)</c></seealso><c>)</c>, but more efficient.</p> @@ -6859,9 +6864,10 @@ ok </func> <func> - <name name="statistics" arity="1" clause_i="16"/> + <name name="statistics" arity="1" clause_i="16" + anchor="statistics_total_active_tasks_all"/> <fsummary>Information about active processes and ports.</fsummary> - <desc><marker id="statistics_total_active_tasks_all"></marker> + <desc> <p>The same as calling <c>lists:sum(</c><seealso marker="#statistics_active_tasks_all"><c>statistics(active_tasks_all)</c></seealso><c>)</c>, but more efficient.</p> @@ -6869,9 +6875,10 @@ ok </func> <func> - <name name="statistics" arity="1" clause_i="17"/> + <name name="statistics" arity="1" clause_i="17" + anchor="statistics_total_run_queue_lengths"/> <fsummary>Information about the run-queue lengths.</fsummary> - <desc><marker id="statistics_total_run_queue_lengths"></marker> + <desc> <p>The same as calling <c>lists:sum(</c><seealso marker="#statistics_run_queue_lengths"><c>statistics(run_queue_lengths)</c></seealso><c>)</c>, but more efficient.</p> @@ -6879,9 +6886,10 @@ ok </func> <func> - <name name="statistics" arity="1" clause_i="18"/> + <name name="statistics" arity="1" clause_i="18" + anchor="statistics_total_run_queue_lengths_all"/> <fsummary>Information about the run-queue lengths.</fsummary> - <desc><marker id="statistics_total_run_queue_lengths_all"></marker> + <desc> <p>The same as calling <c>lists:sum(</c><seealso marker="#statistics_run_queue_lengths_all"><c>statistics(run_queue_lengths_all)</c></seealso><c>)</c>, but more efficient.</p> @@ -7029,7 +7037,8 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="2"/> + <name name="system_flag" arity="2" clause_i="2" + anchor="system_flag_cpu_topology"/> <fsummary>Set system flag <c>cpu_topology</c>.</fsummary> <type name="cpu_topology"/> <type name="level_entry"/> @@ -7038,7 +7047,7 @@ ok <type name="info_list"/> <desc> <warning> - <p><marker id="system_flag_cpu_topology"></marker> + <p> <em>This argument is deprecated.</em> Instead of using this argument, use command-line argument <seealso marker="erts:erl#+sct"><c>+sct</c></seealso> in @@ -7076,10 +7085,11 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="3"/> + <name name="system_flag" arity="2" clause_i="3" + anchor="system_flag_dirty_cpu_schedulers_online"/> <fsummary>Set system_flag_dirty_cpu_schedulers_online.</fsummary> <desc> - <p><marker id="system_flag_dirty_cpu_schedulers_online"></marker> + <p> Sets the number of dirty CPU schedulers online. Range is <c><![CDATA[1 <= DirtyCPUSchedulersOnline <= N]]></c>, where <c>N</c> is the smallest of the return values of @@ -7123,10 +7133,11 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="5"/> + <name name="system_flag" arity="2" clause_i="5" + anchor="system_flag_microstate_accounting"/> <fsummary>Set system flag microstate_accounting.</fsummary> <desc> - <p><marker id="system_flag_microstate_accounting"></marker> + <p> Turns on/off microstate accounting measurements. When passing reset, all counters are reset to 0.</p> <p>For more information see @@ -7168,28 +7179,29 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="8"/> + <name name="system_flag" arity="2" clause_i="8" + anchor="system_flag_max_heap_size"/> <fsummary>Set system flag max_heap_size.</fsummary> <type name="max_heap_size"/> <desc> - <marker id="system_flag_max_heap_size"></marker> <p> Sets the default maximum heap size settings for processes. The size is specified in words. The new <c>max_heap_size</c> effects only processes spawned efter the change has been made. <c>max_heap_size</c> can be set for individual processes using <seealso marker="#spawn_opt/4"><c>spawn_opt/2,3,4</c></seealso> or - <seealso marker="#process_flag_message_queue_data"> + <seealso marker="#process_flag_max_heap_size"> <c>process_flag/2</c></seealso>.</p> <p>Returns the old value of the flag.</p> </desc> </func> <func> - <name name="system_flag" arity="2" clause_i="9"/> + <name name="system_flag" arity="2" clause_i="9" + anchor="system_flag_multi_scheduling"/> <fsummary>Set system flag multi_scheduling.</fsummary> <desc> - <p><marker id="system_flag_multi_scheduling"></marker> + <p> If multi-scheduling is enabled, more than one scheduler thread is used by the emulator. Multi-scheduling can be blocked in two different ways. Either all schedulers but @@ -7241,12 +7253,13 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="10"/> + <name name="system_flag" arity="2" clause_i="10" + anchor="system_flag_scheduler_bind_type"/> <fsummary>Set system flag scheduler_bind_type.</fsummary> <type name="scheduler_bind_type"/> <desc> <warning> - <p><marker id="system_flag_scheduler_bind_type"></marker> + <p> <em>This argument is deprecated.</em> Instead of using this argument, use command-line argument <seealso marker="erts:erl#+sbt"><c>+sbt</c></seealso> in @@ -7367,10 +7380,11 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="11"/> + <name name="system_flag" arity="2" clause_i="11" + anchor="system_flag_scheduler_wall_time"/> <fsummary>Set system flag scheduler_wall_time.</fsummary> <desc> - <p><marker id="system_flag_scheduler_wall_time"></marker> + <p> Turns on or off scheduler wall time measurements.</p> <p>For more information, see <seealso marker="#statistics_scheduler_wall_time"> @@ -7379,10 +7393,11 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="12"/> + <name name="system_flag" arity="2" clause_i="12" + anchor="system_flag_schedulers_online"/> <fsummary>Set system flag schedulers_online.</fsummary> <desc> - <p><marker id="system_flag_schedulers_online"></marker> + <p> Sets the number of schedulers online. Range is <c><![CDATA[1 <= SchedulersOnline <= erlang:system_info(schedulers)]]></c>.</p> @@ -7421,10 +7436,11 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="14"/> + <name name="system_flag" arity="2" clause_i="14" + anchor="system_flag_time_offset"/> <fsummary>Finalize the time offset.</fsummary> <desc> - <p><marker id="system_flag_time_offset"></marker> + <p> Finalizes the <seealso marker="#time_offset/0">time offset</seealso> when <seealso marker="time_correction#Single_Time_Warp_Mode">single time warp mode</seealso> is used. If another time warp mode @@ -7597,7 +7613,8 @@ ok </func> <func> - <name name="system_info" arity="1" clause_i="12"/> + <name name="system_info" arity="1" clause_i="12" + anchor="system_info_cpu_topology"/> <name name="system_info" arity="1" clause_i="13"/> <fsummary>Information about the CPU topology of the system.</fsummary> <type name="cpu_topology"/> @@ -7625,7 +7642,6 @@ ok </type_desc> <desc> <marker id="system_info_cpu_topology_tags"></marker> - <marker id="system_info_cpu_topology"></marker> <p>Returns various information about the CPU topology of the current system (emulator) as specified by <c><anno>Item</anno></c>:</p> diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index 25b72ce774..bf41b61136 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -31,6 +31,49 @@ </header> <p>This document describes the changes made to the ERTS application.</p> +<section><title>Erts 9.1.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Microstate accounting sometimes produced incorrect + results for dirty schedulers.</p> + <p> + Own Id: OTP-14707</p> + </item> + <item> + <p>Fixed a regression in <c>zlib:gunzip/1</c> that + prevented it from working when the decompressed size was + a perfect multiple of 16384. This regression was + introduced in 20.1.1</p> + <p> + Own Id: OTP-14730 Aux Id: ERL-507 </p> + </item> + <item> + <p>Fixed a memory corruption bug in + <c>enif_inspect_iovec</c>; writable binaries stayed + writable after entering the iovec.</p> + <p> + Own Id: OTP-14745</p> + </item> + <item> + <p>Fixed a crash in <c>enif_inspect_iovec</c> on + encountering empty binaries.</p> + <p> + Own Id: OTP-14750</p> + </item> + <item> + <p><c>zlib:deflateParams/3</c> will no longer return + <c>buf_error</c> when called after <c>zlib:deflate/2</c> + with zlib <c>1.2.11</c>.</p> + <p> + Own Id: OTP-14751</p> + </item> + </list> + </section> + +</section> + <section><title>Erts 9.1.3</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c index fe1e15701b..0832b3f374 100644 --- a/erts/emulator/beam/beam_bp.c +++ b/erts/emulator/beam/beam_bp.c @@ -998,7 +998,9 @@ do_call_trace(Process* c_p, ErtsCodeInfo* info, Eterm* reg, fixup_cp_before_trace(c_p, &return_to_trace); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); flags = erts_call_trace(c_p, info, ms, reg, local, &tracer); + ERTS_REQ_PROC_MAIN_LOCK(c_p); /* restore cp after potential fixup */ c_p->cp = cp_save; diff --git a/erts/emulator/beam/erl_msacc.h b/erts/emulator/beam/erl_msacc.h index 2d4637f800..2588dec903 100644 --- a/erts/emulator/beam/erl_msacc.h +++ b/erts/emulator/beam/erl_msacc.h @@ -270,18 +270,32 @@ void erts_msacc_init_thread(char *type, int id, int liberty); #define ERTS_MSACC_PUSH_STATE_M() \ ERTS_MSACC_DECLARE_CACHE(); \ ERTS_MSACC_PUSH_STATE_CACHED_M() -#define ERTS_MSACC_PUSH_STATE_CACHED_M() \ - __erts_msacc_state = ERTS_MSACC_IS_ENABLED_CACHED() ? \ - erts_msacc_get_state_m__(__erts_msacc_cache) : ERTS_MSACC_STATE_OTHER +#define ERTS_MSACC_PUSH_STATE_CACHED_M() \ + do { \ + if (ERTS_MSACC_IS_ENABLED_CACHED()) { \ + ASSERT(!__erts_msacc_cache->unmanaged); \ + __erts_msacc_state = erts_msacc_get_state_m__(__erts_msacc_cache); \ + } else { \ + __erts_msacc_state = ERTS_MSACC_STATE_OTHER; \ + } \ + } while(0) #define ERTS_MSACC_SET_STATE_M(state) \ ERTS_MSACC_DECLARE_CACHE(); \ ERTS_MSACC_SET_STATE_CACHED_M(state) -#define ERTS_MSACC_SET_STATE_CACHED_M(state) \ - if (ERTS_MSACC_IS_ENABLED_CACHED()) \ - erts_msacc_set_state_m__(__erts_msacc_cache, state, 1) -#define ERTS_MSACC_POP_STATE_M() \ - if (ERTS_MSACC_IS_ENABLED_CACHED()) \ - erts_msacc_set_state_m__(__erts_msacc_cache, __erts_msacc_state, 0) +#define ERTS_MSACC_SET_STATE_CACHED_M(state) \ + do { \ + if (ERTS_MSACC_IS_ENABLED_CACHED()) { \ + ASSERT(!__erts_msacc_cache->unmanaged); \ + erts_msacc_set_state_m__(__erts_msacc_cache, state, 1); \ + } \ + } while(0) +#define ERTS_MSACC_POP_STATE_M() \ + do { \ + if (ERTS_MSACC_IS_ENABLED_CACHED()) { \ + ASSERT(!__erts_msacc_cache->unmanaged); \ + erts_msacc_set_state_m__(__erts_msacc_cache, __erts_msacc_state, 0); \ + } \ + } while(0) #define ERTS_MSACC_PUSH_AND_SET_STATE_M(state) \ ERTS_MSACC_PUSH_STATE_M(); ERTS_MSACC_SET_STATE_CACHED_M(state) diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index f7f12efe28..c21b139cfa 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -3323,36 +3323,38 @@ static int examine_iovec_term(Eterm list, UWord max_length, iovec_slice_t *resul size = binary_size(binary); binary_header = binary_val(binary); - /* If we're a sub-binary we'll need to check our underlying binary to - * determine whether we're on-heap or not. */ - if(thing_subtag(*binary_header) == SUB_BINARY_SUBTAG) { - ErlSubBin *sb = (ErlSubBin*)binary_header; - - /* Reject bitstrings */ - if((sb->bitoffs + sb->bitsize) > 0) { - return 0; + if (size > 0) { + /* If we're a sub-binary we'll need to check our underlying binary + * to determine whether we're on-heap or not. */ + if (thing_subtag(*binary_header) == SUB_BINARY_SUBTAG) { + ErlSubBin *sb = (ErlSubBin*)binary_header; + + /* Reject bitstrings */ + if((sb->bitoffs + sb->bitsize) > 0) { + return 0; + } + + ASSERT(size <= binary_size(sb->orig)); + binary_header = binary_val(sb->orig); } - ASSERT(size <= binary_size(sb->orig)); - binary_header = binary_val(sb->orig); - } - - if(thing_subtag(*binary_header) == HEAP_BINARY_SUBTAG) { - ASSERT(size <= ERL_ONHEAP_BIN_LIMIT); + if (thing_subtag(*binary_header) == HEAP_BINARY_SUBTAG) { + ASSERT(size <= ERL_ONHEAP_BIN_LIMIT); - result->iovec_len += 1; - result->onheap_size += size; - } else { - ASSERT(thing_subtag(*binary_header) == REFC_BINARY_SUBTAG); + result->iovec_len += 1; + result->onheap_size += size; + } else { + ASSERT(thing_subtag(*binary_header) == REFC_BINARY_SUBTAG); - result->iovec_len += 1 + size / MAX_SYSIOVEC_IOVLEN; - result->offheap_size += size; + result->iovec_len += 1 + size / MAX_SYSIOVEC_IOVLEN; + result->offheap_size += size; + } } result->sublist_length += 1; lookahead = CDR(cell); - if(result->sublist_length >= max_length) { + if (result->sublist_length >= max_length) { break; } } @@ -3385,6 +3387,10 @@ static void inspect_raw_binary_data(Eterm binary, ErlNifBinary *result) { if (thing_subtag(*parent_header) == REFC_BINARY_SUBTAG) { ProcBin *pb = (ProcBin*)parent_header; + if (pb->flags & (PB_IS_WRITABLE | PB_ACTIVE_WRITER)) { + erts_emasculate_writable_binary(pb); + } + ASSERT(pb->val != NULL); ASSERT(byte_offset < pb->size); ASSERT(&pb->bytes[byte_offset] >= (byte*)(pb->val)->orig_bytes); @@ -3428,7 +3434,7 @@ static int fill_iovec_with_slice(ErlNifEnv *env, /* If this isn't a refc binary, copy its contents to the onheap buffer * and reference that instead. */ - if (raw_data.ref_bin == NULL) { + if (raw_data.size > 0 && raw_data.ref_bin == NULL) { ASSERT(onheap_offset < onheap_data.size); ASSERT(slice->onheap_size > 0); @@ -3439,12 +3445,11 @@ static int fill_iovec_with_slice(ErlNifEnv *env, raw_data.ref_bin = onheap_data.ref_bin; } - ASSERT(raw_data.ref_bin != NULL); - while (raw_data.size > 0) { UWord chunk_len = MIN(raw_data.size, MAX_SYSIOVEC_IOVLEN); ASSERT(iovec_idx < iovec->iovcnt); + ASSERT(raw_data.ref_bin != NULL); iovec->iov[iovec_idx].iov_base = raw_data.data; iovec->iov[iovec_idx].iov_len = chunk_len; diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 3d12b3bc21..3c0a126fe2 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -3276,7 +3276,7 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq) erts_aint32_t aux_work = 0; int thr_prgr_active = 1; erts_aint32_t flgs; - ERTS_MSACC_PUSH_STATE_M(); + ERTS_MSACC_PUSH_STATE(); ERTS_LC_ASSERT(erts_lc_runq_is_locked(rq)); @@ -3385,9 +3385,9 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq) - 1) + 1; } else timeout = -1; - ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_SLEEP); + ERTS_MSACC_SET_STATE_CACHED(ERTS_MSACC_STATE_SLEEP); res = erts_tse_twait(ssi->event, timeout); - ERTS_MSACC_POP_STATE_M(); + ERTS_MSACC_POP_STATE(); current_time = ERTS_SCHEDULER_IS_DIRTY(esdp) ? 0 : erts_get_monotonic_time(esdp); } while (res == EINTR); @@ -9701,7 +9701,7 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls) | ERTS_PROC_LOCK_STATUS | ERTS_PROC_LOCK_TRACE)); - ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_OTHER); + ERTS_MSACC_SET_STATE_CACHED(ERTS_MSACC_STATE_OTHER); if (state & ERTS_PSFLG_FREE) { if (!is_normal_sched) { @@ -9916,7 +9916,7 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls) case 0: /* No process at all */ default: ASSERT(qmask == 0); - ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_OTHER); + ERTS_MSACC_SET_STATE_CACHED(ERTS_MSACC_STATE_OTHER); goto check_activities_to_run; } @@ -10034,7 +10034,7 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls) } - ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_EMULATOR); + ERTS_MSACC_SET_STATE_CACHED(ERTS_MSACC_STATE_EMULATOR); if (flags & ERTS_RUNQ_FLG_PROTECTED) @@ -10824,7 +10824,7 @@ request_system_task(Process *c_p, Eterm requester, Eterm target, goto badarg; req_type = tp[1]; req_id = tp[2]; - req_id_sz = is_immed(req_id) ? req_id : size_object(req_id); + req_id_sz = is_immed(req_id) ? 0 : size_object(req_id); tot_sz = req_id_sz; for (i = 0; i < ERTS_MAX_PROC_SYS_TASK_ARGS; i++) { int tix = 3 + i; diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index 554c48059f..95d61fcc5d 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -1136,7 +1136,6 @@ static int packet_inet_init(void); static void packet_inet_stop(ErlDrvData); static void packet_inet_command(ErlDrvData, char*, ErlDrvSizeT); static void packet_inet_drv_input(ErlDrvData data, ErlDrvEvent event); -static void packet_inet_drv_output(ErlDrvData data, ErlDrvEvent event); static ErlDrvData udp_inet_start(ErlDrvPort, char* command); #ifdef HAVE_SCTP static ErlDrvData sctp_inet_start(ErlDrvPort, char* command); @@ -1161,7 +1160,7 @@ static struct erl_drv_entry udp_inet_driver_entry = NULL, #else packet_inet_drv_input, - packet_inet_drv_output, + NULL, #endif "udp_inet", NULL, @@ -1196,7 +1195,7 @@ static struct erl_drv_entry sctp_inet_driver_entry = NULL, #else packet_inet_drv_input, - packet_inet_drv_output, + NULL, #endif "sctp_inet", NULL, @@ -1262,7 +1261,6 @@ typedef struct { static int packet_inet_input(udp_descriptor* udesc, HANDLE event); -static int packet_inet_output(udp_descriptor* udesc, HANDLE event); #endif /* convert descriptor pointer to inet_descriptor pointer */ @@ -11300,24 +11298,20 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, (desc->sfamily, &remote, &buf, &len)) != NULL) return ctl_xerror(xerror, rbuf, rsize); - sock_select(desc, FD_CONNECT, 1); code = sock_connect(desc->s, &remote.sa, len); if (IS_SOCKET_ERROR(code) && (sock_errno() == EINPROGRESS)) { /* XXX: Unix only -- WinSock would have a different cond! */ - desc->state = INET_STATE_CONNECTING; if (timeout != INET_INFINITY) driver_set_timer(desc->port, timeout); enq_async(desc, tbuf, INET_REQ_CONNECT); + async_ok(desc); } else if (code == 0) { /* OK we are connected */ - sock_select(desc, FD_CONNECT, 0); - desc->state = INET_STATE_CONNECTED; enq_async(desc, tbuf, INET_REQ_CONNECT); async_ok(desc); } else { - sock_select(desc, FD_CONNECT, 0); return ctl_error(sock_errno(), rbuf, rsize); } return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize); @@ -11832,77 +11826,6 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event) return count; } -static void packet_inet_drv_output(ErlDrvData e, ErlDrvEvent event) -{ - (void) packet_inet_output((udp_descriptor*)e, (HANDLE)event); -} - -/* UDP/SCTP socket ready for output: -** This is a Back-End for Non-Block SCTP Connect (INET_STATE_CONNECTING) -*/ -static int packet_inet_output(udp_descriptor* udesc, HANDLE event) -{ - inet_descriptor* desc = INETP(udesc); - int ret = 0; - ErlDrvPort ix = desc->port; - - DEBUGF(("packet_inet_output(%ld) {s=%d\r\n", - (long)desc->port, desc->s)); - - if (desc->state == INET_STATE_CONNECTING) { - sock_select(desc, FD_CONNECT, 0); - - driver_cancel_timer(ix); /* posssibly cancel a timer */ -#ifndef __WIN32__ - /* - * XXX This is strange. This *should* work on Windows NT too, - * but doesn't. An bug in Winsock 2.0 for Windows NT? - * - * See "Unix Netwok Programming", W.R.Stevens, p 412 for a - * discussion about Unix portability and non blocking connect. - */ - -#ifndef SO_ERROR - { - int sz = sizeof(desc->remote); - int code = sock_peer(desc->s, - (struct sockaddr*) &desc->remote, &sz); - - if (IS_SOCKET_ERROR(code)) { - desc->state = INET_STATE_OPEN; /* restore state */ - ret = async_error(desc, sock_errno()); - goto done; - } - } -#else - { - int error = 0; /* Has to be initiated, we check it */ - unsigned int sz = sizeof(error); /* even if we get -1 */ - int code = sock_getopt(desc->s, SOL_SOCKET, SO_ERROR, - (void *)&error, &sz); - - if ((code < 0) || error) { - desc->state = INET_STATE_OPEN; /* restore state */ - ret = async_error(desc, error); - goto done; - } - } -#endif /* SO_ERROR */ -#endif /* !__WIN32__ */ - - desc->state = INET_STATE_CONNECTED; - async_ok(desc); - } - else { - sock_select(desc,FD_CONNECT,0); - - DEBUGF(("packet_inet_output(%ld): bad state: %04x\r\n", - (long)desc->port, desc->state)); - } - done: - DEBUGF(("packet_inet_output(%ld) }\r\n", (long)desc->port)); - return ret; -} #endif /*---------------------------------------------------------------------------*/ diff --git a/erts/emulator/hipe/hipe_amd64_bifs.m4 b/erts/emulator/hipe/hipe_amd64_bifs.m4 index b3c9a460bb..cf4c59c9af 100644 --- a/erts/emulator/hipe/hipe_amd64_bifs.m4 +++ b/erts/emulator/hipe/hipe_amd64_bifs.m4 @@ -462,6 +462,7 @@ ASYM($1): TYPE_FUNCTION(ASYM($1)) #endif') + /* * noproc_primop_interface_0(nbif_name, cbif_name) * noproc_primop_interface_1(nbif_name, cbif_name) diff --git a/erts/emulator/hipe/hipe_bif0.tab b/erts/emulator/hipe/hipe_bif0.tab index 4038ca7ef8..0380e8c795 100644 --- a/erts/emulator/hipe/hipe_bif0.tab +++ b/erts/emulator/hipe/hipe_bif0.tab @@ -135,8 +135,8 @@ atom bs_utf16_size atom bs_put_utf16be atom bs_put_utf16le atom bs_get_utf16 -atom bs_validate_unicode atom bs_validate_unicode_retract atom emulate_fpe atom emasculate_binary atom is_divisible +atom is_unicode
\ No newline at end of file diff --git a/erts/emulator/hipe/hipe_bif_list.m4 b/erts/emulator/hipe/hipe_bif_list.m4 index bebe20a18e..7e3851f20e 100644 --- a/erts/emulator/hipe/hipe_bif_list.m4 +++ b/erts/emulator/hipe/hipe_bif_list.m4 @@ -223,6 +223,7 @@ standard_bif_interface_3(nbif_find_na_or_make_stub, hipe_find_na_or_make_stub) standard_bif_interface_2(nbif_nonclosure_address, hipe_nonclosure_address) nocons_nofail_primop_interface_0(nbif_fclearerror_error, hipe_fclearerror_error) standard_bif_interface_2(nbif_is_divisible, hipe_is_divisible) +noproc_primop_interface_1(nbif_is_unicode, hipe_is_unicode) /* * Mbox primops with implicit P parameter. @@ -247,7 +248,6 @@ nofail_primop_interface_3(nbif_bs_get_float_2, erts_bs_get_float_2) standard_bif_interface_3(nbif_bs_put_utf8, hipe_bs_put_utf8) standard_bif_interface_3(nbif_bs_put_utf16be, hipe_bs_put_utf16be) standard_bif_interface_3(nbif_bs_put_utf16le, hipe_bs_put_utf16le) -standard_bif_interface_1(nbif_bs_validate_unicode, hipe_bs_validate_unicode) /* * Bit-syntax primops without any P parameter. diff --git a/erts/emulator/hipe/hipe_debug.c b/erts/emulator/hipe/hipe_debug.c index 222a11db3d..cfe60b379e 100644 --- a/erts/emulator/hipe/hipe_debug.c +++ b/erts/emulator/hipe/hipe_debug.c @@ -135,7 +135,9 @@ static void print_heap(Eterm *pos, Eterm *end) printf("From: 0x%0*lx to 0x%0*lx\n\r", 2*(int)sizeof(long), (unsigned long)pos, 2*(int)sizeof(long), (unsigned long)end); - printf(" | H E A P |\r\n"); + printf(" | %*s H E A P %*s |\r\n", + 2*(int)sizeof(long)-1, "", + 2*(int)sizeof(long)-1, ""); printf(" | %*s | %*s |\r\n", 2+2*(int)sizeof(long), "Address", 2+2*(int)sizeof(long), "Contents"); @@ -158,8 +160,10 @@ static void print_heap(Eterm *pos, Eterm *end) ++pos; --ari; } - } else + } else { + fflush(stdout); erts_printf("%.30T", val); + } printf("\r\n"); } printf(" |%s|%s|\r\n", dashes, dashes); diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c index 23f64a6991..f5471285c2 100644 --- a/erts/emulator/hipe/hipe_native_bif.c +++ b/erts/emulator/hipe/hipe_native_bif.c @@ -482,15 +482,12 @@ static int validate_unicode(Eterm arg) return 1; } -BIF_RETTYPE nbif_impl_hipe_bs_validate_unicode(NBIF_ALIST_1) +Uint hipe_is_unicode(Eterm arg) { - Process *p = BIF_P; - Eterm arg = BIF_ARG_1; - if (!validate_unicode(arg)) - BIF_ERROR(p, BADARG); - return NIL; + return (Uint) validate_unicode(arg); } + int hipe_bs_validate_unicode_retract(ErlBinMatchBuffer* mb, Eterm arg) { if (!validate_unicode(arg)) { diff --git a/erts/emulator/hipe/hipe_native_bif.h b/erts/emulator/hipe/hipe_native_bif.h index cbc7ab8dc6..a4919f4886 100644 --- a/erts/emulator/hipe/hipe_native_bif.h +++ b/erts/emulator/hipe/hipe_native_bif.h @@ -66,7 +66,7 @@ AEXTERN(Eterm,nbif_bs_utf16_size,(Eterm)); AEXTERN(Eterm,nbif_bs_put_utf16be,(Process*,Eterm,byte*,unsigned int)); AEXTERN(Eterm,nbif_bs_put_utf16le,(Process*,Eterm,byte*,unsigned int)); AEXTERN(Eterm,nbif_bs_get_utf16,(void)); -AEXTERN(Eterm,nbif_bs_validate_unicode,(Process*,Eterm)); +AEXTERN(Uint,nbif_is_unicode,(Eterm)); AEXTERN(Eterm,nbif_bs_validate_unicode_retract,(void)); AEXTERN(void,nbif_is_divisible,(Process*,Uint,Uint)); @@ -91,7 +91,7 @@ BIF_RETTYPE nbif_impl_hipe_bs_put_utf8(NBIF_ALIST_3); Eterm hipe_bs_utf16_size(Eterm); BIF_RETTYPE nbif_impl_hipe_bs_put_utf16be(NBIF_ALIST_3); BIF_RETTYPE nbif_impl_hipe_bs_put_utf16le(NBIF_ALIST_3); -BIF_RETTYPE nbif_impl_hipe_bs_validate_unicode(NBIF_ALIST_1); +Uint hipe_is_unicode(Eterm); struct erl_bin_match_buffer; int hipe_bs_validate_unicode_retract(struct erl_bin_match_buffer*, Eterm); BIF_RETTYPE nbif_impl_hipe_is_divisible(NBIF_ALIST_2); diff --git a/erts/emulator/hipe/hipe_primops.h b/erts/emulator/hipe/hipe_primops.h index 6aac5e6205..a6abd3e011 100644 --- a/erts/emulator/hipe/hipe_primops.h +++ b/erts/emulator/hipe/hipe_primops.h @@ -63,7 +63,7 @@ PRIMOP_LIST(am_bs_utf16_size, &nbif_bs_utf16_size) PRIMOP_LIST(am_bs_put_utf16be, &nbif_bs_put_utf16be) PRIMOP_LIST(am_bs_put_utf16le, &nbif_bs_put_utf16le) PRIMOP_LIST(am_bs_get_utf16, &nbif_bs_get_utf16) -PRIMOP_LIST(am_bs_validate_unicode, &nbif_bs_validate_unicode) +PRIMOP_LIST(am_is_unicode, &nbif_is_unicode) PRIMOP_LIST(am_bs_validate_unicode_retract, &nbif_bs_validate_unicode_retract) PRIMOP_LIST(am_is_divisible, &nbif_is_divisible) diff --git a/erts/emulator/nifs/common/zlib_nif.c b/erts/emulator/nifs/common/zlib_nif.c index fa29b4fb71..b709ed5a6f 100644 --- a/erts/emulator/nifs/common/zlib_nif.c +++ b/erts/emulator/nifs/common/zlib_nif.c @@ -717,7 +717,9 @@ static ERL_NIF_TERM zlib_deflateEnd(ErlNifEnv *env, int argc, const ERL_NIF_TERM static ERL_NIF_TERM zlib_deflateParams(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { zlib_data_t *d; + int res, level, strategy; + Bytef dummy_buffer; if(argc != 3 || !get_zlib_data(env, argv[0], &d) || !enif_get_int(env, argv[1], &level) @@ -729,12 +731,27 @@ static ERL_NIF_TERM zlib_deflateParams(ErlNifEnv *env, int argc, const ERL_NIF_T return enif_raise_exception(env, am_not_initialized); } - /* deflateParams will flush everything currently in the stream, corrupting - * the heap unless it's empty. We therefore pretend to have a full output - * buffer, forcing a Z_BUF_ERROR if there's anything left to be flushed. */ - d->s.avail_out = 0; + /* This is a bit of a hack; deflateParams flushes with Z_BLOCK which won't + * stop at a byte boundary, so we can't split this operation up, and we + * can't allocate a buffer large enough to fit it in one go since we have + * to support zlib versions that lack deflatePending. + * + * We therefore flush everything prior to this call to ensure that we are + * stopped on a byte boundary and have no pending data. We then hand it a + * dummy buffer to detect when this assumption doesn't hold (Hopefully + * never), and to smooth over an issue with zlib 1.2.11 which always + * returns Z_BUF_ERROR when d->s.avail_out is 0, regardless of whether + * there's any pending data or not. */ + + d->s.next_out = &dummy_buffer; + d->s.avail_out = 1; + res = deflateParams(&d->s, level, strategy); + if(d->s.avail_out == 0) { + return zlib_return(env, Z_STREAM_ERROR); + } + return zlib_return(env, res); } @@ -929,7 +946,7 @@ static ERL_NIF_TERM zlib_inflate(ErlNifEnv *env, int argc, const ERL_NIF_TERM ar return enif_raise_exception(env, am_not_initialized); } - if(d->eos_seen) { + if(d->eos_seen && enif_ioq_size(d->input_queue) > 0) { int res; switch(d->eos_behavior) { @@ -943,11 +960,10 @@ static ERL_NIF_TERM zlib_inflate(ErlNifEnv *env, int argc, const ERL_NIF_TERM ar } d->eos_seen = 0; + break; case EOS_BEHAVIOR_CUT: zlib_reset_input(d); - - return enif_make_tuple2(env, am_finished, enif_make_list(env, 0)); } } diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index a9f20f9928..a8bcfac84d 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -2532,8 +2532,13 @@ system_task_on_suspended(Config) when is_list(Config) -> end. gc_request_when_gc_disabled(Config) when is_list(Config) -> - Master = self(), AIS = erts_debug:set_internal_state(available_internal_state, true), + gc_request_when_gc_disabled_do(ref), + gc_request_when_gc_disabled_do(immed), + erts_debug:set_internal_state(available_internal_state, AIS). + +gc_request_when_gc_disabled_do(ReqIdType) -> + Master = self(), {P, M} = spawn_opt(fun () -> true = erts_debug:set_internal_state(gc_state, false), @@ -2545,7 +2550,10 @@ gc_request_when_gc_disabled(Config) when is_list(Config) -> receive after 100 -> ok end end, [monitor, link]), receive {P, gc_state, false} -> ok end, - ReqId = make_ref(), + ReqId = case ReqIdType of + ref -> make_ref(); + immed -> immed + end, async = garbage_collect(P, [{async, ReqId}]), receive {garbage_collect, ReqId, Result} -> @@ -2554,7 +2562,6 @@ gc_request_when_gc_disabled(Config) when is_list(Config) -> ok end, receive {garbage_collect, ReqId, true} -> ok end, - erts_debug:set_internal_state(available_internal_state, AIS), receive {'DOWN', M, process, P, _Reason} -> ok end, ok. diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam Binary files differindex f388bc723a..4ad5f37434 100644 --- a/erts/preloaded/ebin/zlib.beam +++ b/erts/preloaded/ebin/zlib.beam diff --git a/erts/preloaded/src/zlib.erl b/erts/preloaded/src/zlib.erl index 03c9ae38a1..a4ef42204d 100644 --- a/erts/preloaded/src/zlib.erl +++ b/erts/preloaded/src/zlib.erl @@ -188,14 +188,13 @@ deflateReset_nif(_Z) -> deflateParams(Z, Level0, Strategy0) -> Level = arg_level(Level0), Strategy = arg_strategy(Strategy0), + Progress = deflate(Z, <<>>, sync), case deflateParams_nif(Z, Level, Strategy) of - buf_error -> - %% We had data left in the pipe; flush everything and stash it away - %% for the next deflate call before trying again. - Output = deflate(Z, <<>>, full), - save_progress(Z, deflate, Output), - deflateParams_nif(Z, Level, Strategy); - Any -> Any + ok -> + save_progress(Z, deflate, Progress), + ok; + Other -> + Other end. deflateParams_nif(_Z, _Level, _Strategy) -> erlang:nif_error(undef). diff --git a/erts/vsn.mk b/erts/vsn.mk index a788b2e491..220c3b5f6c 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -18,7 +18,7 @@ # %CopyrightEnd% # -VSN = 9.1.3 +VSN = 9.1.4 # Port number 4365 in 4.2 # Port number 4366 in 4.3 |