aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/configure.in10
-rw-r--r--erts/doc/src/erlang.xml8
-rw-r--r--erts/emulator/beam/atom.c2
-rw-r--r--erts/emulator/beam/erl_db.c4
-rw-r--r--erts/emulator/beam/erl_db_hash.c2
-rw-r--r--erts/emulator/beam/erl_fun.c2
-rw-r--r--erts/emulator/beam/erl_node_tables.c4
-rw-r--r--erts/emulator/beam/export.c2
-rw-r--r--erts/emulator/beam/register.c2
-rw-r--r--erts/emulator/drivers/common/inet_drv.c60
-rw-r--r--erts/emulator/hipe/hipe_amd64_glue.S2
-rw-r--r--erts/emulator/hipe/hipe_arm_glue.S2
-rw-r--r--erts/emulator/hipe/hipe_ppc_glue.S2
-rw-r--r--erts/emulator/hipe/hipe_sparc_glue.S2
-rw-r--r--erts/emulator/hipe/hipe_x86_glue.S6
-rw-r--r--erts/emulator/hipe/hipe_x86_signal.c9
-rw-r--r--erts/emulator/sys/common/erl_mseg.c8
-rw-r--r--erts/emulator/sys/unix/sys_float.c23
-rw-r--r--erts/include/internal/ethr_mutex.h8
-rw-r--r--erts/include/internal/gcc/ethr_atomic.h9
-rw-r--r--erts/lib_src/common/ethr_mutex.c80
21 files changed, 172 insertions, 75 deletions
diff --git a/erts/configure.in b/erts/configure.in
index 2b1aedc992..8c6f2ac076 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -1788,6 +1788,9 @@ AC_CHECK_FUNCS([fdatasync])
dnl Find which C libraries are required to use fdatasync
AC_SEARCH_LIBS(fdatasync, [rt])
+AC_CHECK_HEADERS(net/if_dl.h ifaddrs.h)
+AC_CHECK_FUNCS([getifaddrs])
+
dnl ----------------------------------------------------------------------
dnl Checks for features/quirks in the system that affects Erlang.
dnl ----------------------------------------------------------------------
@@ -2673,7 +2676,7 @@ static __inline__ int check_fpe(double f)
* Implement SIGFPE handler based on CPU/OS combination
*/
-#if (defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__sparc__) || defined(__powerpc__))) || (defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))) || (defined(__FreeBSD__) && (defined(__i386__) || defined(__x86_64__))) || (defined(__OpenBSD__) && defined(__x86_64__)) || (defined(__sun__) && defined(__x86_64__))
+#if (defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__sparc__) || defined(__powerpc__))) || (defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))) || (defined(__FreeBSD__) && (defined(__i386__) || defined(__x86_64__))) || ((defined(__OpenBSD__) || defined(__NetBSD__)) && defined(__x86_64__)) || (defined(__sun__) && defined(__x86_64__))
#if defined(__linux__) && defined(__i386__)
#if !defined(X86_FXSR_MAGIC)
@@ -2787,6 +2790,11 @@ static void fpe_sig_action(int sig, siginfo_t *si, void *puc)
struct fxsave64 *fxsave = uc->sc_fpstate;
fxsave->fx_mxcsr = 0x1F80;
fxsave->fx_fsw &= ~0xFF;
+#elif defined(__NetBSD__) && defined(__x86_64__)
+ mcontext_t *mc = &uc->uc_mcontext;
+ struct fxsave64 *fxsave = (struct fxsave64 *)&mc->__fpregs;
+ fxsave->fx_mxcsr = 0x1F80;
+ fxsave->fx_fsw &= ~0xFF;
#elif defined(__sun__) && defined(__x86_64__)
mcontext_t *mc = &uc->uc_mcontext;
struct fpchip_state *fpstate = &mc->fpregs.fp_reg_set.fpchip_state;
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index ce7fde05d9..ba93fe34d3 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -147,7 +147,7 @@ iolist() = [char() | binary() | iolist()]
<c>Tuple1</c>, and contains the elements in <c>Tuple1</c>
followed by <c>Term</c> as the last element. Semantically
equivalent to
- <c>list_to_tuple(tuple_to_list(Tuple ++ [Term])</c>, but much
+ <c>list_to_tuple(tuple_to_list(Tuple) ++ [Term])</c>, but much
faster.</p>
<pre>
> <input>erlang:append_element({one, two}, three).</input>
@@ -2035,9 +2035,9 @@ os_prompt%</pre>
</type>
<desc>
<note>
- <p>In releases older than OTP R14B, NIF's where an
+ <p>In releases older than OTP R14B, NIFs were an
experimental feature. Versions of OTP older than R14B might
- have different and possibly incompatible NIF semanticts and
+ have different and possibly incompatible NIF semantics and
interfaces. For example, in R13B03 the return value on
failure was
<c>{error,Reason,Text}</c>.</p>
@@ -2045,7 +2045,7 @@ os_prompt%</pre>
<p>Loads and links a dynamic library containing native
implemented functions (NIFs) for a module. <c>Path</c> is a
file path to the sharable object/dynamic library file minus
- the OS-dependant file extension (.so for Unix and .ddl for
+ the OS-dependent file extension (.so for Unix and .dll for
Windows). See <seealso marker="erl_nif">erl_nif</seealso>
on how to implement a NIF library.</p>
<p><c>LoadInfo</c> can be any term. It will be passed on to
diff --git a/erts/emulator/beam/atom.c b/erts/emulator/beam/atom.c
index 6b3c106a97..b97705ed96 100644
--- a/erts/emulator/beam/atom.c
+++ b/erts/emulator/beam/atom.c
@@ -303,7 +303,7 @@ init_atom_table(void)
HashFunctions f;
int i;
Atom a;
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index b0369a402b..52d5f86ee0 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -265,7 +265,7 @@ static ERTS_INLINE void db_init_lock(DbTable* tb, int use_frequent_read_lock,
char *rwname, char* fixname)
{
#ifdef ERTS_SMP
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
if (use_frequent_read_lock)
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
#endif
@@ -2746,7 +2746,7 @@ void init_db(void)
size_t size;
#ifdef ERTS_SMP
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index 5abd2e50fa..fa707f4eed 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -623,7 +623,7 @@ int db_create_hash(Process *p, DbTable *tbl)
erts_smp_atomic_init(&tb->is_resizing, 0);
#ifdef ERTS_SMP
if (tb->common.type & DB_FINE_LOCKED) {
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
int i;
if (tb->common.type & DB_FREQ_READ)
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c
index 5dce5ad262..84869f12d6 100644
--- a/erts/emulator/beam/erl_fun.c
+++ b/erts/emulator/beam/erl_fun.c
@@ -55,7 +55,7 @@ void
erts_init_fun_table(void)
{
HashFunctions f;
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index e430b4ad77..d0b08bf72e 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -80,7 +80,7 @@ dist_table_alloc(void *dep_tmpl)
Eterm chnl_nr;
Eterm sysname;
DistEntry *dep;
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
if(((DistEntry *) dep_tmpl) == erts_this_dist_entry)
@@ -710,7 +710,7 @@ erts_set_this_node(Eterm sysname, Uint creation)
void erts_init_node_tables(void)
{
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
HashFunctions f;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
diff --git a/erts/emulator/beam/export.c b/erts/emulator/beam/export.c
index 5e81a2d624..5bc402fe22 100644
--- a/erts/emulator/beam/export.c
+++ b/erts/emulator/beam/export.c
@@ -109,7 +109,7 @@ void
init_export_table(void)
{
HashFunctions f;
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
diff --git a/erts/emulator/beam/register.c b/erts/emulator/beam/register.c
index c9bb7bbe91..26d64887d0 100644
--- a/erts/emulator/beam/register.c
+++ b/erts/emulator/beam/register.c
@@ -145,7 +145,7 @@ static void reg_free(RegProc *obj)
void init_register_table(void)
{
HashFunctions f;
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 79e58beb40..3de48194fb 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -48,6 +48,12 @@
#include <sys/uio.h>
#endif
+#ifdef HAVE_NET_IF_DL_H
+#include <net/if_dl.h>
+#endif
+#ifdef HAVE_IFADDRS_H
+#include <ifaddrs.h>
+#endif
/* All platforms fail on malloc errors. */
#define FATAL_MALLOC
@@ -2168,7 +2174,7 @@ static int http_error_inetdrv(void* arg, const char* buf, int len)
ErlDrvTermData spec[19];
if (desc->inet.active == INET_PASSIVE) {
- /* {inet_async,S,Ref,{error,{http_error,Line}}} */
+ /* {inet_async,S,Ref,{ok,{http_error,Line}}} */
int req;
int aid;
ErlDrvTermData caller;
@@ -2178,7 +2184,7 @@ static int http_error_inetdrv(void* arg, const char* buf, int len)
i = LOAD_ATOM(spec, i, am_inet_async);
i = LOAD_PORT(spec, i, desc->inet.dport);
i = LOAD_INT(spec, i, aid);
- i = LOAD_ATOM(spec, i, am_error);
+ i = LOAD_ATOM(spec, i, am_ok);
i = LOAD_ATOM(spec, i, am_http_error);
i = http_load_string(desc, spec, i, buf, len);
i = LOAD_TUPLE(spec, i, 2);
@@ -3905,7 +3911,7 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
INTERFACE_INFO* ifp;
long namaddr;
- if ((len == 0) || ((namlen = buf[0]) > len))
+ if ((len == 0) || ((namlen = get_int8(buf)) > len))
goto error;
if (parse_addr(buf+1, namlen, &namaddr) < 0)
goto error;
@@ -4089,6 +4095,10 @@ static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize)
}
+/* FIXME: temporary hack */
+#ifndef IFHWADDRLEN
+#define IFHWADDRLEN 6
+#endif
static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
char** rbuf, int rsize)
@@ -4099,11 +4109,11 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
struct ifreq ifreq;
int namlen;
- if ((len == 0) || ((namlen = buf[0]) > len))
+ if ((len == 0) || ((namlen = get_int8(buf)) > len))
goto error;
sys_memset(ifreq.ifr_name, '\0', IFNAMSIZ);
sys_memcpy(ifreq.ifr_name, buf+1,
- (namlen > IFNAMSIZ) ? IFNAMSIZ : namlen);
+ (namlen >= IFNAMSIZ) ? IFNAMSIZ-1 : namlen);
buf += (namlen+1);
len -= (namlen+1);
sptr = sbuf;
@@ -4128,6 +4138,32 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
/* raw memcpy (fix include autoconf later) */
sys_memcpy(sptr, (char*)(&ifreq.ifr_hwaddr.sa_data), IFHWADDRLEN);
sptr += IFHWADDRLEN;
+#elif defined(HAVE_GETIFADDRS)
+ struct ifaddrs *ifa, *ifp;
+ int found = 0;
+
+ if (getifaddrs(&ifa) == -1)
+ goto error;
+
+ for (ifp = ifa; ifp; ifp = ifp->ifa_next) {
+ if ((ifp->ifa_addr->sa_family == AF_LINK) &&
+ (sys_strcmp(ifp->ifa_name, ifreq.ifr_name) == 0)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found == 0) {
+ freeifaddrs(ifa);
+ break;
+ }
+
+ buf_check(sptr, s_end, 1+IFHWADDRLEN);
+ *sptr++ = INET_IFOPT_HWADDR;
+ sys_memcpy(sptr, ((struct sockaddr_dl *)ifp->ifa_addr)->sdl_data +
+ ((struct sockaddr_dl *)ifp->ifa_addr)->sdl_nlen, IFHWADDRLEN);
+ freeifaddrs(ifa);
+ sptr += IFHWADDRLEN;
#endif
break;
}
@@ -4240,10 +4276,6 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
return ctl_error(EINVAL, rbuf, rsize);
}
-/* FIXME: temporary hack */
-#ifndef IFHWADDRLEN
-#define IFHWADDRLEN 6
-#endif
static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
char** rbuf, int rsize)
@@ -4252,11 +4284,11 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
int namlen;
char* b_end = buf + len;
- if ((len == 0) || ((namlen = buf[0]) > len))
+ if ((len == 0) || ((namlen = get_int8(buf)) > len))
goto error;
sys_memset(ifreq.ifr_name, '\0', IFNAMSIZ);
sys_memcpy(ifreq.ifr_name, buf+1,
- (namlen > IFNAMSIZ) ? IFNAMSIZ : namlen);
+ (namlen >= IFNAMSIZ) ? IFNAMSIZ-1 : namlen);
buf += (namlen+1);
len -= (namlen+1);
@@ -6851,13 +6883,13 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len,
if (len < 2)
return ctl_error(EINVAL, rbuf, rsize);
- n = buf[0]; buf++; len--;
+ n = get_int8(buf); buf++; len--;
if (n >= len) /* the = sign makes the test inklude next length byte */
return ctl_error(EINVAL, rbuf, rsize);
memcpy(namebuf, buf, n);
namebuf[n] = '\0';
len -= n; buf += n;
- n = buf[0]; buf++; len--;
+ n = get_int8(buf); buf++; len--;
if (n > len)
return ctl_error(EINVAL, rbuf, rsize);
memcpy(protobuf, buf, n);
@@ -6880,7 +6912,7 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len,
port = get_int16(buf);
port = sock_htons(port);
buf += 2;
- n = buf[0]; buf++; len -= 3;
+ n = get_int8(buf); buf++; len -= 3;
if (n > len)
return ctl_error(EINVAL, rbuf, rsize);
memcpy(protobuf, buf, n);
diff --git a/erts/emulator/hipe/hipe_amd64_glue.S b/erts/emulator/hipe/hipe_amd64_glue.S
index 83b7b0397b..ede762aae0 100644
--- a/erts/emulator/hipe/hipe_amd64_glue.S
+++ b/erts/emulator/hipe/hipe_amd64_glue.S
@@ -346,6 +346,8 @@ nbif_3_gc_after_bif:
subq $(16-8), %rsp
movq P, %rdi
movq %rax, %rsi
+ xorl %edx, %edx # Pass NULL in regs
+ xorl %ecx, %ecx # Pass 0 in arity
call CSYM(erts_gc_after_bif_call)
addq $(16-8), %rsp
movl $0, P_NARITY(P) # Note: narity is a 32-bit field
diff --git a/erts/emulator/hipe/hipe_arm_glue.S b/erts/emulator/hipe/hipe_arm_glue.S
index 5d626a5f69..2bce01954e 100644
--- a/erts/emulator/hipe/hipe_arm_glue.S
+++ b/erts/emulator/hipe/hipe_arm_glue.S
@@ -311,6 +311,8 @@ nbif_3_gc_after_bif:
str TEMP_LR, [P, #P_NRA]
str NSP, [P, #P_NSP]
mov TEMP_LR, lr
+ mov r3, #0 /* Pass 0 in arity */
+ mov r2, #0 /* Pass NULL in regs */
mov r1, r0
mov r0, P
bl erts_gc_after_bif_call
diff --git a/erts/emulator/hipe/hipe_ppc_glue.S b/erts/emulator/hipe/hipe_ppc_glue.S
index 97b07353f9..0651963294 100644
--- a/erts/emulator/hipe/hipe_ppc_glue.S
+++ b/erts/emulator/hipe/hipe_ppc_glue.S
@@ -476,6 +476,8 @@ CSYM(nbif_3_gc_after_bif):
STORE TEMP_LR, P_NRA(P)
STORE NSP, P_NSP(P)
mflr TEMP_LR
+ li r6, 0 /* Pass 0 in arity */
+ li r5, 0 /* Pass NULL in regs */
mr r4, r3
mr r3, P
bl CSYM(erts_gc_after_bif_call)
diff --git a/erts/emulator/hipe/hipe_sparc_glue.S b/erts/emulator/hipe/hipe_sparc_glue.S
index d1af5c43f5..73cefd4896 100644
--- a/erts/emulator/hipe/hipe_sparc_glue.S
+++ b/erts/emulator/hipe/hipe_sparc_glue.S
@@ -333,6 +333,8 @@ nbif_3_gc_after_bif:
st TEMP_RA, [P+P_NRA]
st NSP, [P+P_NSP]
mov RA, TEMP_RA
+ mov 0, %o3 /* Pass 0 in arity */
+ mov 0, %o2 /* Pass NULL in regs */
mov %o0, %o1
call erts_gc_after_bif_call
mov P, %o0 /* delay slot */
diff --git a/erts/emulator/hipe/hipe_x86_glue.S b/erts/emulator/hipe/hipe_x86_glue.S
index 2f7dff39f5..43392111fe 100644
--- a/erts/emulator/hipe/hipe_x86_glue.S
+++ b/erts/emulator/hipe/hipe_x86_glue.S
@@ -320,11 +320,13 @@ nbif_3_gc_after_bif:
.align 4
.gc_after_bif:
movl %edx, P_NARITY(P)
- subl $(16-4), %esp
+ subl $(32-4), %esp
movl P, (%esp)
movl %eax, 4(%esp)
+ movl $0, 8(%esp) # Pass NULL in regs
+ movl $0, 12(%esp) # Pass 0 in arity
call CSYM(erts_gc_after_bif_call)
- addl $(16-4), %esp
+ addl $(32-4), %esp
movl $0, P_NARITY(P)
ret
diff --git a/erts/emulator/hipe/hipe_x86_signal.c b/erts/emulator/hipe/hipe_x86_signal.c
index a4fff4ce31..0c61e7bf96 100644
--- a/erts/emulator/hipe/hipe_x86_signal.c
+++ b/erts/emulator/hipe/hipe_x86_signal.c
@@ -195,7 +195,7 @@ static void do_init(void)
#define INIT() do { if (!init_done()) do_init(); } while (0)
#endif /* __DARWIN__ */
-#if !defined(__GLIBC__) && !defined(__DARWIN__)
+#if !defined(__GLIBC__) && !defined(__DARWIN__) && !defined(__NetBSD__)
/*
* Assume Solaris/x86 2.8.
* There is a number of sigaction() procedures in libc:
@@ -231,6 +231,7 @@ static void do_init(void)
#define INIT() do { if (!init_done()) do_init(); } while (0)
#endif /* not glibc or darwin */
+#if !defined(__NetBSD__)
/*
* This is our wrapper for sigaction(). sigaction() can be called before
* hipe_signal_init() has been executed, especially when threads support
@@ -253,7 +254,7 @@ static int my_sigaction(int signum, const struct sigaction *act, struct sigactio
}
return __next_sigaction(signum, act, oldact);
}
-
+#endif
/*
* This overrides the C library's core sigaction() procedure, catching
* all its internal calls.
@@ -268,7 +269,7 @@ int __SIGACTION(int signum, const struct sigaction *act, struct sigaction *oldac
/*
* This catches the application's own sigaction() calls.
*/
-#if !defined(__DARWIN__)
+#if !defined(__DARWIN__) && !defined(__NetBSD__)
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
return my_sigaction(signum, act, oldact);
@@ -326,7 +327,9 @@ void hipe_signal_init(void)
struct sigaction sa;
int i;
+#ifndef __NetBSD__
INIT();
+#endif
hipe_sigaltstack_init();
diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c
index 1c4c37b01a..b1ee165489 100644
--- a/erts/emulator/sys/common/erl_mseg.c
+++ b/erts/emulator/sys/common/erl_mseg.c
@@ -382,6 +382,14 @@ mseg_recreate(void *old_seg, Uint old_size, Uint new_size)
new_seg = (void *) pmremap((void *) old_seg,
(size_t) old_size,
(size_t) new_size);
+#elif defined(__NetBSD__)
+ new_seg = (void *) mremap((void *) old_seg,
+ (size_t) old_size,
+ NULL,
+ (size_t) new_size,
+ 0);
+ if (new_seg == (void *) MAP_FAILED)
+ new_seg = NULL;
#else
new_seg = (void *) mremap((void *) old_seg,
(size_t) old_size,
diff --git a/erts/emulator/sys/unix/sys_float.c b/erts/emulator/sys/unix/sys_float.c
index 5a682ab045..6e9376b0f3 100644
--- a/erts/emulator/sys/unix/sys_float.c
+++ b/erts/emulator/sys/unix/sys_float.c
@@ -476,7 +476,7 @@ static int mask_fpe(void)
#endif
-#if (defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__sparc__) || defined(__powerpc__))) || (defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))) || (defined(__FreeBSD__) && (defined(__x86_64__) || defined(__i386__))) || (defined(__OpenBSD__) && defined(__x86_64__)) || (defined(__sun__) && defined(__x86_64__))
+#if (defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__sparc__) || defined(__powerpc__))) || (defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))) || (defined(__FreeBSD__) && (defined(__x86_64__) || defined(__i386__))) || ((defined(__NetBSD__) || defined(__OpenBSD__)) && defined(__x86_64__)) || (defined(__sun__) && defined(__x86_64__))
#if defined(__linux__) && defined(__i386__)
#if !defined(X86_FXSR_MAGIC)
@@ -519,6 +519,10 @@ static int mask_fpe(void)
#define mc_pc(mc) ((mc)->mc_rip)
#elif defined(__FreeBSD__) && defined(__i386__)
#define mc_pc(mc) ((mc)->mc_eip)
+#elif defined(__NetBSD__) && defined(__x86_64__)
+#define mc_pc(mc) ((mc)->__gregs[_REG_RIP])
+#elif defined(__NetBSD__) && defined(__i386__)
+#define mc_pc(mc) ((mc)->__gregs[_REG_EIP])
#elif defined(__OpenBSD__) && defined(__x86_64__)
#define mc_pc(mc) ((mc)->sc_rip)
#elif defined(__sun__) && defined(__x86_64__)
@@ -610,6 +614,23 @@ static void fpe_sig_action(int sig, siginfo_t *si, void *puc)
struct env87 *env87 = &savefpu->sv_87.sv_env;
env87->en_sw &= ~0xFF;
}
+#elif defined(__NetBSD__) && defined(__x86_64__)
+ mcontext_t *mc = &uc->uc_mcontext;
+ struct fxsave64 *fxsave = (struct fxsave64 *)&mc->__fpregs;
+ pc = mc_pc(mc);
+ fxsave->fx_mxcsr = 0x1F80;
+ fxsave->fx_fsw &= ~0xFF;
+#elif defined(__NetBSD__) && defined(__i386__)
+ mcontext_t *mc = &uc->uc_mcontext;
+ pc = mc_pc(mc);
+ if (uc->uc_flags & _UC_FXSAVE) {
+ struct envxmm *envxmm = (struct envxmm *)&mc->__fpregs;
+ envxmm->en_mxcsr = 0x1F80;
+ envxmm->en_sw &= ~0xFF;
+ } else {
+ struct env87 *env87 = (struct env87 *)&mc->__fpregs;
+ env87->en_sw &= ~0xFF;
+ }
#elif defined(__OpenBSD__) && defined(__x86_64__)
struct fxsave64 *fxsave = uc->sc_fpstate;
pc = mc_pc(uc);
diff --git a/erts/include/internal/ethr_mutex.h b/erts/include/internal/ethr_mutex.h
index 4ce3e75c78..8d9d5e3d08 100644
--- a/erts/include/internal/ethr_mutex.h
+++ b/erts/include/internal/ethr_mutex.h
@@ -346,7 +346,9 @@ do { \
#ifdef ETHR_USE_OWN_MTX_IMPL__
-#define ETHR_MTX_DEFAULT_MAIN_SPINCOUNT 1000
+#define ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_MAX 2000
+#define ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_BASE 800
+#define ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_INC 50
#define ETHR_MTX_DEFAULT_AUX_SPINCOUNT 50
#define ETHR_CND_DEFAULT_MAIN_SPINCOUNT 0
@@ -443,7 +445,9 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
#ifdef ETHR_USE_OWN_RWMTX_IMPL__
-#define ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT 1000
+#define ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_MAX 2000
+#define ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_BASE 800
+#define ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_INC 50
#define ETHR_RWMTX_DEFAULT_AUX_SPINCOUNT 50
#else /* pthread_rwlock */
diff --git a/erts/include/internal/gcc/ethr_atomic.h b/erts/include/internal/gcc/ethr_atomic.h
index 5fe6e23477..e8e529dd48 100644
--- a/erts/include/internal/gcc/ethr_atomic.h
+++ b/erts/include/internal/gcc/ethr_atomic.h
@@ -31,7 +31,7 @@
#define ETHR_IMMED_ATOMIC_SET_GET_SAFE__ 0
/* Enable immediate read/write on platforms where we know it is safe */
#if defined(__i386__) || defined(__x86_64__) || defined(__sparc__) \
- || defined(__powerpc__) || defined(__ppc__)
+ || defined(__powerpc__) || defined(__ppc__) || defined(__mips__)
# undef ETHR_IMMED_ATOMIC_SET_GET_SAFE__
# define ETHR_IMMED_ATOMIC_SET_GET_SAFE__ 1
#endif
@@ -48,13 +48,18 @@ typedef struct {
* a noop on at least some platforms with some gcc versions.
* This has suposedly been fixed in some gcc version, but we
* don't know from which version. Therefore, we use the
- * workaround implemented below on all gcc versions.
+ * workaround implemented below on all gcc versions except
+ * for gcc 4.2 or above for MIPS, where it's been verified.
*/
+#if defined(__mips__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
+#define ETHR_MEMORY_BARRIER __sync_synchronize()
+#else
#define ETHR_MEMORY_BARRIER \
do { \
volatile long x___ = 0; \
(void) __sync_val_compare_and_swap(&x___, (long) 0, (long) 1); \
} while (0)
+#endif
#define ETHR_READ_DEPEND_MEMORY_BARRIER ETHR_MEMORY_BARRIER
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_AUX_IMPL__)
diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c
index aac0d44a32..78323b62a3 100644
--- a/erts/lib_src/common/ethr_mutex.c
+++ b/erts/lib_src/common/ethr_mutex.c
@@ -35,7 +35,7 @@
#define ETHR_SPIN_WITH_WAITERS 1
-#define ETHR_MTX_MAX_FLGS_SPIN 1000
+#define ETHR_MTX_MAX_FLGS_SPIN 10
#ifdef ETHR_USE_OWN_RWMTX_IMPL__
static int default_rwmtx_main_spincount;
@@ -90,7 +90,7 @@ ethr_mutex_lib_init(int cpu_conf)
no_spin = cpu_conf == 1;
#ifdef ETHR_USE_OWN_MTX_IMPL__
- default_mtx_main_spincount = ETHR_MTX_DEFAULT_MAIN_SPINCOUNT;
+ default_mtx_main_spincount = ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_BASE;
default_mtx_aux_spincount = ETHR_MTX_DEFAULT_AUX_SPINCOUNT;
default_cnd_main_spincount = ETHR_CND_DEFAULT_MAIN_SPINCOUNT;
default_cnd_aux_spincount = ETHR_CND_DEFAULT_AUX_SPINCOUNT;
@@ -98,7 +98,7 @@ ethr_mutex_lib_init(int cpu_conf)
#ifdef ETHR_USE_OWN_RWMTX_IMPL__
- default_rwmtx_main_spincount = ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT;
+ default_rwmtx_main_spincount = ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_BASE;
default_rwmtx_aux_spincount = ETHR_RWMTX_DEFAULT_AUX_SPINCOUNT;
#else
@@ -146,7 +146,21 @@ static int main_threads_array_size = 0;
int
ethr_mutex_lib_late_init(int no_reader_groups, int no_main_threads)
{
+
+#ifdef ETHR_USE_OWN_MTX_IMPL__
+ default_mtx_main_spincount += (no_main_threads
+ * ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_INC);
+ if (default_mtx_main_spincount > ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_MAX)
+ default_mtx_main_spincount = ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_MAX;
+#endif
+
#ifdef ETHR_USE_OWN_RWMTX_IMPL__
+
+ default_rwmtx_main_spincount += (no_main_threads
+ * ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_INC);
+ if (default_rwmtx_main_spincount > ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_MAX)
+ default_rwmtx_main_spincount = ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_MAX;
+
reader_groups_array_size = (no_reader_groups <= 1
? 1
: no_reader_groups + 1);
@@ -593,24 +607,31 @@ initial_spincount(struct ethr_mutex_base_ *mtxb)
static ETHR_INLINE int
update_spincount(struct ethr_mutex_base_ *mtxb,
ethr_ts_event *tse,
- int *start_scnt,
+ int *scnt_state,
int *scnt)
{
- int sscnt = *start_scnt;
- if (sscnt < 0) {
- *scnt = ((tse->iflgs & ETHR_TS_EV_MAIN_THR)
- ? mtxb->main_scnt
- : mtxb->aux_scnt);
- *scnt -= ETHR_MTX_MAX_FLGS_SPIN;
+ int state = *scnt_state;
+ if (state <= 0) {
+ /* Here state is max spincount to do on event negated */
+ *scnt = -state;
}
else {
+ /* Here state is initial spincount made on flags */
*scnt = ((tse->iflgs & ETHR_TS_EV_MAIN_THR)
? mtxb->main_scnt
: mtxb->aux_scnt);
- *scnt -= sscnt;
- if (*scnt > 0 && sscnt < ETHR_MTX_MAX_FLGS_SPIN) {
- *scnt = ETHR_MTX_MAX_FLGS_SPIN - sscnt;
- *start_scnt = -1;
+ if (*scnt <= state)
+ *scnt = 0;
+ else {
+ if (*scnt <= ETHR_MTX_MAX_FLGS_SPIN)
+ *scnt_state = 0; /* No spin on event */
+ else {
+ /* Spin on event after... */
+ *scnt_state = -1*(*scnt - ETHR_MTX_MAX_FLGS_SPIN);
+ /* ... we have spun on flags */
+ *scnt = ETHR_MTX_MAX_FLGS_SPIN;
+ }
+ *scnt -= state;
return 0;
}
}
@@ -619,8 +640,7 @@ update_spincount(struct ethr_mutex_base_ *mtxb,
int check_readers_array(ethr_rwmutex *rwmtx,
int start_rix,
- int length,
- int pre_check);
+ int length);
static ETHR_INLINE void
write_lock_wait(struct ethr_mutex_base_ *mtxb,
@@ -666,8 +686,7 @@ write_lock_wait(struct ethr_mutex_base_ *mtxb,
}
res = check_readers_array(rwmtx,
freq_read_start_ix,
- freq_read_size,
- 1);
+ freq_read_size);
scnt--;
if (res == 0) {
act = ethr_atomic_read(&mtxb->flgs);
@@ -708,7 +727,6 @@ write_lock_wait(struct ethr_mutex_base_ *mtxb,
act = ethr_atomic_read(&mtxb->flgs);
scnt--;
}
- ETHR_ASSERT(scnt >= 0);
exp = act;
@@ -985,7 +1003,6 @@ enqueue_mtx(ethr_mutex *mtx, ethr_ts_event *tse_start, ethr_ts_event *tse_end)
int
ethr_cond_init_opt(ethr_cond *cnd, ethr_cond_opt *opt)
{
- int res;
#if ETHR_XCHK
if (!cnd) {
ETHR_ASSERT(0);
@@ -1085,7 +1102,6 @@ ethr_cond_signal(ethr_cond *cnd)
void
ethr_cond_broadcast(ethr_cond *cnd)
{
- int res;
int got_all;
ethr_ts_event *tse;
ETHR_ASSERT(!ethr_not_inited__);
@@ -1153,7 +1169,6 @@ ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx)
{
int woken;
int scnt;
- int res;
void *udata = NULL;
ethr_ts_event *tse;
@@ -1466,17 +1481,11 @@ multiple_w_waiters(ethr_rwmutex *rwmtx)
int check_readers_array(ethr_rwmutex *rwmtx,
int start_rix,
- int length,
- int pre_check)
+ int length)
{
int ix = start_rix;
-#ifndef ETHR_READ_MEMORY_BARRIER_IS_FULL
- if (pre_check)
- ETHR_READ_MEMORY_BARRIER;
- else
-#endif
- ETHR_MEMORY_BARRIER;
+ ETHR_MEMORY_BARRIER;
do {
long act = rwmutex_freqread_rdrs_read(rwmtx, ix);
@@ -1559,7 +1568,7 @@ rwmutex_try_complete_runlock(ethr_rwmutex *rwmtx,
ethr_leave_ts_event(tse_tmp);
if (check_before_try) {
- res = check_readers_array(rwmtx, six, length, 1);
+ res = check_readers_array(rwmtx, six, length);
if (res == EBUSY)
return try_write_lock ? EBUSY : 0;
}
@@ -1597,7 +1606,7 @@ rwmutex_try_complete_runlock(ethr_rwmutex *rwmtx,
}
}
- res = check_readers_array(rwmtx, six, length, 0);
+ res = check_readers_array(rwmtx, six, length);
if (res == EBUSY) {
act = ethr_atomic_dec_read(&rwmtx->mtxb.flgs);
if (act & ETHR_RWMTX_R_MASK__)
@@ -1691,7 +1700,7 @@ rwmutex_normal_rlock_wait(ethr_rwmutex *rwmtx,
#endif
while (act & (ETHR_RWMTX_W_FLG__|ETHR_RWMTX_W_WAIT_FLG__)) {
- if (scnt == 0) {
+ if (scnt >= 0) {
tse = ethr_get_ts_event();
if (update_spincount(&rwmtx->mtxb, tse, &start_scnt, &scnt)) {
event_wait(&rwmtx->mtxb, tse, scnt,
@@ -1708,7 +1717,6 @@ rwmutex_normal_rlock_wait(ethr_rwmutex *rwmtx,
scnt--;
}
exp = act;
- ETHR_ASSERT(scnt >= 0);
#ifdef ETHR_RLOCK_WITH_INC_DEC
act = ethr_atomic_inc_read(&rwmtx->mtxb.flgs);
@@ -1749,7 +1757,7 @@ rwmutex_freqread_rlock_wait(ethr_rwmutex *rwmtx,
act = ethr_atomic_read(&rwmtx->mtxb.flgs);
while (act & ~(ETHR_RWMTX_R_FLG__|ETHR_RWMTX_R_WAIT_FLG__)) {
- if (scnt == 0) {
+ if (scnt >= 0) {
if (update_spincount(&rwmtx->mtxb, tse, &start_scnt, &scnt)) {
event_wait(&rwmtx->mtxb, tse, scnt,
ETHR_RWMTX_R_WAIT_FLG__, 1, 1);
@@ -1765,8 +1773,6 @@ rwmutex_freqread_rlock_wait(ethr_rwmutex *rwmtx,
scnt--;
}
- ETHR_ASSERT(scnt >= 0);
-
rwmutex_freqread_rdrs_inc(rwmtx, tse);
ETHR_MEMORY_BARRIER;