aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/configure.in107
-rw-r--r--erts/doc/src/erl.xml13
-rw-r--r--erts/doc/src/erl_dist_protocol.xml12
-rw-r--r--erts/doc/src/erlang.xml128
-rw-r--r--erts/doc/src/erlc.xml10
-rw-r--r--erts/emulator/Makefile.in18
-rw-r--r--erts/emulator/beam/atom.names12
-rw-r--r--erts/emulator/beam/beam_emu.c38
-rw-r--r--erts/emulator/beam/bif.c72
-rw-r--r--erts/emulator/beam/bif.tab15
-rw-r--r--erts/emulator/beam/erl_arith.c43
-rw-r--r--erts/emulator/beam/erl_bif_guard.c14
-rw-r--r--erts/emulator/beam/erl_bif_info.c91
-rw-r--r--erts/emulator/beam/erl_debug.c14
-rw-r--r--erts/emulator/beam/erl_gc.c252
-rw-r--r--erts/emulator/beam/erl_init.c132
-rw-r--r--erts/emulator/beam/erl_message.c24
-rw-r--r--erts/emulator/beam/erl_message.h23
-rw-r--r--erts/emulator/beam/erl_port_task.c58
-rw-r--r--erts/emulator/beam/erl_process.c39
-rw-r--r--erts/emulator/beam/erl_process.h36
-rw-r--r--erts/emulator/beam/erl_trace.c29
-rw-r--r--erts/emulator/beam/erl_vm.h78
-rw-r--r--erts/emulator/beam/external.c276
-rw-r--r--erts/emulator/beam/external.h26
-rw-r--r--erts/emulator/beam/global.h11
-rw-r--r--erts/emulator/beam/utils.c60
-rw-r--r--erts/emulator/test/binary_SUITE.erl46
-rw-r--r--erts/emulator/test/fun_SUITE.erl18
-rw-r--r--erts/emulator/test/process_SUITE.erl54
-rw-r--r--erts/emulator/test/statistics_SUITE.erl75
-rw-r--r--erts/emulator/test/system_info_SUITE.erl27
-rw-r--r--erts/emulator/test/trace_SUITE.erl77
-rw-r--r--erts/epmd/src/epmd_int.h11
-rw-r--r--erts/epmd/src/epmd_srv.c28
-rw-r--r--erts/etc/common/erlc.c13
-rw-r--r--erts/etc/common/erlexec.c35
-rw-r--r--erts/lib_src/Makefile.in13
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin48420 -> 48420 bytes
-rw-r--r--erts/preloaded/ebin/erlang.beambin23232 -> 23284 bytes
-rw-r--r--erts/preloaded/ebin/init.beambin44460 -> 44416 bytes
-rw-r--r--erts/preloaded/ebin/otp_ring0.beambin1392 -> 1392 bytes
-rw-r--r--erts/preloaded/ebin/prim_file.beambin29480 -> 29480 bytes
-rw-r--r--erts/preloaded/ebin/prim_inet.beambin57308 -> 57308 bytes
-rw-r--r--erts/preloaded/ebin/prim_zip.beambin20756 -> 20756 bytes
-rw-r--r--erts/preloaded/ebin/zlib.beambin10624 -> 10624 bytes
-rw-r--r--erts/preloaded/src/erlang.erl3
-rw-r--r--erts/test/erlc_SUITE.erl17
48 files changed, 1312 insertions, 736 deletions
diff --git a/erts/configure.in b/erts/configure.in
index faccf5f102..48d236351b 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -1,20 +1,20 @@
dnl Process this file with autoconf to produce a configure script. -*-m4-*-
dnl %CopyrightBegin%
-dnl
-dnl Copyright Ericsson AB 1997-2009. All Rights Reserved.
-dnl
+dnl
+dnl Copyright Ericsson AB 1997-2010. All Rights Reserved.
+dnl
dnl The contents of this file are subject to the Erlang Public License,
dnl Version 1.1, (the "License"); you may not use this file except in
dnl compliance with the License. You should have received a copy of the
dnl Erlang Public License along with this software. If not, it can be
dnl retrieved online at http://www.erlang.org/.
-dnl
+dnl
dnl Software distributed under the License is distributed on an "AS IS"
dnl basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
dnl the License for the specific language governing rights and limitations
dnl under the License.
-dnl
+dnl
dnl %CopyrightEnd%
dnl The string "FIXME convbreak" means that there is a break of
@@ -325,6 +325,7 @@ dnl Checks for programs.
dnl ----------------------------------------------------------------------
AC_PROG_CC
+AC_SUBST(GCC)
dnl ---------------------------------------------------------------------
dnl Special stuff regarding CFLAGS and details in the environment...
@@ -344,6 +345,9 @@ case $host_os in
AC_MSG_WARN([Reverting to 32-bit time_t])
CPPFLAGS="$CPPFLAGS -D_USE_32BIT_TIME_T"
;;
+ darwin*)
+ CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE"
+ ;;
*)
;;
esac
@@ -2098,6 +2102,44 @@ if test X${enable_hipe} != Xno; then
esac
fi
fi
+
+case $ARCH-$OPSYS in
+ amd64-darwin*|x86-darwin*)
+ AC_MSG_CHECKING([For modern (leopard) style mcontext_t])
+ AC_TRY_COMPILE([
+ #include <stdlib.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <mach/mach.h>
+ #include <pthread.h>
+ #include <machine/signal.h>
+ #include <ucontext.h>
+ ],[
+ #if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
+ #define __DARWIN__ 1
+ #endif
+
+ #ifndef __DARWIN__
+ #error inpossible
+ #else
+
+ mcontext_t mc = NULL;
+ int x = mc->__fs.__fpu_mxcsr;
+
+ #endif
+ ],darwin_mcontext_leopard=yes,
+ darwin_mcontext_leopard=no)
+ if test X"$darwin_mcontext_leopard" = X"yes"; then
+ AC_DEFINE(DARWIN_MODERN_MCONTEXT,[],[Modern style mcontext_t in MacOSX])
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ ;;
+ *)
+ darwin_mcontext_leopard=no
+ ;;
+esac
if test X${enable_fp_exceptions} = Xauto ; then
if test X${enable_hipe} = Xyes; then
enable_fp_exceptions=yes
@@ -2487,6 +2529,7 @@ static void fpe_sig_action(int sig, siginfo_t *si, void *puc)
regs[PT_FPSCR] = 0x80|0x40|0x10; /* VE, OE, ZE; not UE or XE */
#endif
#elif defined(__DARWIN__)
+#if defined(DARWIN_MODERN_MCONTEXT)
#if defined(__x86_64__)
mcontext_t mc = uc->uc_mcontext;
struct __darwin_x86_float_state64 *fpstate = &mc->__fs;
@@ -2502,6 +2545,23 @@ static void fpe_sig_action(int sig, siginfo_t *si, void *puc)
mc->ss.srr0 += 4;
mc->fs.fpscr = 0x80|0x40|0x10;
#endif
+#else
+#if defined(__x86_64__)
+ mcontext_t mc = uc->uc_mcontext;
+ struct x86_float_state64_t *fpstate = &mc->fs;
+ fpstate->fpu_mxcsr = 0x1F80;
+ *(unsigned short *)&fpstate->fpu_fsw &= ~0xFF;
+#elif defined(__i386__)
+ mcontext_t mc = uc->uc_mcontext;
+ x86_float_state32_t *fpstate = &mc->fs;
+ fpstate->fpu_mxcsr = 0x1F80;
+ *(unsigned short *)&fpstate->fpu_fsw &= ~0xFF;
+#elif defined(__ppc__)
+ mcontext_t mc = uc->uc_mcontext;
+ mc->ss.srr0 += 4;
+ mc->fs.fpscr = 0x80|0x40|0x10;
+#endif
+#endif
#elif defined(__FreeBSD__) && defined(__x86_64__)
mcontext_t *mc = &uc->uc_mcontext;
struct savefpu *savefpu = (struct savefpu*)&mc->mc_fpstate;
@@ -2615,43 +2675,6 @@ fi)
fi
fi
-case $ARCH-$OPSYS in
- amd64-darwin*|x86-darwin*)
- AC_MSG_CHECKING([For modern (leopard) style mcontext_t])
- AC_TRY_COMPILE([
- #include <stdlib.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <mach/mach.h>
- #include <pthread.h>
- #include <machine/signal.h>
- #include <ucontext.h>
- ],[
- #if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
- #define __DARWIN__ 1
- #endif
-
- #ifndef __DARWIN__
- #error inpossible
- #else
-
- mcontext_t mc = NULL;
- int x = mc->__fs.__fpu_mxcsr;
-
- #endif
- ],darwin_mcontext_leopard=yes,
- darwin_mcontext_leopard=no)
- if test X"$darwin_mcontext_leopard" = X"yes"; then
- AC_DEFINE(DARWIN_MODERN_MCONTEXT,[],[Modern style mcontext_t in MacOSX])
- AC_MSG_RESULT(yes)
- else
- AC_MSG_RESULT(no)
- fi
- ;;
- *)
- darwin_mcontext_leopard=no
- ;;
-esac
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 90a3c53a37..6f5dd248ce 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -4,7 +4,7 @@
<comref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -13,12 +13,12 @@
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.
-
+
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
-
+
</legalnotice>
<title>erl</title>
@@ -527,11 +527,16 @@
<p>Calling <c>erlang:halt/1</c> with a string argument will still
produce a crash dump.</p>
</item>
- <tag><c><![CDATA[+h Size]]></c></tag>
+ <tag><c><![CDATA[+hms Size]]></c></tag>
<item>
<p>Sets the default heap size of processes to the size
<c><![CDATA[Size]]></c>.</p>
</item>
+ <tag><c><![CDATA[+hmbs Size]]></c></tag>
+ <item>
+ <p>Sets the default binary virtual heap size of processes to the size
+ <c><![CDATA[Size]]></c>.</p>
+ </item>
<tag><c><![CDATA[+K true | false]]></c></tag>
<item>
<p>Enables or disables the kernel poll functionality if
diff --git a/erts/doc/src/erl_dist_protocol.xml b/erts/doc/src/erl_dist_protocol.xml
index 9a203289e9..5978af178a 100644
--- a/erts/doc/src/erl_dist_protocol.xml
+++ b/erts/doc/src/erl_dist_protocol.xml
@@ -129,8 +129,8 @@ By default EPMD listens on port 4369.
<cell align="center">PortNo</cell>
<cell align="center">NodeType</cell>
<cell align="center">Protocol</cell>
- <cell align="center">LowestVersion</cell>
<cell align="center">HighestVersion</cell>
+ <cell align="center">LowestVersion</cell>
<cell align="center">Nlen</cell>
<cell align="center">NodeName</cell>
<cell align="center">Elen</cell>
@@ -150,16 +150,16 @@ By default EPMD listens on port 4369.
<item>
0 = tcp/ip-v4, ...
</item>
- <tag><c>LowestVersion</c></tag>
- <item>
- The lowest distribution version that this node can handle.
- See the next field for possible values.
- </item>
<tag><c>HighestVersion</c></tag>
<item>
The highest distribution version that this node can handle.
The value in R6B and later is 5.
</item>
+ <tag><c>LowestVersion</c></tag>
+ <item>
+ The lowest distribution version that this node can handle.
+ The value in R6B and later is 5.
+ </item>
<tag><c>Nlen</c></tag>
<item>
The length of the <c>NodeName</c>.
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 871fc0fd63..28b040a441 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -13,12 +13,12 @@
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.
-
+
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
-
+
</legalnotice>
<title>erlang</title>
@@ -342,8 +342,50 @@ iolist() = [char() | binary() | iolist()]
<desc>
<p>Returns an Erlang term which is the result of decoding
the binary object <c>Binary</c>, which must be encoded
- according to the Erlang external term format. See also
- <seealso marker="#term_to_binary/1">term_to_binary/1</seealso>.</p>
+ according to the Erlang external term format.</p>
+ <warning>
+ <p>When decoding binaries from untrusted sources, consider using
+ <c>binary_to_term/2</c> to prevent denial of service attacks.</p>
+ </warning>
+ <p>See also
+ <seealso marker="#term_to_binary/1">term_to_binary/1</seealso>
+ and
+ <seealso marker="#binary_to_term/2">binary_to_term/2</seealso>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>erlang:binary_to_term(Binary, Opts) -> term()</name>
+ <fsummary>Decode an Erlang external term format binary</fsummary>
+ <type>
+ <v>Opts = [safe]</v>
+ <v>Binary = ext_binary()</v>
+ </type>
+ <desc>
+ <p>As <c>binary_to_term/1</c>, but takes options that affect decoding
+ of the binary.</p>
+ <taglist>
+ <tag><c>safe</c></tag>
+ <item>
+ <p>Use this option when receiving binaries from an untrusted
+ source.</p>
+ <p>When enabled, it prevents decoding data that may be used to
+ attack the Erlang system. In the event of receiving unsafe
+ data, decoding fails with a badarg error.</p>
+ <p>Currently, this prevents creation of new atoms directly,
+ creation of new atoms indirectly (as they are embedded in
+ certain structures like pids, refs, funs, etc.), and creation of
+ new external function references. None of those resources are
+ currently garbage collected, so unchecked creation of them can
+ exhaust available memory.</p>
+ </item>
+ </taglist>
+ <p>Failure: <c>badarg</c> if <c>safe</c> is specified and unsafe data
+ is decoded.</p>
+ <p>See also
+ <seealso marker="#term_to_binary/1">term_to_binary/1</seealso>,
+ <seealso marker="#binary_to_term/1">binary_to_term/1</seealso>,
+ and <seealso marker="#list_to_existing_atom/1">
+ list_to_existing_atom/1</seealso>.</p>
</desc>
</func>
<func>
@@ -3427,6 +3469,11 @@ os_prompt%</pre>
<p>This changes the minimum heap size for the calling
process.</p>
</item>
+ <tag><c>process_flag(min_bin_vheap_size, MinBinVHeapSize)</c></tag>
+ <item>
+ <p>This changes the minimum binary virtual heap size for the calling
+ process.</p>
+ </item>
<tag><c>process_flag(priority, Level)</c></tag>
<item>
<marker id="process_flag_priority"></marker>
@@ -3758,6 +3805,14 @@ os_prompt%</pre>
<p><c>MessageQueue</c> is a list of the messages to
the process, which have not yet been processed.</p>
</item>
+ <tag><c>{min_heap_size, MinHeapSize}</c></tag>
+ <item>
+ <p><c>MinHeapSize</c> is the minimum heap size for the process.</p>
+ </item>
+ <tag><c>{min_bin_vheap_size, MinBinVHeapSize}</c></tag>
+ <item>
+ <p><c>MinBinVHeapSize</c> is the minimum binary virtual heap size for the process.</p>
+ </item>
<tag><c>{monitored_by, Pids}</c></tag>
<item>
<p>A list of pids that are monitoring the process (with
@@ -4491,10 +4546,11 @@ true</pre>
<fsummary>Create a new process with a fun as entry point</fsummary>
<type>
<v>Fun = fun()</v>
- <v>Option = link | monitor | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size}</v>
+ <v>Option = link | monitor | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size} | {min_bin_vheap_size, VSize}</v>
<v>&nbsp;Level = low | normal | high</v>
<v>&nbsp;Number = int()</v>
<v>&nbsp;Size = int()</v>
+ <v>&nbsp;VSize = int()</v>
</type>
<desc>
<p>Returns the pid of a new process started by the application
@@ -4512,10 +4568,11 @@ true</pre>
<type>
<v>Node = node()</v>
<v>Fun = fun()</v>
- <v>Option = link | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size}</v>
+ <v>Option = link | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size} | {min_bin_vheap_size, VSize}</v>
<v>&nbsp;Level = low | normal | high</v>
<v>&nbsp;Number = int()</v>
<v>&nbsp;Size = int()</v>
+ <v>&nbsp;VSize = int()</v>
</type>
<desc>
<p>Returns the pid of a new process started by the application
@@ -4531,10 +4588,11 @@ true</pre>
<type>
<v>Module = Function = atom()</v>
<v>Args = [term()]</v>
- <v>Option = link | monitor | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size}</v>
+ <v>Option = link | monitor | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size} | {min_bin_vheap_size, VSize}</v>
<v>&nbsp;Level = low | normal | high</v>
<v>&nbsp;Number = int()</v>
<v>&nbsp;Size = int()</v>
+ <v>&nbsp;VSize = int()</v>
</type>
<desc>
<p>Works exactly like
@@ -4614,6 +4672,23 @@ true</pre>
fine-tuning an application and to measure the execution
time with various <c>Size</c> values.</p>
</item>
+ <tag><c>{min_bin_vheap_size, VSize}</c></tag>
+ <item>
+ <p>This option is only useful for performance tuning.
+ In general, you should not use this option unless you
+ know that there is problem with execution times and/or
+ memory consumption, and you should measure to make sure
+ that the option improved matters.
+ </p>
+ <p>Gives a minimum binary virtual heap size in words. Setting this value
+ higher than the system default might speed up some
+ processes because less garbage collection is done.
+ Setting too high value, however, might waste memory.
+ Therefore, it is recommended to use this option only for
+ fine-tuning an application and to measure the execution
+ time with various <c>VSize</c> values.</p>
+ </item>
+
</taglist>
</desc>
</func>
@@ -4624,10 +4699,11 @@ true</pre>
<v>Node = node()</v>
<v>Module = Function = atom()</v>
<v>Args = [term()]</v>
- <v>Option = link | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size}</v>
+ <v>Option = link | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size} | {min_bin_vheap_size, VSize}</v>
<v>&nbsp;Level = low | normal | high</v>
<v>&nbsp;Number = int()</v>
<v>&nbsp;Size = int()</v>
+ <v>&nbsp;VSize = int()</v>
</type>
<desc>
<p>Returns the pid of a new process started by the application
@@ -4960,6 +5036,17 @@ true</pre>
<seealso marker="#spawn_opt/4">spawn_opt/N</seealso> or
<seealso marker="#process_flag/2">process_flag/2</seealso>. </p>
</item>
+ <tag><c>erlang:system_flag(min_bin_vheap_size, MinBinVHeapSize)</c></tag>
+ <item>
+ <p>Sets the default minimum binary virtual heap size for processes. The
+ size is given in words. The new <c>min_bin_vhheap_size</c> only
+ effects processes spawned after the change of
+ <c>min_bin_vhheap_size</c> has been made.
+ The <c>min_bin_vheap_size</c> can be set for individual
+ processes by use of
+ <seealso marker="#spawn_opt/4">spawn_opt/N</seealso> or
+ <seealso marker="#process_flag/2">process_flag/2</seealso>. </p>
+ </item>
<tag><c>erlang:system_flag(multi_scheduling, BlockState)</c></tag>
<item>
<marker id="system_flag_multi_scheduling"></marker>
@@ -5571,6 +5658,16 @@ true</pre>
<item>
<p>Returns a string containing the Erlang machine name.</p>
</item>
+ <tag><c>min_heap_size</c></tag>
+ <item>
+ <p>Returns <c>{min_heap_size, MinHeapSize}</c> where <c>MinHeapSize</c> is the current system wide
+ minimum heap size for spawned processes.</p>
+ </item>
+ <tag><c>min_bin_vheap_size</c></tag>
+ <item>
+ <p>Returns <c>{min_bin_vheap_size, MinBinVHeapSize}</c> where <c>MinBinVHeapSize</c> is the current system wide
+ minimum binary virtual heap size for spawned processes.</p>
+ </item>
<tag><c>modified_timing_level</c></tag>
<item>
<p>Returns the modified timing level (an integer) if
@@ -6407,6 +6504,19 @@ true</pre>
<tag><c>mbuf_size</c></tag>
<item>The combined size of message buffers associated with
the process.</item>
+
+ <tag><c>bin_vheap_size</c></tag>
+ <item>The total size of unique off-heap binaries referenced from the process heap.</item>
+ <tag><c>bin_vheap_block_size</c></tag>
+ <item>The total size of binaries, in words, allowed in the virtual
+ heap in the process before doing a garbage collection. </item>
+ <tag><c>bin_old_vheap_size</c></tag>
+ <item>The total size of unique off-heap binaries referenced from the process old heap.</item>
+ <tag><c>bin_vheap_block_size</c></tag>
+ <item>The total size of binaries, in words, allowed in the virtual
+ old heap in the process before doing a garbage collection. </item>
+
+
</taglist>
<p>All sizes are in words.</p>
</item>
diff --git a/erts/doc/src/erlc.xml b/erts/doc/src/erlc.xml
index 3859ac8365..1e8960c22c 100644
--- a/erts/doc/src/erlc.xml
+++ b/erts/doc/src/erlc.xml
@@ -4,7 +4,7 @@
<comref>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -13,12 +13,12 @@
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.
-
+
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
-
+
</legalnotice>
<title>erlc</title>
@@ -104,6 +104,10 @@
must be quoted. Terms which contain spaces
must be quoted on all platforms.</p>
</item>
+ <tag>-W<em>error</em></tag>
+ <item>
+ <p>Makes all warnings into errors.</p>
+ </item>
<tag>-W<em>number</em></tag>
<item>
<p>Sets warning level to <em>number</em>. Default is <c><![CDATA[1]]></c>.
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index 903e1e96ba..bc846d1e3d 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -1,24 +1,25 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2009. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1996-2010. All Rights Reserved.
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
-#
+#
# %CopyrightEnd%
#
include $(ERL_TOP)/make/target.mk
include ../vsn.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
ENABLE_ALLOC_TYPE_VARS = @ENABLE_ALLOC_TYPE_VARS@
HIPE_ENABLED=@HIPE_ENABLED@
@@ -213,7 +214,7 @@ else
OPT_LEVEL = -O3
endif
-ifeq ($(CC), gcc)
+ifeq ($(GCC),yes)
ifeq ($(NO_INLINE_FUNCTIONS),true)
GEN_OPT_FLGS = $(OPT_LEVEL) -fno-inline-functions
else
@@ -252,7 +253,7 @@ CS_TYPE_FLAGS = $(subst QUANTIFY,FAKE_QUANTIFY, \
$(subst PURIFY,FAKE_PURIFY, $(TYPE_FLAGS)))
endif
CS_CFLAGS_ = $(CS_TYPE_FLAGS) @DEFS@ $(WFLAGS)
-ifeq ($(CC), gcc)
+ifeq ($(GCC),yes)
CS_CFLAGS = $(subst -O2, $(GEN_OPT_FLGS) $(UNROLL_FLG), $(CS_CFLAGS_))
else
CS_CFLAGS = $(CS_CFLAGS_)
@@ -351,7 +352,6 @@ endif
CS_EXECUTABLE = child_setup$(TYPEMARKER)
# ----------------------------------------------------------------------
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
ifeq ($(ERLANG_OSTYPE), unix)
UNIX_ONLY_BUILDS = $(BINDIR)/$(CS_EXECUTABLE)
@@ -692,7 +692,7 @@ $(OBJDIR)/%.kp.o: sys/common/%.c
$(OBJDIR)/%.nkp.o: sys/common/%.c
$(CC) -DERTS_NO_KERNEL_POLL_VERSION $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@
-ifeq ($(CC), gcc)
+ifeq ($(GCC),yes)
$(OBJDIR)/erl_obsolete.o: beam/erl_obsolete.c
$(CC) $(subst -Wstrict-prototypes, , $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS))) $(INCLUDES) -c $< -o $@
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 04eac2d807..57c8b08223 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -1,19 +1,19 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2009. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1996-2010. All Rights Reserved.
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
-#
+#
# %CopyrightEnd%
#
@@ -303,6 +303,7 @@ atom messages
atom meta
atom meta_match_spec
atom min_heap_size
+atom min_bin_vheap_size
atom minor_version
atom Minus='-'
atom module
@@ -446,6 +447,7 @@ atom running
atom running_ports
atom running_procs
atom runtime
+atom safe
atom save_calls
atom scheduler
atom scheduler_id
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 4ebb8853be..13757b7d1c 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -286,6 +286,15 @@ extern int count_instructions;
#endif
+#ifdef FORCE_HEAP_FRAGS
+# define HEAP_SPACE_VERIFIED(Words) do { \
+ c_p->space_verified = (Words); \
+ c_p->space_verified_from = HTOP; \
+ }while(0)
+#else
+# define HEAP_SPACE_VERIFIED(Words) ((void)0)
+#endif
+
#define PRE_BIF_SWAPOUT(P) \
HEAP_TOP((P)) = HTOP; \
(P)->stop = E; \
@@ -411,6 +420,7 @@ extern int count_instructions;
r(0) = reg[0]; \
SWAPIN; \
} \
+ HEAP_SPACE_VERIFIED(need); \
} while (0)
@@ -432,6 +442,7 @@ extern int count_instructions;
r(0) = reg[0]; \
SWAPIN; \
} \
+ HEAP_SPACE_VERIFIED(need); \
} while (0)
/*
@@ -456,6 +467,7 @@ extern int count_instructions;
Extra = reg[Live]; \
SWAPIN; \
} \
+ HEAP_SPACE_VERIFIED(need); \
} while (0)
#ifdef HYBRID
@@ -832,6 +844,7 @@ extern int count_instructions;
LIGHT_SWAPOUT; \
_result = erts_bs_get_float_2(c_p, _size, (Flags), _mb); \
LIGHT_SWAPIN; \
+ HEAP_SPACE_VERIFIED(0); \
if (is_non_value(_result)) { Fail; } \
else { Store(_result, Dst); } \
} while (0)
@@ -845,6 +858,7 @@ extern int count_instructions;
LIGHT_SWAPOUT; \
_result = erts_bs_get_binary_2(c_p, (Sz), (Flags), _mb); \
LIGHT_SWAPIN; \
+ HEAP_SPACE_VERIFIED(0); \
if (is_non_value(_result)) { Fail; } \
else { Store(_result, Dst); } \
} while (0)
@@ -859,6 +873,7 @@ extern int count_instructions;
LIGHT_SWAPOUT; \
_result = erts_bs_get_binary_2(c_p, _size, (Flags), _mb); \
LIGHT_SWAPIN; \
+ HEAP_SPACE_VERIFIED(0); \
if (is_non_value(_result)) { Fail; } \
else { Store(_result, Dst); } \
} while (0)
@@ -873,9 +888,12 @@ extern int count_instructions;
LIGHT_SWAPOUT; \
_result = erts_bs_get_binary_all_2(c_p, _mb); \
LIGHT_SWAPIN; \
+ HEAP_SPACE_VERIFIED(0); \
ASSERT(is_value(_result)); \
Store(_result, Dst); \
- } else { Fail; } \
+ } else { \
+ HEAP_SPACE_VERIFIED(0); \
+ Fail; } \
} while (0)
#define BsSkipBits2(Ms, Bits, Unit, Fail) \
@@ -1360,6 +1378,7 @@ void process_main(void)
*/
c_p->cp = 0;
CHECK_TERM(r(0));
+ HEAP_SPACE_VERIFIED(0);
Goto(*I);
}
@@ -2379,6 +2398,7 @@ void process_main(void)
if (is_big(tmp_arg1)) {
HTOP += bignum_header_arity(*HTOP) + 1;
}
+ HEAP_SPACE_VERIFIED(0);
if (is_nil(tmp_arg1)) {
/*
* This result must have been only slight larger
@@ -3225,6 +3245,7 @@ apply_bif_or_nif_epilogue:
sb->orig = new_binary;
new_binary = make_binary(sb);
}
+ HEAP_SPACE_VERIFIED(0);
StoreBifResult(2, new_binary);
} else {
Binary* bptr;
@@ -3712,6 +3733,7 @@ apply_bif_or_nif_epilogue:
*dst = *ms;
*HTOP = HEADER_BIN_MATCHSTATE(slots);
HTOP += wordsneeded;
+ HEAP_SPACE_VERIFIED(0);
StoreResult(make_matchstate(dst), Arg(3));
}
} else if (is_binary_header(header)) {
@@ -3725,6 +3747,7 @@ apply_bif_or_nif_epilogue:
#endif
result = erts_bs_start_match_2(c_p, tmp_arg1, slots);
HTOP = HEAP_TOP(c_p);
+ HEAP_SPACE_VERIFIED(0);
if (is_non_value(result)) {
ClauseFail();
} else {
@@ -3917,6 +3940,7 @@ apply_bif_or_nif_epilogue:
TestHeap(BIG_UINT_HEAP_SIZE, Arg(1));
_result = uint_to_big((Uint) _integer, HTOP);
HTOP += BIG_UINT_HEAP_SIZE;
+ HEAP_SPACE_VERIFIED(0);
}
#endif
StoreBifResult(2, _result);
@@ -3982,6 +4006,7 @@ apply_bif_or_nif_epilogue:
LIGHT_SWAPOUT;
result = erts_bs_get_integer_2(c_p, tmp_arg2, Arg(1), mb);
LIGHT_SWAPIN;
+ HEAP_SPACE_VERIFIED(0);
if (is_non_value(result)) {
ClauseFail();
}
@@ -4009,6 +4034,7 @@ apply_bif_or_nif_epilogue:
LIGHT_SWAPOUT;
result = erts_bs_get_integer_2(c_p, size, flags, mb);
LIGHT_SWAPIN;
+ HEAP_SPACE_VERIFIED(0);
if (is_non_value(result)) {
ClauseFail();
}
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 74b231d56d..9c8c0df9f0 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -807,11 +807,12 @@ BIF_RETTYPE spawn_opt_1(BIF_ALIST_1)
/*
* Store default values for options.
*/
- so.flags = SPO_USE_ARGS;
- so.min_heap_size = H_MIN_SIZE;
- so.priority = PRIORITY_NORMAL;
- so.max_gen_gcs = (Uint16) erts_smp_atomic_read(&erts_max_gen_gcs);
- so.scheduler = 0;
+ so.flags = SPO_USE_ARGS;
+ so.min_heap_size = H_MIN_SIZE;
+ so.min_vheap_size = BIN_VH_MIN_SIZE;
+ so.priority = PRIORITY_NORMAL;
+ so.max_gen_gcs = (Uint16) erts_smp_atomic_read(&erts_max_gen_gcs);
+ so.scheduler = 0;
/*
* Walk through the option list.
@@ -850,6 +851,15 @@ BIF_RETTYPE spawn_opt_1(BIF_ALIST_1)
} else {
so.min_heap_size = erts_next_heap_size(min_heap_size, 0);
}
+ } else if (arg == am_min_bin_vheap_size && is_small(val)) {
+ Sint min_vheap_size = signed_val(val);
+ if (min_vheap_size < 0) {
+ goto error;
+ } else if (min_vheap_size < BIN_VH_MIN_SIZE) {
+ so.min_vheap_size = BIN_VH_MIN_SIZE;
+ } else {
+ so.min_vheap_size = erts_next_heap_size(min_vheap_size, 0);
+ }
} else if (arg == am_fullsweep_after && is_small(val)) {
Sint max_gen_gcs = signed_val(val);
if (max_gen_gcs < 0) {
@@ -1485,6 +1495,23 @@ BIF_RETTYPE process_flag_2(BIF_ALIST_2)
}
BIF_RET(old_value);
}
+ else if (BIF_ARG_1 == am_min_bin_vheap_size) {
+ Sint i;
+ if (!is_small(BIF_ARG_2)) {
+ goto error;
+ }
+ i = signed_val(BIF_ARG_2);
+ if (i < 0) {
+ goto error;
+ }
+ old_value = make_small(BIF_P->min_vheap_size);
+ if (i < BIN_VH_MIN_SIZE) {
+ BIF_P->min_vheap_size = BIN_VH_MIN_SIZE;
+ } else {
+ BIF_P->min_vheap_size = erts_next_heap_size(i, 0);
+ }
+ BIF_RET(old_value);
+ }
else if (BIF_ARG_1 == am_sensitive) {
Uint is_sensitive;
if (BIF_ARG_2 == am_true) {
@@ -3736,10 +3763,35 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
BIF_RET(make_small(oval));
} else if (BIF_ARG_1 == am_min_heap_size) {
int oval = H_MIN_SIZE;
+
if (!is_small(BIF_ARG_2) || (n = signed_val(BIF_ARG_2)) < 0) {
goto error;
}
+
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erts_smp_block_system(0);
+
H_MIN_SIZE = erts_next_heap_size(n, 0);
+
+ erts_smp_release_system();
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
+
+ BIF_RET(make_small(oval));
+ } else if (BIF_ARG_1 == am_min_bin_vheap_size) {
+ int oval = BIN_VH_MIN_SIZE;
+
+ if (!is_small(BIF_ARG_2) || (n = signed_val(BIF_ARG_2)) < 0) {
+ goto error;
+ }
+
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erts_smp_block_system(0);
+
+ BIN_VH_MIN_SIZE = erts_next_heap_size(n, 0);
+
+ erts_smp_release_system();
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
+
BIF_RET(make_small(oval));
} else if (BIF_ARG_1 == am_display_items) {
int oval = display_items;
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 85a729208f..b6fa06354a 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -1,19 +1,19 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2009. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1996-2010. All Rights Reserved.
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
-#
+#
# %CopyrightEnd%
#
@@ -755,6 +755,11 @@ bif erlang:call_on_load_function/1
bif erlang:finish_after_on_load/2
#
+# New Bifs in R13B4
+#
+bif erlang:binary_to_term/2
+
+#
# Obsolete
#
diff --git a/erts/emulator/beam/erl_arith.c b/erts/emulator/beam/erl_arith.c
index b692832677..126ec7cc73 100644
--- a/erts/emulator/beam/erl_arith.c
+++ b/erts/emulator/beam/erl_arith.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1999-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -50,18 +50,16 @@ static ERTS_INLINE void maybe_shrink(Process* p, Eterm* hp, Eterm res, Uint allo
if (is_immed(res)) {
if (p->heap <= hp && hp < p->htop) {
p->htop = hp;
-#if defined(CHECK_FOR_HOLES)
- } else {
- erts_arith_shrink(p, hp);
-#endif
+ }
+ else {
+ erts_heap_frag_shrink(p, hp);
}
} else if ((actual = bignum_header_arity(*hp)+1) < alloc) {
if (p->heap <= hp && hp < p->htop) {
p->htop = hp+actual;
-#if defined(CHECK_FOR_HOLES)
- } else {
- erts_arith_shrink(p, hp+actual);
-#endif
+ }
+ else {
+ erts_heap_frag_shrink(p, hp+actual);
}
}
}
@@ -397,12 +395,11 @@ erts_mixed_plus(Process* p, Eterm arg1, Eterm arg2)
need_heap = BIG_NEED_SIZE(sz);
hp = HAlloc(p, need_heap);
res = big_plus(arg1, arg2, hp);
+ maybe_shrink(p, hp, res, need_heap);
if (is_nil(res)) {
- erts_arith_shrink(p, hp);
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}
- maybe_shrink(p, hp, res, need_heap);
return res;
case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):
if (big_to_double(arg1, &f1.fd) < 0) {
@@ -533,12 +530,11 @@ erts_mixed_minus(Process* p, Eterm arg1, Eterm arg2)
need_heap = BIG_NEED_SIZE(sz);
hp = HAlloc(p, need_heap);
res = big_minus(arg1, arg2, hp);
+ maybe_shrink(p, hp, res, need_heap);
if (is_nil(res)) {
- erts_arith_shrink(p, hp);
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}
- maybe_shrink(p, hp, res, need_heap);
return res;
default:
goto badarith;
@@ -731,12 +727,11 @@ erts_mixed_times(Process* p, Eterm arg1, Eterm arg2)
* the absolute value of the other is > 1.
*/
+ maybe_shrink(p, hp, res, need_heap);
if (is_nil(res)) {
- erts_arith_shrink(p, hp);
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
- }
- maybe_shrink(p, hp, res, need_heap);
+ }
return res;
case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):
if (big_to_double(arg1, &f1.fd) < 0) {
@@ -956,12 +951,11 @@ erts_int_div(Process* p, Eterm arg1, Eterm arg2)
need = BIG_NEED_SIZE(i-ires+1) + BIG_NEED_SIZE(i);
hp = HAlloc(p, need);
arg1 = big_div(arg1, arg2, hp);
+ maybe_shrink(p, hp, arg1, need);
if (is_nil(arg1)) {
- erts_arith_shrink(p, hp);
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}
- maybe_shrink(p, hp, arg1, need);
}
return arg1;
default:
@@ -1004,12 +998,11 @@ erts_int_rem(Process* p, Eterm arg1, Eterm arg2)
Eterm* hp = HAlloc(p, need);
arg1 = big_rem(arg1, arg2, hp);
+ maybe_shrink(p, hp, arg1, need);
if (is_nil(arg1)) {
- erts_arith_shrink(p, hp);
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}
- maybe_shrink(p, hp, arg1, need);
}
return arg1;
default:
@@ -1147,7 +1140,7 @@ trim_heap(Process* p, Eterm* hp, Eterm res)
* a garbage collection if there is insufficient heap space.
*/
-#define erts_arith_shrink horrible error
+#define erts_heap_frag_shrink horrible error
#define maybe_shrink horrible error
Eterm
diff --git a/erts/emulator/beam/erl_bif_guard.c b/erts/emulator/beam/erl_bif_guard.c
index 8b47db10dd..440b0b4f14 100644
--- a/erts/emulator/beam/erl_bif_guard.c
+++ b/erts/emulator/beam/erl_bif_guard.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 2006-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 2006-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -318,6 +318,10 @@ double_to_integer(Process* p, double x)
* The following code is used when a guard that may build on the
* heap is called directly. They must not use HAlloc(), but must
* do a garbage collection if there is insufficient heap space.
+ *
+ * Important note: All error checking MUST be done before doing
+ * a garbage collection. The compiler assumes that all registers
+ * are still valid if a guard BIF generates an exception.
*/
#define ERTS_NEED_GC(p, need) ((HEAP_LIMIT((p)) - HEAP_TOP((p))) <= (need))
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 60216aa8e4..5ff1f794df 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1999-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -543,6 +543,8 @@ static Eterm pi_args[] = {
am_last_calls,
am_total_heap_size,
am_suspending,
+ am_min_heap_size,
+ am_min_bin_vheap_size,
#ifdef HYBRID
am_message_binary
#endif
@@ -589,8 +591,10 @@ pi_arg2ix(Eterm arg)
case am_last_calls: return 24;
case am_total_heap_size: return 25;
case am_suspending: return 26;
+ case am_min_heap_size: return 27;
+ case am_min_bin_vheap_size: return 28;
#ifdef HYBRID
- case am_message_binary: return 27;
+ case am_message_binary: return 29;
#endif
default: return -1;
}
@@ -1355,6 +1359,30 @@ process_info_aux(Process *BIF_P,
break;
}
+ case am_fullsweep_after: {
+ Uint hsz = 3;
+ (void) erts_bld_uint(NULL, &hsz, MAX_GEN_GCS(rp));
+ hp = HAlloc(BIF_P, hsz);
+ res = erts_bld_uint(&hp, NULL, MAX_GEN_GCS(rp));
+ break;
+ }
+
+ case am_min_heap_size: {
+ Uint hsz = 3;
+ (void) erts_bld_uint(NULL, &hsz, MIN_HEAP_SIZE(rp));
+ hp = HAlloc(BIF_P, hsz);
+ res = erts_bld_uint(&hp, NULL, MIN_HEAP_SIZE(rp));
+ break;
+ }
+
+ case am_min_bin_vheap_size: {
+ Uint hsz = 3;
+ (void) erts_bld_uint(NULL, &hsz, MIN_VHEAP_SIZE(rp));
+ hp = HAlloc(BIF_P, hsz);
+ res = erts_bld_uint(&hp, NULL, MIN_VHEAP_SIZE(rp));
+ break;
+ }
+
case am_total_heap_size: {
ErlMessage *mp;
Uint total_heap_size;
@@ -1433,15 +1461,17 @@ process_info_aux(Process *BIF_P,
DECL_AM(minor_gcs);
Eterm t;
- hp = HAlloc(BIF_P, 3+2+3+2+3);
- t = TUPLE2(hp, AM_minor_gcs, make_small(GEN_GCS(rp)));
- hp += 3;
- res = CONS(hp, t, NIL);
- hp += 2;
- t = TUPLE2(hp, am_fullsweep_after, make_small(MAX_GEN_GCS(rp)));
- hp += 3;
- res = CONS(hp, t, res);
- hp += 2;
+ hp = HAlloc(BIF_P, 3+2 + 3+2 + 3+2 + 3+2 + 3); /* last "3" is for outside tuple */
+
+ t = TUPLE2(hp, AM_minor_gcs, make_small(GEN_GCS(rp))); hp += 3;
+ res = CONS(hp, t, NIL); hp += 2;
+ t = TUPLE2(hp, am_fullsweep_after, make_small(MAX_GEN_GCS(rp))); hp += 3;
+ res = CONS(hp, t, res); hp += 2;
+
+ t = TUPLE2(hp, am_min_heap_size, make_small(MIN_HEAP_SIZE(rp))); hp += 3;
+ res = CONS(hp, t, res); hp += 2;
+ t = TUPLE2(hp, am_min_bin_vheap_size, make_small(MIN_VHEAP_SIZE(rp))); hp += 3;
+ res = CONS(hp, t, res); hp += 2;
break;
}
@@ -1897,16 +1927,32 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
BIF_RET(res);
} else if (BIF_ARG_1 == am_garbage_collection){
Uint val = (Uint) erts_smp_atomic_read(&erts_max_gen_gcs);
- hp = HAlloc(BIF_P, 3+2);
- res = TUPLE2(hp, am_fullsweep_after, make_small(val));
- hp += 3;
- res = CONS(hp, res, NIL);
+ Eterm tup;
+ hp = HAlloc(BIF_P, 3+2 + 3+2 + 3+2);
+
+ tup = TUPLE2(hp, am_fullsweep_after, make_small(val)); hp += 3;
+ res = CONS(hp, tup, NIL); hp += 2;
+
+ tup = TUPLE2(hp, am_min_heap_size, make_small(H_MIN_SIZE)); hp += 3;
+ res = CONS(hp, tup, res); hp += 2;
+
+ tup = TUPLE2(hp, am_min_bin_vheap_size, make_small(BIN_VH_MIN_SIZE)); hp += 3;
+ res = CONS(hp, tup, res); hp += 2;
+
BIF_RET(res);
} else if (BIF_ARG_1 == am_fullsweep_after){
Uint val = (Uint) erts_smp_atomic_read(&erts_max_gen_gcs);
hp = HAlloc(BIF_P, 3);
res = TUPLE2(hp, am_fullsweep_after, make_small(val));
BIF_RET(res);
+ } else if (BIF_ARG_1 == am_min_heap_size) {
+ hp = HAlloc(BIF_P, 3);
+ res = TUPLE2(hp, am_min_heap_size,make_small(H_MIN_SIZE));
+ BIF_RET(res);
+ } else if (BIF_ARG_1 == am_min_bin_vheap_size) {
+ hp = HAlloc(BIF_P, 3);
+ res = TUPLE2(hp, am_min_bin_vheap_size,make_small(BIN_VH_MIN_SIZE));
+ BIF_RET(res);
} else if (BIF_ARG_1 == am_process_count) {
BIF_RET(make_small(erts_process_count()));
} else if (BIF_ARG_1 == am_process_limit) {
@@ -3131,6 +3177,13 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
else if (ERTS_IS_ATOM_STR("available_internal_state", BIF_ARG_1)) {
BIF_RET(am_true);
}
+ else if (ERTS_IS_ATOM_STR("force_heap_frags", BIF_ARG_1)) {
+#ifdef FORCE_HEAP_FRAGS
+ BIF_RET(am_true);
+#else
+ BIF_RET(am_false);
+#endif
+ }
}
else if (is_tuple(BIF_ARG_1)) {
Eterm* tp = tuple_val(BIF_ARG_1);
diff --git a/erts/emulator/beam/erl_debug.c b/erts/emulator/beam/erl_debug.c
index 34ce87bc5d..e5c3c76fdd 100644
--- a/erts/emulator/beam/erl_debug.c
+++ b/erts/emulator/beam/erl_debug.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1998-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -344,7 +344,7 @@ void erts_check_for_holes(Process* p)
if (hf == p->last_mbuf) {
break;
}
- check_memory(hf->mem, hf->mem+hf->size);
+ check_memory(hf->mem, hf->mem+hf->used_size);
}
p->last_mbuf = MBUF(p);
}
@@ -386,7 +386,7 @@ void erts_check_heap(Process *p)
}
while (bp) {
- erts_check_memory(p,bp->mem,bp->mem + bp->size);
+ erts_check_memory(p,bp->mem,bp->mem + bp->used_size);
bp = bp->next;
}
}
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index 6945317e65..e9bf37a173 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 2002-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 2002-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
#ifdef HAVE_CONFIG_H
@@ -961,12 +961,13 @@ do_minor(Process *p, int new_sz, Eterm* objv, int nobj)
n_htop = sweep_one_area(n_heap, n_htop, heap, heap_size);
} else {
Eterm* n_hp = n_heap;
+ Eterm* ptr;
+ Eterm val;
+ Eterm gval;
while (n_hp != n_htop) {
- Eterm* ptr;
- Eterm val;
- Eterm gval = *n_hp;
-
+ ASSERT(n_hp < n_htop);
+ gval = *n_hp;
switch (primary_tag(gval)) {
case TAG_PRIMARY_BOXED: {
ptr = boxed_val(gval);
@@ -1402,68 +1403,6 @@ remove_message_buffers(Process* p)
}
}
-/*
- * Go through one root set array, move everything that it is one of the
- * heap fragments to our new heap.
- */
-static Eterm*
-collect_root_array(Process* p, Eterm* n_htop, Eterm* objv, int nobj)
-{
- ErlHeapFragment* qb;
- Eterm gval;
- Eterm* ptr;
- Eterm val;
-
- ASSERT(p->htop != NULL);
- while (nobj--) {
- gval = *objv;
-
- switch (primary_tag(gval)) {
-
- case TAG_PRIMARY_BOXED: {
- ptr = boxed_val(gval);
- val = *ptr;
- if (IS_MOVED(val)) {
- ASSERT(is_boxed(val));
- *objv++ = val;
- } else {
- for (qb = MBUF(p); qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->size*sizeof(Eterm))) {
- MOVE_BOXED(ptr,val,n_htop,objv);
- break;
- }
- }
- objv++;
- }
- break;
- }
-
- case TAG_PRIMARY_LIST: {
- ptr = list_val(gval);
- val = *ptr;
- if (is_non_value(val)) {
- *objv++ = ptr[1];
- } else {
- for (qb = MBUF(p); qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->size*sizeof(Eterm))) {
- MOVE_CONS(ptr,val,n_htop,objv);
- break;
- }
- }
- objv++;
- }
- break;
- }
-
- default: {
- objv++;
- break;
- }
- }
- }
- return n_htop;
-}
-
#ifdef HARDDEBUG
/*
@@ -1707,11 +1646,13 @@ sweep_rootset(Rootset* rootset, Eterm* htop, char* src, Uint src_size)
static Eterm*
sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size)
{
- while (n_hp != n_htop) {
- Eterm* ptr;
- Eterm val;
- Eterm gval = *n_hp;
+ Eterm* ptr;
+ Eterm val;
+ Eterm gval;
+ while (n_hp != n_htop) {
+ ASSERT(n_hp < n_htop);
+ gval = *n_hp;
switch (primary_tag(gval)) {
case TAG_PRIMARY_BOXED: {
ptr = boxed_val(gval);
@@ -1820,6 +1761,35 @@ sweep_one_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop, char* src, Uint sr
}
/*
+ * Move an area (heap fragment) by sweeping over it and set move markers.
+ */
+static Eterm*
+move_one_area(Eterm* n_htop, char* src, Uint src_size)
+{
+ Eterm* ptr = (Eterm*) src;
+ Eterm* end = ptr + src_size/sizeof(Eterm);
+ Eterm dummy_ref;
+
+ while (ptr != end) {
+ Eterm val;
+ ASSERT(ptr < end);
+ val = *ptr;
+ ASSERT(val != ERTS_HOLE_MARKER);
+ if (is_header(val)) {
+ ASSERT(ptr + header_arity(val) < end);
+ MOVE_BOXED(ptr, val, n_htop, &dummy_ref);
+ }
+ else { /* must be a cons cell */
+ ASSERT(ptr+1 < end);
+ MOVE_CONS(ptr, val, n_htop, &dummy_ref);
+ ptr += 2;
+ }
+ }
+
+ return n_htop;
+}
+
+/*
* Collect heap fragments and check that they point in the correct direction.
*/
@@ -1830,7 +1800,6 @@ collect_heap_frags(Process* p, Eterm* n_hstart, Eterm* n_htop,
ErlHeapFragment* qb;
char* frag_begin;
Uint frag_size;
- ErlMessage* mp;
/*
* We don't allow references to a heap fragments from the stack, heap,
@@ -1845,65 +1814,44 @@ collect_heap_frags(Process* p, Eterm* n_hstart, Eterm* n_htop,
#endif
/*
- * Go through the subset of the root set that is allowed to
- * reference data in heap fragments and move data from heap fragments
- * to our new heap.
- */
-
- if (nobj != 0) {
- n_htop = collect_root_array(p, n_htop, objv, nobj);
- }
- if (is_not_immed(p->fvalue)) {
- n_htop = collect_root_array(p, n_htop, &p->fvalue, 1);
- }
- if (is_not_immed(p->ftrace)) {
- n_htop = collect_root_array(p, n_htop, &p->ftrace, 1);
- }
- if (is_not_immed(p->seq_trace_token)) {
- n_htop = collect_root_array(p, n_htop, &p->seq_trace_token, 1);
- }
- if (is_not_immed(p->group_leader)) {
- n_htop = collect_root_array(p, n_htop, &p->group_leader, 1);
- }
-
- /*
- * Go through the message queue, move everything that is in one of the
- * heap fragments to our new heap.
- */
-
- for (mp = p->msg.first; mp != NULL; mp = mp->next) {
- /*
- * In most cases, mp->data.attached points to a heap fragment which is
- * self-contained and we will copy it to the heap at the
- * end of the GC to avoid scanning it.
- *
- * In a few cases, however, such as in process_info(Pid, messages)
- * and trace_delivered/1, a new message points to a term that has
- * been allocated by HAlloc() and mp->data.attached is NULL. Therefore
- * we need this loop.
- */
- if (mp->data.attached == NULL) {
- n_htop = collect_root_array(p, n_htop, mp->m, 2);
- }
- }
-
- /*
- * Now all references in the root set point to the new heap. However,
- * many references on the new heap point to heap fragments.
- */
-
+ * Move the heap fragments to the new heap. Note that no GC is done on
+ * the heap fragments. Any garbage will thus be moved as well and survive
+ * until next GC.
+ */
qb = MBUF(p);
- while (qb != NULL) {
- frag_begin = (char *) qb->mem;
- frag_size = qb->size * sizeof(Eterm);
+ while (qb != NULL) {
+ frag_size = qb->used_size * sizeof(Eterm);
if (frag_size != 0) {
- n_htop = sweep_one_area(n_hstart, n_htop, frag_begin, frag_size);
+ frag_begin = (char *) qb->mem;
+ n_htop = move_one_area(n_htop, frag_begin, frag_size);
}
qb = qb->next;
}
return n_htop;
}
+#ifdef DEBUG
+static Eterm follow_moved(Eterm term)
+{
+ Eterm* ptr;
+ switch (primary_tag(term)) {
+ case TAG_PRIMARY_IMMED1:
+ break;
+ case TAG_PRIMARY_BOXED:
+ ptr = boxed_val(term);
+ if (IS_MOVED(*ptr)) term = *ptr;
+ break;
+ case TAG_PRIMARY_LIST:
+ ptr = list_val(term);
+ if (is_non_value(ptr[0])) term = ptr[1];
+ break;
+ default:
+ abort();
+ }
+ return term;
+}
+#endif
+
static Uint
setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
{
@@ -1932,7 +1880,7 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
}
ASSERT((is_nil(p->seq_trace_token) ||
- is_tuple(p->seq_trace_token) ||
+ is_tuple(follow_moved(p->seq_trace_token)) ||
is_atom(p->seq_trace_token)));
if (is_not_immed(p->seq_trace_token)) {
roots[n].v = &p->seq_trace_token;
@@ -1944,7 +1892,7 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
is_internal_pid(p->tracer_proc) ||
is_internal_port(p->tracer_proc));
- ASSERT(is_pid(p->group_leader));
+ ASSERT(is_pid(follow_moved(p->group_leader)));
if (is_not_immed(p->group_leader)) {
roots[n].v = &p->group_leader;
roots[n].sz = 1;
@@ -2083,23 +2031,45 @@ shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj)
}
static Uint
-next_vheap_size(Uint vheap, Uint vheap_sz) {
- if (vheap < H_MIN_SIZE) {
- return H_MIN_SIZE;
- }
+do_next_vheap_size(Uint vheap, Uint vheap_sz) {
+
+ /* grow
+ *
+ * vheap_sz ======================
+ *
+ * vheap 75% + grow
+ * ----------------------
+ *
+ * vheap 25 - 75% same
+ * ----------------------
+ *
+ * vheap ~ - 25% shrink
+ *
+ * ----------------------
+ */
+
+ if (vheap > (Uint) (vheap_sz*3/4)) {
+
+ while(vheap > (Uint) (vheap_sz*3/4)) {
+ vheap_sz = vheap_sz*2;
+ }
- /* grow */
- if (vheap > vheap_sz) {
- return erts_next_heap_size(2*vheap, 0);
+ return erts_next_heap_size(vheap_sz, 0);
}
- /* shrink */
- if ( vheap < vheap_sz/2) {
- return (Uint)vheap_sz*3/4;
+
+ if (vheap < (Uint) (vheap_sz/4)) {
+ return erts_next_heap_size((Uint) (vheap_sz / 2), 0);
}
return vheap_sz;
+
}
+static Uint
+next_vheap_size(Process* p, Uint vheap, Uint vheap_sz) {
+ vheap_sz = do_next_vheap_size(vheap, vheap_sz);
+ return vheap_sz < p->min_vheap_size ? p->min_vheap_size : vheap_sz;
+}
static void
sweep_proc_externals(Process *p, int fullsweep)
@@ -2302,8 +2272,8 @@ sweep_proc_bins(Process *p, int fullsweep)
FLAGS(p) |= F_NEED_FULLSWEEP;
}
- BIN_VHEAP_SZ(p) = next_vheap_size(bin_vheap, BIN_VHEAP_SZ(p));
- BIN_OLD_VHEAP_SZ(p) = next_vheap_size(BIN_OLD_VHEAP(p), BIN_OLD_VHEAP_SZ(p));
+ BIN_VHEAP_SZ(p) = next_vheap_size(p, bin_vheap, BIN_VHEAP_SZ(p));
+ BIN_OLD_VHEAP_SZ(p) = next_vheap_size(p, BIN_OLD_VHEAP(p), BIN_OLD_VHEAP_SZ(p));
MSO(p).overhead = bin_vheap;
/*
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index 8afd349b85..bdf888eaff 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1997-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -84,9 +84,10 @@ int erts_use_sender_punish;
* Configurable parameters.
*/
-Uint display_items; /* no of items to display in traces etc */
+Uint display_items; /* no of items to display in traces etc */
Uint display_loads; /* print info about loaded modules */
int H_MIN_SIZE; /* The minimum heap grain */
+int BIN_VH_MIN_SIZE; /* The minimum binary virtual*/
Uint32 erts_debug_flags; /* Debug flags. */
#ifdef ERTS_OPCODE_COUNTER_SUPPORT
@@ -252,7 +253,8 @@ erl_init(void)
no_schedulers,
no_schedulers_online);
- H_MIN_SIZE = erts_next_heap_size(H_MIN_SIZE, 0);
+ H_MIN_SIZE = erts_next_heap_size(H_MIN_SIZE, 0);
+ BIN_VH_MIN_SIZE = erts_next_heap_size(BIN_VH_MIN_SIZE, 0);
erts_init_trace();
erts_init_binary();
@@ -513,67 +515,69 @@ void erts_usage(void)
/* erts_fprintf(stderr, "-# number set the number of items to be used in traces etc\n"); */
- erts_fprintf(stderr, "-a size suggested stack size in kilo words for threads\n");
- erts_fprintf(stderr, " in the async-thread pool, valid range is [%d-%d]\n",
+ erts_fprintf(stderr, "-a size suggested stack size in kilo words for threads\n");
+ erts_fprintf(stderr, " in the async-thread pool, valid range is [%d-%d]\n",
ERTS_ASYNC_THREAD_MIN_STACK_SIZE,
ERTS_ASYNC_THREAD_MAX_STACK_SIZE);
- erts_fprintf(stderr, "-A number set number of threads in async thread pool,\n");
- erts_fprintf(stderr, " valid range is [0-%d]\n",
+ erts_fprintf(stderr, "-A number set number of threads in async thread pool,\n");
+ erts_fprintf(stderr, " valid range is [0-%d]\n",
ERTS_MAX_NO_OF_ASYNC_THREADS);
- erts_fprintf(stderr, "-B[c|d|i] c to have Ctrl-c interrupt the Erlang shell,\n");
- erts_fprintf(stderr, " d (or no extra option) to disable the break\n");
- erts_fprintf(stderr, " handler, i to ignore break signals\n");
+ erts_fprintf(stderr, "-B[c|d|i] c to have Ctrl-c interrupt the Erlang shell,\n");
+ erts_fprintf(stderr, " d (or no extra option) to disable the break\n");
+ erts_fprintf(stderr, " handler, i to ignore break signals\n");
/* erts_fprintf(stderr, "-b func set the boot function (default boot)\n"); */
- erts_fprintf(stderr, "-c disable continuous date/time correction with\n");
- erts_fprintf(stderr, " respect to uptime\n");
+ erts_fprintf(stderr, "-c disable continuous date/time correction with\n");
+ erts_fprintf(stderr, " respect to uptime\n");
- erts_fprintf(stderr, "-d don't write a crash dump for internally detected errors\n");
- erts_fprintf(stderr, " (halt(String) will still produce a crash dump)\n");
+ erts_fprintf(stderr, "-d don't write a crash dump for internally detected errors\n");
+ erts_fprintf(stderr, " (halt(String) will still produce a crash dump)\n");
- erts_fprintf(stderr, "-h number set minimum heap size in words (default %d)\n",
+ erts_fprintf(stderr, "-hms size set minimum heap size in words (default %d)\n",
H_DEFAULT_SIZE);
+ erts_fprintf(stderr, "-hmbs size set minimum binary virtual heap size in words (default %d)\n",
+ VH_DEFAULT_SIZE);
/* erts_fprintf(stderr, "-i module set the boot module (default init)\n"); */
- erts_fprintf(stderr, "-K boolean enable or disable kernel poll\n");
+ erts_fprintf(stderr, "-K boolean enable or disable kernel poll\n");
- erts_fprintf(stderr, "-l turn on auto load tracing\n");
+ erts_fprintf(stderr, "-l turn on auto load tracing\n");
- erts_fprintf(stderr, "-M<X> <Y> memory allocator switches,\n");
- erts_fprintf(stderr, " see the erts_alloc(3) documentation for more info.\n");
+ erts_fprintf(stderr, "-M<X> <Y> memory allocator switches,\n");
+ erts_fprintf(stderr, " see the erts_alloc(3) documentation for more info.\n");
- erts_fprintf(stderr, "-P number set maximum number of processes on this node,\n");
- erts_fprintf(stderr, " valid range is [%d-%d]\n",
+ erts_fprintf(stderr, "-P number set maximum number of processes on this node,\n");
+ erts_fprintf(stderr, " valid range is [%d-%d]\n",
ERTS_MIN_PROCESSES, ERTS_MAX_PROCESSES);
- erts_fprintf(stderr, "-R number set compatibility release number,\n");
- erts_fprintf(stderr, " valid range [%d-%d]\n",
+ erts_fprintf(stderr, "-R number set compatibility release number,\n");
+ erts_fprintf(stderr, " valid range [%d-%d]\n",
ERTS_MIN_COMPAT_REL, this_rel_num());
- erts_fprintf(stderr, "-r force ets memory block to be moved on realloc\n");
- erts_fprintf(stderr, "-sbt type set scheduler bind type, valid types are:\n");
- erts_fprintf(stderr, " u|ns|ts|ps|s|nnts|nnps|tnnps|db\n");
- erts_fprintf(stderr, "-sct cput set cpu topology,\n");
- erts_fprintf(stderr, " see the erl(1) documentation for more info.\n");
- erts_fprintf(stderr, "-sss size suggested stack size in kilo words for scheduler threads,\n");
- erts_fprintf(stderr, " valid range is [%d-%d]\n",
+ erts_fprintf(stderr, "-r force ets memory block to be moved on realloc\n");
+ erts_fprintf(stderr, "-sbt type set scheduler bind type, valid types are:\n");
+ erts_fprintf(stderr, " u|ns|ts|ps|s|nnts|nnps|tnnps|db\n");
+ erts_fprintf(stderr, "-sct cput set cpu topology,\n");
+ erts_fprintf(stderr, " see the erl(1) documentation for more info.\n");
+ erts_fprintf(stderr, "-sss size suggested stack size in kilo words for scheduler threads,\n");
+ erts_fprintf(stderr, " valid range is [%d-%d]\n",
ERTS_SCHED_THREAD_MIN_STACK_SIZE,
ERTS_SCHED_THREAD_MAX_STACK_SIZE);
- erts_fprintf(stderr, "-S n1:n2 set number of schedulers (n1), and number of\n");
- erts_fprintf(stderr, " schedulers online (n2), valid range for both\n");
- erts_fprintf(stderr, " numbers are [1-%d]\n",
+ erts_fprintf(stderr, "-S n1:n2 set number of schedulers (n1), and number of\n");
+ erts_fprintf(stderr, " schedulers online (n2), valid range for both\n");
+ erts_fprintf(stderr, " numbers are [1-%d]\n",
ERTS_MAX_NO_OF_SCHEDULERS);
- erts_fprintf(stderr, "-T number set modified timing level,\n");
- erts_fprintf(stderr, " valid range is [0-%d]\n",
+ erts_fprintf(stderr, "-T number set modified timing level,\n");
+ erts_fprintf(stderr, " valid range is [0-%d]\n",
ERTS_MODIFIED_TIMING_LEVELS-1);
- erts_fprintf(stderr, "-V print Erlang version\n");
+ erts_fprintf(stderr, "-V print Erlang version\n");
- erts_fprintf(stderr, "-v turn on chatty mode (GCs will be reported etc)\n");
+ erts_fprintf(stderr, "-v turn on chatty mode (GCs will be reported etc)\n");
- erts_fprintf(stderr, "-W<i|w> set error logger warnings mapping,\n");
- erts_fprintf(stderr, " see error_logger documentation for details\n");
+ erts_fprintf(stderr, "-W<i|w> set error logger warnings mapping,\n");
+ erts_fprintf(stderr, " see error_logger documentation for details\n");
erts_fprintf(stderr, "\n");
erts_fprintf(stderr, "Note that if the emulator is started with erlexec (typically\n");
@@ -604,6 +608,7 @@ early_init(int *argc, char **argv) /*
erts_async_max_threads = 0;
erts_async_thread_suggested_stack_size = ERTS_ASYNC_THREAD_MIN_STACK_SIZE;
H_MIN_SIZE = H_DEFAULT_SIZE;
+ BIN_VH_MIN_SIZE = VH_DEFAULT_SIZE;
erts_initialized = 0;
@@ -922,17 +927,40 @@ erl_start(int argc, char **argv)
fprintf(stderr, "The undocumented +H option has been removed (R10B-6).\n\n");
break;
- case 'h':
- /* set default heap size */
- arg = get_arg(argv[i]+2, argv[i+1], &i);
- if ((H_MIN_SIZE = atoi(arg)) <= 0) {
- erts_fprintf(stderr, "bad heap size %s\n", arg);
- erts_usage();
+ case 'h': {
+ char *sub_param = argv[i]+2;
+ /* set default heap size
+ *
+ * h|ms - min_heap_size
+ * h|mbs - min_bin_vheap_size
+ *
+ */
+ if (has_prefix("mbs", sub_param)) {
+ arg = get_arg(sub_param+3, argv[i+1], &i);
+ if ((BIN_VH_MIN_SIZE = atoi(arg)) <= 0) {
+ erts_fprintf(stderr, "bad heap size %s\n", arg);
+ erts_usage();
+ }
+ VERBOSE(DEBUG_SYSTEM, ("using minimum binary virtual heap size %d\n", BIN_VH_MIN_SIZE));
+
+ } else if (has_prefix("ms", sub_param)) {
+ arg = get_arg(sub_param+2, argv[i+1], &i);
+ if ((H_MIN_SIZE = atoi(arg)) <= 0) {
+ erts_fprintf(stderr, "bad heap size %s\n", arg);
+ erts_usage();
+ }
+ VERBOSE(DEBUG_SYSTEM, ("using minimum heap size %d\n", H_MIN_SIZE));
+ } else {
+ /* backward compatibility */
+ arg = get_arg(argv[i]+2, argv[i+1], &i);
+ if ((H_MIN_SIZE = atoi(arg)) <= 0) {
+ erts_fprintf(stderr, "bad heap size %s\n", arg);
+ erts_usage();
+ }
+ VERBOSE(DEBUG_SYSTEM, ("using minimum heap size %d\n", H_MIN_SIZE));
}
- VERBOSE(DEBUG_SYSTEM,
- ("using minimum heap size %d\n",H_MIN_SIZE));
break;
-
+ }
case 'd':
/*
* Never produce crash dumps for internally detected
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index 81fbdfbd5a..a056fce0c5 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1997-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
/*
@@ -114,12 +114,8 @@ erts_resize_message_buffer(ErlHeapFragment *bp, Uint size,
nbp = (ErlHeapFragment*) ERTS_HEAP_REALLOC(ERTS_ALC_T_HEAP_FRAG,
(void *) bp,
- (sizeof(ErlHeapFragment)
- - sizeof(Eterm)
- + bp->size*sizeof(Eterm)),
- (sizeof(ErlHeapFragment)
- - sizeof(Eterm)
- + size*sizeof(Eterm)));
+ ERTS_HEAP_FRAG_SIZE(bp->size),
+ ERTS_HEAP_FRAG_SIZE(size));
if (bp != nbp) {
Uint off_sz = size < nbp->size ? size : nbp->size;
Eterm *sp = &bp->mem[0];
@@ -140,7 +136,7 @@ erts_resize_message_buffer(ErlHeapFragment *bp, Uint size,
#endif
}
nbp->size = size;
-
+ nbp->used_size = size;
#ifdef HARD_DEBUG
for (i = 0; i < brefs_size; i++)
@@ -175,9 +171,7 @@ free_message_buffer(ErlHeapFragment* bp)
erts_cleanup_offheap(&bp->off_heap);
ERTS_HEAP_FREE(ERTS_ALC_T_HEAP_FRAG,
(void *) bp,
- (sizeof(ErlHeapFragment)
- - sizeof(Eterm)
- + bp->size*sizeof(Eterm)));
+ ERTS_HEAP_FRAG_SIZE(bp->size));
}
static ERTS_INLINE void
diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h
index f14f14a586..5cf7c209bd 100644
--- a/erts/emulator/beam/erl_message.h
+++ b/erts/emulator/beam/erl_message.h
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1997-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -50,19 +50,10 @@ struct erl_heap_fragment {
ErlHeapFragment* next; /* Next heap fragment */
ErlOffHeap off_heap; /* Offset heap data. */
unsigned size; /* Size in words of mem */
+ unsigned used_size; /* With terms to be moved to heap by GC */
Eterm mem[1]; /* Data */
};
-#define ERTS_SET_MBUF_HEAP_END(BP, HENDP) \
-do { \
- unsigned real_size__ = (BP)->size; \
- ASSERT((BP)->mem <= (HENDP) && (HENDP) <= (BP)->mem + real_size__); \
- (BP)->size = (HENDP) - (BP)->mem; \
- /* We do not reallocate since buffer *might* be moved. */ \
- /* FIXME: Memory count is wrong, but at least it's almost */ \
- /* right... */ \
-} while (0)
-
typedef struct erl_mesg {
struct erl_mesg* next; /* Next message */
union {
@@ -196,10 +187,12 @@ do { \
#define ERTS_HEAP_FRAG_SIZE(DATA_WORDS) \
(sizeof(ErlHeapFragment) - sizeof(Eterm) + (DATA_WORDS)*sizeof(Eterm))
+
#define ERTS_INIT_HEAP_FRAG(HEAP_FRAG_P, DATA_WORDS) \
do { \
(HEAP_FRAG_P)->next = NULL; \
(HEAP_FRAG_P)->size = (DATA_WORDS); \
+ (HEAP_FRAG_P)->used_size = (DATA_WORDS); \
(HEAP_FRAG_P)->off_heap.mso = NULL; \
(HEAP_FRAG_P)->off_heap.funs = NULL; \
(HEAP_FRAG_P)->off_heap.externals = NULL; \
diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c
index 0fb264a53c..3cb5a966ac 100644
--- a/erts/emulator/beam/erl_port_task.c
+++ b/erts/emulator/beam/erl_port_task.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 2006-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 2006-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -902,25 +902,45 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
*curr_port_pp = NULL;
- if (pp->sched.taskq) {
+#ifdef ERTS_SMP
+ ASSERT(runq == (ErtsRunQueue *) erts_smp_atomic_read(&pp->run_queue));
+#endif
+
+ if (!pp->sched.taskq) {
+ ASSERT(pp->sched.exe_taskq);
+ pp->sched.exe_taskq = NULL;
+ }
+ else {
+#ifdef ERTS_SMP
+ ErtsRunQueue *xrunq;
+#endif
+
ASSERT(!(pp->status & ERTS_PORT_SFLGS_DEAD));
ASSERT(pp->sched.taskq->first);
- enqueue_port(runq, pp);
- port_was_enqueued = 1;
-
- /*
- erts_smp_notify_inc_runq();
- * No need to notify schedulers about the increase in run
- * queue length since at least this thread, which is a
- * scheduler, will discover that the port run queue isn't
- * empty before trying to go to sleep.
- */
+#ifdef ERTS_SMP
+ xrunq = erts_check_emigration_need(runq, ERTS_PORT_PRIO_LEVEL);
+ if (!xrunq) {
+#endif
+ enqueue_port(runq, pp);
+ ASSERT(pp->sched.exe_taskq);
+ pp->sched.exe_taskq = NULL;
+ /* No need to notify ourselves about inc in runq. */
+#ifdef ERTS_SMP
+ }
+ else {
+ /* Port emigrated ... */
+ erts_smp_atomic_set(&pp->run_queue, (long) xrunq);
+ enqueue_port(xrunq, pp);
+ ASSERT(pp->sched.exe_taskq);
+ pp->sched.exe_taskq = NULL;
+ erts_smp_notify_inc_runq(xrunq);
+ erts_smp_runq_unlock(xrunq);
+ }
+#endif
+ port_was_enqueued = 1;
}
- ASSERT(pp->sched.exe_taskq);
- pp->sched.exe_taskq = NULL;
-
res = erts_smp_atomic_read(&erts_port_task_outstanding_io_tasks) != (long) 0;
ERTS_PT_CHK_PRES_PORTQ(runq, pp);
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index a4afe0574f..476e29d96f 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -5517,6 +5517,8 @@ erts_proc_migrate(Process *p, ErtsProcLocks *plcks,
p->run_queue = to_rq;
enqueue_process(to_rq, p);
+ smp_notify_inc_runq(to_rq);
+
return ERTS_MIGRATE_SUCCESS;
}
#endif /* ERTS_SMP */
@@ -6272,7 +6274,7 @@ Process *schedule(Process *p, int calls)
erts_check_my_tracer_proc(p);
#endif
- if ((FLAGS(p) & F_FORCE_GC) || (MSO(p).overhead >= BIN_VHEAP_SZ(p))) {
+ if ((FLAGS(p) & F_FORCE_GC) || (MSO(p).overhead > BIN_VHEAP_SZ(p))) {
reds -= erts_garbage_collect(p, 0, p->arg_reg, p->arity);
if (reds < 0) {
reds = 1;
@@ -6683,13 +6685,15 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
* noone except us has access to the process.
*/
if (so->flags & SPO_USE_ARGS) {
- p->min_heap_size = so->min_heap_size;
- p->prio = so->priority;
- p->max_gen_gcs = so->max_gen_gcs;
+ p->min_heap_size = so->min_heap_size;
+ p->min_vheap_size = so->min_vheap_size;
+ p->prio = so->priority;
+ p->max_gen_gcs = so->max_gen_gcs;
} else {
- p->min_heap_size = H_MIN_SIZE;
- p->prio = PRIORITY_NORMAL;
- p->max_gen_gcs = (Uint16) erts_smp_atomic_read(&erts_max_gen_gcs);
+ p->min_heap_size = H_MIN_SIZE;
+ p->min_vheap_size = BIN_VH_MIN_SIZE;
+ p->prio = PRIORITY_NORMAL;
+ p->max_gen_gcs = (Uint16) erts_smp_atomic_read(&erts_max_gen_gcs);
}
p->skipped = 0;
ASSERT(p->min_heap_size == erts_next_heap_size(p->min_heap_size, 0));
@@ -6736,9 +6740,9 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->heap_sz = sz;
p->catches = 0;
- p->bin_vheap_sz = H_MIN_SIZE;
- p->bin_old_vheap_sz = H_MIN_SIZE;
- p->bin_old_vheap = 0;
+ p->bin_vheap_sz = p->min_vheap_size;
+ p->bin_old_vheap_sz = p->min_vheap_size;
+ p->bin_old_vheap = 0;
/* No need to initialize p->fcalls. */
@@ -6969,6 +6973,7 @@ void erts_init_empty_process(Process *p)
p->gen_gcs = 0;
p->max_gen_gcs = 0;
p->min_heap_size = 0;
+ p->min_vheap_size = 0;
p->status = P_RUNABLE;
p->gcstatus = P_RUNABLE;
p->rstatus = P_RUNABLE;
@@ -6985,8 +6990,8 @@ void erts_init_empty_process(Process *p)
p->ftrace = NIL;
p->fcalls = 0;
- p->bin_vheap_sz=H_MIN_SIZE;
- p->bin_old_vheap_sz=H_MIN_SIZE;
+ p->bin_vheap_sz = BIN_VH_MIN_SIZE;
+ p->bin_old_vheap_sz = BIN_VH_MIN_SIZE;
p->bin_old_vheap = 0;
#ifdef ERTS_SMP
p->u.ptimer = NULL;
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index 7597eb5e31..f58b6932b3 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -477,6 +477,7 @@ struct ErtsPendingSuspend_ {
# define MSO(p) (p)->off_heap
# define MIN_HEAP_SIZE(p) (p)->min_heap_size
+# define MIN_VHEAP_SIZE(p) (p)->min_vheap_size
# define BIN_VHEAP_SZ(p) (p)->bin_vheap_sz
# define BIN_OLD_VHEAP_SZ(p) (p)->bin_old_vheap_sz
# define BIN_OLD_VHEAP(p) (p)->bin_old_vheap
@@ -495,6 +496,7 @@ struct process {
Eterm* hend; /* Heap end */
Uint heap_sz; /* Size of heap in words */
Uint min_heap_size; /* Minimum size of heap (in words). */
+ Uint min_vheap_size; /* Minimum size of virtual heap (in words). */
#if !defined(NO_FPE_SIGNALS)
volatile unsigned long fp_exception;
@@ -654,6 +656,11 @@ struct process {
* heap fragments.
*/
#endif
+
+#ifdef FORCE_HEAP_FRAGS
+ Uint space_verified; /* Avoid HAlloc forcing heap fragments when */
+ Eterm* space_verified_from; /* we rely on available heap space (TestHeap) */
+#endif
};
#ifdef CHECK_FOR_HOLES
@@ -725,8 +732,8 @@ typedef struct {
* The following items are only initialized if the SPO_USE_ARGS flag is set.
*/
Uint min_heap_size; /* Minimum heap size (must be a valued returned
- * from next_heap_size()).
- */
+ * from next_heap_size()). */
+ Uint min_vheap_size; /* Minimum virtual heap size */
int priority; /* Priority for process. */
Uint16 max_gen_gcs; /* Maximum number of gen GCs before fullsweep. */
int scheduler;
@@ -738,7 +745,20 @@ typedef struct {
#define KILL_CATCHES(p) (p)->catches = -1
-void erts_arith_shrink(Process* p, Eterm* hp);
+/* Shrink heap fragment from _last_ HAlloc.
+*/
+ERTS_GLB_INLINE void erts_heap_frag_shrink(Process* p, Eterm* hp);
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+ERTS_GLB_INLINE void erts_heap_frag_shrink(Process* p, Eterm* hp)
+{
+ ErlHeapFragment* hf = MBUF(p);
+
+ ASSERT(hf!=NULL && (hp - hf->mem < (unsigned long)hf->size));
+
+ hf->used_size = hp - hf->mem;
+}
+#endif /* inline */
+
Eterm* erts_heap_alloc(Process* p, Uint need);
#ifdef CHECK_FOR_HOLES
Eterm* erts_set_hole_marker(Eterm* ptr, Uint sz);
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index 2afb16fc52..2842c2361a 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1999-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -2171,6 +2171,11 @@ erts_bif_trace(int bif_index, Process* p,
void
trace_gc(Process *p, Eterm what)
{
+ ERTS_DECL_AM(bin_vheap_size);
+ ERTS_DECL_AM(bin_vheap_block_size);
+ ERTS_DECL_AM(bin_old_vheap_size);
+ ERTS_DECL_AM(bin_old_vheap_block_size);
+
ErlHeapFragment *bp = NULL;
ErlOffHeap *off_heap;
ERTS_TRACER_REF_TYPE tracer_ref = ERTS_NULL_TRACER_REF; /* Initialized
@@ -2180,6 +2185,7 @@ trace_gc(Process *p, Eterm what)
Eterm* hp;
Eterm msg = NIL;
Uint size;
+
Eterm tags[] = {
am_old_heap_block_size,
am_heap_block_size,
@@ -2187,8 +2193,13 @@ trace_gc(Process *p, Eterm what)
am_recent_size,
am_stack_size,
am_old_heap_size,
- am_heap_size
+ am_heap_size,
+ AM_bin_vheap_size,
+ AM_bin_vheap_block_size,
+ AM_bin_old_vheap_size,
+ AM_bin_old_vheap_block_size
};
+
Uint values[] = {
OLD_HEAP(p) ? OLD_HEND(p) - OLD_HEAP(p) : 0,
HEAP_SIZE(p),
@@ -2196,7 +2207,11 @@ trace_gc(Process *p, Eterm what)
HIGH_WATER(p) - HEAP_START(p),
STACK_START(p) - p->stop,
OLD_HEAP(p) ? OLD_HTOP(p) - OLD_HEAP(p) : 0,
- HEAP_TOP(p) - HEAP_START(p)
+ HEAP_TOP(p) - HEAP_START(p),
+ MSO(p).overhead,
+ BIN_VHEAP_SZ(p),
+ BIN_OLD_VHEAP(p),
+ BIN_OLD_VHEAP_SZ(p)
};
Eterm local_heap[(sizeof(values)/sizeof(Uint))
*(2/*cons*/ + 3/*2-tuple*/ + BIG_UINT_HEAP_SIZE)
diff --git a/erts/emulator/beam/erl_vm.h b/erts/emulator/beam/erl_vm.h
index 4d8315ab95..5b0d3c2bfa 100644
--- a/erts/emulator/beam/erl_vm.h
+++ b/erts/emulator/beam/erl_vm.h
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -22,6 +22,13 @@
/* #define ERTS_OPCODE_COUNTER_SUPPORT */
+/* FORCE_HEAP_FRAGS:
+ * Debug provocation to make HAlloc always create heap fragments (if allowed)
+ * even if there is room on heap.
+ */
+/* #define FORCE_HEAP_FRAGS */
+
+
#if defined(HYBRID)
/* # define CHECK_FOR_HOLES */
#endif
@@ -50,7 +57,8 @@
#define INPUT_REDUCTIONS (2 * CONTEXT_REDS)
-#define H_DEFAULT_SIZE 233 /* default (heap + stack) min size */
+#define H_DEFAULT_SIZE 233 /* default (heap + stack) min size */
+#define VH_DEFAULT_SIZE 32768 /* default virtual (bin) heap min size (words) */
#ifdef HYBRID
# define SH_DEFAULT_SIZE 2629425 /* default message area min size */
@@ -70,6 +78,7 @@
&& (P) == (P)->scheduler_data->match_pseudo_process) \
|| erts_is_system_blocked(0))
+
#ifdef DEBUG
/*
* Debug HAlloc that initialize all memory to bad things.
@@ -80,55 +89,43 @@
VERBOSE(DEBUG_ALLOCATION,("HAlloc @ 0x%08lx (%d) %s:%d\n", \
(unsigned long)HEAP_TOP(p),(sz),__FILE__,__LINE__)), \
*/
-#ifdef CHECK_FOR_HOLES
-#define HAlloc(p, sz) \
- (ASSERT_EXPR((sz) >= 0), \
- ErtsHAllocLockCheck(p), \
- ((((HEAP_LIMIT(p) - HEAP_TOP(p)) < (sz))) \
- ? erts_heap_alloc((p),(sz)) \
- : (erts_set_hole_marker(HEAP_TOP(p), (sz)), \
- HEAP_TOP(p) = HEAP_TOP(p) + (sz), HEAP_TOP(p) - (sz))))
+# ifdef CHECK_FOR_HOLES
+# define INIT_HEAP_MEM(p,sz) erts_set_hole_marker(HEAP_TOP(p), (sz))
+# else
+# define INIT_HEAP_MEM(p,sz) memset(HEAP_TOP(p),DEBUG_BAD_BYTE,(sz)*sizeof(Eterm*))
+# endif
#else
-#define HAlloc(p, sz) \
- (ASSERT_EXPR((sz) >= 0), \
- ErtsHAllocLockCheck(p), \
- ((((HEAP_LIMIT(p) - HEAP_TOP(p)) < (sz))) \
- ? erts_heap_alloc((p),(sz)) \
- : (memset(HEAP_TOP(p),DEBUG_BAD_BYTE,(sz)*sizeof(Eterm*)), \
- HEAP_TOP(p) = HEAP_TOP(p) + (sz), HEAP_TOP(p) - (sz))))
-#endif
+# define INIT_HEAP_MEM(p,sz) ((void)0)
+#endif /* DEBUG */
+
+
+#ifdef FORCE_HEAP_FRAGS
+# define IS_FORCE_HEAP_FRAGS 1
#else
+# define IS_FORCE_HEAP_FRAGS 0
+#endif
/*
* Allocate heap memory, first on the ordinary heap;
* failing that, in a heap fragment.
*/
-#define HAlloc(p, sz) \
- (ASSERT_EXPR((sz) >= 0), \
- ErtsHAllocLockCheck(p), \
- ((((HEAP_LIMIT(p) - HEAP_TOP(p)) < (sz))) \
- ? erts_heap_alloc((p),(sz)) \
- : (HEAP_TOP(p) = HEAP_TOP(p) + (sz), HEAP_TOP(p) - (sz))))
+#define HAlloc(p, sz) \
+ (ASSERT_EXPR((sz) >= 0), \
+ ErtsHAllocLockCheck(p), \
+ (IS_FORCE_HEAP_FRAGS || (((HEAP_LIMIT(p) - HEAP_TOP(p)) < (sz))) \
+ ? erts_heap_alloc((p),(sz)) \
+ : (INIT_HEAP_MEM(p,sz), \
+ HEAP_TOP(p) = HEAP_TOP(p) + (sz), HEAP_TOP(p) - (sz))))
-#endif /* DEBUG */
-#if defined(CHECK_FOR_HOLES)
-# define HRelease(p, endp, ptr) \
+#define HRelease(p, endp, ptr) \
if ((ptr) == (endp)) { \
; \
} else if (HEAP_START(p) <= (ptr) && (ptr) < HEAP_TOP(p)) { \
HEAP_TOP(p) = (ptr); \
} else { \
- erts_arith_shrink(p, ptr); \
+ erts_heap_frag_shrink(p, ptr); \
}
-#else
-# define HRelease(p, endp, ptr) \
- if ((ptr) == (endp)) { \
- ; \
- } else if (HEAP_START(p) <= (ptr) && (ptr) < HEAP_TOP(p)) { \
- HEAP_TOP(p) = (ptr); \
- }
-#endif
#define HeapWordsLeft(p) (HEAP_LIMIT(p) - HEAP_TOP(p))
@@ -182,6 +179,7 @@ extern int num_instructions; /* Number of instruction in opc[]. */
#define MAX_PORT_LINK 8 /* Maximum number of links to a port */
extern int H_MIN_SIZE; /* minimum (heap + stack) */
+extern int BIN_VH_MIN_SIZE; /* minimum virtual (bin) heap */
#define ORIG_CREATION 0
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index f856cce18f..24887b3dea 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -1013,6 +1013,34 @@ term_to_binary_2(Process* p, Eterm Term, Eterm Flags)
return erts_term_to_binary(p, Term, level, flags);
}
+static uLongf binary2term_uncomp_size(byte* data, Sint size)
+{
+ z_stream stream;
+ int err;
+ const uInt chunk_size = 64*1024; /* Ask tmp-alloc about a suitable size? */
+ void* tmp_buf = erts_alloc(ERTS_ALC_T_TMP, chunk_size);
+ uLongf uncomp_size = 0;
+
+ stream.next_in = (Bytef*)data;
+ stream.avail_in = (uInt)size;
+ stream.next_out = tmp_buf;
+ stream.avail_out = (uInt)chunk_size;
+
+ erl_zlib_alloc_init(&stream);
+
+ err = inflateInit(&stream);
+ if (err == Z_OK) {
+ while ((err = inflate(&stream, Z_NO_FLUSH)) == Z_OK) {
+ uncomp_size += chunk_size - stream.avail_out;
+ stream.next_out = tmp_buf;
+ stream.avail_out = chunk_size;
+ }
+ inflateEnd(&stream);
+ }
+ erts_free(ERTS_ALC_T_TMP, tmp_buf);
+ return err == Z_STREAM_END ? uncomp_size : 0;
+}
+
static ERTS_INLINE Sint
binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size)
{
@@ -1036,10 +1064,18 @@ binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size)
state->extp = bytes;
}
else {
- uLongf dest_len = get_int32(bytes+1);
- state->extp = erts_alloc(ERTS_ALC_T_TMP, dest_len);
+ uLongf dest_len = (Uint32) get_int32(bytes+1);
+ bytes += 5;
+ size -= 5;
+ if (dest_len > 32*1024*1024
+ || (state->extp = erts_alloc_fnf(ERTS_ALC_T_TMP, dest_len)) == NULL) {
+ if (dest_len != binary2term_uncomp_size(bytes, size)) {
+ goto error;
+ }
+ state->extp = erts_alloc(ERTS_ALC_T_TMP, dest_len);
+ }
state->exttmp = 1;
- if (erl_zlib_uncompress(state->extp, &dest_len, bytes+5, size-5) != Z_OK)
+ if (erl_zlib_uncompress(state->extp, &dest_len, bytes, size) != Z_OK)
goto error;
size = (Sint) dest_len;
}
@@ -1059,10 +1095,10 @@ binary2term_abort(ErtsBinary2TermState *state)
}
static ERTS_INLINE Eterm
-binary2term_create(ErtsBinary2TermState *state, Eterm **hpp, ErlOffHeap *ohp)
+binary2term_create(ErtsDistExternal *edep, ErtsBinary2TermState *state, Eterm **hpp, ErlOffHeap *ohp)
{
Eterm res;
- if (!dec_term(NULL, hpp, state->extp, ohp, &res))
+ if (!dec_term(edep, hpp, state->extp, ohp, &res))
res = THE_NON_VALUE;
if (state->exttmp) {
state->exttmp = 0;
@@ -1086,7 +1122,7 @@ erts_binary2term_abort(ErtsBinary2TermState *state)
Eterm
erts_binary2term_create(ErtsBinary2TermState *state, Eterm **hpp, ErlOffHeap *ohp)
{
- return binary2term_create(state, hpp, ohp);
+ return binary2term_create(NULL,state, hpp, ohp);
}
BIF_RETTYPE binary_to_term_1(BIF_ALIST_1)
@@ -1114,7 +1150,67 @@ BIF_RETTYPE binary_to_term_1(BIF_ALIST_1)
hp = HAlloc(BIF_P, heap_size);
endp = hp + heap_size;
- res = binary2term_create(&b2ts, &hp, &MSO(BIF_P));
+ res = binary2term_create(NULL, &b2ts, &hp, &MSO(BIF_P));
+
+ erts_free_aligned_binary_bytes(temp_alloc);
+
+ if (hp > endp) {
+ erl_exit(1, ":%s, line %d: heap overrun by %d words(s)\n",
+ __FILE__, __LINE__, hp-endp);
+ }
+
+ HRelease(BIF_P, endp, hp);
+
+ if (res == THE_NON_VALUE)
+ goto error;
+
+ return res;
+}
+
+BIF_RETTYPE binary_to_term_2(BIF_ALIST_2)
+{
+ Sint heap_size;
+ Eterm res;
+ Eterm opts;
+ Eterm opt;
+ Eterm* hp;
+ Eterm* endp;
+ Sint size;
+ byte* bytes;
+ byte* temp_alloc = NULL;
+ ErtsBinary2TermState b2ts;
+ ErtsDistExternal fakedep;
+
+ fakedep.flags = 0;
+ opts = BIF_ARG_2;
+ while (is_list(opts)) {
+ opt = CAR(list_val(opts));
+ if (opt == am_safe) {
+ fakedep.flags |= ERTS_DIST_EXT_BTT_SAFE;
+ } else {
+ goto error;
+ }
+ opts = CDR(list_val(opts));
+ }
+
+ if (is_not_nil(opts))
+ goto error;
+
+ if ((bytes = erts_get_aligned_binary_bytes(BIF_ARG_1, &temp_alloc)) == NULL) {
+ error:
+ erts_free_aligned_binary_bytes(temp_alloc);
+ BIF_ERROR(BIF_P, BADARG);
+ }
+ size = binary_size(BIF_ARG_1);
+
+ heap_size = binary2term_prepare(&b2ts, bytes, size);
+ if (heap_size < 0)
+ goto error;
+
+ hp = HAlloc(BIF_P, heap_size);
+ endp = hp + heap_size;
+
+ res = binary2term_create(&fakedep, &b2ts, &hp, &MSO(BIF_P));
erts_free_aligned_binary_bytes(temp_alloc);
@@ -1300,7 +1396,7 @@ dec_atom(ErtsDistExternal *edep, byte* ep, Eterm* objp)
switch (*ep++) {
case ATOM_CACHE_REF:
- if (!(edep->flags & ERTS_DIST_EXT_ATOM_TRANS_TAB))
+ if (!(edep && (edep->flags & ERTS_DIST_EXT_ATOM_TRANS_TAB)))
goto error;
n = get_int8(ep);
ep++;
@@ -1312,13 +1408,18 @@ dec_atom(ErtsDistExternal *edep, byte* ep, Eterm* objp)
case ATOM_EXT:
len = get_int16(ep),
ep += 2;
- *objp = am_atom_put((char*)ep, len);
- ep += len;
- break;
+ goto dec_atom_common;
case SMALL_ATOM_EXT:
len = get_int8(ep);
ep++;
- *objp = am_atom_put((char*)ep, len);
+ dec_atom_common:
+ if (edep && (edep->flags & ERTS_DIST_EXT_BTT_SAFE)) {
+ if (!erts_atom_get((char*)ep, len, objp)) {
+ goto error;
+ }
+ } else {
+ *objp = am_atom_put((char*)ep, len);
+ }
ep += len;
break;
default:
@@ -1775,9 +1876,80 @@ is_external_string(Eterm list, int* p_is_string)
return len;
}
+/* Assumes that the ones to undo are preluding the lists. */
+static void
+undo_offheap_in_area(ErlOffHeap* off_heap, Eterm* start, Eterm* end)
+{
+ const Uint area_sz = (end - start) * sizeof(Eterm);
+ struct proc_bin* mso;
+ struct proc_bin** mso_nextp = NULL;
+#ifndef HYBRID /* FIND ME! */
+ struct erl_fun_thing* funs;
+ struct erl_fun_thing** funs_nextp = NULL;
+#endif
+ struct external_thing_* ext;
+ struct external_thing_** ext_nextp = NULL;
+
+ for (mso = off_heap->mso; ; mso=mso->next) {
+ if (!in_area(mso, start, area_sz)) {
+ if (mso_nextp != NULL) {
+ *mso_nextp = NULL;
+ erts_cleanup_mso(off_heap->mso);
+ off_heap->mso = mso;
+ }
+ break;
+ }
+ mso_nextp = &mso->next;
+ }
+
+#ifndef HYBRID /* FIND ME! */
+ for (funs = off_heap->funs; ; funs=funs->next) {
+ if (!in_area(funs, start, area_sz)) {
+ if (funs_nextp != NULL) {
+ *funs_nextp = NULL;
+ erts_cleanup_funs(off_heap->funs);
+ off_heap->funs = funs;
+ }
+ break;
+ }
+ funs_nextp = &funs->next;
+ }
+#endif
+ for (ext = off_heap->externals; ; ext=ext->next) {
+ if (!in_area(ext, start, area_sz)) {
+ if (ext_nextp != NULL) {
+ *ext_nextp = NULL;
+ erts_cleanup_externals(off_heap->externals);
+ off_heap->externals = ext;
+ }
+ break;
+ }
+ ext_nextp = &ext->next;
+ }
+
+ /* Assert that the ones to undo were indeed preluding the lists. */
+#ifdef DEBUG
+ for (mso = off_heap->mso; mso != NULL; mso=mso->next) {
+ ASSERT(!in_area(mso, start, area_sz));
+ }
+# ifndef HYBRID /* FIND ME! */
+ for (funs = off_heap->funs; funs != NULL; funs=funs->next) {
+ ASSERT(!in_area(funs, start, area_sz));
+ }
+# endif
+ for (ext = off_heap->externals; ext != NULL; ext=ext->next) {
+ ASSERT(!in_area(ext, start, area_sz));
+ }
+#endif /* DEBUG */
+}
+
+/* Decode term from external format into *objp.
+** On failure return NULL and (R13B04) *hpp will be unchanged.
+*/
static byte*
dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Eterm* objp)
{
+ Eterm* hp_saved = *hpp;
int n;
register Eterm* hp = *hpp; /* Please don't take the address of hp */
Eterm* next = objp;
@@ -1864,13 +2036,18 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et
case ATOM_EXT:
n = get_int16(ep);
ep += 2;
- *objp = am_atom_put((char*)ep, n);
- ep += n;
- break;
+ goto dec_term_atom_common;
case SMALL_ATOM_EXT:
n = get_int8(ep);
ep++;
- *objp = am_atom_put((char*)ep, n);
+dec_term_atom_common:
+ if (edep && (edep->flags & ERTS_DIST_EXT_BTT_SAFE)) {
+ if (!erts_atom_get((char*)ep, n, objp)) {
+ goto error;
+ }
+ } else {
+ *objp = am_atom_put((char*)ep, n);
+ }
ep += n;
break;
case LARGE_TUPLE_EXT:
@@ -1973,7 +2150,7 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et
ep = dec_pid(edep, hpp, ep, off_heap, objp);
hp = *hpp;
if (ep == NULL) {
- return NULL;
+ goto error;
}
break;
case PORT_EXT:
@@ -2039,7 +2216,6 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et
goto ref_ext_common;
case NEW_REFERENCE_EXT:
-
ref_words = get_int16(ep);
ep += 2;
@@ -2209,7 +2385,7 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et
ep = dec_term(edep, hpp, ep, off_heap, &temp);
hp = *hpp;
if (ep == NULL) {
- return NULL;
+ goto error;
}
if (!is_small(temp)) {
goto error;
@@ -2218,6 +2394,10 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et
if (arity < 0) {
goto error;
}
+ if (edep && (edep->flags & ERTS_DIST_EXT_BTT_SAFE)) {
+ if (!erts_find_export_entry(mod, name, arity))
+ goto error;
+ }
*objp = make_export(hp);
*hp++ = HEADER_EXPORT;
*hp++ = (Eterm) erts_export_get_or_make_stub(mod, name, arity);
@@ -2235,8 +2415,6 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et
Sint old_index;
unsigned num_free;
int i;
- Eterm* temp_hp;
- Eterm** hpp = &temp_hp;
Eterm temp;
ep += 4; /* Skip total size in bytes */
@@ -2248,23 +2426,16 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et
num_free = get_int32(ep);
ep += 4;
hp += ERL_FUN_SIZE;
- if (num_free > 0) {
- /* Don't leave a hole in case we fail */
- *hp = make_pos_bignum_header(num_free-1);
- }
hp += num_free;
- *hpp = hp;
funp->thing_word = HEADER_FUN;
funp->num_free = num_free;
- funp->creator = NIL; /* Don't leave a hole in case we fail */
*objp = make_fun(funp);
/* Module */
- if ((ep = dec_atom(edep, ep, &temp)) == NULL) {
+ if ((ep = dec_atom(edep, ep, &module)) == NULL) {
goto error;
}
- module = temp;
-
+ *hpp = hp;
/* Index */
if ((ep = dec_term(edep, hpp, ep, off_heap, &temp)) == NULL) {
goto error;
@@ -2321,17 +2492,11 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et
Sint old_index;
unsigned num_free;
int i;
- Eterm* temp_hp;
- Eterm** hpp = &temp_hp;
Eterm temp;
num_free = get_int32(ep);
ep += 4;
hp += ERL_FUN_SIZE;
- if (num_free > 0) {
- /* Don't leave a hole in the heap in case we fail. */
- *hp = make_pos_bignum_header(num_free-1);
- }
hp += num_free;
*hpp = hp;
funp->thing_word = HEADER_FUN;
@@ -2339,23 +2504,16 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et
*objp = make_fun(funp);
/* Creator pid */
- switch(*ep) {
- case PID_EXT:
- ep = dec_pid(edep, hpp, ++ep, off_heap, &funp->creator);
- if (ep == NULL) {
- funp->creator = NIL; /* Don't leave a hole in the heap */
- goto error;
- }
- break;
- default:
+ if (*ep != PID_EXT
+ || (ep = dec_pid(edep, hpp, ++ep, off_heap,
+ &funp->creator))==NULL) {
goto error;
}
/* Module */
- if ((ep = dec_atom(edep, ep, &temp)) == NULL) {
+ if ((ep = dec_atom(edep, ep, &module)) == NULL) {
goto error;
}
- module = temp;
/* Index */
if ((ep = dec_term(edep, hpp, ep, off_heap, &temp)) == NULL) {
@@ -2382,7 +2540,6 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et
funp->next = off_heap->funs;
off_heap->funs = funp;
#endif
-
old_uniq = unsigned_val(temp);
funp->fe = erts_put_fun_entry(module, old_uniq, old_index);
@@ -2401,12 +2558,15 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et
}
default:
error:
- /*
- * Be careful to return the updated heap pointer, to avoid
- * that the caller wipes out binaries or other off-heap objects
- * that may have been linked into the process.
+ /* UNDO:
+ * Must unlink all off-heap objects that may have been
+ * linked into the process.
*/
- *hpp = hp;
+ if (hp < *hpp) { /* Sometimes we used hp and sometimes *hpp */
+ hp = *hpp; /* the largest must be the freshest */
+ }
+ undo_offheap_in_area(off_heap, hp_saved, hp);
+ *hpp = hp_saved;
return NULL;
}
}
diff --git a/erts/emulator/beam/external.h b/erts/emulator/beam/external.h
index f308680f89..eada6d4f27 100644
--- a/erts/emulator/beam/external.h
+++ b/erts/emulator/beam/external.h
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -98,9 +98,19 @@ typedef struct {
Eterm atom[ERTS_ATOM_CACHE_SIZE];
} ErtsAtomTranslationTable;
-#define ERTS_DIST_EXT_DFLAG_HDR (((Uint32) 1) << 31)
-#define ERTS_DIST_EXT_ATOM_TRANS_TAB (((Uint32) 1) << 30)
-#define ERTS_DIST_EXT_CON_ID_MASK ((Uint32) 0x3fffffff)
+/*
+ * These flags are tagged onto the high bits of a connection ID and stored in
+ * the ErtsDistExternal structure's flags field. They are used to indicate
+ * various bits of state necessary to decode binaries in a variety of
+ * scenarios. The mask ERTS_DIST_EXT_CON_ID_MASK is used later to separate the
+ * connection ID from the flags. Be careful to ensure that the mask does not
+ * overlap any of the bits used for flags, or ERTS will leak flags bits into
+ * connection IDs and leak connection ID bits into the flags.
+ */
+#define ERTS_DIST_EXT_DFLAG_HDR ((Uint32) 0x80000000)
+#define ERTS_DIST_EXT_ATOM_TRANS_TAB ((Uint32) 0x40000000)
+#define ERTS_DIST_EXT_BTT_SAFE ((Uint32) 0x20000000)
+#define ERTS_DIST_EXT_CON_ID_MASK ((Uint32) 0x1fffffff)
#define ERTS_DIST_EXT_CON_ID(DIST_EXTP) \
((DIST_EXTP)->flags & ERTS_DIST_EXT_CON_ID_MASK)
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 62a788cbff..df0ab40074 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -1658,7 +1658,6 @@ void erts_bif_trace_init(void);
/*
** Call_trace uses this API for the parameter matching functions
*/
- struct erl_heap_fragment* saved_program_buf;
#define MatchSetRef(MPSP) \
do { \
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index be442fa480..c162395159 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -95,6 +95,7 @@ dispatch_profile_msg_q(profile_sched_msg_q *psmq)
#endif
+
Eterm*
erts_heap_alloc(Process* p, Uint need)
{
@@ -105,13 +106,29 @@ erts_heap_alloc(Process* p, Uint need)
Uint i;
#endif
+#ifdef FORCE_HEAP_FRAGS
+ if (p->space_verified && p->space_verified_from!=NULL
+ && HEAP_TOP(p) >= p->space_verified_from
+ && HEAP_TOP(p) + need <= p->space_verified_from + p->space_verified
+ && HEAP_LIMIT(p) - HEAP_TOP(p) >= need) {
+
+ Uint consumed = need + (HEAP_TOP(p) - p->space_verified_from);
+ ASSERT(consumed <= p->space_verified);
+ p->space_verified -= consumed;
+ p->space_verified_from += consumed;
+ HEAP_TOP(p) = p->space_verified_from;
+ return HEAP_TOP(p) - need;
+ }
+ p->space_verified = 0;
+ p->space_verified_from = NULL;
+#endif /* FORCE_HEAP_FRAGS */
+
n = need;
#ifdef DEBUG
n++;
#endif
bp = (ErlHeapFragment*)
- ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP_FRAG,
- sizeof(ErlHeapFragment) + ((n-1)*sizeof(Eterm)));
+ ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP_FRAG, ERTS_HEAP_FRAG_SIZE(n));
#ifdef DEBUG
n--;
@@ -140,6 +157,7 @@ erts_heap_alloc(Process* p, Uint need)
bp->next = MBUF(p);
MBUF(p) = bp;
bp->size = n;
+ bp->used_size = n;
MBUF_SIZE(p) += n;
bp->off_heap.mso = NULL;
#ifndef HYBRID /* FIND ME! */
@@ -151,34 +169,6 @@ erts_heap_alloc(Process* p, Uint need)
return bp->mem;
}
-void erts_arith_shrink(Process* p, Eterm* hp)
-{
-#if defined(CHECK_FOR_HOLES)
- ErlHeapFragment* hf;
-
- /*
- * We must find the heap fragment that hp points into.
- * If we are unlucky, we might have to search through
- * a large part of the list. We'll hope that will not
- * happen too often.
- */
- for (hf = MBUF(p); hf != 0; hf = hf->next) {
- if (hp - hf->mem < (unsigned long)hf->size) {
- /*
- * We are not allowed to changed hf->size (because the
- * size must be correct when deallocating). Therefore,
- * clear out the uninitialized part of the heap fragment.
- */
- Eterm* to = hf->mem + hf->size;
- while (hp < to) {
- *hp++ = NIL;
- }
- break;
- }
- }
-#endif
-}
-
#ifdef CHECK_FOR_HOLES
Eterm*
erts_set_hole_marker(Eterm* ptr, Uint sz)
diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl
index e47dfa18f7..db2b3e10db 100644
--- a/erts/emulator/test/binary_SUITE.erl
+++ b/erts/emulator/test/binary_SUITE.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -27,6 +27,7 @@
%% binary_to_list/1
%% binary_to_list/3
%% binary_to_term/1
+%% binary_to_term/2
%% bitstr_to_list/1
%% term_to_binary/1
%% erlang:external_size/1
@@ -49,7 +50,7 @@
t_hash/1,
bad_size/1,
bad_term_to_binary/1,
- bad_binary_to_term_2/1,
+ bad_binary_to_term_2/1,safe_binary_to_term2/1,
bad_binary_to_term/1, bad_terms/1, more_bad_terms/1,
otp_5484/1,otp_5933/1,
ordering/1,unaligned_order/1,gc_test/1,
@@ -66,7 +67,7 @@ all(suite) ->
t_split_binary, bad_split, t_concat_binary,
bad_list_to_binary, bad_binary_to_list, terms, terms_float,
external_size, t_iolist_size,
- bad_binary_to_term_2,
+ bad_binary_to_term_2,safe_binary_to_term2,
bad_binary_to_term, bad_terms, t_hash, bad_size, bad_term_to_binary,
more_bad_terms, otp_5484, otp_5933, ordering, unaligned_order,
gc_test, bit_sized_binary_sizes, bitlevel_roundtrip, otp_6817, otp_8117,
@@ -438,8 +439,11 @@ terms(Config) when is_list(Config) ->
ok
end,
Term = binary_to_term(Bin),
+ Term = erlang:binary_to_term(Bin, [safe]),
Unaligned = make_unaligned_sub_binary(Bin),
Term = binary_to_term(Unaligned),
+ Term = erlang:binary_to_term(Unaligned, []),
+ Term = erlang:binary_to_term(Bin, [safe]),
BinC = erlang:term_to_binary(Term, [compressed]),
Term = binary_to_term(BinC),
true = size(BinC) =< size(Bin),
@@ -538,6 +542,23 @@ bad_binary_to_term(Config) when is_list(Config) ->
bad_bin_to_term(BadBin) ->
{'EXIT',{badarg,_}} = (catch binary_to_term(BadBin)).
+bad_bin_to_term(BadBin,Opts) ->
+ {'EXIT',{badarg,_}} = (catch erlang:binary_to_term(BadBin,Opts)).
+
+safe_binary_to_term2(doc) -> "Test safety options for binary_to_term/2";
+safe_binary_to_term2(Config) when is_list(Config) ->
+ ?line bad_bin_to_term(<<131,100,0,14,"undefined_atom">>, [safe]),
+ ?line bad_bin_to_term(<<131,100,0,14,"other_bad_atom">>, [safe]),
+ BadHostAtom = <<100,0,14,"badguy@badhost">>,
+ Empty = <<0,0,0,0>>,
+ BadRef = <<131,114,0,3,BadHostAtom/binary,0,<<0,0,0,255>>/binary,
+ Empty/binary,Empty/binary>>,
+ ?line bad_bin_to_term(BadRef, [safe]), % good ref, with a bad atom
+ ?line fullsweep_after = erlang:binary_to_term(<<131,100,0,15,"fullsweep_after">>, [safe]), % should be a good atom
+ BadExtFun = <<131,113,100,0,4,98,108,117,101,100,0,4,109,111,111,110,97,3>>,
+ ?line bad_bin_to_term(BadExtFun, [safe]),
+ ok.
+
%% Tests bad input to binary_to_term/1.
bad_terms(suite) -> [];
@@ -559,11 +580,18 @@ corrupter(Term) ->
?line corrupter(CompressedBin, size(CompressedBin)-1).
corrupter(Bin, Pos) when Pos >= 0 ->
- ?line {ShorterBin, _} = split_binary(Bin, Pos),
+ ?line {ShorterBin, Rest} = split_binary(Bin, Pos),
?line catch binary_to_term(ShorterBin), %% emulator shouldn't crash
?line MovedBin = list_to_binary([ShorterBin]),
?line catch binary_to_term(MovedBin), %% emulator shouldn't crash
- ?line corrupter(MovedBin, Pos-1);
+
+ %% Bit faults, shouldn't crash
+ <<Byte,Tail/binary>> = Rest,
+ Fun = fun(M) -> FaultyByte = Byte bxor M,
+ catch binary_to_term(<<ShorterBin/binary,
+ FaultyByte, Tail/binary>>) end,
+ ?line lists:foreach(Fun,[1,2,4,8,16,32,64,128,255]),
+ ?line corrupter(Bin, Pos-1);
corrupter(_Bin, _) ->
ok.
diff --git a/erts/emulator/test/fun_SUITE.erl b/erts/emulator/test/fun_SUITE.erl
index 716ee3707d..a7889dfe90 100644
--- a/erts/emulator/test/fun_SUITE.erl
+++ b/erts/emulator/test/fun_SUITE.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -627,7 +627,13 @@ refc_dist_1() ->
%% Fun is passed in an exit signal. Wait until it is gone.
?line wait_until(fun () -> 4 =/= fun_refc(F2) end),
?line 3 = fun_refc(F2),
- ?line 3 = fun_refc(F),
+ erts_debug:set_internal_state(available_internal_state, true),
+ ?line F_refc = case erts_debug:get_internal_state(force_heap_frags) of
+ false -> 3;
+ true -> 2 % GC after bif already decreased it
+ end,
+ ?line F_refc = fun_refc(F),
+ erts_debug:set_internal_state(available_internal_state, false),
refc_dist_send(Node, F).
refc_dist_send(Node, F) ->
diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl
index fdedf30e78..77f850d0fb 100644
--- a/erts/emulator/test/process_SUITE.erl
+++ b/erts/emulator/test/process_SUITE.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -41,7 +41,8 @@
bump_reductions/1, low_prio/1, binary_owner/1, yield/1, yield2/1,
process_status_exiting/1,
otp_4725/1, bad_register/1, garbage_collect/1, otp_6237/1,
- process_info_messages/1, process_flag_badarg/1,
+ process_info_messages/1, process_flag_badarg/1, process_flag_heap_size/1,
+ spawn_opt_heap_size/1,
processes_large_tab/1, processes_default_tab/1, processes_small_tab/1,
processes_this_tab/1, processes_apply_trap/1,
processes_last_call_trap/1, processes_gc_trap/1,
@@ -63,9 +64,8 @@ all(suite) ->
process_info_lock_reschedule, process_info_lock_reschedule2,
process_status_exiting,
bump_reductions, low_prio, yield, yield2, otp_4725, bad_register,
- garbage_collect, process_info_messages, process_flag_badarg, otp_6237,
- processes_bif,
- otp_7738].
+ garbage_collect, process_info_messages, process_flag_badarg, process_flag_heap_size,
+ spawn_opt_heap_size, otp_6237, processes_bif, otp_7738].
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
Dog=?t:timetrap(?t:minutes(10)),
@@ -388,6 +388,8 @@ t_process_info(Config) when is_list(Config) ->
?line register(my_name, self()),
?line {registered_name, my_name} = process_info(self(), registered_name),
?line {status, running} = process_info(self(), status),
+ ?line {min_heap_size, 233} = process_info(self(), min_heap_size),
+ ?line {min_bin_vheap_size, 46368} = process_info(self(), min_bin_vheap_size),
?line {current_function, {?MODULE, t_process_info, 1}} =
process_info(self(), current_function),
?line Gleader = group_leader(),
@@ -437,6 +439,10 @@ process_info_other_msg(Config) when is_list(Config) ->
empty -> ok
end,
?line {messages,[]} = process_info(Pid, messages),
+
+ ?line {min_heap_size, 233} = process_info(Pid, min_heap_size),
+ ?line {min_bin_vheap_size, 46368} = process_info(Pid, min_bin_vheap_size),
+
?line Pid ! stop,
ok.
@@ -1148,6 +1154,8 @@ process_flag_badarg(Config) when is_list(Config) ->
?line chk_badarg(fun () -> process_flag(trap_exit, gurka) end),
?line chk_badarg(fun () -> process_flag(error_handler, 1) end),
?line chk_badarg(fun () -> process_flag(min_heap_size, gurka) end),
+ ?line chk_badarg(fun () -> process_flag(min_bin_vheap_size, gurka) end),
+ ?line chk_badarg(fun () -> process_flag(min_bin_vheap_size, -1) end),
?line chk_badarg(fun () -> process_flag(priority, 4711) end),
?line chk_badarg(fun () -> process_flag(save_calls, hmmm) end),
?line P= spawn_link(fun () -> receive die -> ok end end),
@@ -1774,6 +1782,34 @@ processes_gc_trap(Config) when is_list(Config) ->
?line exit(Suspendee, bang),
?line ok.
+process_flag_heap_size(doc) ->
+ [];
+process_flag_heap_size(suite) ->
+ [];
+process_flag_heap_size(Config) when is_list(Config) ->
+ HSize = 2584, % must be gc fib number
+ VHSize = 317811, % must be gc fib number
+ ?line OldHmin = erlang:process_flag(min_heap_size, HSize),
+ ?line {min_heap_size, HSize} = erlang:process_info(self(), min_heap_size),
+ ?line OldVHmin = erlang:process_flag(min_bin_vheap_size, VHSize),
+ ?line {min_bin_vheap_size, VHSize} = erlang:process_info(self(), min_bin_vheap_size),
+ ?line HSize = erlang:process_flag(min_heap_size, OldHmin),
+ ?line VHSize = erlang:process_flag(min_bin_vheap_size, OldVHmin),
+ ?line ok.
+
+spawn_opt_heap_size(doc) ->
+ [];
+spawn_opt_heap_size(suite) ->
+ [];
+spawn_opt_heap_size(Config) when is_list(Config) ->
+ HSize = 987, % must be gc fib number
+ VHSize = 46368, % must be gc fib number
+ ?line Pid = spawn_opt(fun () -> receive stop -> ok end end,
+ [{min_heap_size, HSize},{ min_bin_vheap_size, VHSize}]),
+ ?line {min_heap_size, HSize} = process_info(Pid, min_heap_size),
+ ?line {min_bin_vheap_size, VHSize} = process_info(Pid, min_bin_vheap_size),
+ ?line Pid ! stop,
+ ?line ok.
processes_term_proc_list(doc) ->
[];
diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl
index bc12821887..898908c40f 100644
--- a/erts/emulator/test/statistics_SUITE.erl
+++ b/erts/emulator/test/statistics_SUITE.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -25,7 +25,7 @@
init_per_testcase/2,
fin_per_testcase/2,
wall_clock/1, wall_clock_zero_diff/1, wall_clock_update/1,
- runtime/1, runtime_zero_diff/1, runtime_zero_update/1,
+ runtime/1, runtime_zero_diff/1,
runtime_update/1, runtime_diff/1,
run_queue/1, run_queue_one/1,
reductions/1, reductions_big/1, garbage_collection/1, io/1,
@@ -99,8 +99,7 @@ wall_clock_update1(0) ->
%%% Test statistics(runtime).
-runtime(suite) -> [runtime_zero_diff, runtime_zero_update, runtime_update,
- runtime_diff].
+runtime(suite) -> [runtime_zero_diff, runtime_update, runtime_diff].
runtime_zero_diff(doc) ->
"Tests that the difference between the times returned from two consectuitive "
@@ -117,55 +116,32 @@ runtime_zero_diff1(N) when N > 0 ->
runtime_zero_diff1(0) ->
?line test_server:fail("statistics(runtime) never returned zero difference").
-runtime_zero_update(doc) ->
- "Test that the time differences returned by two calls to "
- "statistics(runtime) several seconds apart is zero.";
-runtime_zero_update(Config) when is_list(Config) ->
- case ?t:is_debug() of
- false -> ?line runtime_zero_update1(6);
- true -> {skip,"Unreliable in DEBUG build"}
- end.
-
-runtime_zero_update1(N) when N > 0 ->
- ?line {T1, _} = statistics(runtime),
- ?line receive after 7000 -> ok end,
- ?line case statistics(runtime) of
- {T, Td} when Td =< 80 ->
- test_server:format("ok, Runtime before: {~p, _} after: {~p, ~p}",
- [T1, T, Td]),
- ok;
- {T, R} ->
- test_server:format("nok, Runtime before: {~p, _} after: {~p, ~p}",
- [T1, T, R]),
- runtime_zero_update1(N-1)
- end;
-runtime_zero_update1(0) ->
- ?line test_server:fail("statistics(runtime) never returned zero difference").
-
runtime_update(doc) ->
- "Test that the statistics(runtime) returns a substanstially updated difference "
- "after running a process that takes all CPU power of the Erlang process "
- "for a second.";
+ "Test that the statistics(runtime) returns a substanstially "
+ "updated difference after running a process that takes all CPU "
+ " power of the Erlang process for a second.";
runtime_update(Config) when is_list(Config) ->
case ?t:is_cover() of
false ->
?line process_flag(priority, high),
- ?line test_server:m_out_of_n(1, 10, fun runtime_update/0);
+ do_runtime_update(10);
true ->
{skip,"Cover-compiled"}
end.
-runtime_update() ->
- ?line {T1,_} = statistics(runtime),
+do_runtime_update(0) ->
+ {comment,"Never close enough"};
+do_runtime_update(N) ->
+ ?line {T1,Diff0} = statistics(runtime),
?line spawn_link(fun cpu_heavy/0),
receive after 1000 -> ok end,
?line {T2,Diff} = statistics(runtime),
- ?line Delta = abs(Diff-1000),
- ?line test_server:format("T1 = ~p, T2 = ~p, Diff = ~p, abs(Diff-1000) = ~p",
- [T1,T2,Diff,Delta]),
+ ?line true = is_integer(T1+T2+Diff0+Diff),
+ ?line test_server:format("T1 = ~p, T2 = ~p, Diff = ~p, T2-T1 = ~p",
+ [T1,T2,Diff,T2-T1]),
?line if
- abs(Diff-1000) =:= Delta, Delta =< 100 ->
- ok
+ T2 - T1 =:= Diff, 900 =< Diff, Diff =< 1500 -> ok;
+ true -> do_runtime_update(N-1)
end.
cpu_heavy() ->
@@ -212,17 +188,18 @@ reductions(Config) when is_list(Config) ->
%% 300 * 4 is more than CONTEXT_REDS (1000). Thus, there will be one or
%% more context switches.
- reductions(300, Reductions).
+ Mask = (1 bsl erlang:system_info(wordsize)*8) - 1,
+ reductions(300, Reductions, Mask).
-reductions(N, Previous) when N > 0 ->
+reductions(N, Previous, Mask) when N > 0 ->
?line {Reductions, Diff} = statistics(reductions),
?line build_some_garbage(),
?line if Reductions > 0 -> ok end,
?line if Diff >= 0 -> ok end,
io:format("Previous = ~p, Reductions = ~p, Diff = ~p, DiffShouldBe = ~p",
- [Previous, Reductions, Diff, Reductions-Previous]),
- ?line if Reductions == Previous+Diff -> reductions(N-1, Reductions) end;
-reductions(0, _) ->
+ [Previous, Reductions, Diff, (Reductions-Previous) band Mask]),
+ ?line if Reductions == ((Previous+Diff) band Mask) -> reductions(N-1, Reductions, Mask) end;
+reductions(0, _, _) ->
ok.
build_some_garbage() ->
diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl
index 2c7124839a..e782d2f293 100644
--- a/erts/emulator/test/system_info_SUITE.erl
+++ b/erts/emulator/test/system_info_SUITE.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -35,12 +35,12 @@
%-compile(export_all).
-export([all/1, init_per_testcase/2, fin_per_testcase/2]).
--export([process_count/1, system_version/1, misc_smoke_tests/1]).
+-export([process_count/1, system_version/1, misc_smoke_tests/1, heap_size/1]).
-define(DEFAULT_TIMEOUT, ?t:minutes(2)).
all(doc) -> [];
-all(suite) -> [process_count, system_version, misc_smoke_tests].
+all(suite) -> [process_count, system_version, misc_smoke_tests, heap_size].
init_per_testcase(_Case, Config) when is_list(Config) ->
Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
@@ -135,8 +135,13 @@ misc_smoke_tests(Config) when is_list(Config) ->
?line ok.
-
-
-
-
+heap_size(doc) -> [];
+heap_size(suite) -> [];
+heap_size(Config) when is_list(Config) ->
+ ?line {min_bin_vheap_size, VHmin} = erlang:system_info(min_bin_vheap_size),
+ ?line {min_heap_size, Hmin} = erlang:system_info(min_heap_size),
+ ?line GCinf = erlang:system_info(garbage_collection),
+ ?line VHmin = proplists:get_value(min_bin_vheap_size, GCinf),
+ ?line Hmin = proplists:get_value(min_heap_size, GCinf),
+ ok.
diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl
index 2c60ba6838..e9713fcf0f 100644
--- a/erts/emulator/test/trace_SUITE.erl
+++ b/erts/emulator/test/trace_SUITE.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -498,19 +498,23 @@ system_monitor_long_gc_1(doc) ->
["Tests erlang:system_monitor(Pid, [{long_gc,Time}])"];
system_monitor_long_gc_1(Config) when is_list(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
- try
- %% Add ?LONG_GC_SLEEP ms to all gc
- ?line erts_debug:set_internal_state(test_long_gc_sleep,
- ?LONG_GC_SLEEP),
- ?line LoadFun =
- fun () ->
- garbage_collect(),
- self()
- end,
- ?line long_gc(LoadFun, false)
+ try
+ case erts_debug:get_internal_state(force_heap_frags) of
+ true ->
+ {skip,"emulator with FORCE_HEAP_FRAGS defined"};
+ false ->
+ %% Add ?LONG_GC_SLEEP ms to all gc
+ ?line erts_debug:set_internal_state(test_long_gc_sleep,
+ ?LONG_GC_SLEEP),
+ ?line LoadFun = fun () ->
+ garbage_collect(),
+ self()
+ end,
+ ?line long_gc(LoadFun, false)
+ end
after
erts_debug:set_internal_state(test_long_gc_sleep, 0),
- erts_debug:set_internal_state(available_internal_state, false)
+ erts_debug:set_internal_state(available_internal_state, false)
end.
system_monitor_long_gc_2(suite) ->
@@ -520,24 +524,29 @@ system_monitor_long_gc_2(doc) ->
system_monitor_long_gc_2(Config) when is_list(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
try
- %% Add ?LONG_GC_SLEEP ms to all gc
- ?line erts_debug:set_internal_state(test_long_gc_sleep,
- ?LONG_GC_SLEEP),
- ?line Parent = self(),
- ?line LoadFun =
- fun () ->
- Ref = make_ref(),
- Pid =
- spawn_link(
- fun () ->
- garbage_collect(),
- Parent ! {Ref, self()}
- end),
- receive {Ref, Pid} -> Pid end
- end,
- ?line long_gc(LoadFun, true),
- ?line long_gc(LoadFun, true),
- ?line long_gc(LoadFun, true)
+ case erts_debug:get_internal_state(force_heap_frags) of
+ true ->
+ {skip,"emulator with FORCE_HEAP_FRAGS defined"};
+ false ->
+ %% Add ?LONG_GC_SLEEP ms to all gc
+ ?line erts_debug:set_internal_state(test_long_gc_sleep,
+ ?LONG_GC_SLEEP),
+ ?line Parent = self(),
+ ?line LoadFun =
+ fun () ->
+ Ref = make_ref(),
+ Pid =
+ spawn_link(
+ fun () ->
+ garbage_collect(),
+ Parent ! {Ref, self()}
+ end),
+ receive {Ref, Pid} -> Pid end
+ end,
+ ?line long_gc(LoadFun, true),
+ ?line long_gc(LoadFun, true),
+ ?line long_gc(LoadFun, true)
+ end
after
erts_debug:set_internal_state(test_long_gc_sleep, 0),
erts_debug:set_internal_state(available_internal_state, false)
diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h
index b120b44579..65fcf9bacb 100644
--- a/erts/epmd/src/epmd_int.h
+++ b/erts/epmd/src/epmd_int.h
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1998-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
/*
@@ -294,6 +294,7 @@ struct enode {
char protocol; /* 0 = tcp/ipv4 */
unsigned short highvsn; /* 0 = OTP-R3 erts-4.6.x, 1 = OTP-R4 erts-4.7.x*/
unsigned short lowvsn;
+ int extralen;
char extra[MAXSYMLEN+1];
};
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index b71e27cffd..a033fab244 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -1,20 +1,20 @@
/* -*- c-indent-level: 2; c-continued-statement-offset: 2 -*- */
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1998-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -99,7 +99,7 @@ static int conn_close_fd(EpmdVars*,int);
static void node_init(EpmdVars*);
static Node *node_reg(EpmdVars*,char*,int,int);
-static Node *node_reg2(EpmdVars*,char*, int, int, unsigned char, unsigned char, int, int, char*);
+static Node *node_reg2(EpmdVars*,char*, int, int, unsigned char, unsigned char, int, int, int, char*);
static int node_unreg(EpmdVars*,char*);
static int node_unreg_sock(EpmdVars*,int);
@@ -558,11 +558,11 @@ static void do_request(g, fd, s, buf, bsize)
}
name = &buf[11];
name[namelen]='\000';
- extra = &buf[11+namelen+1];
+ extra = &buf[11+namelen+2];
extra[extralen]='\000';
wbuf[0] = EPMD_ALIVE2_RESP;
if ((node = node_reg2(g, name, fd, eport, nodetype, protocol,
- highvsn, lowvsn, extra)) == NULL) {
+ highvsn, lowvsn, extralen, extra)) == NULL) {
wbuf[1] = 1; /* error */
put_int16(99, wbuf+2);
} else {
@@ -622,10 +622,10 @@ static void do_request(g, fd, s, buf, bsize)
offset = 12;
strcpy(wbuf + offset,node->symname);
offset += strlen(node->symname);
- put_int16(strlen(node->extra),wbuf + offset);
+ put_int16(node->extralen,wbuf + offset);
offset += 2;
- strcpy(wbuf + offset,node->extra);
- offset += (strlen(node->extra)-1);
+ memcpy(wbuf + offset,node->extra,node->extralen);
+ offset += node->extralen;
if (reply(g, fd, wbuf, offset) != offset)
{
dbg_tty_printf(g,1,"** failed to send PORT2_RESP (ok) for \"%s\"",name);
@@ -994,7 +994,7 @@ static int node_unreg_sock(EpmdVars *g,int fd)
static Node *node_reg(EpmdVars *g,char *name,int fd, int port)
{
- return node_reg2(g, name, fd, port, 0, 0, 0, 0, NULL);
+ return node_reg2(g, name, fd, port, 0, 0, 0, 0, 0, NULL);
}
static Node *node_reg2(EpmdVars *g,
@@ -1005,6 +1005,7 @@ static Node *node_reg2(EpmdVars *g,
unsigned char protocol,
int highvsn,
int lowvsn,
+ int extralen,
char* extra)
{
Node *prev; /* Point to previous node or NULL */
@@ -1103,7 +1104,8 @@ static Node *node_reg2(EpmdVars *g,
node->protocol = protocol;
node->highvsn = highvsn;
node->lowvsn = lowvsn;
- strcpy(node->extra,extra);
+ node->extralen = extralen;
+ memcpy(node->extra,extra,extralen);
strcpy(node->symname,name);
FD_SET(fd,&g->orig_read_mask);
diff --git a/erts/etc/common/erlc.c b/erts/etc/common/erlc.c
index c958fed741..09aca19e6c 100644
--- a/erts/etc/common/erlc.c
+++ b/erts/etc/common/erlc.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1997-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
/*
@@ -310,6 +310,8 @@ main(int argc, char** argv)
case 'W': /* Enable warnings. */
if (strcmp(argv[1]+2, "all") == 0) {
PUSH2("@warn", "999");
+ } else if (strcmp(argv[1]+2, "error") == 0) {
+ PUSH2("@option", "warnings_as_errors");
} else if (isdigit((int)argv[1][2])) {
PUSH2("@warn", argv[1]+2);
} else {
@@ -566,6 +568,7 @@ usage(void)
{"-pz path", "add path to the end of Erlang's code path"},
{"-smp", "compile using SMP emulator"},
{"-v", "verbose compiler output"},
+ {"-Werror", "make all warnings into errors"},
{"-W0", "disable warnings"},
{"-Wnumber", "set warning level to number"},
{"-Wall", "enable all warnings"},
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index 4325418e7c..0ad26aeea7 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -123,6 +123,14 @@ static char *pluss_val_switches[] = {
"ss",
NULL
};
+/* +h arguments with values */
+static char *plush_val_switches[] = {
+ "ms",
+ "mbs",
+ "",
+ NULL
+};
+
/*
* Define sleep(seconds) in terms of Sleep() on Windows.
@@ -783,7 +791,6 @@ int main(int argc, char **argv)
case 'a':
case 'A':
case 'b':
- case 'h':
case 'i':
case 'P':
case 'S':
@@ -850,6 +857,20 @@ int main(int argc, char **argv)
goto the_default;
break;
}
+ case 'h':
+ if (!is_one_of_strings(&argv[i][2], plush_val_switches)) {
+ goto the_default;
+ } else {
+ if (i+1 >= argc
+ || argv[i+1][0] == '-'
+ || argv[i+1][0] == '+')
+ usage(argv[i]);
+ argv[i][0] = '-';
+ add_Eargs(argv[i]);
+ add_Eargs(argv[i+1]);
+ i++;
+ }
+ break;
case 's':
if (!is_one_of_strings(&argv[i][2],
pluss_val_switches))
@@ -1048,7 +1069,7 @@ usage_aux(void)
#endif
"[-make] [-man [manopts] MANPAGE] [-x] [-emu_args] "
"[-args_file FILENAME] "
- "[+A THREADS] [+a SIZE] [+B[c|d|i]] [+c] [+h HEAP_SIZE] [+K BOOLEAN] "
+ "[+A THREADS] [+a SIZE] [+B[c|d|i]] [+c] [+h HEAP_SIZE_OPTION] [+K BOOLEAN] "
"[+l] [+M<SUBSWITCH> <ARGUMENT>] [+P MAX_PROCS] [+R COMPAT_REL] "
"[+r] [+s SCHEDULER_OPTION] [+S NO_SCHEDULERS:NO_SCHEDULERS_ONLINE] [+T LEVEL] [+V] [+v] [+W<i|w>] "
"[args ...]\n");
diff --git a/erts/lib_src/Makefile.in b/erts/lib_src/Makefile.in
index ce5c846677..1d2cc7cb0c 100644
--- a/erts/lib_src/Makefile.in
+++ b/erts/lib_src/Makefile.in
@@ -1,19 +1,19 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2004-2009. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2004-2010. All Rights Reserved.
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
-#
+#
# %CopyrightEnd%
#
@@ -24,6 +24,7 @@ OMIT_OMIT_FP=no
CC=@CC@
+GCC=@GCC@
LD=@LD@
AR=@AR@
RANLIB=@RANLIB@
@@ -114,7 +115,7 @@ endif
CREATE_DIRS=
-ifeq ($(CC)-$(OMIT_FP), gcc-true)
+ifeq ($(GCC)-$(OMIT_FP),yes-true)
CFLAGS += -fomit-frame-pointer
endif
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index a031c90188..d7134967bf 100644
--- a/erts/preloaded/ebin/erl_prim_loader.beam
+++ b/erts/preloaded/ebin/erl_prim_loader.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index 39452f53d6..f490fe7c3d 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam
index be1f71e6c5..39118a0109 100644
--- a/erts/preloaded/ebin/init.beam
+++ b/erts/preloaded/ebin/init.beam
Binary files differ
diff --git a/erts/preloaded/ebin/otp_ring0.beam b/erts/preloaded/ebin/otp_ring0.beam
index af44a8c9b9..4680d645cb 100644
--- a/erts/preloaded/ebin/otp_ring0.beam
+++ b/erts/preloaded/ebin/otp_ring0.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index 9391aa45cd..2cacb6808c 100644
--- a/erts/preloaded/ebin/prim_file.beam
+++ b/erts/preloaded/ebin/prim_file.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam
index b7be06e6bc..aa9b255ebb 100644
--- a/erts/preloaded/ebin/prim_inet.beam
+++ b/erts/preloaded/ebin/prim_inet.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam
index 6e1230d649..0e7adad9e8 100644
--- a/erts/preloaded/ebin/prim_zip.beam
+++ b/erts/preloaded/ebin/prim_zip.beam
Binary files differ
diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam
index 4d9996cc74..93b05172d8 100644
--- a/erts/preloaded/ebin/zlib.beam
+++ b/erts/preloaded/ebin/zlib.beam
Binary files differ
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 6f92b319b7..552121d485 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -51,6 +51,7 @@
-export([await_proc_exit/3]).
-deprecated([hash/2]).
+-deprecated([concat_binary/1]).
-compile(nowarn_bif_clash).
diff --git a/erts/test/erlc_SUITE.erl b/erts/test/erlc_SUITE.erl
index 1d944811aa..6b4484b31e 100644
--- a/erts/test/erlc_SUITE.erl
+++ b/erts/test/erlc_SUITE.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
-module(erlc_SUITE).
@@ -56,6 +56,13 @@ compile_erl(Config) when is_list(Config) ->
?line run(Config, Cmd, FileName, "-W0", ["_OK_"]),
+ %% Try treating warnings as errors.
+
+ ?line run(Config, Cmd, FileName, "-Werror",
+ ["compile: warnings being treated as errors\$",
+ "Warning: function foo/0 is unused\$",
+ "_ERROR_"]),
+
%% Check a bad file.
?line BadFile = filename:join(SrcDir, "erl_test_bad.erl"),