diff options
Diffstat (limited to 'erts')
69 files changed, 2057 insertions, 1070 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..73d15c33d7 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> @@ -410,7 +410,7 @@ <tag><c><![CDATA[-setcookie Cookie]]></c></tag> <item> <p>Sets the magic cookie of the node to <c><![CDATA[Cookie]]></c>, see - <seealso marker="erlang#erlang:set_cookie/2">erlang:set_cookie/2</seealso>.</p> + <seealso marker="erlang#set_cookie/2">erlang:set_cookie/2</seealso>.</p> </item> <tag><c><![CDATA[-shutdown_time Time]]></c></tag> <item> @@ -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 @@ -793,6 +798,11 @@ Valid range is 4-8192 kilowords. The default stack size is OS dependent.</p> </item> + <tag><c><![CDATA[+t size]]></c></tag> + <item> + <marker id="+t"></marker> + <p>Set the maximum number of atoms the VM can handle. Default is 1048576.</p> + </item> <tag><c><![CDATA[+T Level]]></c></tag> <item> <marker id="+T"></marker> diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml index 0b11f4bbcb..5d7a11b70a 100644 --- a/erts/doc/src/erl_driver.xml +++ b/erts/doc/src/erl_driver.xml @@ -4,7 +4,7 @@ <cref> <header> <copyright> - <year>2001</year><year>2009</year> + <year>2001</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_driver</title> @@ -1292,7 +1292,7 @@ typedef struct ErlIOVec { has been set in the <seealso marker="driver_entry">driver_entry</seealso>, data can be forced into the driver via - <seealso marker="erlang#erlang:port_command/3">port_command(Port, Data, [force])</seealso> + <seealso marker="erlang#port_command/3">port_command(Port, Data, [force])</seealso> even though the driver has signaled that it is busy. </p> </desc> diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index 2033ba8a66..2902d70976 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -148,7 +148,7 @@ ok that the library needs in able to keep a state between NIF calls. <c>enif_get_data()</c> will return this pointer.</p> <p><c>load_info</c> is the second argument to <seealso - marker="erlang#erlang:load_nif-2">erlang:load_nif/2</seealso>.</p> + marker="erlang#load_nif-2">erlang:load_nif/2</seealso>.</p> <p>The library will fail to load if <c>load</c> returns anything other than 0. <c>load</c> can be NULL in case no initialization is needed.</p> @@ -397,7 +397,7 @@ typedef struct { </funcs> <section> <title>SEE ALSO</title> - <p><seealso marker="erlang#erlang:load_nif-2">load_nif(3)</seealso></p> + <p><seealso marker="erlang#load_nif-2">load_nif(3)</seealso></p> </section> </cref> diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 871fc0fd63..207aabca35 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> @@ -410,19 +452,19 @@ iolist() = [char() | binary() | iolist()] <desc> <p>Cancels a timer, where <c>TimerRef</c> was returned by either - <seealso marker="#erlang:send_after/3">erlang:send_after/3</seealso> + <seealso marker="#send_after/3">erlang:send_after/3</seealso> or - <seealso marker="#erlang:start_timer/3">erlang:start_timer/3</seealso>. + <seealso marker="#start_timer/3">erlang:start_timer/3</seealso>. If the timer is there to be removed, the function returns the time in milliseconds left until the timer would have expired, otherwise <c>false</c> (which means that <c>TimerRef</c> was never a timer, that it has already been cancelled, or that it has already delivered its message).</p> <p>See also - <seealso marker="#erlang:send_after/3">erlang:send_after/3</seealso>, - <seealso marker="#erlang:start_timer/3">erlang:start_timer/3</seealso>, + <seealso marker="#send_after/3">erlang:send_after/3</seealso>, + <seealso marker="#start_timer/3">erlang:start_timer/3</seealso>, and - <seealso marker="#erlang:read_timer/1">erlang:read_timer/1</seealso>.</p> + <seealso marker="#read_timer/1">erlang:read_timer/1</seealso>.</p> <p>Note: Cancelling a timer does not guarantee that the message has not already been delivered to the message queue.</p> </desc> @@ -673,7 +715,7 @@ false</pre> <desc> <p>If <c>MonitorRef</c> is a reference which the calling process obtained by calling - <seealso marker="#erlang:monitor/2">erlang:monitor/2</seealso>, + <seealso marker="#monitor/2">erlang:monitor/2</seealso>, this monitoring is turned off. If the monitoring is already turned off, nothing happens.</p> <p>Once <c>erlang:demonitor(MonitorRef)</c> has returned it is @@ -684,7 +726,7 @@ false</pre> the call, though. Therefore, in most cases, it is advisable to remove such a <c>'DOWN'</c> message from the message queue after monitoring has been stopped. - <seealso marker="#erlang:demonitor/2">erlang:demonitor(MonitorRef, [flush])</seealso> can be used instead of + <seealso marker="#demonitor/2">erlang:demonitor(MonitorRef, [flush])</seealso> can be used instead of <c>erlang:demonitor(MonitorRef)</c> if this cleanup is wanted.</p> <note> <p>Prior to OTP release R11B (erts version 5.5) <c>erlang:demonitor/1</c> @@ -718,7 +760,7 @@ false</pre> of <c>OptionList</c>. </p> <p><c>erlang:demonitor(MonitorRef, [])</c> is equivalent to - <seealso marker="#erlang:demonitor/1">erlang:demonitor(MonitorRef)</seealso>.</p> + <seealso marker="#demonitor/1">erlang:demonitor(MonitorRef)</seealso>.</p> <p>Currently the following <c>Option</c>s are valid:</p> <taglist> <tag><c>flush</c></tag> @@ -768,7 +810,7 @@ false</pre> </note> <p>Failure: <c>badarg</c> if <c>OptionList</c> is not a list, or if <c>Option</c> is not a valid option, or the same failure as for - <seealso marker="#erlang:demonitor/1">erlang:demonitor/1</seealso></p> + <seealso marker="#demonitor/1">erlang:demonitor/1</seealso></p> </desc> </func> <func> @@ -1087,7 +1129,7 @@ b</pre> <c>uniq</c>, and <c>pid</c>. For an external fun, the value of any of these items is always the atom <c>undefined</c>.</p> <p>See - <seealso marker="#erlang:fun_info/1">erlang:fun_info/1</seealso>.</p> + <seealso marker="#fun_info/1">erlang:fun_info/1</seealso>.</p> </desc> </func> <func> @@ -1233,8 +1275,8 @@ b</pre> returns, for example:</p> <p><c>{'EXIT',{badarg,Stacktrace}} = catch abs(x)</c></p> <p>See also - <seealso marker="#erlang:error/1">erlang:error/1</seealso> and - <seealso marker="#erlang:error/2">erlang:error/2</seealso>.</p> + <seealso marker="#error/1">erlang:error/1</seealso> and + <seealso marker="#error/2">erlang:error/2</seealso>.</p> </desc> </func> <func> @@ -2345,7 +2387,7 @@ os_prompt%</pre> <item> If <c>Type</c> is not one of the memory types listed in the documentation of - <seealso marker="#erlang:memory/0">erlang:memory/0</seealso>. + <seealso marker="#memory/0">erlang:memory/0</seealso>. </item> <tag><c>badarg</c></tag> <item> @@ -2359,7 +2401,7 @@ os_prompt%</pre> </item> </taglist> <p>See also - <seealso marker="#erlang:memory/0">erlang:memory/0</seealso>.</p> + <seealso marker="#memory/0">erlang:memory/0</seealso>.</p> </desc> </func> <func> @@ -2468,7 +2510,7 @@ os_prompt%</pre> </note> <p>The monitoring is turned off either when the <c>'DOWN'</c> message is sent, or when - <seealso marker="#erlang:demonitor/1">erlang:demonitor/1</seealso> + <seealso marker="#demonitor/1">erlang:demonitor/1</seealso> is called.</p> <p>If an attempt is made to monitor a process on an older node (where remote process monitoring is not implemented or one @@ -3337,7 +3379,7 @@ os_prompt%</pre> registered name, [] is returned.</p> <p>For valid values of <c>Item</c>, and corresponding values of <c>Info</c>, see - <seealso marker="#erlang:port_info/1">erlang:port_info/1</seealso>.</p> + <seealso marker="#port_info/1">erlang:port_info/1</seealso>.</p> <p>Failure: <c>badarg</c> if <c>Port</c> is not a local port.</p> </desc> </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 @@ -3813,9 +3868,9 @@ os_prompt%</pre> ActiveSuspendCount, OutstandingSuspendCount}</c> tuples. <c>Suspendee</c> is the pid of a process that have been or is to be suspended by the process identified by <c>Pid</c> via the - <seealso marker="#erlang:suspend_process/2">erlang:suspend_process/2</seealso> + <seealso marker="#suspend_process/2">erlang:suspend_process/2</seealso> BIF, or the - <seealso marker="#erlang:suspend_process/1">erlang:suspend_process/1</seealso> + <seealso marker="#suspend_process/1">erlang:suspend_process/1</seealso> BIF. <c>ActiveSuspendCount</c> is the number of times the <c>Suspendee</c> has been suspended by <c>Pid</c>. <c>OutstandingSuspendCount</c> is the number of not yet @@ -3966,19 +4021,19 @@ os_prompt%</pre> </type> <desc> <p><c>TimerRef</c> is a timer reference returned by - <seealso marker="#erlang:send_after/3">erlang:send_after/3</seealso> + <seealso marker="#send_after/3">erlang:send_after/3</seealso> or - <seealso marker="#erlang:start_timer/3">erlang:start_timer/3</seealso>. + <seealso marker="#start_timer/3">erlang:start_timer/3</seealso>. If the timer is active, the function returns the time in milliseconds left until the timer will expire, otherwise <c>false</c> (which means that <c>TimerRef</c> was never a timer, that it has been cancelled, or that it has already delivered its message).</p> <p>See also - <seealso marker="#erlang:send_after/3">erlang:send_after/3</seealso>, - <seealso marker="#erlang:start_timer/3">erlang:start_timer/3</seealso>, + <seealso marker="#send_after/3">erlang:send_after/3</seealso>, + <seealso marker="#start_timer/3">erlang:start_timer/3</seealso>, and - <seealso marker="#erlang:cancel_timer/1">erlang:cancel_timer/1</seealso>.</p> + <seealso marker="#cancel_timer/1">erlang:cancel_timer/1</seealso>.</p> </desc> </func> <func> @@ -4043,9 +4098,9 @@ true</pre> <p>Decreases the suspend count on the process identified by <c>Suspendee</c>. <c>Suspendee</c> should previously have been suspended via - <seealso marker="#erlang:suspend_process/2">erlang:suspend_process/2</seealso>, + <seealso marker="#suspend_process/2">erlang:suspend_process/2</seealso>, or - <seealso marker="#erlang:suspend_process/1">erlang:suspend_process/1</seealso> + <seealso marker="#suspend_process/1">erlang:suspend_process/1</seealso> by the process calling <c>erlang:resume_process(Suspendee)</c>. When the suspend count on <c>Suspendee</c> reach zero, <c>Suspendee</c> will be resumed, i.e., the state of the <c>Suspendee</c> is changed @@ -4131,9 +4186,9 @@ true</pre> <p>Sends a message and returns <c>ok</c>, or does not send the message but returns something else (see below). Otherwise the same as - <seealso marker="#erlang:send/2">erlang:send/2</seealso>. See + <seealso marker="#send/2">erlang:send/2</seealso>. See also - <seealso marker="#erlang:send_nosuspend/2">erlang:send_nosuspend/2,3</seealso>. + <seealso marker="#send_nosuspend/2">erlang:send_nosuspend/2,3</seealso>. for more detailed explanation and warnings.</p> <p>The possible options are:</p> <taglist> @@ -4179,10 +4234,10 @@ true</pre> erts version 5.4.11. Note that timers will not be automatically canceled when <c>Dest</c> is an atom.</p> <p>See also - <seealso marker="#erlang:start_timer/3">erlang:start_timer/3</seealso>, - <seealso marker="#erlang:cancel_timer/1">erlang:cancel_timer/1</seealso>, + <seealso marker="#start_timer/3">erlang:start_timer/3</seealso>, + <seealso marker="#cancel_timer/1">erlang:cancel_timer/1</seealso>, and - <seealso marker="#erlang:read_timer/1">erlang:read_timer/1</seealso>.</p> + <seealso marker="#read_timer/1">erlang:read_timer/1</seealso>.</p> <p>Failure: <c>badarg</c> if the arguments does not satisfy the requirements specified above.</p> </desc> @@ -4198,7 +4253,7 @@ true</pre> </type> <desc> <p>The same as - <seealso marker="#erlang:send/3">erlang:send(Dest, Msg, [nosuspend])</seealso>, but returns <c>true</c> if + <seealso marker="#send/3">erlang:send(Dest, Msg, [nosuspend])</seealso>, but returns <c>true</c> if the message was sent and <c>false</c> if the message was not sent because the sender would have had to be suspended.</p> <p>This function is intended for send operations towards an @@ -4250,10 +4305,10 @@ true</pre> </type> <desc> <p>The same as - <seealso marker="#erlang:send/3">erlang:send(Dest, Msg, [nosuspend | Options])</seealso>, + <seealso marker="#send/3">erlang:send(Dest, Msg, [nosuspend | Options])</seealso>, but with boolean return value.</p> <p>This function behaves like - <seealso marker="#erlang:send_nosuspend/2">erlang:send_nosuspend/2)</seealso>, + <seealso marker="#send_nosuspend/2">erlang:send_nosuspend/2)</seealso>, but takes a third parameter, a list of options. The only currently implemented option is <c>noconnect</c>. The option <c>noconnect</c> makes the function return <c>false</c> if @@ -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> Level = low | normal | high</v> <v> Number = int()</v> <v> Size = int()</v> + <v> 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> Level = low | normal | high</v> <v> Number = int()</v> <v> Size = int()</v> + <v> 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> Level = low | normal | high</v> <v> Number = int()</v> <v> Size = int()</v> + <v> VSize = int()</v> </type> <desc> <p>Works exactly like @@ -4552,7 +4610,7 @@ true</pre> <tag><c>monitor</c></tag> <item> <p>Monitor the new process (just like - <seealso marker="#erlang:monitor/2">erlang:monitor/2</seealso> does).</p> + <seealso marker="#monitor/2">erlang:monitor/2</seealso> does).</p> </item> <tag><c>{priority, Level}</c></tag> <item> @@ -4595,7 +4653,7 @@ true</pre> and no virtual memory, one might want to preserve memory by setting <c>Number</c> to zero. (The value may be set globally, see - <seealso marker="#erlang:system_flag/2">erlang:system_flag/2</seealso>.)</p> + <seealso marker="#system_flag/2">erlang:system_flag/2</seealso>.)</p> </item> <tag><c>{min_heap_size, Size}</c></tag> <item> @@ -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> Level = low | normal | high</v> <v> Number = int()</v> <v> Size = int()</v> + <v> VSize = int()</v> </type> <desc> <p>Returns the pid of a new process started by the application @@ -4688,10 +4764,10 @@ true</pre> erts version 5.4.11. Note that timers will not be automatically canceled when <c>Dest</c> is an atom.</p> <p>See also - <seealso marker="#erlang:send_after/3">erlang:send_after/3</seealso>, - <seealso marker="#erlang:cancel_timer/1">erlang:cancel_timer/1</seealso>, + <seealso marker="#send_after/3">erlang:send_after/3</seealso>, + <seealso marker="#cancel_timer/1">erlang:cancel_timer/1</seealso>, and - <seealso marker="#erlang:read_timer/1">erlang:read_timer/1</seealso>.</p> + <seealso marker="#read_timer/1">erlang:read_timer/1</seealso>.</p> <p>Failure: <c>badarg</c> if the arguments does not satisfy the requirements specified above.</p> </desc> @@ -4796,7 +4872,7 @@ true</pre> process will not leave the suspended state until its suspend count reach zero. The suspend count of <c>Suspendee</c> is decreased when - <seealso marker="#erlang:resume_process/1">erlang:resume_process(Suspendee)</seealso> + <seealso marker="#resume_process/1">erlang:resume_process(Suspendee)</seealso> is called by the same process that called <c>erlang:suspend_process(Suspendee)</c>. All increased suspend counts on other processes acquired by a process will automatically be @@ -4885,7 +4961,7 @@ true</pre> <desc> <p>Suspends the process identified by <c>Suspendee</c>. The same as calling - <seealso marker="#erlang:suspend_process/2">erlang:suspend_process(Suspendee, [])</seealso>. For more information see the documentation of <seealso marker="#erlang:suspend_process/2">erlang:suspend_process/2</seealso>. + <seealso marker="#suspend_process/2">erlang:suspend_process(Suspendee, [])</seealso>. For more information see the documentation of <seealso marker="#suspend_process/2">erlang:suspend_process/2</seealso>. </p> <warning> <p>This BIF is intended for debugging only.</p> @@ -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> @@ -5185,7 +5272,7 @@ true</pre> Some values are part of other values, and some memory areas are not part of the result. If you are interested in the total amount of memory allocated by the emulator - see <seealso marker="#erlang:memory/0">erlang:memory/0,1</seealso>.</p> + see <seealso marker="#memory/0">erlang:memory/0,1</seealso>.</p> </item> <tag><c>allocator</c></tag> <item> @@ -5500,7 +5587,7 @@ true</pre> <c>spawn</c> or <c>spawn_link</c> will use these garbage collection settings. The default settings can be changed by use of - <seealso marker="#erlang:system_flag/2">system_flag/2</seealso>. + <seealso marker="#system_flag/2">system_flag/2</seealso>. <seealso marker="#spawn_opt/4">spawn_opt/4</seealso> can spawn a process that does not use the default settings.</p> @@ -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 @@ -5803,7 +5900,7 @@ true</pre> </type> <desc> <p>Returns the current system monitoring settings set by - <seealso marker="#erlang:system_monitor/2">erlang:system_monitor/2</seealso> + <seealso marker="#system_monitor/2">erlang:system_monitor/2</seealso> as <c>{MonitorPid, Options}</c>, or <c>undefined</c> if there are no settings. The order of the options may be different from the one that was set.</p> @@ -5821,9 +5918,9 @@ true</pre> system performance monitoring settings are cleared.</p> <p>Calling the function with <c>{MonitorPid, Options}</c> as argument, is the same as calling - <seealso marker="#erlang:system_monitor/2">erlang:system_monitor(MonitorPid, Options)</seealso>.</p> + <seealso marker="#system_monitor/2">erlang:system_monitor(MonitorPid, Options)</seealso>.</p> <p>Returns the previous system monitor settings just like - <seealso marker="#erlang:system_monitor/0">erlang:system_monitor/0</seealso>.</p> + <seealso marker="#system_monitor/0">erlang:system_monitor/0</seealso>.</p> </desc> </func> @@ -5859,7 +5956,7 @@ true</pre> explained in the documentation of the <seealso marker="#gc_start">gc_start</seealso> trace message (see - <seealso marker="#erlang:trace/3">erlang:trace/3</seealso>). + <seealso marker="#trace/3">erlang:trace/3</seealso>). New tuples may be added, and the order of the tuples in the <c>Info</c> list may be changed at any time without prior notice. @@ -5901,7 +5998,7 @@ true</pre> </item> </taglist> <p>Returns the previous system monitor settings just like - <seealso marker="#erlang:system_monitor/0">erlang:system_monitor/0</seealso>.</p> + <seealso marker="#system_monitor/0">erlang:system_monitor/0</seealso>.</p> <note> <p>If a monitoring process gets so large that it itself starts to cause system monitor messages when garbage @@ -5925,7 +6022,7 @@ true</pre> </type> <desc> <p>Returns the current system profiling settings set by - <seealso marker="#erlang:system_profile/2">erlang:system_profile/2</seealso> + <seealso marker="#system_profile/2">erlang:system_profile/2</seealso> as <c>{ProfilerPid, Options}</c>, or <c>undefined</c> if there are no settings. The order of the options may be different from the one that was set.</p> @@ -6153,7 +6250,7 @@ true</pre> <item> <p>Trace certain function calls. Specify which function calls to trace by calling - <seealso marker="#erlang:trace_pattern/3">erlang:trace_pattern/3</seealso>.</p> + <seealso marker="#trace_pattern/3">erlang:trace_pattern/3</seealso>.</p> <p>Message tags: <c>call</c>, <c>return_from</c>.</p> </item> <tag><c>silent</c></tag> @@ -6182,7 +6279,7 @@ true</pre> Trace the actual return from a traced function back to its caller. Only works for functions traced with the <c>local</c> option to - <seealso marker="#erlang:trace_pattern/3">erlang:trace_pattern/3</seealso>.</p> + <seealso marker="#trace_pattern/3">erlang:trace_pattern/3</seealso>.</p> <p>The semantics is that a trace message is sent when a call traced function actually returns, that is, when a chain of tail recursive calls is ended. There will be @@ -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> @@ -6557,7 +6667,7 @@ true</pre> <c>true</c> for the pseudo function <c>on_load</c> if call count tracing is active. Return <c>false</c> otherwise. See also - <seealso marker="#erlang:trace_pattern/3">erlang:trace_pattern/3</seealso>.</p> + <seealso marker="#trace_pattern/3">erlang:trace_pattern/3</seealso>.</p> </item> <tag><c>all</c></tag> <item> @@ -6580,7 +6690,7 @@ true</pre> <fsummary>Set trace patterns for global call tracing</fsummary> <desc> <p>The same as - <seealso marker="#erlang:trace_pattern/3">erlang:trace_pattern(MFA, MatchSpec, [])</seealso>, + <seealso marker="#trace_pattern/3">erlang:trace_pattern(MFA, MatchSpec, [])</seealso>, retained for backward compatibility.</p> </desc> </func> @@ -6593,7 +6703,7 @@ true</pre> <desc> <p>This BIF is used to enable or disable call tracing for exported functions. It must be combined with - <seealso marker="#erlang:trace/3">erlang:trace/3</seealso> + <seealso marker="#trace/3">erlang:trace/3</seealso> to set the <c>call</c> trace flag for one or more processes.</p> <p>Conceptually, call tracing works like this: Inside the Erlang virtual machine there is a set of processes to be @@ -6603,7 +6713,7 @@ true</pre> in the traced function set, the trace action will be taken. Otherwise, nothing will happen.</p> <p>Use - <seealso marker="#erlang:trace/3">erlang:trace/3</seealso> to + <seealso marker="#trace/3">erlang:trace/3</seealso> to add or remove one or more processes to the set of traced processes. Use <c>erlang:trace_pattern/2</c> to add or remove exported functions to the set of traced functions.</p> @@ -6720,7 +6830,7 @@ true</pre> counters can be restarted from zero with <c>MatchSpec == restart</c>.</p> <p>The counter value can be read with - <seealso marker="#erlang:trace_info/2">erlang:trace_info/2</seealso>.</p> + <seealso marker="#trace_info/2">erlang:trace_info/2</seealso>.</p> </item> </taglist> <p>The <c>global</c> and <c>local</c> options are mutually @@ -6740,7 +6850,7 @@ true</pre> specification list. If a function has a match specification, you can replace it with a completely new one. If you need to change an existing match specification, use the - <seealso marker="#erlang:trace_info/2">erlang:trace_info/2</seealso> + <seealso marker="#trace_info/2">erlang:trace_info/2</seealso> BIF to retrieve the existing match specification.</p> <p>Returns the number of exported functions that matched the <c>MFA</c> argument. This will be zero if none matched at 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/doc/src/notes.xml b/erts/doc/src/notes.xml index 2252358e0d..5fe414841e 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2004</year><year>2009</year> + <year>2004</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>ERTS Release Notes</title> @@ -242,7 +242,7 @@ <item> <p> The <seealso - marker="erlang#erlang:port_command/3">erlang:port_command/3</seealso> + marker="erlang#port_command/3">erlang:port_command/3</seealso> BIF has been added. <c>erlang:port_command/3</c> is currently not auto imported, but it is planned to be auto imported in OTP R14. For more information see the 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.c b/erts/emulator/beam/atom.c index dfc3cde6a7..e2a79d6e4f 100644 --- a/erts/emulator/beam/atom.c +++ b/erts/emulator/beam/atom.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% */ @@ -322,7 +322,7 @@ init_atom_table(void) text_list = NULL; erts_index_init(ERTS_ALC_T_ATOM_TABLE, &erts_atom_table, - "atom_tab", ATOM_SIZE, ATOM_LIMIT, f); + "atom_tab", ATOM_SIZE, erts_atom_table_size, f); more_atom_space(); /* Ordinary atoms */ diff --git a/erts/emulator/beam/atom.h b/erts/emulator/beam/atom.h index e7e0dc440d..cb245a87b1 100644 --- a/erts/emulator/beam/atom.h +++ b/erts/emulator/beam/atom.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% */ @@ -28,6 +28,17 @@ #define MAX_ATOM_LENGTH 255 #define ATOM_LIMIT (1024*1024) +#define MIN_ATOM_TABLE_SIZE 8192 + +#ifndef ARCH_32 +/* Internal atom cache needs MAX_ATOM_TABLE_SIZE to be less than an + unsigned 32 bit integer. See external.c(erts_encode_ext_dist_header_setup) + for more details. */ +#define MAX_ATOM_TABLE_SIZE ((MAX_ATOM_INDEX + 1 < (1UL << 32)) ? MAX_ATOM_INDEX + 1 : (1UL << 32)) +#else +#define MAX_ATOM_TABLE_SIZE (MAX_ATOM_INDEX + 1) +#endif + /* * Atom entry. 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_bif_re.c b/erts/emulator/beam/erl_bif_re.c index 16abab65b0..c027cd5984 100644 --- a/erts/emulator/beam/erl_bif_re.c +++ b/erts/emulator/beam/erl_bif_re.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2008-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2008-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% */ @@ -884,7 +884,7 @@ re_run_3(BIF_ALIST_3) int capture_count; if (pflags & PARSE_FLAG_UNICODE && - (!is_binary(BIF_ARG_1) || + (!is_binary(BIF_ARG_2) || !is_binary(BIF_ARG_1) || (is_list_cap && !(pflags & PARSE_FLAG_GLOBAL)))) { BIF_TRAP3(urun_trap_exportp, BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3); } @@ -1020,6 +1020,9 @@ re_run_3(BIF_ALIST_3) goto handle_iolist; } pb = (ProcBin *) bptr; + if (pb->flags) { + erts_emasculate_writable_binary(pb); + } restart.subject = (char *) (pb->bytes+offset); restart.flags |= RESTART_FLAG_SUBJECT_IN_BINARY; } else { diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c index d3a916d2d9..b421da591b 100644 --- a/erts/emulator/beam/erl_db_tree.c +++ b/erts/emulator/beam/erl_db_tree.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% */ @@ -2529,7 +2529,9 @@ static TreeDbTerm *find_node(DbTableTree *tb, Eterm key) this = this->right; } } - release_stack(tb,stack); + if (stack) { + release_stack(tb,stack); + } return this; } 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..17cf3b9597 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 @@ -118,6 +119,8 @@ int erts_disable_tolerant_timeofday; /* Time correction can be disabled it is * not and/or it is too slow. */ +int erts_atom_table_size = ATOM_LIMIT; /* Maximum number of atoms */ + int erts_modified_timing_level; int erts_no_crash_dump = 0; /* Use -d to suppress crash dump. */ @@ -252,7 +255,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 +517,73 @@ 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 size set the maximum number of atoms the " + "emulator can handle\n"); + erts_fprintf(stderr, " valid range is [%d-%d]\n", + MIN_ATOM_TABLE_SIZE, MAX_ATOM_TABLE_SIZE); + 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 +614,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 +933,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 @@ -1112,6 +1146,22 @@ erl_start(int argc, char **argv) } break; } + case 't': + /* set atom table size */ + arg = get_arg(argv[i]+2, argv[i+1], &i); + errno = 0; + erts_atom_table_size = strtol(arg, NULL, 10); + if (errno != 0 || + erts_atom_table_size < MIN_ATOM_TABLE_SIZE || + erts_atom_table_size > MAX_ATOM_TABLE_SIZE) { + erts_fprintf(stderr, "bad atom table size %s\n", arg); + erts_usage(); + } + VERBOSE(DEBUG_SYSTEM, + ("setting maximum number of atoms to %d\n", + erts_atom_table_size)); + break; + case 'T' : arg = get_arg(argv[i]+2, argv[i+1], &i); errno = 0; diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c index 25f1d420d1..074b08ea57 100644 --- a/erts/emulator/beam/erl_lock_check.c +++ b/erts/emulator/beam/erl_lock_check.c @@ -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% */ @@ -84,6 +84,9 @@ static erts_lc_lock_order_t erts_lock_order[] = { { "reg_tab", NULL }, { "migration_info_update", NULL }, { "proc_main", "pid" }, +#ifdef HIPE + { "hipe_mfait_lock", NULL }, +#endif { "nodes_monitors", NULL }, { "driver_list", NULL }, { "proc_link", "pid" }, 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..2789691c55 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% */ @@ -2522,8 +2522,11 @@ suspend_scheduler(ErtsSchedulerData *esdp) NULL); } - erts_smp_atomic_inc(&schdlr_sspnd.active); - + active_schedulers = erts_smp_atomic_inctest(&schdlr_sspnd.active); + if (schdlr_sspnd.changing == ERTS_SCHED_CHANGING_MULTI_SCHED + && schdlr_sspnd.online == active_schedulers) { + schdlr_sspnd.changing = 0; + } erts_smp_mtx_unlock(&schdlr_sspnd.mtx); if (erts_system_profile_flags.scheduler) @@ -2750,18 +2753,19 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all) ErtsProcList *plp; erts_smp_mtx_lock(&schdlr_sspnd.mtx); - if (on) { - if (schdlr_sspnd.changing) { - res = ERTS_SCHDLR_SSPND_YIELD_RESTART; /* Yield */ - } - else if (erts_is_multi_scheduling_blocked()) { + + if (schdlr_sspnd.changing) { + res = ERTS_SCHDLR_SSPND_YIELD_RESTART; /* Yield */ + } + else if (on) { /* ------ BLOCK ------ */ + if (erts_is_multi_scheduling_blocked()) { plp = proclist_create(p); plp->next = schdlr_sspnd.msb.procs; schdlr_sspnd.msb.procs = plp; p->flags |= F_HAVE_BLCKD_MSCHED; ASSERT(erts_smp_atomic_read(&schdlr_sspnd.active) == 1); ASSERT(p->scheduler_data->no == 1); - res = 1; + res = ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED; } else { p->flags |= F_HAVE_BLCKD_MSCHED; @@ -2842,10 +2846,11 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all) } } else if (!ongoing_multi_scheduling_block()) { + /* unblock not ongoing */ ASSERT(!schdlr_sspnd.msb.procs); res = ERTS_SCHDLR_SSPND_DONE; } - else { + else { /* ------ UNBLOCK ------ */ if (p->flags & F_HAVE_BLCKD_MSCHED) { ErtsProcList **plpp = &schdlr_sspnd.msb.procs; plp = schdlr_sspnd.msb.procs; @@ -2891,12 +2896,16 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all) #endif p->flags &= ~F_HAVE_BLCKD_MSCHED; erts_smp_atomic_set(&schdlr_sspnd.msb.ongoing, 0); - if (schdlr_sspnd.online == 1) - /* No schedulers to resume */; + if (schdlr_sspnd.online == 1) { + /* No schedulers to resume */ + ASSERT(erts_smp_atomic_read(&schdlr_sspnd.active) == 1); + schdlr_sspnd.changing = 0; + } else if (erts_common_run_queue) { for (ix = 1; ix < schdlr_sspnd.online; ix++) erts_smp_atomic_set(&ERTS_SCHEDULER_IX(ix)->suspended, 0); wake_all_schedulers(); + erts_smp_cnd_broadcast(&schdlr_sspnd.cnd); } else { int online = schdlr_sspnd.online; @@ -2928,9 +2937,8 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all) erts_smp_runq_unlock(ERTS_RUNQ_IX(0)); erts_smp_mtx_unlock(&balance_info.update_mtx); erts_smp_mtx_lock(&schdlr_sspnd.mtx); + erts_smp_cnd_broadcast(&schdlr_sspnd.cnd); } - erts_smp_cnd_broadcast(&schdlr_sspnd.cnd); - schdlr_sspnd.changing = 0; res = ERTS_SCHDLR_SSPND_DONE; } } @@ -5517,6 +5525,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 +6282,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 +6693,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 +6748,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 +6981,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 +6998,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; @@ -8024,11 +8037,6 @@ erts_do_exit_process(Process* p, Eterm reason) if (p->bif_timers) erts_cancel_bif_timers(p, ERTS_PROC_LOCKS_ALL); -#ifdef ERTS_SMP - if (p->flags & F_HAVE_BLCKD_MSCHED) - erts_block_multi_scheduling(p, ERTS_PROC_LOCKS_ALL, 0, 1); -#endif - erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_ALL_MINOR); #ifdef ERTS_SMP @@ -8073,6 +8081,27 @@ continue_exit_process(Process *p erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS); #endif +#ifdef ERTS_SMP + if (p->flags & F_HAVE_BLCKD_MSCHED) { + ErtsSchedSuspendResult ssr; + ssr = erts_block_multi_scheduling(p, ERTS_PROC_LOCK_MAIN, 0, 1); + switch (ssr) { + case ERTS_SCHDLR_SSPND_YIELD_RESTART: + goto yield; + case ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED: + case ERTS_SCHDLR_SSPND_YIELD_DONE_MSCHED_BLOCKED: + case ERTS_SCHDLR_SSPND_DONE: + case ERTS_SCHDLR_SSPND_YIELD_DONE: + p->flags &= ~F_HAVE_BLCKD_MSCHED; + break; + case ERTS_SCHDLR_SSPND_EINVAL: + default: + erl_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error: %d\n", + __FILE__, __LINE__, (int) ssr); + } + } +#endif + if (p->flags & F_USING_DB) { if (erts_db_process_exiting(p, ERTS_PROC_LOCK_MAIN)) goto yield; 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_time_sup.c b/erts/emulator/beam/erl_time_sup.c index 76bfdecd9f..c15f85f8f1 100644 --- a/erts/emulator/beam/erl_time_sup.c +++ b/erts/emulator/beam/erl_time_sup.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% */ @@ -754,12 +754,8 @@ get_sys_now(Uint* megasec, Uint* sec, Uint* microsec) { SysTimeval now; - erts_smp_mtx_lock(&erts_timeofday_mtx); - sys_gettimeofday(&now); - erts_smp_mtx_unlock(&erts_timeofday_mtx); - *megasec = (Uint) (now.tv_sec / 1000000); *sec = (Uint) (now.tv_sec % 1000000); *microsec = (Uint) (now.tv_usec); 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..50b3e5b61c 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,9 @@ 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 */ + +extern int erts_atom_table_size;/* Atom table size */ #define ORIG_CREATION 0 diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index f856cce18f..b011d4c0de 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% */ @@ -271,11 +271,8 @@ erts_encode_ext_dist_header_size(ErtsAtomCacheMap *acmp) byte *erts_encode_ext_dist_header_setup(byte *ctl_ext, ErtsAtomCacheMap *acmp) { -#ifndef ARCH_32 -#if ATOM_LIMIT >= (1UL << 32) -#error "ATOM_LIMIT too large for interal atom cache update instructions. New instructions needed." -#endif -#endif + /* Maximum number of atom must be less than the maximum of a 32 bits + unsigned integer. Check is done in erl_init.c, erl_start function. */ if (!acmp) return ctl_ext; else { @@ -1013,6 +1010,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 +1061,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 +1092,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 +1119,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 +1147,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 +1393,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 +1405,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 +1873,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 +2033,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 +2147,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 +2213,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 +2382,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 +2391,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 +2412,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 +2423,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 +2489,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 +2501,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 +2537,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 +2555,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/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c index 032bf2e896..5291374e25 100644 --- a/erts/emulator/hipe/hipe_bif0.c +++ b/erts/emulator/hipe/hipe_bif0.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2001-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2001-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% */ /* $Id$ @@ -656,6 +656,7 @@ static void *hipe_get_emu_address(Eterm m, Eterm f, unsigned int arity, int is_r address = hipe_find_emu_address(m, f, arity); if (!address) { /* if not found, stub it via the export entry */ + /* no lock needed around erts_export_get_or_make_stub() */ Export *export_entry = erts_export_get_or_make_stub(m, f, arity); address = export_entry->address; } @@ -1188,8 +1189,31 @@ static struct { unsigned int mask; /* INV: mask == (1 << log2size)-1 */ unsigned int used; struct hipe_mfa_info **bucket; + /* + * The mfa info table is normally updated by the loader, + * which runs in non-concurrent mode. Unfortunately runtime + * apply operations (get_na_nofail) update the table if + * they create a new stub for the mfa, which forces locking. + * XXX: Redesign apply et al to avoid those updates. + */ + erts_smp_mtx_t lock; } hipe_mfa_info_table; +static inline void hipe_mfa_info_table_init_lock(void) +{ + erts_smp_mtx_init(&hipe_mfa_info_table.lock, "hipe_mfait_lock"); +} + +static inline void hipe_mfa_info_table_lock(void) +{ + erts_smp_mtx_lock(&hipe_mfa_info_table.lock); +} + +static inline void hipe_mfa_info_table_unlock(void) +{ + erts_smp_mtx_unlock(&hipe_mfa_info_table.lock); +} + #define HIPE_MFA_HASH(M,F,A) ((M) * (F) + (A)) static struct hipe_mfa_info **hipe_mfa_info_table_alloc_bucket(unsigned int size) @@ -1258,9 +1282,11 @@ void hipe_mfa_info_table_init(void) hipe_mfa_info_table.mask = size - 1; hipe_mfa_info_table.used = 0; hipe_mfa_info_table.bucket = hipe_mfa_info_table_alloc_bucket(size); + + hipe_mfa_info_table_init_lock(); } -static inline struct hipe_mfa_info *hipe_mfa_info_table_get(Eterm m, Eterm f, unsigned int arity) +static inline struct hipe_mfa_info *hipe_mfa_info_table_get_locked(Eterm m, Eterm f, unsigned int arity) { unsigned long h; unsigned int i; @@ -1286,7 +1312,7 @@ void *hipe_mfa_find_na(Eterm m, Eterm f, unsigned int arity) } #endif -static struct hipe_mfa_info *hipe_mfa_info_table_put(Eterm m, Eterm f, unsigned int arity) +static struct hipe_mfa_info *hipe_mfa_info_table_put_locked(Eterm m, Eterm f, unsigned int arity) { unsigned long h; unsigned int i; @@ -1313,7 +1339,10 @@ static struct hipe_mfa_info *hipe_mfa_info_table_put(Eterm m, Eterm f, unsigned static void hipe_mfa_set_na(Eterm m, Eterm f, unsigned int arity, void *address, int is_exported) { - struct hipe_mfa_info *p = hipe_mfa_info_table_put(m, f, arity); + struct hipe_mfa_info *p; + + hipe_mfa_info_table_lock(); + p = hipe_mfa_info_table_put_locked(m, f, arity); #ifdef DEBUG_LINKER printf("%s: ", __FUNCTION__); print_mfa(m, f, arity); @@ -1322,19 +1351,30 @@ static void hipe_mfa_set_na(Eterm m, Eterm f, unsigned int arity, void *address, p->local_address = address; if (is_exported) p->remote_address = address; + hipe_mfa_info_table_unlock(); } #if defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__) || defined(__arm__) void *hipe_mfa_get_trampoline(Eterm m, Eterm f, unsigned int arity) { - struct hipe_mfa_info *p = hipe_mfa_info_table_put(m, f, arity); - return p->trampoline; + struct hipe_mfa_info *p; + void *trampoline; + + hipe_mfa_info_table_lock(); + p = hipe_mfa_info_table_put_locked(m, f, arity); + trampoline = p->trampoline; + hipe_mfa_info_table_unlock(); + return trampoline; } void hipe_mfa_set_trampoline(Eterm m, Eterm f, unsigned int arity, void *trampoline) { - struct hipe_mfa_info *p = hipe_mfa_info_table_put(m, f, arity); + struct hipe_mfa_info *p; + + hipe_mfa_info_table_lock(); + p = hipe_mfa_info_table_put_locked(m, f, arity); p->trampoline = trampoline; + hipe_mfa_info_table_unlock(); } #endif @@ -1365,12 +1405,13 @@ BIF_RETTYPE hipe_bifs_invalidate_funinfo_native_addresses_1(BIF_ALIST_1) struct mfa mfa; struct hipe_mfa_info *p; + hipe_mfa_info_table_lock(); lst = BIF_ARG_1; while (is_list(lst)) { if (!term_to_mfa(CAR(list_val(lst)), &mfa)) - BIF_ERROR(BIF_P, BADARG); + break; lst = CDR(list_val(lst)); - p = hipe_mfa_info_table_get(mfa.mod, mfa.fun, mfa.ari); + p = hipe_mfa_info_table_get_locked(mfa.mod, mfa.fun, mfa.ari); if (p) { p->remote_address = NULL; p->local_address = NULL; @@ -1393,6 +1434,7 @@ BIF_RETTYPE hipe_bifs_invalidate_funinfo_native_addresses_1(BIF_ALIST_1) } } } + hipe_mfa_info_table_unlock(); if (is_not_nil(lst)) BIF_ERROR(BIF_P, BADARG); BIF_RET(NIL); @@ -1406,7 +1448,8 @@ void hipe_mfa_save_orig_beam_op(Eterm mod, Eterm fun, unsigned int ari, Eterm *p orig_beam_op = pc[0]; if (orig_beam_op != BeamOpCode(op_hipe_trap_call_closure) && orig_beam_op != BeamOpCode(op_hipe_trap_call)) { - p = hipe_mfa_info_table_put(mod, fun, ari); + hipe_mfa_info_table_lock(); + p = hipe_mfa_info_table_put_locked(mod, fun, ari); #ifdef DEBUG_LINKER printf("%s: ", __FUNCTION__); print_mfa(mod, fun, ari); @@ -1414,6 +1457,7 @@ void hipe_mfa_save_orig_beam_op(Eterm mod, Eterm fun, unsigned int ari, Eterm *p #endif p->beam_code = pc; p->orig_beam_op = orig_beam_op; + hipe_mfa_info_table_unlock(); } else { #ifdef DEBUG_LINKER printf("%s: ", __FUNCTION__); @@ -1440,12 +1484,12 @@ static void *hipe_make_stub(Eterm m, Eterm f, unsigned int arity, int is_remote) return StubAddress; } -static void *hipe_get_na_nofail(Eterm m, Eterm f, unsigned int a, int is_remote) +static void *hipe_get_na_nofail_locked(Eterm m, Eterm f, unsigned int a, int is_remote) { struct hipe_mfa_info *p; void *address; - p = hipe_mfa_info_table_get(m, f, a); + p = hipe_mfa_info_table_get_locked(m, f, a); if (p) { /* find address, predicting for a runtime apply call */ address = p->remote_address; @@ -1459,13 +1503,23 @@ static void *hipe_get_na_nofail(Eterm m, Eterm f, unsigned int a, int is_remote) if (address) return address; } else - p = hipe_mfa_info_table_put(m, f, a); + p = hipe_mfa_info_table_put_locked(m, f, a); address = hipe_make_stub(m, f, a, is_remote); /* XXX: how to tell if a BEAM MFA is exported or not? */ p->remote_address = address; return address; } +static void *hipe_get_na_nofail(Eterm m, Eterm f, unsigned int a, int is_remote) +{ + void *p; + + hipe_mfa_info_table_lock(); + p = hipe_get_na_nofail_locked(m, f, a, is_remote); + hipe_mfa_info_table_unlock(); + return p; +} + /* used for apply/3 in hipe_mode_switch */ void *hipe_get_remote_na(Eterm m, Eterm f, unsigned int a) { @@ -1549,6 +1603,8 @@ int hipe_find_mfa_from_ra(const void *ra, Eterm *m, Eterm *f, unsigned int *a) /* Note about locking: the table is only updated from the loader, which runs with the rest of the system suspended. */ + /* XXX: alas not true; see comment at hipe_mfa_info_table.lock */ + hipe_mfa_info_table_lock(); bucket = hipe_mfa_info_table.bucket; nrbuckets = 1 << hipe_mfa_info_table.log2size; mfa = NULL; @@ -1564,12 +1620,13 @@ int hipe_find_mfa_from_ra(const void *ra, Eterm *m, Eterm *f, unsigned int *a) b = b->bucket.next; } } - if (!mfa) - return 0; - *m = mfa->m; - *f = mfa->f; - *a = mfa->a; - return 1; + if (mfa) { + *m = mfa->m; + *f = mfa->f; + *a = mfa->a; + } + hipe_mfa_info_table_unlock(); + return mfa ? 1 : 0; } /* @@ -1645,8 +1702,9 @@ BIF_RETTYPE hipe_bifs_add_ref_2(BIF_ALIST_2) default: goto badarg; } - callee_mfa = hipe_mfa_info_table_put(callee.mod, callee.fun, callee.ari); - caller_mfa = hipe_mfa_info_table_put(caller.mod, caller.fun, caller.ari); + hipe_mfa_info_table_lock(); + callee_mfa = hipe_mfa_info_table_put_locked(callee.mod, callee.fun, callee.ari); + caller_mfa = hipe_mfa_info_table_put_locked(caller.mod, caller.fun, caller.ari); refers_to = erts_alloc(ERTS_ALC_T_HIPE, sizeof(*refers_to)); refers_to->mfa = callee_mfa; @@ -1660,6 +1718,7 @@ BIF_RETTYPE hipe_bifs_add_ref_2(BIF_ALIST_2) ref->flags = flags; ref->next = callee_mfa->referred_from; callee_mfa->referred_from = ref; + hipe_mfa_info_table_unlock(); BIF_RET(NIL); @@ -1679,10 +1738,12 @@ BIF_RETTYPE hipe_bifs_mark_referred_from_1(BIF_ALIST_1) /* get_refs_from */ if (!term_to_mfa(BIF_ARG_1, &mfa)) BIF_ERROR(BIF_P, BADARG); - p = hipe_mfa_info_table_get(mfa.mod, mfa.fun, mfa.ari); + hipe_mfa_info_table_lock(); + p = hipe_mfa_info_table_get_locked(mfa.mod, mfa.fun, mfa.ari); if (p) for (ref = p->referred_from; ref != NULL; ref = ref->next) ref->flags |= REF_FLAG_PENDING_REDIRECT; + hipe_mfa_info_table_unlock(); BIF_RET(NIL); } @@ -1695,7 +1756,8 @@ BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1) if (!term_to_mfa(BIF_ARG_1, &mfa)) BIF_ERROR(BIF_P, BADARG); - caller_mfa = hipe_mfa_info_table_get(mfa.mod, mfa.fun, mfa.ari); + hipe_mfa_info_table_lock(); + caller_mfa = hipe_mfa_info_table_get_locked(mfa.mod, mfa.fun, mfa.ari); if (caller_mfa) { refers_to = caller_mfa->refers_to; while (refers_to) { @@ -1725,6 +1787,7 @@ BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1) } caller_mfa->refers_to = NULL; } + hipe_mfa_info_table_unlock(); BIF_RET(NIL); } @@ -1742,14 +1805,15 @@ BIF_RETTYPE hipe_bifs_redirect_referred_from_1(BIF_ALIST_1) if (!term_to_mfa(BIF_ARG_1, &mfa)) BIF_ERROR(BIF_P, BADARG); - p = hipe_mfa_info_table_get(mfa.mod, mfa.fun, mfa.ari); + hipe_mfa_info_table_lock(); + p = hipe_mfa_info_table_get_locked(mfa.mod, mfa.fun, mfa.ari); if (p) { prev = &p->referred_from; ref = *prev; while (ref) { if (ref->flags & REF_FLAG_PENDING_REDIRECT) { is_remote = ref->flags & REF_FLAG_IS_REMOTE; - new_address = hipe_get_na_nofail(p->m, p->f, p->a, is_remote); + new_address = hipe_get_na_nofail_locked(p->m, p->f, p->a, is_remote); if (ref->flags & REF_FLAG_IS_LOAD_MFA) res = hipe_patch_insn(ref->address, (Uint)new_address, am_load_mfa); else @@ -1772,6 +1836,7 @@ BIF_RETTYPE hipe_bifs_redirect_referred_from_1(BIF_ALIST_1) } } } + hipe_mfa_info_table_unlock(); BIF_RET(NIL); } 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/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index e644ad4dc8..c9101b77c2 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-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% %% @@ -48,7 +48,8 @@ scheduler_bind_types/1, cpu_topology/1, sct_cmd/1, - sbt_cmd/1]). + sbt_cmd/1, + scheduler_suspend/1]). -define(DEFAULT_TIMEOUT, ?t:minutes(10)). @@ -65,7 +66,8 @@ all(suite) -> equal_with_high, equal_with_high_max, bound_process, - scheduler_bind]. + scheduler_bind, + scheduler_suspend]. init_per_testcase(Case, Config) when is_list(Config) -> Dog = ?t:timetrap(?DEFAULT_TIMEOUT), @@ -882,11 +884,103 @@ sbt_test(Config, CpuTCmd, ClBt, Bt, LP) -> ?line stop_node(Node), ?line ok. +scheduler_suspend(Config) when is_list(Config) -> + ?line Dog = ?t:timetrap(?t:minutes(2)), + ?line lists:foreach(fun (S) -> scheduler_suspend_test(Config, S) end, + [64, 32, 16, default]), + ?line ?t:timetrap_cancel(Dog), + ?line ok. +scheduler_suspend_test(Config, Schedulers) -> + ?line Cmd = case Schedulers of + default -> + ""; + _ -> + S = integer_to_list(Schedulers), + "+S"++S++":"++S + end, + ?line {ok, Node} = start_node(Config, Cmd), + ?line [SState] = mcall(Node, [fun () -> + erlang:system_info(schedulers_state) + end]), + ?line {Sched, _, _} = SState, + ?line true = is_integer(Sched), + ?line [ok] = mcall(Node, [fun () -> sst0_loop(300) end]), + ?line [ok] = mcall(Node, [fun () -> sst1_loop(300) end]), + ?line [ok] = mcall(Node, [fun () -> sst2_loop(300) end]), + ?line [ok, ok, ok, ok, ok] = mcall(Node, + [fun () -> sst0_loop(200) end, + fun () -> sst1_loop(200) end, + fun () -> sst2_loop(200) end, + fun () -> sst2_loop(200) end, + fun () -> sst3_loop(Sched, 200) end]), + ?line [SState] = mcall(Node, [fun () -> + erlang:system_info(schedulers_state) + end]), + ?line stop_node(Node), + ?line ok. + + +sst0_loop(0) -> + ok; +sst0_loop(N) -> + erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, unblock), + erlang:yield(), + sst0_loop(N-1). + +sst1_loop(0) -> + ok; +sst1_loop(N) -> + erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, unblock), + sst1_loop(N-1). + +sst2_loop(0) -> + ok; +sst2_loop(N) -> + erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, unblock), + erlang:system_flag(multi_scheduling, unblock), + erlang:system_flag(multi_scheduling, unblock), + sst2_loop(N-1). + +sst3_loop(_S, 0) -> + ok; +sst3_loop(S, N) -> + erlang:system_flag(schedulers_online, (S div 2)+1), + erlang:system_flag(schedulers_online, 1), + erlang:system_flag(schedulers_online, (S div 2)+1), + erlang:system_flag(schedulers_online, S), + erlang:system_flag(schedulers_online, 1), + erlang:system_flag(schedulers_online, S), + sst3_loop(S, N-1). + -% +%% %% Utils %% +mcall(Node, Funs) -> + Parent = self(), + Refs = lists:map(fun (Fun) -> + Ref = make_ref(), + spawn_link(Node, + fun () -> + Res = Fun(), + unlink(Parent), + Parent ! {Ref, Res} + end), + Ref + end, Funs), + lists:map(fun (Ref) -> + receive + {Ref, Res} -> + Res + end + end, Refs). + erl_rel_flag_var() -> "ERL_"++erlang:system_info(otp_release)++"_FLAGS". 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/epmd/test/Makefile b/erts/epmd/test/Makefile index c1d62f0f93..13dad09ae3 100644 --- a/erts/epmd/test/Makefile +++ b/erts/epmd/test/Makefile @@ -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% # include $(ERL_TOP)/make/target.mk @@ -34,6 +34,8 @@ ERL_FILES= $(MODULES:%=%.erl) TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) +EMAKEFILE=Emakefile + # ---------------------------------------------------- # Release directory specification # ---------------------------------------------------- @@ -43,15 +45,17 @@ RELEPMDDIR = $(RELEASE_PATH)/epmd_test # FLAGS # ---------------------------------------------------- -ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \ - -I$(ERL_TOP)/lib/kernel/src/ \ - $(EPMD_FLAGS) +ERL_COMPILE_FLAGS += $(EPMD_FLAGS) # ---------------------------------------------------- # Targets # ---------------------------------------------------- -tests debug opt: $(TARGET_FILES) +tests debug opt: $(EMAKEFILE) + +$(EMAKEFILE): Makefile $(ERL_FILES) + $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) \ + -o$(EBIN) $(MODULES) > $(EMAKEFILE) clean: rm -f $(TARGET_FILES) @@ -69,7 +73,7 @@ release_spec: release_tests_spec: opt $(INSTALL_DIR) $(RELEPMDDIR) $(INSTALL_DATA) epmd.spec epmd.spec.vxworks $(ERL_FILES) \ - $(TARGET_FILES) $(RELEPMDDIR) + $(EMAKEFILE) $(RELEPMDDIR) chmod -f -R u+w $(RELEPMDDIR) release_docs_spec: diff --git a/erts/epmd/test/epmd_SUITE.erl b/erts/epmd/test/epmd_SUITE.erl index 513c87a13e..91e09faf75 100644 --- a/erts/epmd/test/epmd_SUITE.erl +++ b/erts/epmd/test/epmd_SUITE.erl @@ -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% %% -module(epmd_SUITE). @@ -31,6 +31,9 @@ -define(MEDIUM_PAUSE, ?t:seconds(1)). -define(LONG_PAUSE, ?t:seconds(5)). +% Information about nodes +-record(node_info, {port, node_type, prot, lvsn, hvsn, node_name, extra}). + % Test server specific exports -export([all/1, init_per_testcase/2, fin_per_testcase/2]). @@ -57,7 +60,10 @@ too_large/1, alive_req_too_small_1/1, alive_req_too_small_2/1, - alive_req_too_large/1 + alive_req_too_large/1, + + returns_valid_empty_extra/1, + returns_valid_populated_extra_with_nulls/1 ]). @@ -76,9 +82,13 @@ -define(REG_REPEAT_LIM,1000). % Message codes in epmd protocol --define(EPMD_ALIVE_REQ, $a). --define(EPMD_ALIVE_OK_RESP, $Y). --define(EPMD_PORT_REQ, $p). +-define(EPMD_ALIVE_REQ, $a). +-define(EPMD_ALIVE2_REQ, $x). +-define(EPMD_ALIVE_OK_RESP, $Y). +-define(EPMD_ALIVE2_RESP, $y). +-define(EPMD_PORT_REQ, $p). +-define(EPMD_PORT_PLEASE2_REQ, $z). +-define(EPMD_PORT2_RESP, $w). -define(EPMD_NAMES_REQ, $n). -define(EPMD_DUMP_REQ, $d). -define(EPMD_KILL_REQ, $k). @@ -111,7 +121,10 @@ all(suite) -> too_large, alive_req_too_small_1, alive_req_too_small_2, - alive_req_too_large + alive_req_too_large, + + returns_valid_empty_extra, + returns_valid_populated_extra_with_nulls ]. %% @@ -182,29 +195,70 @@ register_node(Name) -> register_node(Name,?DUMMY_PORT). register_node(Name, Port) -> - case connect() of + case send_req([?EPMD_ALIVE_REQ, put16(Port), Name]) of {ok,Sock} -> - M = [?EPMD_ALIVE_REQ, put16(Port), Name], - case send(Sock, [size16(M), M]) of - ok -> - case recv(Sock,3) of - {ok, [?EPMD_ALIVE_OK_RESP,_D1,_D0]} -> - {ok,Sock}; - Other -> - test_server:format("recv on sock ~w: ~p~n", - [Sock,Other]), - error - end; + case recv(Sock,3) of + {ok, [?EPMD_ALIVE_OK_RESP,_D1,_D0]} -> + {ok,Sock}; Other -> - test_server:format("send on sock ~w: ~w~n",[Sock,Other]), + test_server:format("recv on sock ~w: ~p~n", + [Sock,Other]), error end; - Other -> - test_server:format("Connect on port ~w: ~p~n",[Port,Other]), + error -> + error + end. + +register_node_v2(Port, NodeType, Prot, HVsn, LVsn, Name, Extra) -> + Req = [?EPMD_ALIVE2_REQ, put16(Port), NodeType, Prot, + put16(HVsn), put16(LVsn), + size16(Name), Name, + size16(Extra), Extra], + case send_req(Req) of + {ok,Sock} -> + case recv(Sock,4) of + {ok, [?EPMD_ALIVE2_RESP,_Res=0,_C0,_C1]} -> + {ok,Sock}; + Other -> + test_server:format("recv on sock ~w: ~p~n", + [Sock,Other]), + error + end; + error -> error end. +% Internal function to fetch information about a node + +port_please_v2(Name) -> + case send_req([?EPMD_PORT_PLEASE2_REQ, Name]) of + {ok,Sock} -> + case recv_until_sock_closes(Sock) of + {ok, Resp} -> + parse_port2_resp(Resp); + Other -> + test_server:format("recv on sock ~w: ~p~n", + [Sock,Other]), + error + end; + error -> + error + end. +parse_port2_resp(Resp) -> + case list_to_binary(Resp) of + <<?EPMD_PORT2_RESP,Res,Port:16,NodeType,Prot,HVsn:16,LVsn:16, + NLen:16,NodeName:NLen/binary, + ELen:16,Extra:ELen/binary>> when Res =:= 0 -> + {ok, #node_info{port=Port,node_type=NodeType,prot=Prot, + hvsn=HVsn,lvsn=LVsn, + node_name=binary_to_list(NodeName), + extra=binary_to_list(Extra)}}; + Other -> + test_server:format("invalid port2 resp: ~p~n", + [Resp]), + error + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -631,6 +685,32 @@ alive_req_too_large(Config) when list(Config) -> ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +returns_valid_empty_extra(doc) -> + ["Check that an empty extra is prefixed by a two byte length"]; +returns_valid_empty_extra(suite) -> + []; +returns_valid_empty_extra(Config) when list(Config) -> + ?line ok = epmdrun(), + ?line {ok,Sock} = register_node_v2(4711, 72, 0, 5, 5, "foo", []), + ?line {ok,#node_info{extra=[]}} = port_please_v2("foo"), + ?line ok = close(Sock), + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +returns_valid_populated_extra_with_nulls(doc) -> + ["Check a populated extra with embedded null characters"]; +returns_valid_populated_extra_with_nulls(suite) -> + []; +returns_valid_populated_extra_with_nulls(Config) when list(Config) -> + ?line ok = epmdrun(), + ?line {ok,Sock} = register_node_v2(4711, 72, 0, 5, 5, "foo", "ABC\000\000"), + ?line {ok,#node_info{extra="ABC\000\000"}} = port_please_v2("foo"), + ?line ok = close(Sock), + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Terminate all tests with killing epmd. cleanup() -> @@ -813,6 +893,36 @@ send_direct(Sock, Bytes) -> Any end. +send_req(Req) -> + case connect() of + {ok,Sock} -> + case send(Sock, [size16(Req), Req]) of + ok -> + {ok,Sock}; + Other -> + test_server:format("Failed to send ~w on sock ~w: ~w~n", + [Req,Sock,Other]), + error + end; + Other -> + test_server:format("Connect failed when sending ~w: ~p~n", + [Req, Other]), + error + end. + +recv_until_sock_closes(Sock) -> + recv_until_sock_closes_2(Sock,[]). + +recv_until_sock_closes_2(Sock,AccData) -> + case recv(Sock,0) of + {ok,Data} -> + recv_until_sock_closes_2(Sock,AccData++Data); + closed -> + {ok,AccData}; + Other -> + Other + end. + sleep(MilliSeconds) -> timer:sleep(MilliSeconds). 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..f79f5cc978 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,10 +791,10 @@ int main(int argc, char **argv) case 'a': case 'A': case 'b': - case 'h': case 'i': case 'P': case 'S': + case 't': case 'T': case 'R': case 'W': @@ -850,6 +858,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 +1070,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..49f5b1f048 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% # @@ -483,6 +483,8 @@ ifneq ($(strip $(INTERNAL_RELEASE_LIBS)),) $(INSTALL_DATA) $(INTERNAL_RELEASE_LIBS) $(RELSYSDIR)/lib/internal endif +docs: + release_docs_spec: diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam Binary files differindex d7134967bf..e966f727c4 100644 --- a/erts/preloaded/ebin/erl_prim_loader.beam +++ b/erts/preloaded/ebin/erl_prim_loader.beam diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex f490fe7c3d..620ee733bd 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam Binary files differindex 39118a0109..aa9bd13dd0 100644 --- a/erts/preloaded/ebin/init.beam +++ b/erts/preloaded/ebin/init.beam diff --git a/erts/preloaded/ebin/otp_ring0.beam b/erts/preloaded/ebin/otp_ring0.beam Binary files differindex 4680d645cb..f060ac73b7 100644 --- a/erts/preloaded/ebin/otp_ring0.beam +++ b/erts/preloaded/ebin/otp_ring0.beam diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam Binary files differindex 2cacb6808c..34f9565fe3 100644 --- a/erts/preloaded/ebin/prim_file.beam +++ b/erts/preloaded/ebin/prim_file.beam diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam Binary files differindex aa9b255ebb..0ec3130d44 100644 --- a/erts/preloaded/ebin/prim_inet.beam +++ b/erts/preloaded/ebin/prim_inet.beam diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam Binary files differindex 0e7adad9e8..b7897dd798 100644 --- a/erts/preloaded/ebin/prim_zip.beam +++ b/erts/preloaded/ebin/prim_zip.beam diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam Binary files differindex 93b05172d8..c9be5d2aa0 100644 --- a/erts/preloaded/ebin/zlib.beam +++ b/erts/preloaded/ebin/zlib.beam diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl index 399c2bb55d..c0785083de 100644 --- a/erts/preloaded/src/erl_prim_loader.erl +++ b/erts/preloaded/src/erl_prim_loader.erl @@ -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% %% @@ -49,7 +49,7 @@ prim_read_file_info/2, prim_get_cwd/2]). %% Used by escript and code --export([set_primary_archive/2, release_archives/0]). +-export([set_primary_archive/3, release_archives/0]). %% Internal function. Exported to avoid dialyzer warnings -export([concat/1]). @@ -220,14 +220,15 @@ get_cwd(Drive) -> check_file_result(get_cwd, Drive, request({get_cwd,[Drive]})). -spec set_primary_archive(File :: string() | 'undefined', - ArchiveBin :: binary() | 'undefined') - -> {ok, [string()]} | {error,_}. + ArchiveBin :: binary() | 'undefined', + FileInfo :: #file_info{} | 'undefined') + -> {ok, [string()]} | {error,_}. -set_primary_archive(undefined, undefined) -> - request({set_primary_archive, undefined, undefined}); -set_primary_archive(File, ArchiveBin) - when is_list(File), is_binary(ArchiveBin) -> - request({set_primary_archive, File, ArchiveBin}). +set_primary_archive(undefined, undefined, undefined) -> + request({set_primary_archive, undefined, undefined, undefined}); +set_primary_archive(File, ArchiveBin, FileInfo) + when is_list(File), is_binary(ArchiveBin), is_record(FileInfo, file_info) -> + request({set_primary_archive, File, ArchiveBin, FileInfo}). -spec release_archives() -> 'ok' | {'error', _}. @@ -315,8 +316,8 @@ loop(State, Parent, Paths) -> {get_cwd,[_]=Args} -> {Res,State1} = handle_get_cwd(State, Args), {Res,State1,Paths}; - {set_primary_archive,File,Bin} -> - {Res,State1} = handle_set_primary_archive(State, File, Bin), + {set_primary_archive,File,Bin,FileInfo} -> + {Res,State1} = handle_set_primary_archive(State, File, Bin,FileInfo), {Res,State1,Paths}; release_archives -> {Res,State1} = handle_release_archives(State), @@ -356,8 +357,8 @@ handle_get_file(State = #state{loader = efile}, Paths, File) -> handle_get_file(State = #state{loader = inet}, Paths, File) -> ?SAFE2(inet_get_file_from_port(State, File, Paths), State). -handle_set_primary_archive(State= #state{loader = efile}, File, Bin) -> - ?SAFE2(efile_set_primary_archive(State, File, Bin), State). +handle_set_primary_archive(State= #state{loader = efile}, File, Bin, FileInfo) -> + ?SAFE2(efile_set_primary_archive(State, File, Bin, FileInfo), State). handle_release_archives(State= #state{loader = efile}) -> ?SAFE2(efile_release_archives(State), State). @@ -481,8 +482,8 @@ efile_get_file_from_port3(State, File, [P | Paths]) -> efile_get_file_from_port3(State, _File, []) -> {{error,enoent},State}. -efile_set_primary_archive(#state{prim_state = PS} = State, File, Bin) -> - {Res, PS2} = prim_set_primary_archive(PS, File, Bin), +efile_set_primary_archive(#state{prim_state = PS} = State, File, Bin, FileInfo) -> + {Res, PS2} = prim_set_primary_archive(PS, File, Bin, FileInfo), {Res,State#state{prim_state = PS2}}. efile_release_archives(#state{prim_state = PS} = State) -> @@ -572,13 +573,14 @@ find_loop(U, Retry, AL, ReqDelay, SReSleep, Ignore, Tries, LReSleep) -> case find_loop(U, Retry, AL, ReqDelay, []) of [] -> % no response from any server erlang:display({erl_prim_loader,'no server found'}), % lifesign - Tries1 = if Tries > 0 -> - sleep(SReSleep), - Tries - 1; - true -> - sleep(LReSleep), - 0 - end, + Tries1 = + if Tries > 0 -> + sleep(SReSleep), + Tries - 1; + true -> + sleep(LReSleep), + 0 + end, find_loop(U, Retry, AL, ReqDelay, SReSleep, Ignore, Tries1, LReSleep); Servers -> keysort(1, Servers -- Ignore) @@ -787,9 +789,9 @@ prim_release_archives(PS) -> prim_do_release_archives(PS, [{ArchiveFile, DictVal} | KeyVals], Acc) -> Res = case DictVal of - {primary, _PrimZip} -> + {primary, _PrimZip, _FI} -> ok; % Keep primary archive - {_Mtime, Cache} -> + {Cache, _FI} -> debug(PS, {release, cache, ArchiveFile}), erase(ArchiveFile), clear_cache(ArchiveFile, Cache) @@ -805,7 +807,7 @@ prim_do_release_archives(PS, [], []) -> prim_do_release_archives(PS, [], Errors) -> {{error, Errors}, PS#prim_state{primary_archive = undefined}}. -prim_set_primary_archive(PS, undefined, undefined) -> +prim_set_primary_archive(PS, undefined, undefined, undefined) -> debug(PS, {set_primary_archive, clean}), case PS#prim_state.primary_archive of undefined -> @@ -813,15 +815,15 @@ prim_set_primary_archive(PS, undefined, undefined) -> debug(PS, {return, Res}), {Res, PS}; ArchiveFile -> - {primary, PrimZip} = erase(ArchiveFile), + {primary, PrimZip, _FI} = erase(ArchiveFile), ok = prim_zip:close(PrimZip), PS2 = PS#prim_state{primary_archive = undefined}, Res = {ok, []}, debug(PS2, {return, Res}), {Res, PS2} end; -prim_set_primary_archive(PS, ArchiveFile, ArchiveBin) - when is_list(ArchiveFile), is_binary(ArchiveBin) -> +prim_set_primary_archive(PS, ArchiveFile, ArchiveBin, FileInfo) + when is_list(ArchiveFile), is_binary(ArchiveBin), is_record(FileInfo, file_info) -> %% Try the archive file debug(PS, {set_primary_archive, ArchiveFile, byte_size(ArchiveBin)}), {Res3, PS3} = @@ -833,17 +835,17 @@ prim_set_primary_archive(PS, ArchiveFile, ArchiveBin) ["", "nibe", RevApp] -> % Reverse ebin %% Collect ebin directories in archive Ebin = reverse(RevApp) ++ "/ebin", - {true, [Ebin | A]}; + {true, [Ebin | A]}; _ -> {true, A} end end, Ebins0 = [ArchiveFile], - case open_archive({ArchiveFile, ArchiveBin}, Ebins0, Fun) of - {ok, PrimZip, RevEbins} -> + case open_archive({ArchiveFile, ArchiveBin}, FileInfo, Ebins0, Fun) of + {ok, PrimZip, {RevEbins, FI, _}} -> Ebins = reverse(RevEbins), debug(PS, {set_primary_archive, Ebins}), - put(ArchiveFile, {primary, PrimZip}), + put(ArchiveFile, {primary, PrimZip, FI}), {{ok, Ebins}, PS#prim_state{primary_archive = ArchiveFile}}; Error -> debug(PS, {set_primary_archive, Error}), @@ -851,10 +853,10 @@ prim_set_primary_archive(PS, ArchiveFile, ArchiveBin) end; OldArchiveFile -> debug(PS, {set_primary_archive, clean}), - PrimZip = erase(OldArchiveFile), + {primary, PrimZip, _FI} = erase(OldArchiveFile), ok = prim_zip:close(PrimZip), PS2 = PS#prim_state{primary_archive = undefined}, - prim_set_primary_archive(PS2, ArchiveFile, ArchiveBin) + prim_set_primary_archive(PS2, ArchiveFile, ArchiveBin, FileInfo) end, debug(PS3, {return, Res3}), {Res3, PS3}. @@ -956,15 +958,15 @@ prim_read_file_info(PS, File) -> FunnyFile = funny_split(FileInArchive, $/), Fun = fun({Funny, GetInfo, _GetBin}, Acc) -> - if - hd(Funny) =:= "", - tl(Funny) =:= FunnyFile -> + case Funny of + [H | T] when H =:= "", + T =:= FunnyFile -> %% Directory {false, {ok, GetInfo()}}; - Funny =:= FunnyFile -> + F when F =:= FunnyFile -> %% Plain file {false, {ok, GetInfo()}}; - true -> + _ -> %% No match {true, Acc} end @@ -990,33 +992,36 @@ prim_get_cwd(PS, [Drive]) -> apply_archive(PS, Fun, Acc, Archive) -> case get(Archive) of undefined -> + case open_archive(Archive, Acc, Fun) of + {ok, PrimZip, {Acc2, FI, _}} -> + debug(PS, {cache, ok}), + put(Archive, {{ok, PrimZip}, FI}), + {Acc2, PS}; + Error -> + debug(PS, {cache, Error}), + %% put(Archive, {Error, FI}), + {Error, PS} + end; + {primary, PrimZip, FI} -> + case prim_file:read_file_info(Archive) of + {ok, FI2} + when FI#file_info.mtime =:= FI2#file_info.mtime -> + case foldl_archive(PrimZip, Acc, Fun) of + {ok, _PrimZip2, Acc2} -> + {Acc2, PS}; + Error -> + debug(PS, {primary, Error}), + {Error, PS} + end; + Error -> + debug(PS, {cache, {clear, Error}}), + clear_cache(Archive, {ok, PrimZip}), + apply_archive(PS, Fun, Acc, Archive) + end; + {Cache, FI} -> case prim_file:read_file_info(Archive) of - {ok, #file_info{mtime = Mtime}} -> - case open_archive(Archive, Acc, Fun) of - {ok, PrimZip, Acc2} -> - debug(PS, {cache, ok}), - put(Archive, {Mtime, {ok, PrimZip}}), - {Acc2, PS}; - Error -> - debug(PS, {cache, Error}), - put(Archive, {Mtime, Error}), - {Error, PS} - end; - Error -> - debug(PS, {cache, Error}), - {Error, PS} - end; - {primary, PrimZip} -> - case foldl_archive(PrimZip, Acc, Fun) of - {ok, _PrimZip2, Acc2} -> - {Acc2, PS}; - Error -> - debug(PS, {primary, Error}), - {Error, PS} - end; - {Mtime, Cache} -> - case prim_file:read_file_info(Archive) of - {ok, #file_info{mtime = Mtime2}} when Mtime2 =:= Mtime -> + {ok, FI2} + when FI#file_info.mtime =:= FI2#file_info.mtime -> case Cache of {ok, PrimZip} -> case foldl_archive(PrimZip, Acc, Fun) of @@ -1026,7 +1031,8 @@ apply_archive(PS, Fun, Acc, Archive) -> debug(PS, {cache, {clear, Error}}), clear_cache(Archive, Cache), debug(PS, {cache, Error}), - put(Archive, {Mtime, Error}), + erase(Archive), + %% put(Archive, {Error, FI}), {Error, PS} end; Error -> @@ -1041,20 +1047,57 @@ apply_archive(PS, Fun, Acc, Archive) -> end. open_archive(Archive, Acc, Fun) -> + case prim_file:read_file_info(Archive) of + {ok, FileInfo} -> + open_archive(Archive, FileInfo, Acc, Fun); + {error, Reason} -> + {error, Reason} + end. + +open_archive(Archive, FileInfo, Acc, Fun) -> + FakeFI = FileInfo#file_info{type = directory}, Wrapper = - fun({N, GI, GB}, A) -> - %% Ensure full iteration at open - Funny = funny_split(N, $/), - {_Continue, A2} = Fun({Funny, GI, GB}, A), - {true, {true, Funny}, A2} - end, - prim_zip:open(Wrapper, Acc, Archive). + fun({N, GI, GB}, {A, I, FunnyDirs}) -> % Full iteration at open + Funny = funny_split(N, $/), + FunnyDirs2 = + case Funny of + ["" | FunnyDir] -> + [FunnyDir | FunnyDirs]; + _ -> + FunnyDirs + end, + {Includes, FunnyDirs3, A2} = + ensure_virtual_dirs(Funny, Fun, FakeFI, [{true, Funny}], FunnyDirs2, A), + {_Continue, A3} = Fun({Funny, GI, GB}, A2), + {true, Includes, {A3, I, FunnyDirs3}} + end, + prim_zip:open(Wrapper, {Acc, FakeFI, []}, Archive). + +ensure_virtual_dirs(Funny, Fun, FakeFI, Includes, FunnyDirs, Acc) -> + case Funny of + [_ | FunnyDir] -> + case lists:member(FunnyDir, FunnyDirs) of % BIF + false -> + GetInfo = fun() -> FakeFI end, + GetBin = fun() -> <<>> end, + VirtualDir = ["" | FunnyDir], + Includes2 = [{true, VirtualDir, GetInfo, GetBin} | Includes], + FunnyDirs2 = [FunnyDir | FunnyDirs], + {I, F, Acc2} = ensure_virtual_dirs(FunnyDir, Fun, FakeFI, Includes2, FunnyDirs2, Acc), + {_Continue, Acc3} = Fun({VirtualDir, GetInfo, GetBin}, Acc2), + {I, F, Acc3}; + true -> + {reverse(Includes), FunnyDirs, Acc} + end; + [] -> + {reverse(Includes), FunnyDirs, Acc} + end. foldl_archive(PrimZip, Acc, Fun) -> Wrapper = - fun({N, GI, GB}, A) -> + fun({Funny, GI, GB}, A) -> %% Allow partial iteration at foldl - {Continue, A2} = Fun({N, GI, GB}, A), + {Continue, A2} = Fun({Funny, GI, GB}, A), {Continue, true, A2} end, prim_zip:foldl(Wrapper, Acc, PrimZip). diff --git a/erts/preloaded/src/prim_zip.erl b/erts/preloaded/src/prim_zip.erl index 17ef8c6c43..3f5a5b9721 100644 --- a/erts/preloaded/src/prim_zip.erl +++ b/erts/preloaded/src/prim_zip.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-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% %% @@ -94,12 +94,7 @@ do_foldl(FilterFun, FilterAcc, [PF | Tail], Acc0, PrimZip, PrimZipOrig) -> #primzip_file{name = F, get_info = GetInfo, get_bin = GetBin} = PF, case FilterFun({F, GetInfo, GetBin}, FilterAcc) of {Continue, Include, FilterAcc2} -> - Acc1 = - case Include of - false -> Acc0; - true -> [PF | Acc0]; - {true, Nick} -> [PF#primzip_file{name = Nick} | Acc0] - end, + Acc1 = include_acc(Include, PF, Acc0), case Continue of true -> do_foldl(FilterFun, FilterAcc2, Tail, Acc1, PrimZip, PrimZipOrig); @@ -112,6 +107,28 @@ do_foldl(FilterFun, FilterAcc, [PF | Tail], Acc0, PrimZip, PrimZipOrig) -> do_foldl(_FilterFun, FilterAcc, [], Acc, PrimZip, _PrimZipOrig) -> {ok, FilterAcc, PrimZip#primzip{files = reverse(Acc)}}. +include_acc(Include, PF, Acc) -> + case Include of + false -> + Acc; + true -> + [PF | Acc]; + {true, Nick} -> + [PF#primzip_file{name = Nick} | Acc]; + {true, Nick, GetInfo, GetBin} -> + PF2 = #primzip_file{name = Nick, get_info = GetInfo, get_bin = GetBin}, + [PF2 | Acc]; + List when is_list(List) -> + %% Add new entries + Fun = fun(I, A) -> include_acc(I, PF, A) end, + lists_foldl(Fun, Acc, List) + end. + +lists_foldl(F, Accu, [Hd|Tail]) -> + lists_foldl(F, F(Hd, Accu), Tail); +lists_foldl(F, Accu, []) when is_function(F, 2) -> + Accu. + %% close a zip archive close(#primzip{in = In0, input = Input, zlib = Z}) -> Input(close, In0), @@ -199,15 +216,25 @@ get_cd_loop(N, BCD, Acc0, PrimZip, FileName, Offset, CFH, EndOffset, FilterFun, end, %% erlang:display({FileName, N, Offset, Size, NextPF}), GetInfo = fun() -> cd_file_header_to_file_info(FileName, CFH, <<>>) end, - GetBin = fun() -> get_z_file(FileName, Offset, Size, PrimZip) end, + GetBin = fun() -> get_z_file(FileName, Offset, Size, PrimZip) end, PF = #primzip_file{name = FileName, get_info = GetInfo, get_bin = GetBin}, case FilterFun({FileName, GetInfo, GetBin}, FilterAcc) of {Continue, Include, FilterAcc2} -> Acc1 = case Include of - false -> Acc0; - true -> [PF | Acc0]; - {true, Nick} -> [PF#primzip_file{name = Nick} | Acc0] + false -> + Acc0; + true -> + [PF | Acc0]; + {true, Nick} -> + [PF#primzip_file{name = Nick} | Acc0]; + {true, Nick, GI, GB} -> + PF2 = #primzip_file{name = Nick, get_info = GI, get_bin = GB}, + [PF2 | Acc0]; + List when is_list(List) -> + %% Add new entries + Fun = fun(I, A) -> include_acc(I, PF, A) end, + lists_foldl(Fun, Acc0, List) end, case Continue of true when N > 1 -> diff --git a/erts/test/erl_print_SUITE.erl b/erts/test/erl_print_SUITE.erl index b1458d84d0..3bb7d4d016 100644 --- a/erts/test/erl_print_SUITE.erl +++ b/erts/test/erl_print_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% %% @@ -36,7 +36,7 @@ -export([erlang_display/1, integer/1, float/1, string/1, character/1, snprintf/1, quote/1]). --include("test_server.hrl"). +-include_lib("test_server/include/test_server.hrl"). all(doc) -> []; all(suite) -> test_cases(). diff --git a/erts/test/erlc_SUITE.erl b/erts/test/erlc_SUITE.erl index 1d944811aa..437f020f99 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). @@ -23,7 +23,7 @@ -export([all/1, compile_erl/1, compile_yecc/1, compile_script/1, compile_mib/1, good_citizen/1, deep_cwd/1]). --include("test_server.hrl"). +-include_lib("test_server/include/test_server.hrl"). all(suite) -> [compile_erl, compile_yecc, compile_script, compile_mib, @@ -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"), diff --git a/erts/test/erlexec_SUITE.erl b/erts/test/erlexec_SUITE.erl index fcf1e67e9e..164ce9faaf 100644 --- a/erts/test/erlexec_SUITE.erl +++ b/erts/test/erlexec_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2007-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,7 +35,7 @@ -export([args_file/1, evil_args_file/1, env/1, args_file_env/1, otp_7461/1, otp_7461_remote/1, otp_8209/1]). --include("test_server.hrl"). +-include_lib("test_server/include/test_server.hrl"). init_per_testcase(Case, Config) -> diff --git a/erts/test/ethread_SUITE.erl b/erts/test/ethread_SUITE.erl index a8f4f5e90c..bbc79e9381 100644 --- a/erts/test/ethread_SUITE.erl +++ b/erts/test/ethread_SUITE.erl @@ -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% %% @@ -53,7 +53,7 @@ atomic/1, gate/1]). --include("test_server.hrl"). +-include_lib("test_server/include/test_server.hrl"). tests() -> [create_join_thread, diff --git a/erts/test/ignore_cores.erl b/erts/test/ignore_cores.erl index 7ec2cac706..8b1ac0fe6c 100644 --- a/erts/test/ignore_cores.erl +++ b/erts/test/ignore_cores.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-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,7 +27,7 @@ -module(ignore_cores). --include("test_server.hrl"). +-include_lib("test_server/include/test_server.hrl"). -export([init/1, fini/1, setup/3, setup/4, restore/1, dir/1]). diff --git a/erts/test/nt_SUITE.erl b/erts/test/nt_SUITE.erl index 7ff5c908e6..530fb55270 100644 --- a/erts/test/nt_SUITE.erl +++ b/erts/test/nt_SUITE.erl @@ -1,24 +1,25 @@ %% %% %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% %% %%% Purpose: Test NT specific utilities -module(nt_SUITE). --include("test_server.hrl"). + +-include_lib("test_server/include/test_server.hrl"). -include_lib("kernel/include/file.hrl"). -export([all/1,init_per_testcase/2,fin_per_testcase/2,nt/1,handle_eventlog/2, diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl index c6769743dd..425ad31782 100644 --- a/erts/test/otp_SUITE.erl +++ b/erts/test/otp_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2000-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2000-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,7 +24,8 @@ obsolete_but_not_deprecated/1,call_to_deprecated/1, call_to_size_1/1,strong_components/1]). --include("test_server.hrl"). +-include_lib("test_server/include/test_server.hrl"). + -import(lists, [filter/2,foldl/3,foreach/2]). all(suite) -> diff --git a/erts/test/run_erl_SUITE.erl b/erts/test/run_erl_SUITE.erl index afff4120d4..efeafbad8c 100644 --- a/erts/test/run_erl_SUITE.erl +++ b/erts/test/run_erl_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% %% @@ -23,7 +23,7 @@ basic/1,heavy/1,heavier/1,defunct/1]). -export([ping_me_back/1]). --include("test_server.hrl"). +-include_lib("test_server/include/test_server.hrl"). init_per_testcase(_Case, Config) -> Dog = ?t:timetrap(?t:minutes(2)), diff --git a/erts/test/z_SUITE.erl b/erts/test/z_SUITE.erl index 0e37af1ca2..8faddeb0d3 100644 --- a/erts/test/z_SUITE.erl +++ b/erts/test/z_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-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% %% @@ -39,7 +39,7 @@ -export([search_for_core_files/1, core_files/1]). --include("test_server.hrl"). +-include_lib("test_server/include/test_server.hrl"). init_per_testcase(Case, Config) -> |