aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/erl_port.h
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/erl_port.h')
-rw-r--r--erts/emulator/beam/erl_port.h74
1 files changed, 60 insertions, 14 deletions
diff --git a/erts/emulator/beam/erl_port.h b/erts/emulator/beam/erl_port.h
index beeddd09a0..1eb6dea710 100644
--- a/erts/emulator/beam/erl_port.h
+++ b/erts/emulator/beam/erl_port.h
@@ -271,6 +271,30 @@ extern erts_smp_atomic_t erts_bytes_in; /* no bytes sent into the system */
(ERTS_PORT_SFLGS_INVALID_LOOKUP \
| ERTS_PORT_SFLG_DISTRIBUTION)
+
+/*
+ * Costs in reductions for some port operations.
+ */
+#define ERTS_PORT_REDS_EXECUTE 10
+#define ERTS_PORT_REDS_FREE 100
+#define ERTS_PORT_REDS_TIMEOUT 400
+#define ERTS_PORT_REDS_INPUT 400
+#define ERTS_PORT_REDS_OUTPUT 400
+#define ERTS_PORT_REDS_EVENT 400
+#define ERTS_PORT_REDS_CMD_OUTPUTV 400
+#define ERTS_PORT_REDS_CMD_OUTPUT 400
+#define ERTS_PORT_REDS_EXIT 300
+#define ERTS_PORT_REDS_CONNECT 40
+#define ERTS_PORT_REDS_UNLINK 40
+#define ERTS_PORT_REDS_LINK 40
+#define ERTS_PORT_REDS_BADSIG 40
+#define ERTS_PORT_REDS_CONTROL 400
+#define ERTS_PORT_REDS_CALL 400
+#define ERTS_PORT_REDS_INFO 100
+#define ERTS_PORT_REDS_SET_DATA 40
+#define ERTS_PORT_REDS_GET_DATA 40
+#define ERTS_PORT_REDS_TERMINATE 200
+
void print_port_info(Port *, int, void *);
void erts_port_free(Port *);
#ifndef ERTS_SMP
@@ -278,7 +302,7 @@ void erts_port_cleanup(Port *);
#endif
void erts_fire_port_monitor(Port *prt, Eterm ref);
#ifdef ERTS_SMP
-void erts_smp_xports_unlock(Port *);
+int erts_port_handle_xports(Port *);
#endif
#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
@@ -387,6 +411,9 @@ erts_smp_port_unlock(Port *prt)
extern const Port erts_invalid_port;
#define ERTS_PORT_LOCK_BUSY ((Port *) &erts_invalid_port)
+int erts_is_port_ioq_empty(Port *);
+void erts_terminate_port(Port *);
+
#ifdef ERTS_SMP
Port *erts_de2port(DistEntry *, Process *, ErtsProcLocks);
#endif
@@ -409,6 +436,7 @@ 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 *);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
@@ -700,6 +728,37 @@ erts_is_valid_tracer_port(Eterm id)
{
return !(erts_portid2status(id) & ERTS_PORT_SFLGS_INVALID_TRACER_LOOKUP);
}
+
+ERTS_GLB_INLINE int
+erts_port_driver_callback_epilogue(Port *prt, erts_aint32_t *statep)
+{
+ int reds = 0;
+ erts_aint32_t state;
+
+ ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
+
+ state = erts_atomic32_read_nob(&prt->state);
+ if ((state & ERTS_PORT_SFLG_CLOSING) && erts_is_port_ioq_empty(prt)) {
+ reds += ERTS_PORT_REDS_TERMINATE;
+ erts_terminate_port(prt);
+ state = erts_atomic32_read_nob(&prt->state);
+ ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
+ }
+
+#ifdef ERTS_SMP
+ if (prt->xports) {
+ reds += erts_port_handle_xports(prt);
+ ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
+ ASSERT(!prt->xports);
+ }
+#endif
+
+ if (statep)
+ *statep = state;
+
+ return reds;
+}
+
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
struct binary;
@@ -774,19 +833,6 @@ typedef int (*ErtsProc2PortSigCallback)(Port *,
int,
ErtsProc2PortSigData *);
-#define ERTS_PORT_REDS_CMD_OUTPUTV 400
-#define ERTS_PORT_REDS_CMD_OUTPUT 400
-#define ERTS_PORT_REDS_EXIT 300
-#define ERTS_PORT_REDS_CONNECT 40
-#define ERTS_PORT_REDS_UNLINK 40
-#define ERTS_PORT_REDS_LINK 40
-#define ERTS_PORT_REDS_BADSIG 40
-#define ERTS_PORT_REDS_CONTROL 400
-#define ERTS_PORT_REDS_CALL 400
-#define ERTS_PORT_REDS_INFO 100
-#define ERTS_PORT_REDS_SET_DATA 40
-#define ERTS_PORT_REDS_GET_DATA 40
-
typedef enum {
ERTS_PORT_OP_BADARG,
ERTS_PORT_OP_CALLER_EXIT,