aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/time.c62
-rw-r--r--erts/emulator/test/port_SUITE.erl10
-rw-r--r--erts/emulator/test/port_SUITE_data/Makefile.src2
-rw-r--r--erts/emulator/test/port_SUITE_data/dead_port.c102
4 files changed, 133 insertions, 43 deletions
diff --git a/erts/emulator/beam/time.c b/erts/emulator/beam/time.c
index a07d6a5327..53d39aef0e 100644
--- a/erts/emulator/beam/time.c
+++ b/erts/emulator/beam/time.c
@@ -83,24 +83,8 @@
#define ASSERT_NO_LOCKED_LOCKS
#endif
+static erts_smp_mtx_t tiw_lock;
-#if defined(ERTS_TIMER_THREAD) || 1
-/* I don't yet know why, but using a mutex instead of a spinlock
- or spin-based rwlock avoids excessive delays at startup. */
-static erts_smp_rwmtx_t tiw_lock;
-#define tiw_read_lock() erts_smp_rwmtx_rlock(&tiw_lock)
-#define tiw_read_unlock() erts_smp_rwmtx_runlock(&tiw_lock)
-#define tiw_write_lock() erts_smp_rwmtx_rwlock(&tiw_lock)
-#define tiw_write_unlock() erts_smp_rwmtx_rwunlock(&tiw_lock)
-#define tiw_init_lock() erts_smp_rwmtx_init(&tiw_lock, "timer_wheel")
-#else
-static erts_smp_rwlock_t tiw_lock;
-#define tiw_read_lock() erts_smp_read_lock(&tiw_lock)
-#define tiw_read_unlock() erts_smp_read_unlock(&tiw_lock)
-#define tiw_write_lock() erts_smp_write_lock(&tiw_lock)
-#define tiw_write_unlock() erts_smp_write_unlock(&tiw_lock)
-#define tiw_init_lock() erts_smp_rwlock_init(&tiw_lock, "timer_wheel")
-#endif
/* BEGIN tiw_lock protected variables
**
@@ -224,10 +208,10 @@ int next_time(void)
{
int ret;
- tiw_write_lock();
+ erts_smp_mtx_lock(&tiw_lock);
(void)do_time_update();
ret = next_time_internal();
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return ret;
}
#endif
@@ -241,7 +225,7 @@ static ERTS_INLINE void bump_timer_internal(long dt) /* PRE: tiw_lock is write-l
/* no need to bump the position if there aren't any timeouts */
if (tiw_nto == 0) {
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return;
}
@@ -278,7 +262,7 @@ static ERTS_INLINE void bump_timer_internal(long dt) /* PRE: tiw_lock is write-l
}
tiw_pos = keep_pos;
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
/* Call timedout timers callbacks */
while (timeout_head) {
@@ -299,13 +283,13 @@ static ERTS_INLINE void bump_timer_internal(long dt) /* PRE: tiw_lock is write-l
#if defined(ERTS_TIMER_THREAD)
static void timer_thread_bump_timer(void)
{
- tiw_write_lock();
+ erts_smp_mtx_lock(&tiw_lock);
bump_timer_internal(do_time_reset());
}
#else
void bump_timer(long dt) /* dt is value from do_time */
{
- tiw_write_lock();
+ erts_smp_mtx_lock(&tiw_lock);
bump_timer_internal(dt);
}
#endif
@@ -324,7 +308,7 @@ static int timer_thread_setup_delay(SysTimeval *rem_time)
long elapsed;
int ticks;
- tiw_write_lock();
+ erts_smp_mtx_lock(&tiw_lock);
elapsed = do_time_update();
ticks = next_time_internal();
if (ticks == -1) /* timer queue empty */
@@ -336,7 +320,7 @@ static int timer_thread_setup_delay(SysTimeval *rem_time)
rem_time->tv_sec = ticks / 1000;
rem_time->tv_usec = 1000 * (ticks % 1000);
ticks_end = ticks;
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return ticks;
}
@@ -399,7 +383,7 @@ init_time(void)
if timer thread is enabled */
itime = erts_init_time_sup();
- tiw_init_lock();
+ erts_smp_mtx_init(&tiw_lock, "timer_wheel");
tiw = (ErlTimer**) erts_alloc(ERTS_ALC_T_TIMER_WHEEL,
TIW_SIZE * sizeof(ErlTimer*));
@@ -451,9 +435,9 @@ erl_set_timer(ErlTimer* p, ErlTimeoutProc timeout, ErlCancelProc cancel,
void* arg, Uint t)
{
erts_deliver_time();
- tiw_write_lock();
+ erts_smp_mtx_lock(&tiw_lock);
if (p->active) { /* XXX assert ? */
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return;
}
p->timeout = timeout;
@@ -461,7 +445,7 @@ erl_set_timer(ErlTimer* p, ErlTimeoutProc timeout, ErlCancelProc cancel,
p->arg = arg;
p->active = 1;
insert_timer(p, t);
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
#if defined(ERTS_SMP) && !defined(ERTS_TIMER_THREAD)
if (t <= (Uint) LONG_MAX)
erts_sys_schedule_interrupt_timed(1, (long) t);
@@ -474,9 +458,9 @@ erl_cancel_timer(ErlTimer* p)
ErlTimer *tp;
ErlTimer **prev;
- tiw_write_lock();
+ erts_smp_mtx_lock(&tiw_lock);
if (!p->active) { /* allow repeated cancel (drivers) */
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return;
}
/* find p in linked list at slot p->slot and remove it */
@@ -489,17 +473,17 @@ erl_cancel_timer(ErlTimer* p)
p->slot = p->count = 0;
p->active = 0;
if (p->cancel != NULL) {
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
(*p->cancel)(p->arg);
} else {
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
}
return;
} else {
prev = &tp->next;
}
}
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
}
/*
@@ -514,10 +498,10 @@ time_left(ErlTimer *p)
Uint left;
long dt;
- tiw_read_lock();
+ erts_smp_mtx_lock(&tiw_lock);
if (!p->active) {
- tiw_read_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return 0;
}
@@ -531,7 +515,7 @@ time_left(ErlTimer *p)
else
left -= dt;
- tiw_read_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return left * itime;
}
@@ -543,7 +527,7 @@ void p_slpq()
int i;
ErlTimer* p;
- tiw_read_lock();
+ erts_smp_mtx_lock(&tiw_lock);
/* print the whole wheel, starting at the current position */
erts_printf("\ntiw_pos = %d tiw_nto %d\n", tiw_pos, tiw_nto);
@@ -565,7 +549,7 @@ void p_slpq()
}
}
- tiw_read_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
}
#endif /* DEBUG */
diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl
index 77fa75b78f..a7476ca9bb 100644
--- a/erts/emulator/test/port_SUITE.erl
+++ b/erts/emulator/test/port_SUITE.erl
@@ -2305,7 +2305,11 @@ load_driver(Dir, Driver) ->
close_deaf_port(doc) -> ["Send data to port program that does not read it, then close port."];
close_deaf_port(suite) -> [];
close_deaf_port(Config) when is_list(Config) ->
- Port = open_port({spawn,"sleep 999999"},[]),
- erlang:port_command(Port,"Hello, can you hear me!?!?"),
- port_close(Port),
+ ?line Dog = test_server:timetrap(test_server:seconds(100)),
+ ?line DataDir = ?config(data_dir, Config),
+ ?line DeadPort = os:find_executable("dead_port", DataDir),
+
+ ?line Port = open_port({spawn,DeadPort++" 60"},[]),
+ ?line erlang:port_command(Port,"Hello, can you hear me!?!?"),
+ ?line port_close(Port),
ok.
diff --git a/erts/emulator/test/port_SUITE_data/Makefile.src b/erts/emulator/test/port_SUITE_data/Makefile.src
index d97b37c9ae..ff822ae720 100644
--- a/erts/emulator/test/port_SUITE_data/Makefile.src
+++ b/erts/emulator/test/port_SUITE_data/Makefile.src
@@ -3,7 +3,7 @@ LD = @LD@
CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@
CROSSLDFLAGS = @CROSSLDFLAGS@
-PROGS = port_test@exe@ echo_args@exe@
+PROGS = port_test@exe@ echo_args@exe@ dead_port@exe@
DRIVERS = echo_drv@dll@ exit_drv@dll@ failure_drv@dll@
all: $(PROGS) $(DRIVERS) port_test.@EMULATOR@
diff --git a/erts/emulator/test/port_SUITE_data/dead_port.c b/erts/emulator/test/port_SUITE_data/dead_port.c
new file mode 100644
index 0000000000..6fa77112be
--- /dev/null
+++ b/erts/emulator/test/port_SUITE_data/dead_port.c
@@ -0,0 +1,102 @@
+/*
+ * %CopyrightBegin%
+ *
+ * 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%
+ */
+
+#ifdef VXWORKS
+#include <vxWorks.h>
+#include <taskVarLib.h>
+#include <taskLib.h>
+#include <sysLib.h>
+#include <string.h>
+#include <ioLib.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifndef __WIN32__
+#include <unistd.h>
+
+#ifdef VXWORKS
+#include "reclaim.h"
+#include <sys/times.h>
+#else
+#include <sys/time.h>
+#endif
+
+#define O_BINARY 0
+#define _setmode(fd, mode)
+#endif
+
+#ifdef __WIN32__
+#include "windows.h"
+#include "winbase.h"
+#endif
+
+
+#ifdef VXWORKS
+#define MAIN(argc, argv) port_test(argc, argv)
+#else
+#define MAIN(argc, argv) main(argc, argv)
+#endif
+
+
+extern int errno;
+
+static void delay(unsigned ms);
+
+
+MAIN(argc, argv)
+int argc;
+char *argv[];
+{
+ int x;
+ if (argc < 2) {
+ fprintf(stderr,"Usage %s <seconds>\n",argv[0]);
+ return 1;
+ }
+ if ((x = atoi(argv[1])) <= 0) {
+ fprintf(stderr,"Usage %s <seconds>\n",argv[0]);
+ return 1;
+ }
+ delay(x*1000);
+ return 0;
+}
+
+static void
+delay(unsigned ms)
+{
+#ifdef VXWORKS
+ taskDelay((sysClkRateGet() * ms) / 1000);
+#else
+#ifdef __WIN32__
+ Sleep(ms);
+#else
+ struct timeval t;
+ t.tv_sec = ms/1000;
+ t.tv_usec = (ms % 1000) * 1000;
+
+ select(0, NULL, NULL, NULL, &t);
+#endif
+#endif
+}