aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/beam_emu.c11
-rw-r--r--erts/emulator/beam/dist.c2
-rw-r--r--erts/emulator/beam/erl_async.c4
-rw-r--r--erts/emulator/beam/erl_bif_ddll.c2
-rw-r--r--erts/emulator/beam/erl_port.h140
-rw-r--r--erts/emulator/beam/erl_port_task.c56
-rw-r--r--erts/emulator/beam/io.c192
7 files changed, 216 insertions, 191 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 0e9d140908..e2c3bf292f 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -1070,17 +1070,6 @@ init_emulator(void)
#endif /* USE_VM_PROBES */
-#ifdef USE_VM_PROBES
-void
-dtrace_drvport_str(ErlDrvPort drvport, char *port_buf)
-{
- Port *port = erts_drvport2port(drvport, NULL);
-
- erts_snprintf(port_buf, DTRACE_TERM_BUF_SIZE, "#Port<%lu.%lu>",
- port_channel_no(port->common.id),
- port_number(port->common.id));
-}
-#endif
/*
* process_main() is called twice:
* The first call performs some initialisation, including exporting
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 59fe7ea418..0781665f05 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -2698,7 +2698,7 @@ BIF_RETTYPE setnode_3(BIF_ALIST_3)
*/
{
ErlDrvSizeT disable = ERL_DRV_BUSY_MSGQ_DISABLED;
- erl_drv_busy_msgq_limits((ErlDrvPort) pp, &disable, NULL);
+ erl_drv_busy_msgq_limits(ERTS_Port2ErlDrvPort(pp), &disable, NULL);
}
pp->dist_entry = dep;
diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c
index f2ca193ace..831e29d8a2 100644
--- a/erts/emulator/beam/erl_async.c
+++ b/erts/emulator/beam/erl_async.c
@@ -612,8 +612,8 @@ long driver_async(ErlDrvPort ix, unsigned int* key,
sched_id = 1;
#endif
- prt = erts_drvport2port(ix, NULL);
- if (!prt)
+ prt = erts_drvport2port(ix);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c
index 7cea0bc2eb..1c3e955f47 100644
--- a/erts/emulator/beam/erl_bif_ddll.c
+++ b/erts/emulator/beam/erl_bif_ddll.c
@@ -141,7 +141,7 @@ kill_ports_driver_unloaded(DE_Handle *dh)
state = erts_atomic32_read_nob(&prt->state);
if (!(state & ERTS_PORT_SFLGS_DEAD) && prt->drv_ptr->handle == dh)
- driver_failure_atom((ErlDrvPort) prt, "driver_unloaded");
+ driver_failure_atom(ERTS_Port2ErlDrvPort(prt), "driver_unloaded");
erts_port_release(prt);
}
diff --git a/erts/emulator/beam/erl_port.h b/erts/emulator/beam/erl_port.h
index 65b4cd0bfe..a971685d7b 100644
--- a/erts/emulator/beam/erl_port.h
+++ b/erts/emulator/beam/erl_port.h
@@ -40,7 +40,29 @@ extern int erts_port_parallelism;
typedef struct erts_driver_t_ erts_driver_t;
-#define ERTS_INVALID_ERL_DRV_PORT ((ErlDrvPort) (SWord) -1)
+/*
+ * It would have been preferred to use NULL as value of
+ * ERTS_INVALID_ERL_DRV_PORT. That would, however, not be
+ * backward compatible. In pre-R16 systems, 0 was a valid
+ * port handle and -1 was used as invalid handle, so we
+ * are stuck with it.
+ */
+#define ERTS_INVALID_ERL_DRV_PORT ((struct _erl_drv_port *) ((SWord) -1))
+#ifdef DEBUG
+/* Make sure we use this api, and do not cast directly */
+#define ERTS_ErlDrvPort2Port(PH) \
+ ((PH) == ERTS_INVALID_ERL_DRV_PORT \
+ ? ERTS_INVALID_ERL_DRV_PORT \
+ : ((Port *) ((PH) - 4711)))
+#define ERTS_Port2ErlDrvPort(PH) \
+ ((PH) == ERTS_INVALID_ERL_DRV_PORT \
+ ? ERTS_INVALID_ERL_DRV_PORT \
+ : ((ErlDrvPort) ((PH) + 4711)))
+#else
+#define ERTS_ErlDrvPort2Port(PH) ((Port *) (PH))
+#define ERTS_Port2ErlDrvPort(PH) ((ErlDrvPort) (PH))
+#endif
+
#define SMALL_IO_QUEUE 5 /* Number of fixed elements */
typedef struct {
@@ -429,16 +451,16 @@ ERTS_GLB_INLINE void erts_port_release(Port *);
ERTS_GLB_INLINE Port *erts_thr_id2port_sflgs(Eterm id, Uint32 invalid_sflgs);
ERTS_GLB_INLINE void erts_thr_port_release(Port *prt);
#endif
-ERTS_GLB_INLINE Port *erts_thr_drvport2port_raw(ErlDrvPort, int);
-ERTS_GLB_INLINE Port *erts_drvport2port_raw(ErlDrvPort drvport);
-ERTS_GLB_INLINE Port *erts_drvport2port(ErlDrvPort, erts_aint32_t *);
-ERTS_GLB_INLINE Port *erts_drvportid2port(Eterm);
+ERTS_GLB_INLINE Port *erts_thr_drvport2port(ErlDrvPort, int);
+ERTS_GLB_INLINE Port *erts_drvport2port_state(ErlDrvPort, erts_aint32_t *);
ERTS_GLB_INLINE Eterm erts_drvport2id(ErlDrvPort);
ERTS_GLB_INLINE Uint32 erts_portid2status(Eterm);
ERTS_GLB_INLINE int erts_is_port_alive(Eterm);
ERTS_GLB_INLINE int erts_is_valid_tracer_port(Eterm);
ERTS_GLB_INLINE int erts_port_driver_callback_epilogue(Port *, erts_aint32_t *);
+#define erts_drvport2port(Prt) erts_drvport2port_state((Prt), NULL)
+
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
ERTS_GLB_INLINE Port *erts_pix2port(int ix)
@@ -620,90 +642,72 @@ erts_thr_port_release(Port *prt)
#endif
-ERTS_GLB_INLINE Port*
-erts_thr_drvport2port_raw(ErlDrvPort drvport, int lock_pdl)
+ERTS_GLB_INLINE Port *
+erts_thr_drvport2port(ErlDrvPort drvport, int lock_pdl)
{
+ Port *prt = ERTS_ErlDrvPort2Port(drvport);
+ ASSERT(prt != NULL);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
+ return ERTS_INVALID_ERL_DRV_PORT;
+
+ if (lock_pdl && prt->port_data_lock)
+ driver_pdl_lock(prt->port_data_lock);
+
#if ERTS_ENABLE_LOCK_CHECK
- int emu_thread = erts_lc_is_emu_thr();
-#endif
- if (drvport == ERTS_INVALID_ERL_DRV_PORT)
- return NULL;
- else {
- Port *prt = (Port *) drvport;
- if (lock_pdl && prt->port_data_lock)
- driver_pdl_lock(prt->port_data_lock);
-#if ERTS_ENABLE_LOCK_CHECK
- if (!ERTS_IS_CRASH_DUMPING) {
- if (emu_thread) {
- ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
- ERTS_LC_ASSERT(!prt->port_data_lock
- || erts_lc_mtx_is_locked(&prt->port_data_lock->mtx));
- }
- else {
- ERTS_LC_ASSERT(prt->port_data_lock);
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&prt->port_data_lock->mtx));
- }
+ if (!ERTS_IS_CRASH_DUMPING) {
+ if (erts_lc_is_emu_thr()) {
+ ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
+ ERTS_LC_ASSERT(!prt->port_data_lock
+ || erts_lc_mtx_is_locked(&prt->port_data_lock->mtx));
+ }
+ else {
+ ERTS_LC_ASSERT(prt->port_data_lock);
+ ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&prt->port_data_lock->mtx));
}
-#endif
- return prt;
}
-}
+#endif
-ERTS_GLB_INLINE Port*
-erts_drvport2port_raw(ErlDrvPort drvport)
-{
- ERTS_LC_ASSERT(erts_lc_is_emu_thr());
- if (drvport == ERTS_INVALID_ERL_DRV_PORT)
- return NULL;
- else {
- Port *prt = (Port *) drvport;
- ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt)
- || ERTS_IS_CRASH_DUMPING);
- return prt;
+ if (erts_atomic32_read_nob(&prt->state)
+ & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) {
+ if (lock_pdl && prt->port_data_lock)
+ driver_pdl_unlock(prt->port_data_lock);
+ return ERTS_INVALID_ERL_DRV_PORT;
}
-}
-
-ERTS_GLB_INLINE Port*
-erts_drvport2port(ErlDrvPort drvport, erts_aint32_t *statep)
-{
- Port *prt = erts_drvport2port_raw(drvport);
- erts_aint32_t state;
- if (!prt)
- return NULL;
- state = erts_atomic32_read_nob(&prt->state);
- if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP)
- return NULL;
- if (statep)
- *statep = state;
return prt;
}
-ERTS_GLB_INLINE Port*
-erts_drvportid2port(Eterm id)
+ERTS_GLB_INLINE Port *
+erts_drvport2port_state(ErlDrvPort drvport, erts_aint32_t *statep)
{
- Port *prt;
+ Port *prt = ERTS_ErlDrvPort2Port(drvport);
erts_aint32_t state;
- if (is_not_internal_port(id))
- return NULL;
- prt = (Port *) erts_ptab_pix2intptr_nob(&erts_port,
- internal_port_index(id));
- if (!prt)
- return NULL;
+ ASSERT(prt);
+ ERTS_LC_ASSERT(erts_lc_is_emu_thr());
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
+ return ERTS_INVALID_ERL_DRV_PORT;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt)
|| ERTS_IS_CRASH_DUMPING);
- if (prt->common.id != id)
- return NULL;
+ /*
+ * This state check is only needed since a driver callback
+ * might terminate the port, and then call back into the
+ * emulator. Drivers should preferably have been forbidden
+ * to call into the emulator after terminating the port,
+ * but it has been like this for ages. Perhaps forbid this
+ * in some future major release?
+ */
state = erts_atomic32_read_nob(&prt->state);
if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP)
- return NULL;
+ return ERTS_INVALID_ERL_DRV_PORT;
+ if (statep)
+ *statep = state;
return prt;
}
ERTS_GLB_INLINE Eterm
erts_drvport2id(ErlDrvPort drvport)
{
- Port *prt = erts_drvport2port_raw(drvport);
- if (!prt)
+ Port *prt = erts_drvport2port(drvport);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return am_undefined;
else
return prt->common.id;
diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c
index dbc4a06c2d..9687db4780 100644
--- a/erts/emulator/beam/erl_port_task.c
+++ b/erts/emulator/beam/erl_port_task.c
@@ -685,12 +685,12 @@ enqueue_proc2port_data(Port *pp,
void
erl_drv_busy_msgq_limits(ErlDrvPort dport, ErlDrvSizeT *lowp, ErlDrvSizeT *highp)
{
- Port *pp = erts_drvport2port(dport, NULL);
- ErtsPortTaskBusyPortQ *bpq = pp->sched.taskq.bpq;
+ Port *pp = erts_drvport2port(dport);
+ ErtsPortTaskBusyPortQ *bpq;
int written = 0, resume_procs = 0;
ErlDrvSizeT low, high;
- if (!pp || !bpq) {
+ if (pp == ERTS_INVALID_ERL_DRV_PORT || !(bpq = pp->sched.taskq.bpq)) {
if (lowp)
*lowp = ERL_DRV_BUSY_MSGQ_DISABLED;
if (highp)
@@ -1509,7 +1509,6 @@ fail:
void
erts_port_task_free_port(Port *pp)
{
- ErtsProcList *suspended;
erts_aint32_t flags;
ErtsRunQueue *runq;
@@ -1522,19 +1521,16 @@ erts_port_task_free_port(Port *pp)
erts_port_task_sched_lock(&pp->sched);
flags = erts_smp_atomic32_read_bor_relb(&pp->sched.flags,
ERTS_PTS_FLG_EXIT);
- suspended = pp->suspended;
- pp->suspended = NULL;
erts_port_task_sched_unlock(&pp->sched);
erts_atomic32_read_bset_relb(&pp->state,
- (ERTS_PORT_SFLG_CLOSING
+ (ERTS_PORT_SFLG_CONNECTED
+ | ERTS_PORT_SFLG_EXITING
+ | ERTS_PORT_SFLG_CLOSING
| ERTS_PORT_SFLG_FREE),
ERTS_PORT_SFLG_FREE);
erts_smp_runq_unlock(runq);
- if (erts_proclist_fetch(&suspended, NULL))
- erts_resume_processes(suspended);
-
if (!(flags & (ERTS_PTS_FLG_IN_RUNQ|ERTS_PTS_FLG_EXEC)))
begin_port_cleanup(pp, NULL, NULL);
}
@@ -1793,10 +1789,11 @@ begin_port_cleanup(Port *pp, ErtsPortTask **execqp, int *processing_busy_q_p)
int i, max;
ErtsPortTaskBusyCallerTable *tabp;
ErtsPortTask *qs[3];
+ ErtsPortTaskHandleList *free_nshp = NULL;
+ ErtsProcList *plp;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(pp));
-
/*
* Abort remaining tasks...
*
@@ -1935,7 +1932,42 @@ begin_port_cleanup(Port *pp, ErtsPortTask **execqp, int *processing_busy_q_p)
erts_smp_atomic32_read_band_nob(&pp->sched.flags,
~(ERTS_PTS_FLG_HAVE_BUSY_TASKS
- |ERTS_PTS_FLG_HAVE_TASKS));
+ |ERTS_PTS_FLG_HAVE_TASKS
+ |ERTS_PTS_FLGS_BUSY));
+
+ erts_port_task_sched_lock(&pp->sched);
+
+ /* Cleanup nosuspend handles... */
+ free_nshp = (pp->sched.taskq.local.busy.nosuspend
+ ? get_free_nosuspend_handles(pp)
+ : NULL);
+ ASSERT(!pp->sched.taskq.local.busy.nosuspend);
+
+ /* Make sure not to leave any processes suspended on the port... */
+ plp = pp->suspended;
+ pp->suspended = NULL;
+
+ erts_port_task_sched_unlock(&pp->sched);
+
+ if (free_nshp)
+ free_nosuspend_handles(free_nshp);
+
+ if (erts_proclist_fetch(&plp, NULL)) {
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(process_port_unblocked)) {
+ DTRACE_CHARBUF(port_str, 16);
+ DTRACE_CHARBUF(pid_str, 16);
+ ErtsProcList* plp2 = plp;
+
+ erts_snprintf(port_str, sizeof(port_str), "%T", pp->common.id);
+ while (plp2 != NULL) {
+ erts_snprintf(pid_str, sizeof(pid_str), "%T", plp2->pid);
+ DTRACE2(process_port_unblocked, pid_str, port_str);
+ }
+ }
+#endif
+ erts_resume_processes(plp);
+ }
/*
* Schedule cleanup of port structure...
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 3ea4b24848..99766b7997 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -82,11 +82,11 @@ static void pdl_init(void);
#ifdef ERTS_SMP
static void driver_monitor_lock_pdl(Port *p);
static void driver_monitor_unlock_pdl(Port *p);
-#define DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(Port) erts_thr_drvport2port_raw((Port), 1)
+#define DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(Port) erts_thr_drvport2port((Port), 1)
#define DRV_MONITOR_LOCK_PDL(Port) driver_monitor_lock_pdl(Port)
#define DRV_MONITOR_UNLOCK_PDL(Port) driver_monitor_unlock_pdl(Port)
#else
-#define DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(Port) erts_thr_drvport2port_raw((Port), 0)
+#define DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(Port) erts_thr_drvport2port((Port), 0)
#define DRV_MONITOR_LOCK_PDL(Port) /* nothing */
#define DRV_MONITOR_UNLOCK_PDL(Port) /* nothing */
#endif
@@ -97,12 +97,10 @@ static void driver_monitor_unlock_pdl(Port *p);
static ERTS_INLINE ErlIOQueue*
drvport2ioq(ErlDrvPort drvport)
{
- Port *prt = erts_thr_drvport2port_raw(drvport, 0);
- erts_aint32_t state = erts_atomic32_read_nob(&prt->state);
- if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP)
+ Port *prt = erts_thr_drvport2port(drvport, 0);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return NULL;
- else
- return &prt->ioq;
+ return &prt->ioq;
}
static ERTS_INLINE int
@@ -178,6 +176,22 @@ typedef struct line_buf_context {
\
dtrace_proc_str((PID), process_str); \
dtrace_port_str((PORT), port_str);
+
+void
+dtrace_drvport_str(ErlDrvPort drvport, char *port_buf)
+{
+ Port *port = erts_drvport2port(drvport);
+
+ if (port != ERTS_INVALID_ERL_DRV_PORT)
+ erts_snprintf(port_buf, DTRACE_TERM_BUF_SIZE, "#Port<%lu.%lu>",
+ port_channel_no(port->common.id),
+ port_number(port->common.id));
+ else
+ erts_snprintf(port_buf, DTRACE_TERM_BUF_SIZE, "#Port<INVALID>",
+ port_channel_no(port->common.id),
+ port_number(port->common.id));
+}
+
#endif
static ERTS_INLINE void
@@ -683,7 +697,7 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */
}
#endif
fpe_was_unmasked = erts_block_fpe();
- drv_data = (*driver->start)((ErlDrvPort) port, name, opts);
+ drv_data = (*driver->start)(ERTS_Port2ErlDrvPort(port), name, opts);
if (((SWord) drv_data) == -1)
error_type = -1;
else if (((SWord) drv_data) == -2) {
@@ -777,8 +791,8 @@ driver_create_port(ErlDrvPort creator_port_ix, /* Creating port */
if (!erts_get_scheduler_id())
return ERTS_INVALID_ERL_DRV_PORT;
- creator_port = erts_drvport2port(creator_port_ix, NULL);
- if (!creator_port)
+ creator_port = erts_drvport2port(creator_port_ix);
+ if (creator_port == ERTS_INVALID_ERL_DRV_PORT)
return ERTS_INVALID_ERL_DRV_PORT;
rp = erts_proc_lookup(pid);
@@ -849,7 +863,7 @@ driver_create_port(ErlDrvPort creator_port_ix, /* Creating port */
port->drv_data = (UWord) drv_data;
- return (ErlDrvPort) port;
+ return ERTS_Port2ErlDrvPort(port);
}
#ifdef ERTS_SMP
@@ -3470,7 +3484,7 @@ erts_deliver_port_exit(Port *p, Eterm from, Eterm reason, int send_closed)
{
ErtsLink *lnk;
Eterm rreason;
- erts_aint32_t state;
+ erts_aint32_t state, set_state_flags;
ERTS_SMP_CHK_NO_PROC_LOCKS;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p));
@@ -3499,9 +3513,12 @@ erts_deliver_port_exit(Port *p, Eterm from, Eterm reason, int send_closed)
if (reason == am_normal && from != ERTS_PORT_GET_CONNECTED(p) && from != p->common.id)
return 0;
+ set_state_flags = ERTS_PORT_SFLG_EXITING;
if (send_closed)
- erts_atomic32_read_bor_relb(&p->state,
- ERTS_PORT_SFLG_SEND_CLOSED);
+ set_state_flags |= ERTS_PORT_SFLG_SEND_CLOSED;
+
+ state = erts_atomic32_read_bor_mb(&p->state, set_state_flags);
+ state |= set_state_flags;
if (IS_TRACED_FL(p, F_TRACE_PORTS)) {
trace_port(p, am_closed, reason);
@@ -3509,17 +3526,11 @@ erts_deliver_port_exit(Port *p, Eterm from, Eterm reason, int send_closed)
erts_trace_check_exiting(p->common.id);
- /*
- * Setting the port to not busy here, frees the list of pending
- * processes and makes them runnable.
- */
- set_busy_port((ErlDrvPort) p, 0);
+ set_busy_port(ERTS_Port2ErlDrvPort(p), 0);
if (p->common.u.alive.reg != NULL)
(void) erts_unregister_name(NULL, 0, p, p->common.u.alive.reg->name);
- state = erts_atomic32_read_bor_relb(&p->state, ERTS_PORT_SFLG_EXITING);
-
{
SweepContext sc = {p->common.id, rreason};
lnk = ERTS_P_LINKS(p);
@@ -4759,8 +4770,8 @@ set_busy_port(ErlDrvPort dprt, int on)
ERTS_SMP_CHK_NO_PROC_LOCKS;
- prt = erts_drvport2port_raw(dprt);
- if (!prt)
+ prt = erts_drvport2port(dprt);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return;
if (on) {
@@ -4859,8 +4870,8 @@ erts_port_resume_procs(Port *prt)
void set_port_control_flags(ErlDrvPort port_num, int flags)
{
- Port *prt = erts_drvport2port_raw(port_num);
- if (prt)
+ Port *prt = erts_drvport2port(port_num);
+ if (prt != ERTS_INVALID_ERL_DRV_PORT)
prt->control_flags = flags;
}
@@ -4870,8 +4881,8 @@ int get_port_flags(ErlDrvPort ix)
Port *prt;
erts_aint32_t state;
- prt = erts_drvport2port(ix, &state);
- if (!prt)
+ prt = erts_drvport2port_state(ix, &state);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return 0;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
@@ -4960,7 +4971,7 @@ erts_stale_drv_select(Eterm port,
int deselect)
{
char *type;
- ErlDrvPort drv_port = (ErlDrvPort) erts_port_lookup_raw(port);
+ ErlDrvPort drv_port = ERTS_Port2ErlDrvPort(erts_port_lookup_raw(port));
ErtsPortNames *pnp = erts_get_port_names(port);
erts_dsprintf_buf_t *dsbufp;
@@ -5082,7 +5093,6 @@ ErlDrvTermData driver_mk_term_nil(void)
void driver_report_exit(ErlDrvPort ix, int status)
{
- Port* prt = erts_drvport2port(ix, NULL);
Eterm* hp;
Eterm tuple;
Process *rp;
@@ -5091,6 +5101,10 @@ void driver_report_exit(ErlDrvPort ix, int status)
ErlOffHeap *ohp;
ErtsProcLocks rp_locks = 0;
int scheduler = erts_get_scheduler_id() != 0;
+ Port* prt = erts_drvport2port(ix);
+
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
+ return;
ERTS_SMP_CHK_NO_PROC_LOCKS;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
@@ -5687,8 +5701,18 @@ deliver_term_check_port(ErlDrvTermData port_id, Eterm *connected_p)
#ifdef ERTS_SMP
ErtsThrPrgrDelayHandle dhndl = erts_thr_progress_unmanaged_delay();
#endif
+ erts_aint32_t state;
Port *prt = erts_port_lookup_raw((Eterm) port_id);
- erts_aint32_t state = erts_atomic32_read_nob(&prt->state);
+ if (!prt)
+ return -1;
+ state = erts_atomic32_read_nob(&prt->state);
+ if (state & (ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP
+ | ERTS_PORT_SFLG_CLOSING)) {
+ if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP)
+ return -1;
+ else
+ return 0;
+ }
if (connected_p) {
#ifdef ERTS_SMP
if (dhndl != ERTS_THR_PRGR_DHANDLE_MANAGED)
@@ -5705,9 +5729,7 @@ deliver_term_check_port(ErlDrvTermData port_id, Eterm *connected_p)
ERTS_SMP_LC_ASSERT(dhndl == ERTS_THR_PRGR_DHANDLE_MANAGED
? erts_lc_is_port_locked(prt)
: !erts_lc_is_port_locked(prt));
- return ((state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP)
- ? -1
- : ((state & ERTS_PORT_SFLG_CLOSING) ? 0 : 1));
+ return 1;
}
int erl_drv_output_term(ErlDrvTermData port_id, ErlDrvTermData* data, int len)
@@ -5733,14 +5755,12 @@ driver_output_term(ErlDrvPort drvport, ErlDrvTermData* data, int len)
ERTS_SMP_CHK_NO_PROC_LOCKS;
/* NOTE! It *not* safe to access 'drvport' from unmanaged threads. */
- prt = erts_drvport2port(drvport, &state);
- if (!prt)
+ prt = erts_drvport2port_state(drvport, &state);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1; /* invalid (dead) */
ERTS_SMP_CHK_NO_PROC_LOCKS;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
- if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP)
- return -1;
- else if (state & ERTS_PORT_SFLG_CLOSING)
+ if (state & ERTS_PORT_SFLG_CLOSING)
return 0;
return driver_deliver_term(ERTS_PORT_GET_CONNECTED(prt), data, len);
@@ -5780,13 +5800,11 @@ driver_send_term(ErlDrvPort drvport,
#endif
{
erts_aint32_t state;
- Port* prt = erts_drvport2port(drvport, &state);
- if (!prt)
+ Port* prt = erts_drvport2port_state(drvport, &state);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1; /* invalid (dead) */
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
- if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP)
- return -1;
- else if (state & ERTS_PORT_SFLG_CLOSING)
+ if (state & ERTS_PORT_SFLG_CLOSING)
return 0;
}
return driver_deliver_term(to, data, len);
@@ -5802,11 +5820,11 @@ int driver_output_binary(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen,
ErlDrvBinary* bin, ErlDrvSizeT offs, ErlDrvSizeT len)
{
erts_aint32_t state;
- Port* prt = erts_drvport2port(ix, &state);
+ Port* prt = erts_drvport2port_state(ix, &state);
ERTS_SMP_CHK_NO_PROC_LOCKS;
- if (prt == NULL)
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
if (state & ERTS_PORT_SFLG_CLOSING)
@@ -5837,15 +5855,14 @@ int driver_output2(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen,
char* buf, ErlDrvSizeT len)
{
erts_aint32_t state;
- Port* prt = erts_drvport2port(ix, &state);
+ Port* prt = erts_drvport2port_state(ix, &state);
ERTS_SMP_CHK_NO_PROC_LOCKS;
- if (prt == NULL)
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
-
if (state & ERTS_PORT_SFLG_CLOSING)
return 0;
@@ -5902,8 +5919,8 @@ int driver_outputv(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen,
if (hlen < 0)
hlen = 0;
- prt = erts_drvport2port(ix, &state);
- if (prt == NULL)
+ prt = erts_drvport2port_state(ix, &state);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
@@ -6179,8 +6196,8 @@ ErlDrvPDL
driver_pdl_create(ErlDrvPort dp)
{
ErlDrvPDL pdl;
- Port *pp = erts_drvport2port(dp, NULL);
- if (!pp || pp->port_data_lock)
+ Port *pp = erts_drvport2port(dp);
+ if (pp == ERTS_INVALID_ERL_DRV_PORT || pp->port_data_lock)
return NULL;
pdl = erts_alloc(ERTS_ALC_T_PORT_DATA_LOCK,
sizeof(struct erl_drv_port_data_lock));
@@ -6638,11 +6655,11 @@ drv_cancel_timer(Port *prt)
int driver_set_timer(ErlDrvPort ix, unsigned long t)
{
- Port* prt = erts_drvport2port(ix, NULL);
+ Port* prt = erts_drvport2port(ix);
ERTS_SMP_CHK_NO_PROC_LOCKS;
- if (prt == NULL)
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
if (prt->drv_ptr->timeout == NULL)
@@ -6665,8 +6682,8 @@ int driver_set_timer(ErlDrvPort ix, unsigned long t)
int driver_cancel_timer(ErlDrvPort ix)
{
- Port* prt = erts_drvport2port(ix, NULL);
- if (prt == NULL)
+ Port* prt = erts_drvport2port(ix);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
drv_cancel_timer(prt);
@@ -6677,11 +6694,11 @@ int driver_cancel_timer(ErlDrvPort ix)
int
driver_read_timer(ErlDrvPort ix, unsigned long* t)
{
- Port* prt = erts_drvport2port(ix, NULL);
+ Port* prt = erts_drvport2port(ix);
ERTS_SMP_CHK_NO_PROC_LOCKS;
- if (prt == NULL)
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
#ifdef ERTS_SMP
@@ -6757,19 +6774,13 @@ int driver_monitor_process(ErlDrvPort drvport,
{
Port *prt;
int ret;
- erts_aint32_t state;
#if !HEAP_ON_C_STACK || (defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK))
ErtsSchedulerData *sched = erts_get_scheduler_data();
#endif
prt = DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(drvport);
-
- state = erts_atomic32_read_nob(&prt->state);
-
- if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) {
- DRV_MONITOR_UNLOCK_PDL(prt);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
- }
/* Now (in SMP) we should have either the port lock (if we have a scheduler) or the port data lock
(if we're a driver thread) */
@@ -6836,19 +6847,13 @@ int driver_demonitor_process(ErlDrvPort drvport,
{
Port *prt;
int ret;
- erts_aint32_t state;
#if !HEAP_ON_C_STACK || (defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK))
ErtsSchedulerData *sched = erts_get_scheduler_data();
#endif
prt = DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(drvport);
-
- state = erts_atomic32_read_nob(&prt->state);
-
- if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) {
- DRV_MONITOR_UNLOCK_PDL(prt);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
- }
/* Now we should have either the port lock (if we have a scheduler) or the port data lock
(if we're a driver thread) */
@@ -6897,18 +6902,13 @@ ErlDrvTermData driver_get_monitored_process(ErlDrvPort drvport,
{
Port *prt;
ErlDrvTermData ret;
- erts_aint32_t state;
#if !HEAP_ON_C_STACK || (defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK))
ErtsSchedulerData *sched = erts_get_scheduler_data();
#endif
prt = DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(drvport);
-
- state = erts_atomic32_read_nob(&prt->state);
- if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) {
- DRV_MONITOR_UNLOCK_PDL(prt);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return driver_term_nil;
- }
/* Now we should have either the port lock (if we have a scheduler) or the port data lock
(if we're a driver thread) */
@@ -6981,11 +6981,11 @@ static int
driver_failure_term(ErlDrvPort ix, Eterm term, int eof)
{
erts_aint32_t state;
- Port* prt = erts_drvport2port(ix, &state);
+ Port* prt = erts_drvport2port_state(ix, &state);
ERTS_SMP_CHK_NO_PROC_LOCKS;
- if (prt == NULL)
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
if (eof)
@@ -7014,14 +7014,14 @@ driver_failure_term(ErlDrvPort ix, Eterm term, int eof)
*/
int driver_exit(ErlDrvPort ix, int err)
{
- Port* prt = erts_drvport2port(ix, NULL);
+ Port* prt = erts_drvport2port(ix);
Process* rp;
ErtsLink *lnk, *rlnk = NULL;
Eterm connected;
ERTS_SMP_CHK_NO_PROC_LOCKS;
- if (prt == NULL)
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
connected = ERTS_PORT_GET_CONNECTED(prt);
@@ -7095,16 +7095,18 @@ ErlDrvTermData driver_mk_atom(char* string)
ErlDrvTermData driver_mk_port(ErlDrvPort ix)
{
- Port* prt = erts_drvport2port(ix, NULL);
+ Port* prt = erts_drvport2port(ix);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
+ return (ErlDrvTermData) NIL;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
return (ErlDrvTermData) prt->common.id;
}
ErlDrvTermData driver_connected(ErlDrvPort ix)
{
- Port* prt = erts_drvport2port(ix, NULL);
+ Port* prt = erts_drvport2port(ix);
ERTS_SMP_CHK_NO_PROC_LOCKS;
- if (prt == NULL)
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return NIL;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
return ERTS_PORT_GET_CONNECTED(prt);
@@ -7112,9 +7114,9 @@ ErlDrvTermData driver_connected(ErlDrvPort ix)
ErlDrvTermData driver_caller(ErlDrvPort ix)
{
- Port* prt = erts_drvport2port(ix, NULL);
+ Port* prt = erts_drvport2port(ix);
ERTS_SMP_CHK_NO_PROC_LOCKS;
- if (prt == NULL)
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return NIL;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
return prt->caller;
@@ -7122,17 +7124,15 @@ ErlDrvTermData driver_caller(ErlDrvPort ix)
int driver_lock_driver(ErlDrvPort ix)
{
- Port* prt = erts_drvport2port(ix, NULL);
+ Port* prt = erts_drvport2port(ix);
DE_Handle* dh;
ERTS_SMP_CHK_NO_PROC_LOCKS;
- erts_smp_rwmtx_rwlock(&erts_driver_list_lock);
-
- if (prt == NULL) {
- erts_smp_rwmtx_rwunlock(&erts_driver_list_lock);
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
- }
+
+ erts_smp_rwmtx_rwlock(&erts_driver_list_lock);
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
if ((dh = (DE_Handle*)prt->drv_ptr->handle ) == NULL) {
@@ -7327,7 +7327,7 @@ no_event_callback(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_
{
Port *prt = get_current_port();
report_missing_drv_callback(prt, "Event", "event()");
- driver_event((ErlDrvPort) prt, event, NULL);
+ driver_event(ERTS_Port2ErlDrvPort(prt), event, NULL);
}
static void
@@ -7335,7 +7335,7 @@ no_ready_input_callback(ErlDrvData drv_data, ErlDrvEvent event)
{
Port *prt = get_current_port();
report_missing_drv_callback(prt, "Input", "ready_input()");
- driver_select((ErlDrvPort) prt, event,
+ driver_select(ERTS_Port2ErlDrvPort(prt), event,
(ERL_DRV_READ | ERL_DRV_USE_NO_CALLBACK), 0);
}
@@ -7344,7 +7344,7 @@ no_ready_output_callback(ErlDrvData drv_data, ErlDrvEvent event)
{
Port *prt = get_current_port();
report_missing_drv_callback(prt, "Output", "ready_output()");
- driver_select((ErlDrvPort) prt, event,
+ driver_select(ERTS_Port2ErlDrvPort(prt), event,
(ERL_DRV_WRITE | ERL_DRV_USE_NO_CALLBACK), 0);
}