diff options
Diffstat (limited to 'erts')
30 files changed, 533 insertions, 126 deletions
diff --git a/erts/aclocal.m4 b/erts/aclocal.m4 index b1cf1fe404..9578cd35c4 100644 --- a/erts/aclocal.m4 +++ b/erts/aclocal.m4 @@ -740,11 +740,16 @@ dnl Try to find POSIX threads dnl The usual pthread lib... AC_CHECK_LIB(pthread, pthread_create, THR_LIBS="-lpthread") -dnl FreeBSD has pthreads in special c library, c_r... +dnl Very old versions of FreeBSD have pthreads in special c library, c_r... if test "x$THR_LIBS" = "x"; then AC_CHECK_LIB(c_r, pthread_create, THR_LIBS="-lc_r") fi +dnl QNX has pthreads in standard C library + if test "x$THR_LIBS" = "x"; then + AC_CHECK_FUNC(pthread_create, THR_LIBS="none_needed") + fi + dnl On ofs1 the '-pthread' switch should be used if test "x$THR_LIBS" = "x"; then AC_MSG_CHECKING([if the '-pthread' switch can be used]) @@ -765,6 +770,9 @@ dnl On ofs1 the '-pthread' switch should be used if test "x$THR_LIBS" != "x"; then THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS" THR_LIB_NAME=pthread + if test "x$THR_LIBS" = "xnone_needed"; then + THR_LIBS= + fi case $host_os in solaris*) THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;; diff --git a/erts/configure.in b/erts/configure.in index 6ad1951a4e..3256b0cb59 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -2000,8 +2000,12 @@ case "$erts_cv_have_in6addr_loopback" in [Define to 1 if you have the variable in6addr_loopback declared.]) esac -AC_CHECK_DECLS([IN6ADDR_ANY_INIT, IN6ADDR_LOOPBACK_INIT], [], [], - [#include <netinet/in.h>]) +AC_CHECK_DECLS([IN6ADDR_ANY_INIT, IN6ADDR_LOOPBACK_INIT, IPV6_V6ONLY], [], [], + [ + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + ]) dnl ---------------------------------------------------------------------- dnl Checks for features/quirks in the system that affects Erlang. diff --git a/erts/doc/src/driver_entry.xml b/erts/doc/src/driver_entry.xml index a2efdf3ebc..f31b0cb18b 100644 --- a/erts/doc/src/driver_entry.xml +++ b/erts/doc/src/driver_entry.xml @@ -4,7 +4,7 @@ <cref> <header> <copyright> - <year>2001</year><year>2011</year> + <year>2001</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -34,6 +34,29 @@ <lib>driver_entry</lib> <libsummary>The driver-entry structure used by erlang drivers.</libsummary> <description> + <marker id="WARNING"/> + <warning><p><em>Use this functionality with extreme care!</em></p> + <p>A driver callback is executed as a direct extension of the + native code of the VM. Execution is not made in a safe environment. + The VM can <em>not</em> provide the same services as provided when + executing Erlang code, such as preemptive scheduling or memory + protection. If the driver callback function doesn't behave well, + the whole VM will misbehave.</p> + <list> + <item><p>A driver callback that crash will crash the whole VM.</p></item> + <item><p>An erroneously implemented driver callback might cause + a VM internal state inconsistency which may cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the call + to the driver callback.</p></item> + <item><p>A driver callback that do + <seealso marker="erl_driver#lengthy_work">lengthy work</seealso> + before returning will degrade responsiveness of the VM, + and may cause miscellaneous strange behaviors. Such strange behaviors + include, but are not limited to, extreme memory usage, and bad load + balancing between schedulers. Strange behaviors that might occur due + to lengthy work may also vary between OTP releases.</p></item> + </list> + </warning> <p> As of erts version 5.9 (OTP release R15B) the driver interface has been changed with larger types for the callbacks diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml index 187c263b60..e16fd744c0 100644 --- a/erts/doc/src/erl_driver.xml +++ b/erts/doc/src/erl_driver.xml @@ -34,6 +34,32 @@ <lib>erl_driver</lib> <libsummary>API functions for an Erlang driver</libsummary> <description> + <p>An Erlang driver is a library containing a set of native driver + callback functions that the Erlang VM calls when certain + events occur. There may be multiple instances of a driver, each + instance is associated with an Erlang port.</p> + <marker id="WARNING"/> + <warning><p><em>Use this functionality with extreme care!</em></p> + <p>A driver callback is executed as a direct extension of the + native code of the VM. Execution is not made in a safe environment. + The VM can <em>not</em> provide the same services as provided when + executing Erlang code, such as preemptive scheduling or memory + protection. If the driver callback function doesn't behave well, + the whole VM will misbehave.</p> + <list> + <item><p>A driver callback that crash will crash the whole VM.</p></item> + <item><p>An erroneously implemented driver callback might cause + a VM internal state inconsistency which may cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the call + to the driver callback.</p></item> + <item><p>A driver callback that do <seealso marker="#lengthy_work">lengthy + work</seealso> before returning will degrade responsiveness of the VM, + and may cause miscellaneous strange behaviors. Such strange behaviors + include, but are not limited to, extreme memory usage, and bad load + balancing between schedulers. Strange behaviors that might occur due + to lengthy work may also vary between OTP releases.</p></item> + </list> + </warning> <p>As of erts version 5.5.3 the driver interface has been extended (see <seealso marker="driver_entry#extended_marker">extended marker</seealso>). The extended interface introduce @@ -53,16 +79,12 @@ <p>The driver calls back to the emulator, using the API functions declared in <c>erl_driver.h</c>. They are used for outputting data from the driver, using timers, etc.</p> - <p>A driver is a library with a set of function that the emulator - calls, in response to Erlang functions and message - sending. There may be multiple instances of a driver, each - instance is connected to an Erlang port. Every port has a port - owner process. Communication with the port is normally done - through the port owner process.</p> - <p>Most of the functions take the <c>port</c> handle as an - argument. This identifies the driver instance. Note that this - port handle must be stored by the driver, it is not given when - the driver is called from the emulator (see + <p>Each driver instance is associated with a port. Every port + has a port owner process. Communication with the port is normally + done through the port owner process. Most of the functions take + the <c>port</c> handle as an argument. This identifies the driver + instance. Note that this port handle must be stored by the driver, + it is not given when the driver is called from the emulator (see <seealso marker="driver_entry#emulator">driver_entry</seealso>).</p> <p>Some of the functions take a parameter of type <c>ErlDrvBinary</c>, a driver binary. It should be both @@ -129,6 +151,21 @@ are <em>only</em> thread safe when used in a runtime system with SMP support.</p> </note> + <p><marker id="lengthy_work"/> + As mentioned in the <seealso marker="#WARNING">warning</seealso> text at + the beginning of this document it is of vital importance that a driver callback + does return relatively fast. It is hard to give an exact maximum amount + of time that a driver callback is allowed to work, but as a rule of thumb + a well behaving driver callback should return before a millisecond has + passed. This can be achieved using different approaches. + If you have full control over the code that are to execute in the driver + callback, the best approach is to divide the work into multiple chunks of + work and trigger multiple calls to the + <seealso marker="driver_entry#timeout">timeout callback</seealso> using + zero timeouts. This might, however, not always be possible, e.g. when + calling third party libraries. In this case you typically want to dispatch + the work to another thread. Information about thread primitives can be + found below.</p> </description> <section> diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index f484e9eaf7..f00f7b9f46 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -34,30 +34,6 @@ <lib>erl_nif</lib> <libsummary>API functions for an Erlang NIF library</libsummary> <description> - <note><p>The NIF concept is officially supported from R14B. NIF source code - written for earlier experimental versions might need adaption to run on R14B.</p> - <p>No incompatible changes between <em>R14B</em> and R14A.</p> - <p>Incompatible changes between <em>R14A</em> and R13B04:</p> - <list> - <item>Environment argument removed for <c>enif_alloc</c>, - <c>enif_realloc</c>, <c>enif_free</c>, <c>enif_alloc_binary</c>, - <c>enif_realloc_binary</c>, <c>enif_release_binary</c>, - <c>enif_alloc_resource</c>, <c>enif_release_resource</c>, - <c>enif_is_identical</c> and <c>enif_compare</c>.</item> - <item>Character encoding argument added to <c>enif_get_atom</c> - and <c>enif_make_existing_atom</c>.</item> - <item>Module argument added to <c>enif_open_resource_type</c> - while changing name spaces of resource types from global to module local.</item> - </list> - <p>Incompatible changes between <em>R13B04</em> and R13B03:</p> - <list> - <item>The function prototypes of the NIFs have changed to expect <c>argc</c> and <c>argv</c> - arguments. The arity of a NIF is by that no longer limited to 3.</item> - <item><c>enif_get_data</c> renamed as <c>enif_priv_data</c>.</item> - <item><c>enif_make_string</c> got a third argument for character encoding.</item> - </list> - </note> - <p>A NIF library contains native implementation of some functions of an Erlang module. The native implemented functions (NIFs) are called like any other functions without any difference to the @@ -67,6 +43,57 @@ is to throw an exception. But it can also be used as a fallback implementation if the NIF library is not implemented for some architecture.</p> + <marker id="WARNING"/> + <warning><p><em>Use this functionality with extreme care!</em></p> + <p>A native function is executed as a direct extension of the + native code of the VM. Execution is not made in a safe environment. + The VM can <em>not</em> provide the same services as provided when + executing Erlang code, such as preemptive scheduling or memory + protection. If the native function doesn't behave well, the whole + VM will misbehave.</p> + <list> + <item><p>A native function that crash will crash the whole VM.</p></item> + <item><p>An erroneously implemented native function might cause + a VM internal state inconsistency which may cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the call + to the native function.</p></item> + <item><p>A native function that do <seealso marker="#lengthy_work">lengthy + work</seealso> before returning will degrade responsiveness of the VM, + and may cause miscellaneous strange behaviors. Such strange behaviors + include, but are not limited to, extreme memory usage, and bad load + balancing between schedulers. Strange behaviors that might occur due + to lengthy work may also vary between OTP releases.</p></item> + </list> + </warning> + + <p>The NIF concept is officially supported from R14B. NIF source code + written for earlier experimental versions might need adaption to run on R14B + or later versions:</p> + <list> + <item>No incompatible changes between <em>R14B</em> and R14A.</item> + <item>Incompatible changes between <em>R14A</em> and R13B04: + <list> + <item>Environment argument removed for <c>enif_alloc</c>, + <c>enif_realloc</c>, <c>enif_free</c>, <c>enif_alloc_binary</c>, + <c>enif_realloc_binary</c>, <c>enif_release_binary</c>, + <c>enif_alloc_resource</c>, <c>enif_release_resource</c>, + <c>enif_is_identical</c> and <c>enif_compare</c>.</item> + <item>Character encoding argument added to <c>enif_get_atom</c> + and <c>enif_make_existing_atom</c>.</item> + <item>Module argument added to <c>enif_open_resource_type</c> + while changing name spaces of resource types from global to module local.</item> + </list> + </item> + <item>Incompatible changes between <em>R13B04</em> and R13B03: + <list> + <item>The function prototypes of the NIFs have changed to expect <c>argc</c> and <c>argv</c> + arguments. The arity of a NIF is by that no longer limited to 3.</item> + <item><c>enif_get_data</c> renamed as <c>enif_priv_data</c>.</item> + <item><c>enif_make_string</c> got a third argument for character encoding.</item> + </list> + </item> + </list> + <p>A minimal example of a NIF library can look like this:</p> <p/> <code type="none"> @@ -136,7 +163,23 @@ ok then retrieved by calling <seealso marker="#enif_priv_data">enif_priv_data</seealso>.</p> <p>There is no way to explicitly unload a NIF library. A library will be automatically unloaded when the module code that it belongs to is purged - by the code server.</p> + by the code server.</p> + + <p><marker id="lengthy_work"/> + As mentioned in the <seealso marker="#WARNING">warning</seealso> text at + the beginning of this document it is of vital importance that a native function + does return relatively fast. It is hard to give an exact maximum amount + of time that a native function is allowed to work, but as a rule of thumb + a well behaving native function should return to its caller before a + millisecond has passed. This can be achieved using different approaches. + If you have full control over the code that are to execute in the native + function, the best approach is to divide the work into multiple chunks of + work and call the native function multiple times. This might, however, + not always be possible, e.g. when calling third party libraries. In this + case you typically want to dispatch the work to another thread, return + from the native function, and wait for the result. The thread can send + the result back to the calling thread using message passing. Information + about thread primitives can be found below.</p> </description> <section> <title>FUNCTIONALITY</title> @@ -266,10 +309,6 @@ ok mutable.</p> <p>The library initialization callbacks <c>load</c>, <c>reload</c> and <c>upgrade</c> are all thread-safe even for shared state data.</p> - <p>Avoid doing lengthy work in NIF calls as that may degrade the - responsiveness of the VM. NIFs are called directly by the same scheduler - thread that executed the calling Erlang code. The calling scheduler will thus - be blocked from doing any other work until the NIF returns.</p> </item> </taglist> </section> diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c index 6bc227eeda..3753b618e1 100644 --- a/erts/emulator/beam/erl_bits.c +++ b/erts/emulator/beam/erl_bits.c @@ -1247,6 +1247,12 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, */ erts_bin_offset = 8*sb->size + sb->bitsize; + if (unit > 1) { + if ((unit == 8 && (erts_bin_offset & 7) != 0) || + (erts_bin_offset % unit) != 0) { + goto badarg; + } + } used_size_in_bits = erts_bin_offset + build_size_in_bits; sb->is_writable = 0; /* Make sure that no one else can write. */ pb->size = NBYTES(used_size_in_bits); @@ -1316,6 +1322,12 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, */ ERTS_GET_BINARY_BYTES(bin, src_bytes, bitoffs, bitsize); erts_bin_offset = 8*binary_size(bin) + bitsize; + if (unit > 1) { + if ((unit == 8 && (erts_bin_offset & 7) != 0) || + (erts_bin_offset % unit) != 0) { + goto badarg; + } + } used_size_in_bits = erts_bin_offset + build_size_in_bits; used_size_in_bytes = NBYTES(used_size_in_bits); bin_size = 2*used_size_in_bytes; @@ -1363,12 +1375,6 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, /* * Now copy the data into the binary. */ - if (unit > 1) { - if ((unit == 8 && (erts_bin_offset & 7) != 0) || - (erts_bin_offset % unit) != 0) { - return THE_NON_VALUE; - } - } copy_binary_to_buffer(erts_current_bin, 0, src_bytes, bitoffs, erts_bin_offset); return make_binary(sb); diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c index 4c30905495..1ba1048afa 100644 --- a/erts/emulator/beam/erl_db.c +++ b/erts/emulator/beam/erl_db.c @@ -251,7 +251,6 @@ free_dbtable(void *vtb) #endif ASSERT(is_immed(tb->common.heir_data)); erts_db_free(ERTS_ALC_T_DB_TABLE, tb, (void *) tb, sizeof(DbTable)); - ERTS_ETS_MISC_MEM_ADD(-sizeof(DbTable)); } static void schedule_free_dbtable(DbTable* tb) @@ -1423,7 +1422,6 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2) erts_smp_atomic_init_nob(&init_tb.common.memory_size, 0); tb = (DbTable*) erts_db_alloc(ERTS_ALC_T_DB_TABLE, &init_tb, sizeof(DbTable)); - ERTS_ETS_MISC_MEM_ADD(sizeof(DbTable)); erts_smp_atomic_init_nob(&tb->common.memory_size, erts_smp_atomic_read_nob(&init_tb.common.memory_size)); } @@ -2867,7 +2865,6 @@ void init_db(void) meta_pid_to_tab = (DbTable*) erts_db_alloc(ERTS_ALC_T_DB_TABLE, &init_tb, sizeof(DbTable)); - ERTS_ETS_MISC_MEM_ADD(sizeof(DbTable)); erts_smp_atomic_init_nob(&meta_pid_to_tab->common.memory_size, erts_smp_atomic_read_nob(&init_tb.common.memory_size)); @@ -2899,7 +2896,6 @@ void init_db(void) meta_pid_to_fixed_tab = (DbTable*) erts_db_alloc(ERTS_ALC_T_DB_TABLE, &init_tb, sizeof(DbTable)); - ERTS_ETS_MISC_MEM_ADD(sizeof(DbTable)); erts_smp_atomic_init_nob(&meta_pid_to_fixed_tab->common.memory_size, erts_smp_atomic_read_nob(&init_tb.common.memory_size)); diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 6075a527c3..5ae4b9254b 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -336,6 +336,19 @@ erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity) return result; } +static ERTS_INLINE void reset_active_writer(Process *p) +{ + struct erl_off_heap_header* ptr; + ptr = MSO(p).first; + while (ptr) { + if (ptr->thing_word == HEADER_PROC_BIN) { + ProcBin *pbp = (ProcBin*) ptr; + pbp->flags &= ~PB_ACTIVE_WRITER; + } + ptr = ptr->next; + } +} + /* * Garbage collect a process. * @@ -391,6 +404,7 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj) DTRACE2(gc_minor_end, pidbuf, reclaimed_now); } } + reset_active_writer(p); /* * Finish. @@ -2166,7 +2180,6 @@ link_live_proc_bin(struct shrink_cand_data *shrink, if (pbp->flags & PB_ACTIVE_WRITER) { - pbp->flags &= ~PB_ACTIVE_WRITER; shrink->no_of_active++; } else { /* inactive */ diff --git a/erts/emulator/beam/erl_lock_check.h b/erts/emulator/beam/erl_lock_check.h index b67f36fa06..df7b3758e1 100644 --- a/erts/emulator/beam/erl_lock_check.h +++ b/erts/emulator/beam/erl_lock_check.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2005-2011. All Rights Reserved. + * Copyright Ericsson AB 2005-2012. 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 @@ -104,7 +104,7 @@ void erts_lc_unrequire_lock(erts_lc_lock_t *lck); #define ERTS_LC_ASSERT(A) \ - ((void) ((A) ? 1 : erts_lc_assert_failed(__FILE__, __LINE__, #A))) + ((void) (((A) || ERTS_SOMEONE_IS_CRASH_DUMPING) ? 1 : erts_lc_assert_failed(__FILE__, __LINE__, #A))) #ifdef ERTS_SMP #define ERTS_SMP_LC_ASSERT(A) ERTS_LC_ASSERT(A) #else diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c index 86454fe1fa..b6bc59a1c3 100644 --- a/erts/emulator/beam/erl_port_task.c +++ b/erts/emulator/beam/erl_port_task.c @@ -524,13 +524,8 @@ erts_port_task_schedule(Eterm id, ERTS_PT_CHK_PRES_PORTQ(runq, pp); - if (!pp->sched.taskq) { - pp->sched.taskq = port_taskq_init(port_taskq_alloc(), pp); - enq_port = !pp->sched.in_runq && !pp->sched.exe_taskq; - } - + if (!pp->sched.taskq && !pp->sched.in_runq && !pp->sched.exe_taskq) { #ifdef ERTS_SMP - if (enq_port) { ErtsRunQueue *xrunq = erts_check_emigration_need(runq, ERTS_PORT_PRIO_LEVEL); if (xrunq) { /* Port emigrated ... */ @@ -540,10 +535,18 @@ erts_port_task_schedule(Eterm id, if (!runq) return -1; } - } + enq_port = !pp->sched.taskq && !pp->sched.in_runq && !pp->sched.exe_taskq; +#else + enq_port = 1; #endif + } + + ASSERT(!enq_port + || !(ERTS_RUNQ_FLGS_GET_NOB(runq) & ERTS_RUNQ_FLG_SUSPENDED)); + + if (!pp->sched.taskq) + pp->sched.taskq = port_taskq_init(port_taskq_alloc(), pp); - ASSERT(pp->sched.taskq); ASSERT(ptp); ptp->type = type; @@ -932,8 +935,9 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp) #endif done: - ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(runq)); + runq->scheduler->reductions += reds; + ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(runq)); ERTS_PORT_REDUCTIONS_EXECUTED(runq, reds); return res; diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 09169ba914..61554780c4 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -43,6 +43,9 @@ #include "erl_async.h" #include "dtrace-wrapper.h" +#define ERTS_DELAYED_WAKEUP_INFINITY (~(Uint64) 0) +#define ERTS_DELAYED_WAKEUP_REDUCTIONS ((Uint64) CONTEXT_REDS/2) + #define ERTS_RUNQ_CHECK_BALANCE_REDS_PER_SCHED (2000*CONTEXT_REDS) #define ERTS_RUNQ_CALL_CHECK_BALANCE_REDS \ (ERTS_RUNQ_CHECK_BALANCE_REDS_PER_SCHED/2) @@ -1176,9 +1179,15 @@ haw_thr_prgr_current_check_progress(ErtsAuxWorkData *awdp) } static ERTS_INLINE erts_aint32_t -handle_delayed_aux_work_wakeup(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_delayed_aux_work_wakeup(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { int jix, max_jix; + + ASSERT(awdp->delayed_wakeup.next != ERTS_DELAYED_WAKEUP_INFINITY); + + if (!waiting && awdp->delayed_wakeup.next > awdp->esdp->reductions) + return aux_work; + unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP); ERTS_THR_MEMORY_BARRIER; @@ -1194,11 +1203,14 @@ handle_delayed_aux_work_wakeup(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(sched-1), aux_work); } + awdp->delayed_wakeup.next = ERTS_DELAYED_WAKEUP_INFINITY; return aux_work & ~ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP; } static ERTS_INLINE void -schedule_aux_work_wakeup(ErtsAuxWorkData *awdp, int sched, erts_aint32_t aux_work) +schedule_aux_work_wakeup(ErtsAuxWorkData *awdp, + int sched, + erts_aint32_t aux_work) { int jix = awdp->delayed_wakeup.sched2jix[sched]; if (jix >= 0) { @@ -1211,7 +1223,20 @@ schedule_aux_work_wakeup(ErtsAuxWorkData *awdp, int sched, erts_aint32_t aux_wor awdp->delayed_wakeup.job[jix].sched = sched; awdp->delayed_wakeup.job[jix].aux_work = aux_work; } - set_aux_work_flags_wakeup_nob(awdp->ssi, ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP); + + if (awdp->delayed_wakeup.next != ERTS_DELAYED_WAKEUP_INFINITY) { + ASSERT(erts_atomic32_read_nob(&awdp->ssi->aux_work) + & ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP); + } + else { + awdp->delayed_wakeup.next = (awdp->esdp->reductions + + ERTS_DELAYED_WAKEUP_REDUCTIONS); + + ASSERT(!(erts_atomic32_read_nob(&awdp->ssi->aux_work) + & ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP)); + set_aux_work_flags_wakeup_nob(awdp->ssi, + ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP); + } } #endif @@ -1290,7 +1315,8 @@ misc_aux_work_clean(ErtsThrQ_t *q, static ERTS_INLINE erts_aint32_t handle_misc_aux_work(ErtsAuxWorkData *awdp, - erts_aint32_t aux_work) + erts_aint32_t aux_work, + int waiting) { ErtsThrQ_t *q = &misc_aux_work_queues[awdp->sched_id].q; @@ -1310,7 +1336,8 @@ handle_misc_aux_work(ErtsAuxWorkData *awdp, static ERTS_INLINE erts_aint32_t handle_misc_aux_work_thr_prgr(ErtsAuxWorkData *awdp, - erts_aint32_t aux_work) + erts_aint32_t aux_work, + int waiting) { if (!erts_thr_progress_has_reached_this(haw_thr_prgr_current(awdp), awdp->misc.thr_prgr)) @@ -1389,7 +1416,8 @@ erts_notify_check_async_ready_queue(void *vno) static ERTS_INLINE erts_aint32_t handle_async_ready(ErtsAuxWorkData *awdp, - erts_aint32_t aux_work) + erts_aint32_t aux_work, + int waiting) { ErtsSchedulerSleepInfo *ssi = awdp->ssi; unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_ASYNC_READY); @@ -1411,7 +1439,8 @@ handle_async_ready(ErtsAuxWorkData *awdp, static ERTS_INLINE erts_aint32_t handle_async_ready_clean(ErtsAuxWorkData *awdp, - erts_aint32_t aux_work) + erts_aint32_t aux_work, + int waiting) { void *thr_prgr_p; @@ -1448,7 +1477,7 @@ handle_async_ready_clean(ErtsAuxWorkData *awdp, static ERTS_INLINE erts_aint32_t -handle_fix_alloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_fix_alloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { ErtsSchedulerSleepInfo *ssi = awdp->ssi; erts_aint32_t res; @@ -1482,7 +1511,7 @@ erts_alloc_notify_delayed_dealloc(int ix) } static ERTS_INLINE erts_aint32_t -handle_delayed_dealloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_delayed_dealloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { ErtsSchedulerSleepInfo *ssi = awdp->ssi; int need_thr_progress = 0; @@ -1520,7 +1549,7 @@ handle_delayed_dealloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) } static ERTS_INLINE erts_aint32_t -handle_delayed_dealloc_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_delayed_dealloc_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { ErtsSchedulerSleepInfo *ssi; int need_thr_progress; @@ -1570,7 +1599,7 @@ handle_delayed_dealloc_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) #define ERTS_MAX_THR_PRGR_LATER_OPS 50 static ERTS_INLINE erts_aint32_t -handle_thr_prgr_later_op(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_thr_prgr_later_op(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { int lops; ErtsThrPrgrVal current = haw_thr_prgr_current(awdp); @@ -1719,7 +1748,7 @@ erts_smp_notify_check_children_needed(void) } static ERTS_INLINE erts_aint32_t -handle_check_children(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_check_children(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_CHECK_CHILDREN); erts_check_children(); @@ -1742,7 +1771,7 @@ erts_smp_atomic32_t erts_halt_progress; int erts_halt_code; static ERTS_INLINE erts_aint32_t -handle_reap_ports(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_reap_ports(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_REAP_PORTS); awdp->esdp->run_queue->halt_in_progress = 1; @@ -1790,7 +1819,7 @@ handle_reap_ports(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) #if HAVE_ERTS_MSEG static ERTS_INLINE erts_aint32_t -handle_mseg_cache_check(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_mseg_cache_check(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK); erts_mseg_cache_check(); @@ -1800,7 +1829,7 @@ handle_mseg_cache_check(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) #endif static ERTS_INLINE erts_aint32_t -handle_setup_aux_work_timer(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_setup_aux_work_timer(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_SET_TMO); setup_aux_work_timer(); @@ -1814,7 +1843,7 @@ handle_aux_work(ErtsAuxWorkData *awdp, erts_aint32_t orig_aux_work, int waiting) #define HANDLE_AUX_WORK(FLG, HNDLR) \ ignore |= FLG; \ if (aux_work & FLG) { \ - aux_work = HNDLR(awdp, aux_work); \ + aux_work = HNDLR(awdp, aux_work, waiting); \ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work); \ if (!(aux_work & ~ignore)) { \ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work); \ @@ -4584,6 +4613,7 @@ init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp, char *dawwp) awdp->async_ready.queue = NULL; #endif #ifdef ERTS_SMP + awdp->delayed_wakeup.next = ERTS_DELAYED_WAKEUP_INFINITY; if (!dawwp) { awdp->delayed_wakeup.job = NULL; awdp->delayed_wakeup.sched2jix = NULL; @@ -4778,6 +4808,9 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online) #ifdef ERTS_SMP daww_ptr += daww_sz; #endif + + esdp->reductions = 0; + init_sched_wall_time(&esdp->sched_wall_time); } @@ -6863,6 +6896,8 @@ Process *schedule(Process *p, int calls) | ERTS_PROC_LOCK_STATUS)); #endif + esdp->reductions += reds; + schedule_out_process(rq, state, p); /* Returns with rq locked! */ ERTS_PROC_REDUCTIONS_EXECUTED(rq, diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index fa6961e8a4..e789c873fb 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -478,6 +478,7 @@ typedef struct { #endif #ifdef ERTS_SMP struct { + Uint64 next; int *sched2jix; int jix; ErtsDelayedAuxWorkWakeupJob *job; @@ -520,6 +521,7 @@ struct ErtsSchedulerData_ { ErtsSchedAllocData alloc_data; + Uint64 reductions; ErtsSchedWallTime sched_wall_time; #ifdef ERTS_DO_VERIFY_UNUSED_TEMP_ALLOC diff --git a/erts/emulator/beam/index.c b/erts/emulator/beam/index.c index c981a0a55e..79c3ecf1b3 100644 --- a/erts/emulator/beam/index.c +++ b/erts/emulator/beam/index.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. + * Copyright Ericsson AB 1996-2012. 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 diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index 80f504a361..3210ffa92a 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -660,6 +660,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n) #define UDP_OPT_MULTICAST_LOOP 13 /* set/get IP multicast loopback */ #define UDP_OPT_ADD_MEMBERSHIP 14 /* add an IP group membership */ #define UDP_OPT_DROP_MEMBERSHIP 15 /* drop an IP group membership */ +#define INET_OPT_IPV6_V6ONLY 16 /* IPv6 only socket, no mapped v4 addrs */ /* LOPT is local options */ #define INET_LOPT_BUFFER 20 /* min buffer size hint */ #define INET_LOPT_HEADER 21 /* list header size */ @@ -1167,6 +1168,7 @@ static ErlDrvTermData am_reuseaddr; static ErlDrvTermData am_dontroute; static ErlDrvTermData am_priority; static ErlDrvTermData am_tos; +static ErlDrvTermData am_ipv6_v6only; #endif /* speical errors for bad ports and sequences */ @@ -3486,6 +3488,7 @@ static void inet_init_sctp(void) { INIT_ATOM(dontroute); INIT_ATOM(priority); INIT_ATOM(tos); + INIT_ATOM(ipv6_v6only); /* Option names */ INIT_ATOM(sctp_rtoinfo); @@ -5618,6 +5621,23 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len) #endif /* HAVE_MULTICAST_SUPPORT */ + case INET_OPT_IPV6_V6ONLY: +#if HAVE_DECL_IPV6_V6ONLY + proto = IPPROTO_IPV6; + type = IPV6_V6ONLY; + propagate = 1; + DEBUGF(("inet_set_opts(%ld): s=%d, IPV6_V6ONLY=%d\r\n", + (long)desc->port, desc->s, ival)); + break; +#elif defined(__WIN32__) && defined(HAVE_IN6) && defined(AF_INET6) + /* Fake a'la OpenBSD; set to 'true' is fine but 'false' invalid. */ + if (ival != 0) continue; + else return -1; + break; +#else + continue; +#endif + case INET_OPT_RAW: if (len < 8) { return -1; @@ -5947,6 +5967,22 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) continue; /* Option not supported -- ignore it */ # endif + case INET_OPT_IPV6_V6ONLY: +# if HAVE_DECL_IPV6_V6ONLY + { + arg.ival= get_int32 (curr); curr += 4; + proto = IPPROTO_IPV6; + type = IPV6_V6ONLY; + arg_ptr = (char*) (&arg.ival); + arg_sz = sizeof ( arg.ival); + break; + } +# elif defined(__WIN32__) && defined(HAVE_IN6) && defined(AF_INET6) +# error Here is a fix for Win IPv6 SCTP missing +# else + continue; /* Option not supported -- ignore it */ +# endif + case SCTP_OPT_AUTOCLOSE: { arg.ival= get_int32 (curr); curr += 4; @@ -6435,6 +6471,22 @@ static ErlDrvSSizeT inet_fill_opts(inet_descriptor* desc, break; #endif /* HAVE_MULTICAST_SUPPORT */ + case INET_OPT_IPV6_V6ONLY: +#if HAVE_DECL_IPV6_V6ONLY + proto = IPPROTO_IPV6; + type = IPV6_V6ONLY; + break; +#elif defined(__WIN32__) && defined(HAVE_IN6) && defined(AF_INET6) + /* Fake reading 'true' */ + *ptr++ = opt; + put_int32(1, ptr); + ptr += 4; + continue; +#else + TRUNCATE_TO(0,ptr); + continue; /* skip - no result */ +#endif + case INET_OPT_RAW: { int data_provided; @@ -6739,6 +6791,7 @@ static ErlDrvSSizeT sctp_fill_opts(inet_descriptor* desc, case INET_OPT_DONTROUTE: case INET_OPT_PRIORITY : case INET_OPT_TOS : + case INET_OPT_IPV6_V6ONLY: case SCTP_OPT_AUTOCLOSE: case SCTP_OPT_MAXSEG : /* The following options return true or false: */ @@ -6811,6 +6864,20 @@ static ErlDrvSSizeT sctp_fill_opts(inet_descriptor* desc, continue; # endif } + case INET_OPT_IPV6_V6ONLY: +# if HAVE_DECL_IPV6_V6ONLY + { + proto = IPPROTO_IPV6; + type = IPV6_V6ONLY; + tag = am_ipv6_v6only; + break; + } +# elif defined(__WIN32__) && defined(HAVE_IN6) && defined(AF_INET6) +# error Here is a fix for Win IPv6 SCTP needed +# else + /* Not supported -- ignore */ + continue; +# endif case SCTP_OPT_AUTOCLOSE: { proto = IPPROTO_SCTP; diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index 2aa373aa7d..cf7af71b92 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -851,8 +851,8 @@ efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, } #ifdef HAVE_SENDFILE -// For some reason the maximum size_t cannot be used as the max size -// 3GB seems to work on all platforms +/* For some reason the maximum size_t cannot be used as the max size + 3GB seems to work on all platforms */ #define SENDFILE_CHUNK_SIZE ((1UL << 30) -1) /* @@ -889,7 +889,7 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, #if defined(__linux__) ssize_t retval; do { - // check if *nbytes is 0 or greater than chunk size + /* check if *nbytes is 0 or greater than chunk size */ if (*nbytes == 0 || *nbytes > SENDFILE_CHUNK_SIZE) retval = sendfile(out_fd, in_fd, offset, SENDFILE_CHUNK_SIZE); else @@ -900,7 +900,7 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, } } while (retval == SENDFILE_CHUNK_SIZE); if (written != 0) { - // -1 is not returned by the linux API so we have to simulate it + /* -1 is not returned by the linux API so we have to simulate it */ retval = -1; errno = EAGAIN; } @@ -913,23 +913,29 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, do { fdrec.sfv_off = *offset; len = 0; - // check if *nbytes is 0 or greater than chunk size + /* check if *nbytes is 0 or greater than chunk size */ if (*nbytes == 0 || *nbytes > SENDFILE_CHUNK_SIZE) fdrec.sfv_len = SENDFILE_CHUNK_SIZE; else fdrec.sfv_len = *nbytes; retval = sendfilev(out_fd, &fdrec, 1, &len); - if (retval != -1 || errno == EAGAIN || errno == EINTR) { + + /* Sometimes sendfilev can return -1 and still send data. + When that happens we just pretend that no error happend. */ + if (retval != -1 || errno == EAGAIN || errno == EINTR || + len != 0) { *offset += len; *nbytes -= len; written += len; + if (errno != EAGAIN && errno != EINTR && len != 0) + retval = len; } } while (len == SENDFILE_CHUNK_SIZE); #elif defined(DARWIN) int retval; off_t len; do { - // check if *nbytes is 0 or greater than chunk size + /* check if *nbytes is 0 or greater than chunk size */ if(*nbytes > SENDFILE_CHUNK_SIZE) len = SENDFILE_CHUNK_SIZE; else diff --git a/erts/emulator/hipe/hipe_amd64_bifs.m4 b/erts/emulator/hipe/hipe_amd64_bifs.m4 index ec25c0b9b7..0de69a617f 100644 --- a/erts/emulator/hipe/hipe_amd64_bifs.m4 +++ b/erts/emulator/hipe/hipe_amd64_bifs.m4 @@ -2,7 +2,7 @@ changecom(`/*', `*/')dnl /* * %CopyrightBegin% * - * Copyright Ericsson AB 2004-2011. All Rights Reserved. + * Copyright Ericsson AB 2004-2012. 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 @@ -30,12 +30,12 @@ include(`hipe/hipe_amd64_asm.m4') #define TEST_GOT_EXN cmpq $THE_NON_VALUE, %rax #endif' -define(TEST_GOT_MBUF,`movq P_MBUF(P), %rdx # `TEST_GOT_MBUF' +define(TEST_GOT_MBUF,`movq P_MBUF(P), %rdx /* `TEST_GOT_MBUF' */ testq %rdx, %rdx jnz 3f 2:') define(HANDLE_GOT_MBUF,` -3: call nbif_$1_gc_after_bif # `HANDLE_GOT_MBUF' +3: call nbif_$1_gc_after_bif /* `HANDLE_GOT_MBUF' */ jmp 2b') `#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP) diff --git a/erts/emulator/hipe/hipe_bif_list.m4 b/erts/emulator/hipe/hipe_bif_list.m4 index d9aa09b79e..ab078b9583 100644 --- a/erts/emulator/hipe/hipe_bif_list.m4 +++ b/erts/emulator/hipe/hipe_bif_list.m4 @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2004-2011. All Rights Reserved. + * Copyright Ericsson AB 2004-2012. 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 @@ -246,7 +246,7 @@ noproc_primop_interface_5(nbif_bs_put_big_integer, hipe_bs_put_big_integer) gc_bif_interface_0(nbif_check_get_msg, hipe_check_get_msg) -#ifdef NO_FPE_SIGNALS +#`ifdef' NO_FPE_SIGNALS nocons_nofail_primop_interface_0(nbif_emulate_fpe, hipe_emulate_fpe) #endif diff --git a/erts/emulator/hipe/hipe_x86_bifs.m4 b/erts/emulator/hipe/hipe_x86_bifs.m4 index 3cb7d67be0..dd6980f555 100644 --- a/erts/emulator/hipe/hipe_x86_bifs.m4 +++ b/erts/emulator/hipe/hipe_x86_bifs.m4 @@ -2,7 +2,7 @@ changecom(`/*', `*/')dnl /* * %CopyrightBegin% * - * Copyright Ericsson AB 2001-2011. All Rights Reserved. + * Copyright Ericsson AB 2001-2012. 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 @@ -35,12 +35,12 @@ include(`hipe/hipe_x86_asm.m4') # define CALL_BIF(F) call CSYM(F) #endif' -define(TEST_GOT_MBUF,`movl P_MBUF(P), %edx # `TEST_GOT_MBUF' +define(TEST_GOT_MBUF,`movl P_MBUF(P), %edx /* `TEST_GOT_MBUF' */ testl %edx, %edx jnz 3f 2:') define(HANDLE_GOT_MBUF,` -3: call nbif_$1_gc_after_bif # `HANDLE_GOT_MBUF' +3: call nbif_$1_gc_after_bif /* `HANDLE_GOT_MBUF' */ jmp 2b') /* @@ -70,7 +70,7 @@ ASYM($1): NBIF_ARG_REG(0,P) NBIF_ARG(2,1,0) lea 8(%esp), %eax - NBIF_ARG_REG(1,%eax) # BIF__ARGS + NBIF_ARG_REG(1,%eax) /* BIF__ARGS */ CALL_BIF($2) TEST_GOT_MBUF @@ -105,7 +105,7 @@ ASYM($1): NBIF_ARG(2,2,0) NBIF_ARG(3,2,1) lea 8(%esp), %eax - NBIF_ARG_REG(1,%eax) # BIF__ARGS + NBIF_ARG_REG(1,%eax) /* BIF__ARGS */ CALL_BIF($2) TEST_GOT_MBUF @@ -141,7 +141,7 @@ ASYM($1): NBIF_ARG(3,3,1) NBIF_ARG(4,3,2) lea 8(%esp), %eax - NBIF_ARG_REG(1,%eax) # BIF__ARGS + NBIF_ARG_REG(1,%eax) /* BIF__ARGS */ CALL_BIF($2) TEST_GOT_MBUF diff --git a/erts/emulator/test/bs_bit_binaries_SUITE.erl b/erts/emulator/test/bs_bit_binaries_SUITE.erl index ff1088118d..7f2cd1e881 100644 --- a/erts/emulator/test/bs_bit_binaries_SUITE.erl +++ b/erts/emulator/test/bs_bit_binaries_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2011. All Rights Reserved. +%% Copyright Ericsson AB 2006-2012. 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 @@ -177,14 +177,55 @@ append(Config) when is_list(Config) -> cs_init(), ?line <<(-1):256/signed-unit:8>> = cs(do_append(id(<<>>), 256*8)), ?line <<(-1):256/signed-unit:8>> = cs(do_append2(id(<<>>), 256*4)), + <<(-1):256/signed-unit:8>> = cs(do_append3(id(<<>>), 256*8)), cs_end(). do_append(Bin, N) when N > 0 -> do_append(<<Bin/bits,1:1>>, N-1); do_append(Bin, 0) -> Bin. -do_append2(Bin, N) when N > 0 -> do_append2(<<Bin/bits,3:2>>, N-1); +do_append2(Bin, N) when N > 0 -> do_append2(<<Bin/binary-unit:2,3:2>>, N-1); do_append2(Bin, 0) -> Bin. +do_append3(Bin, N) when N > 0 -> + Bits = bit_size(Bin), + if + Bits rem 2 =:= 0 -> + do_append3(<<Bin/binary-unit:2,1:1>>, N-1); + Bits rem 3 =:= 0 -> + do_append3(<<Bin/binary-unit:3,1:1>>, N-1); + Bits rem 4 =:= 0 -> + do_append3(<<Bin/binary-unit:4,1:1>>, N-1); + Bits rem 5 =:= 0 -> + do_append3(<<Bin/binary-unit:5,1:1>>, N-1); + Bits rem 6 =:= 0 -> + do_append3(<<Bin/binary-unit:6,1:1>>, N-1); + Bits rem 7 =:= 0 -> + do_append3(<<Bin/binary-unit:7,1:1>>, N-1); + Bits rem 8 =:= 0 -> + do_append3(<<Bin/binary-unit:8,1:1>>, N-1); + Bits rem 9 =:= 0 -> + do_append3(<<Bin/binary-unit:9,1:1>>, N-1); + Bits rem 10 =:= 0 -> + do_append3(<<Bin/binary-unit:10,1:1>>, N-1); + Bits rem 11 =:= 0 -> + do_append3(<<Bin/binary-unit:11,1:1>>, N-1); + Bits rem 12 =:= 0 -> + do_append3(<<Bin/binary-unit:12,1:1>>, N-1); + Bits rem 13 =:= 0 -> + do_append3(<<Bin/binary-unit:13,1:1>>, N-1); + Bits rem 14 =:= 0 -> + do_append3(<<Bin/binary-unit:14,1:1>>, N-1); + Bits rem 15 =:= 0 -> + do_append3(<<Bin/binary-unit:15,1:1>>, N-1); + Bits rem 16 =:= 0 -> + do_append3(<<Bin/binary-unit:16,1:1>>, N-1); + Bits rem 17 =:= 0 -> + do_append3(<<Bin/binary-unit:17,1:1>>, N-1); + true -> + do_append3(<<Bin/binary-unit:1,1:1>>, N-1) + end; +do_append3(Bin, 0) -> Bin. + cs_init() -> erts_debug:set_internal_state(available_internal_state, true), ok. diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl index 8b5c82d968..9c88803fea 100644 --- a/erts/emulator/test/bs_construct_SUITE.erl +++ b/erts/emulator/test/bs_construct_SUITE.erl @@ -28,7 +28,7 @@ mem_leak/1, coerce_to_float/1, bjorn/1, huge_float_field/1, huge_binary/1, system_limit/1, badarg/1, copy_writable_binary/1, kostis/1, dynamic/1, bs_add/1, - otp_7422/1, zero_width/1]). + otp_7422/1, zero_width/1, bad_append/1]). -include_lib("test_server/include/test_server.hrl"). @@ -38,7 +38,8 @@ all() -> [test1, test2, test3, test4, test5, testf, not_used, in_guard, mem_leak, coerce_to_float, bjorn, huge_float_field, huge_binary, system_limit, badarg, - copy_writable_binary, kostis, dynamic, bs_add, otp_7422, zero_width]. + copy_writable_binary, kostis, dynamic, bs_add, otp_7422, zero_width, + bad_append]. groups() -> []. @@ -827,5 +828,49 @@ zero_width(Config) when is_list(Config) -> ?line {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):0>>), ok. + +bad_append(_) -> + do_bad_append(<<127:1>>, fun append_unit_3/1), + do_bad_append(<<127:2>>, fun append_unit_3/1), + do_bad_append(<<127:17>>, fun append_unit_3/1), + + do_bad_append(<<127:3>>, fun append_unit_4/1), + do_bad_append(<<127:5>>, fun append_unit_4/1), + do_bad_append(<<127:7>>, fun append_unit_4/1), + do_bad_append(<<127:199>>, fun append_unit_4/1), + + do_bad_append(<<127:7>>, fun append_unit_8/1), + do_bad_append(<<127:9>>, fun append_unit_8/1), + + do_bad_append(<<0:8>>, fun append_unit_16/1), + do_bad_append(<<0:15>>, fun append_unit_16/1), + do_bad_append(<<0:17>>, fun append_unit_16/1), + ok. + +do_bad_append(Bin0, Appender) -> + {'EXIT',{badarg,_}} = (catch Appender(Bin0)), + + Bin1 = id(<<0:3,Bin0/bitstring>>), + <<_:3,Bin2/bitstring>> = Bin1, + {'EXIT',{badarg,_}} = (catch Appender(Bin2)), + + %% Create a writable binary. + Empty = id(<<>>), + Bin3 = <<Empty/bitstring,Bin0/bitstring>>, + {'EXIT',{badarg,_}} = (catch Appender(Bin3)), + ok. + +append_unit_3(Bin) -> + <<Bin/binary-unit:3,0:1>>. + +append_unit_4(Bin) -> + <<Bin/binary-unit:4,0:1>>. + +append_unit_8(Bin) -> + <<Bin/binary,0:1>>. + +append_unit_16(Bin) -> + <<Bin/binary-unit:16,0:1>>. + id(I) -> I. diff --git a/erts/emulator/test/smoke_test_SUITE.erl b/erts/emulator/test/smoke_test_SUITE.erl index 71186d4942..6f5c2080c0 100644 --- a/erts/emulator/test/smoke_test_SUITE.erl +++ b/erts/emulator/test/smoke_test_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011. All Rights Reserved. +%% Copyright Ericsson AB 2011-2012. 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 diff --git a/erts/emulator/valgrind/suppress.halfword b/erts/emulator/valgrind/suppress.halfword new file mode 100644 index 0000000000..8fe448d897 --- /dev/null +++ b/erts/emulator/valgrind/suppress.halfword @@ -0,0 +1,56 @@ +# Extra suppressions specific for the halfword emulator. + +# --- Suppress all offheap binaries --- +# Valgrinds leak check does not recognize pointers that are stored +# at unaligned addresses. In halfword emulator we store 64-bit pointers +# to offheap data on 32-bit aligned heaps. +# We solve this by suppressing allocation of all offheap structures +# that are not referenced by other tables (ie binaries). + +{ +Halfword erts_bin_nrml_alloc +Memcheck:Leak +... +fun:erts_bin_nrml_alloc +... +} + +{ +Halfword erts_bin_realloc +Memcheck:Leak +... +fun:erts_bin_realloc +... +} + +{ +Halfword erts_bin_realloc_fnf +Memcheck:Leak +... +fun:erts_bin_realloc_fnf +... +} + +{ +Halfword erts_bin_drv_alloc +Memcheck:Leak +... +fun:erts_bin_drv_alloc +... +} + +{ +Halfword erts_bin_drv_alloc_fnf +Memcheck:Leak +... +fun:erts_bin_drv_alloc_fnf +... +} + +{ +Halfword erts_create_magic_binary +Memcheck:Leak +... +fun:erts_create_magic_binary +... +} diff --git a/erts/emulator/valgrind/suppress.patched.3.6.0 b/erts/emulator/valgrind/suppress.patched.3.6.0 index 62ba032520..b3507bdba7 100644 --- a/erts/emulator/valgrind/suppress.patched.3.6.0 +++ b/erts/emulator/valgrind/suppress.patched.3.6.0 @@ -133,26 +133,18 @@ fun:pthread_create@@GLIBC_2.2.5 { zlib; ok according to zlib developers Memcheck:Cond -fun:longest_match +... fun:deflate_slow fun:deflate } { zlib; ok according to zlib developers Memcheck:Cond -fun:longest_match +... fun:deflate_fast fun:deflate } { -zlib; ok accordnig to zlib (this one popped up with valgrind-3.6.0) -Memcheck:Cond -fun:deflate_slow -fun:deflate -fun:zlib_deflate -fun:zlib_ctl -} -{ No leak; pointer into block Memcheck:Leak fun:malloc @@ -275,6 +267,14 @@ obj:*/ssleay.* } { + Harmless assembler bug in openssl + Memcheck:Addr8 + ... + fun:AES_cbc_encrypt + ... +} + +{ erts_bits_init_state; Why is this needed? Memcheck:Leak PossiblyLost diff --git a/erts/emulator/valgrind/suppress.standard b/erts/emulator/valgrind/suppress.standard index 5a129bfd10..beecf1a7b5 100644 --- a/erts/emulator/valgrind/suppress.standard +++ b/erts/emulator/valgrind/suppress.standard @@ -120,14 +120,14 @@ fun:pthread_create@@GLIBC_2.2.5 { zlib; ok according to zlib developers Memcheck:Cond -fun:longest_match +... fun:deflate_slow fun:deflate } { zlib; ok according to zlib developers Memcheck:Cond -fun:longest_match +... fun:deflate_fast fun:deflate } @@ -252,6 +252,14 @@ obj:*/ssleay.* } { + Harmless assembler bug in openssl + Memcheck:Addr8 + ... + fun:AES_cbc_encrypt + ... +} + +{ Prebuilt constant terms in os_info_init (PossiblyLost) Memcheck:Leak fun:malloc diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h index e1885c627a..aef31e282a 100644 --- a/erts/include/internal/ethread.h +++ b/erts/include/internal/ethread.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2004-2011. All Rights Reserved. + * Copyright Ericsson AB 2004-2012. 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 diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex 66b7a011d6..bf6d6e871b 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam Binary files differindex 5409cf2dfc..b2d224e560 100644 --- a/erts/preloaded/ebin/prim_inet.beam +++ b/erts/preloaded/ebin/prim_inet.beam diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 646acf5798..9e814ae54b 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -1699,7 +1699,8 @@ nodes(_Arg) -> | in | out | binary - | eof. + | eof + | hide. open_port(_PortName,_PortSettings) -> erlang:nif_error(undefined). @@ -1836,7 +1837,7 @@ process_flag(_Flag, _Value) -> {group_leader, GroupLeader :: pid()} | {heap_size, Size :: non_neg_integer()} | {initial_call, mfa()} | - {links, Pids :: [pid()]} | + {links, Pids :: [pid() | port()]} | {last_calls, false | (Calls :: [mfa()])} | {memory, Size :: non_neg_integer()} | {message_que_len, MessageQueueLen :: non_neg_integer()} | diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl index b639b1efdd..b9800a05da 100644 --- a/erts/preloaded/src/prim_inet.erl +++ b/erts/preloaded/src/prim_inet.erl @@ -1062,6 +1062,7 @@ enc_opt(multicast_ttl) -> ?UDP_OPT_MULTICAST_TTL; enc_opt(multicast_loop) -> ?UDP_OPT_MULTICAST_LOOP; enc_opt(add_membership) -> ?UDP_OPT_ADD_MEMBERSHIP; enc_opt(drop_membership) -> ?UDP_OPT_DROP_MEMBERSHIP; +enc_opt(ipv6_v6only) -> ?INET_OPT_IPV6_V6ONLY; enc_opt(buffer) -> ?INET_LOPT_BUFFER; enc_opt(header) -> ?INET_LOPT_HEADER; enc_opt(active) -> ?INET_LOPT_ACTIVE; @@ -1115,6 +1116,7 @@ dec_opt(?UDP_OPT_MULTICAST_TTL) -> multicast_ttl; dec_opt(?UDP_OPT_MULTICAST_LOOP) -> multicast_loop; dec_opt(?UDP_OPT_ADD_MEMBERSHIP) -> add_membership; dec_opt(?UDP_OPT_DROP_MEMBERSHIP) -> drop_membership; +dec_opt(?INET_OPT_IPV6_V6ONLY) -> ipv6_v6only; dec_opt(?INET_LOPT_BUFFER) -> buffer; dec_opt(?INET_LOPT_HEADER) -> header; dec_opt(?INET_LOPT_ACTIVE) -> active; @@ -1178,6 +1180,7 @@ type_opt_1(recbuf) -> int; type_opt_1(priority) -> int; type_opt_1(tos) -> int; type_opt_1(nodelay) -> bool; +type_opt_1(ipv6_v6only) -> bool; %% multicast type_opt_1(multicast_ttl) -> int; type_opt_1(multicast_loop) -> bool; diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl index b7ceb0a3fd..51f07b5432 100644 --- a/erts/test/otp_SUITE.erl +++ b/erts/test/otp_SUITE.erl @@ -151,8 +151,8 @@ is_hipe_module(Mod) -> end. ssl_crypto_filter(Undef) -> - case {code:lib_dir(crypto),code:lib_dir(ssl)} of - {{error,bad_name},{error,bad_name}} -> + case {app_exists(crypto),app_exists(ssl)} of + {false,false} -> filter(fun({_,{ssl,_,_}}) -> false; ({_,{crypto,_,_}}) -> false; ({_,{ssh,_,_}}) -> false; @@ -176,8 +176,8 @@ eunit_filter(Undef) -> end, Undef). dialyzer_filter(Undef) -> - case code:lib_dir(dialyzer) of - {error,bad_name} -> + case app_exists(dialyzer) of + false -> filter(fun({_,{dialyzer_callgraph,_,_}}) -> false; ({_,{dialyzer_codeserver,_,_}}) -> false; ({_,{dialyzer_contracts,_,_}}) -> false; @@ -192,8 +192,8 @@ dialyzer_filter(Undef) -> end. wx_filter(Undef) -> - case code:lib_dir(wx) of - {error,bad_name} -> + case app_exists(wx) of + false -> filter(fun({_,{MaybeWxModule,_,_}}) -> case atom_to_list(MaybeWxModule) of "wx"++_ -> false; @@ -349,3 +349,16 @@ open_log(Config, Name) -> close_log(Fd) -> ok = file:close(Fd). + +app_exists(AppAtom) -> + case code:lib_dir(AppAtom) of + {error,bad_name} -> + false; + Path -> + case file:read_file_info(filename:join(Path,"ebin")) of + {ok,_} -> + true; + _ -> + false + end + end. |