aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2013-02-09 13:45:43 +0100
committerRickard Green <[email protected]>2013-02-13 12:22:56 +0100
commit69b00e333d7759ab641a53cedf4d13f1919fb00b (patch)
tree9bf3b232c23a8932ae6496ab63da834db9cb31fb /erts/emulator
parent9acad61e2bfa3e281e5e17e087811c8b1006165f (diff)
downloadotp-69b00e333d7759ab641a53cedf4d13f1919fb00b.tar.gz
otp-69b00e333d7759ab641a53cedf4d13f1919fb00b.tar.bz2
otp-69b00e333d7759ab641a53cedf4d13f1919fb00b.zip
Fix driver port accesses
Diffstat (limited to 'erts/emulator')
-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.c6
-rw-r--r--erts/emulator/beam/io.c177
-rw-r--r--erts/emulator/sys/common/erl_check_io.c42
-rw-r--r--erts/emulator/sys/unix/sys.c8
-rwxr-xr-xerts/emulator/sys/win32/sys.c4
10 files changed, 200 insertions, 196 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 8cf8128ab8..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)
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index a944340400..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
@@ -3512,7 +3526,7 @@ erts_deliver_port_exit(Port *p, Eterm from, Eterm reason, int send_closed)
erts_trace_check_exiting(p->common.id);
- 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);
@@ -4756,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) {
@@ -4856,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;
}
@@ -4867,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));
@@ -4957,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;
@@ -5079,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;
@@ -5088,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));
@@ -5684,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)
@@ -5702,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)
@@ -5730,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);
@@ -5777,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);
@@ -5799,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)
@@ -5834,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;
@@ -5899,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));
@@ -6176,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));
@@ -6635,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)
@@ -6662,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);
@@ -6674,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
@@ -6754,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) */
@@ -6833,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) */
@@ -6894,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) */
@@ -6978,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)
@@ -7011,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);
@@ -7092,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);
@@ -7109,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;
@@ -7119,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) {
@@ -7324,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
@@ -7332,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);
}
@@ -7341,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);
}
diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c
index 474408ae7c..c16831a07d 100644
--- a/erts/emulator/sys/common/erl_check_io.c
+++ b/erts/emulator/sys/common/erl_check_io.c
@@ -481,6 +481,7 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix,
int on)
{
void (*stop_select_fn)(ErlDrvEvent, void*) = NULL;
+ Port *prt = erts_drvport2port(ix);
Eterm id = erts_drvport2id(ix);
ErtsSysFdType fd = (ErtsSysFdType) e;
ErtsPollEvents ctl_events = (ErtsPollEvents) 0;
@@ -491,9 +492,11 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix,
#ifdef USE_VM_PROBES
DTRACE_CHARBUF(name, 64);
#endif
-
- ERTS_SMP_LC_ASSERT(erts_drvport2port(ix, NULL)
- && erts_lc_is_port_locked(erts_drvport2port(ix, NULL)));
+
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
+ return -1;
+
+ ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
if ((unsigned)fd >= (unsigned)erts_smp_atomic_read_nob(&drv_ev_state_len)) {
@@ -519,9 +522,9 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix,
if (!on && (mode&ERL_DRV_USE_NO_CALLBACK) == ERL_DRV_USE) {
if (IS_FD_UNKNOWN(state)) {
/* fast track to stop_select callback */
- stop_select_fn = erts_drvport2port(ix, NULL)->drv_ptr->stop_select;
+ stop_select_fn = prt->drv_ptr->stop_select;
#ifdef USE_VM_PROBES
- strncpy(name, erts_drvport2port(ix, NULL)->drv_ptr->name, sizeof(name)-1);
+ strncpy(name, prt->drv_ptr->name, sizeof(name)-1);
name[sizeof(name)-1] = '\0';
#endif
ret = 0;
@@ -654,14 +657,14 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix,
}
}
if ((mode & ERL_DRV_USE_NO_CALLBACK) == ERL_DRV_USE) {
- erts_driver_t* drv_ptr = erts_drvport2port(ix, NULL)->drv_ptr;
+ erts_driver_t* drv_ptr = prt->drv_ptr;
ASSERT(new_events==0);
if (state->remove_cnt == 0 || !wake_poller) {
/* Safe to close fd now as it is not in pollset
or there was no need to eject fd (kernel poll) */
stop_select_fn = drv_ptr->stop_select;
#ifdef USE_VM_PROBES
- strncpy(name, erts_drvport2port(ix, NULL)->drv_ptr->name, sizeof(name)-1);
+ strncpy(name, prt->drv_ptr->name, sizeof(name)-1);
name[sizeof(name)-1] = '\0';
#endif
}
@@ -712,9 +715,12 @@ ERTS_CIO_EXPORT(driver_event)(ErlDrvPort ix,
ErtsDrvEventState *state;
int do_wake = 0;
int ret;
+ Port *prt = erts_drvport2port(ix);
+
+ if (prt == ERTS_INVALID_ERL_DRV_PORT)
+ return -1;
- ERTS_SMP_LC_ASSERT(erts_drvport2port(ix, NULL)
- && erts_lc_is_port_locked(erts_drvport2port(ix, NULL)));
+ ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
if ((unsigned)fd >= (unsigned)erts_smp_atomic_read_nob(&drv_ev_state_len)) {
@@ -949,7 +955,7 @@ static void
print_select_op(erts_dsprintf_buf_t *dsbufp,
ErlDrvPort ix, ErtsSysFdType fd, int mode, int on)
{
- Port *pp = erts_drvport2port(ix, NULL);
+ Port *pp = erts_drvport2port(ix);
erts_dsprintf(dsbufp,
"driver_select(%p, %d,%s%s%s%s, %d) "
"by ",
@@ -960,8 +966,8 @@ print_select_op(erts_dsprintf_buf_t *dsbufp,
mode & ERL_DRV_USE ? " ERL_DRV_USE" : "",
mode & (ERL_DRV_USE_NO_CALLBACK & ~ERL_DRV_USE) ? "_NO_CALLBACK" : "",
on);
- print_driver_name(dsbufp, pp->common.id);
- erts_dsprintf(dsbufp, "driver %T ", pp ? pp->common.id : NIL);
+ print_driver_name(dsbufp, pp != ERTS_INVALID_ERL_DRV_PORT ? pp->common.id : NIL);
+ erts_dsprintf(dsbufp, "driver %T ", pp != ERTS_INVALID_ERL_DRV_PORT ? pp->common.id : NIL);
}
static void
@@ -1020,8 +1026,9 @@ steal_pending_stop_select(erts_dsprintf_buf_t *dsbufp, ErlDrvPort ix,
state->driver.drv_ptr = NULL;
}
else if ((mode & ERL_DRV_USE_NO_CALLBACK) == ERL_DRV_USE) {
- erts_driver_t* drv_ptr = erts_drvport2port(ix, NULL)->drv_ptr;
- if (drv_ptr != state->driver.drv_ptr) {
+ Port *prt = erts_drvport2port(ix);
+ erts_driver_t* drv_ptr = prt != ERTS_INVALID_ERL_DRV_PORT ? prt->drv_ptr : NULL;
+ if (drv_ptr && drv_ptr != state->driver.drv_ptr) {
/* Some other driver wants the stop_select callback */
if (state->driver.drv_ptr->handle) {
erts_ddll_dereference_driver(state->driver.drv_ptr->handle);
@@ -1042,7 +1049,7 @@ static void
print_event_op(erts_dsprintf_buf_t *dsbufp,
ErlDrvPort ix, ErtsSysFdType fd, ErlDrvEventData event_data)
{
- Port *pp = erts_drvport2port(ix, NULL);
+ Port *pp = erts_drvport2port(ix);
erts_dsprintf(dsbufp, "driver_event(%p, %d, ", ix, (int) fd);
if (!event_data)
erts_dsprintf(dsbufp, "NULL");
@@ -1051,8 +1058,9 @@ print_event_op(erts_dsprintf_buf_t *dsbufp,
(unsigned int) event_data->events,
(unsigned int) event_data->revents);
erts_dsprintf(dsbufp, ") by ");
- print_driver_name(dsbufp, pp->common.id);
- erts_dsprintf(dsbufp, "driver %T ", pp ? pp->common.id : NIL);
+ if (pp != ERTS_INVALID_ERL_DRV_PORT)
+ print_driver_name(dsbufp, pp->common.id);
+ erts_dsprintf(dsbufp, "driver %T ", pp != ERTS_INVALID_ERL_DRV_PORT ? pp->common.id : NIL);
}
static void
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index 0b96eded76..dbc163bac1 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -1211,8 +1211,8 @@ static int set_driver_data(ErlDrvPort port_num,
report_exit_list = report_exit;
}
- prt = erts_drvport2port(port_num, NULL);
- if (prt)
+ prt = erts_drvport2port(port_num);
+ if (prt != ERTS_INVALID_ERL_DRV_PORT)
prt->os_pid = pid;
if (read_write & DO_READ) {
@@ -2650,7 +2650,7 @@ report_exit_status(ErtsSysReportExit *rep, int status)
if (rep->ifd >= 0) {
driver_data[rep->ifd].alive = 0;
driver_data[rep->ifd].status = status;
- (void) driver_select((ErlDrvPort) pp,
+ (void) driver_select(ERTS_Port2ErlDrvPort(pp),
rep->ifd,
(ERL_DRV_READ|ERL_DRV_USE),
1);
@@ -2658,7 +2658,7 @@ report_exit_status(ErtsSysReportExit *rep, int status)
if (rep->ofd >= 0) {
driver_data[rep->ofd].alive = 0;
driver_data[rep->ofd].status = status;
- (void) driver_select((ErlDrvPort) pp,
+ (void) driver_select(ERTS_Port2ErlDrvPort(pp),
rep->ofd,
(ERL_DRV_WRITE|ERL_DRV_USE),
1);
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index 1cd9072cea..f7756f99bc 100755
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -1260,9 +1260,9 @@ spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
retval = set_driver_data(dp, hFromChild, hToChild, opts->read_write,
opts->exit_status);
if (retval != ERL_DRV_ERROR_GENERAL && retval != ERL_DRV_ERROR_ERRNO) {
- Port *prt = erts_drvport2port_raw(port_num);
+ Port *prt = erts_drvport2port(port_num);
/* We assume that this cannot generate a negative number */
- ASSERT(prt);
+ ASSERT(prt != ERTS_INVALID_ERL_DRV_PORT);
prt->os_pid = (SWord) pid;
}
}