aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/bif.h2
-rw-r--r--erts/emulator/beam/erl_port.h39
-rw-r--r--erts/emulator/beam/erl_port_task.c10
-rw-r--r--erts/emulator/beam/io.c27
4 files changed, 52 insertions, 26 deletions
diff --git a/erts/emulator/beam/bif.h b/erts/emulator/beam/bif.h
index 71f232035d..4e456988a3 100644
--- a/erts/emulator/beam/bif.h
+++ b/erts/emulator/beam/bif.h
@@ -59,6 +59,8 @@ do { \
} while(0)
#define BUMP_REDS(p, gc) do { \
+ ASSERT(p); \
+ ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));\
(p)->fcalls -= (gc); \
if ((p)->fcalls < 0) { \
if (!ERTS_PROC_GET_SAVED_CALLS_BUF((p))) \
diff --git a/erts/emulator/beam/erl_port.h b/erts/emulator/beam/erl_port.h
index fb07f3d5bc..65b4cd0bfe 100644
--- a/erts/emulator/beam/erl_port.h
+++ b/erts/emulator/beam/erl_port.h
@@ -273,29 +273,28 @@ 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
+#define ERTS_PORT_REDS_EXECUTE (CONTEXT_REDS/4)
+#define ERTS_PORT_REDS_FREE (CONTEXT_REDS/400)
+#define ERTS_PORT_REDS_TIMEOUT (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_INPUT (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_OUTPUT (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_EVENT (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_CMD_OUTPUTV (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_CMD_OUTPUT (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_EXIT (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_CONNECT (CONTEXT_REDS/200)
+#define ERTS_PORT_REDS_UNLINK (CONTEXT_REDS/200)
+#define ERTS_PORT_REDS_LINK (CONTEXT_REDS/200)
+#define ERTS_PORT_REDS_BADSIG (CONTEXT_REDS/200)
+#define ERTS_PORT_REDS_CONTROL (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_CALL (CONTEXT_REDS/50)
+#define ERTS_PORT_REDS_INFO (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_SET_DATA (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_GET_DATA (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_TERMINATE (CONTEXT_REDS/50)
void print_port_info(Port *, int, void *);
void erts_port_free(Port *);
diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c
index 8ceadcdb8c..09c8e760f4 100644
--- a/erts/emulator/beam/erl_port_task.c
+++ b/erts/emulator/beam/erl_port_task.c
@@ -35,6 +35,11 @@
#include "dtrace-wrapper.h"
#include <stdarg.h>
+/*
+ * ERTS_PORT_CALLBACK_VREDS: Limit the amount of callback calls we do...
+ */
+#define ERTS_PORT_CALLBACK_VREDS (CONTEXT_REDS/5)
+
#if defined(DEBUG) && 0
#define ERTS_HARD_DEBUG_TASK_QUEUES
#else
@@ -1544,6 +1549,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
ErtsPortTask *execq;
int processing_busy_q;
int res = 0;
+ int vreds = 0;
int reds = ERTS_PORT_REDS_EXECUTE;
erts_aint_t io_tasks_executed = 0;
int fpe_was_unmasked;
@@ -1688,6 +1694,9 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
break;
}
+ vreds += ERTS_PORT_CALLBACK_VREDS;
+ reds += ERTS_PORT_CALLBACK_VREDS;
+
if (reds >= CONTEXT_REDS)
break;
}
@@ -1757,6 +1766,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
res = (erts_smp_atomic_read_nob(&erts_port_task_outstanding_io_tasks)
!= (erts_aint_t) 0);
+ reds -= vreds;
runq->scheduler->reductions += reds;
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(runq));
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index e466f0e299..04dc9bb236 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1573,6 +1573,8 @@ bad_port_signal(Process *c_p,
try_call_state.state,
flags & ERTS_PORT_SIG_FLG_BAD_OUTPUT);
finalize_imm_drv_call(&try_call_state);
+ if (c_p)
+ BUMP_REDS(c_p, ERTS_PORT_REDS_BADSIG);
return ERTS_PORT_OP_BADARG;
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
return ERTS_PORT_OP_DROPPED;
@@ -1950,10 +1952,11 @@ erts_port_output(Process *c_p,
driver_free_binary(cbin);
if (evp != &ev)
erts_free(ERTS_ALC_T_TMP, evp);
- if (try_call_res == ERTS_TRY_IMM_DRV_CALL_OK)
- return ERTS_PORT_OP_DONE;
- else
+ if (try_call_res != ERTS_TRY_IMM_DRV_CALL_OK)
return ERTS_PORT_OP_DROPPED;
+ if (c_p)
+ BUMP_REDS(c_p, ERTS_PORT_REDS_CMD_OUTPUTV);
+ return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_SCHED_FLAGS:
sched_flags = try_call_state.sched_flags;
case ERTS_TRY_IMM_DRV_CALL_BUSY_LOCK:
@@ -2096,10 +2099,11 @@ erts_port_output(Process *c_p,
/* Fall through... */
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
erts_free(ERTS_ALC_T_TMP, buf);
- if (try_call_res == ERTS_TRY_IMM_DRV_CALL_OK)
- return ERTS_PORT_OP_DONE;
- else
+ if (try_call_res != ERTS_TRY_IMM_DRV_CALL_OK)
return ERTS_PORT_OP_DROPPED;
+ if (c_p)
+ BUMP_REDS(c_p, ERTS_PORT_REDS_CMD_OUTPUT);
+ return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_SCHED_FLAGS:
sched_flags = try_call_state.sched_flags;
case ERTS_TRY_IMM_DRV_CALL_BUSY_LOCK:
@@ -2267,6 +2271,8 @@ erts_port_exit(Process *c_p,
reason,
flags & ERTS_PORT_SIG_FLG_BROKEN_LINK);
finalize_imm_drv_call(&try_call_state);
+ if (res == ERTS_PORT_OP_DONE && c_p)
+ BUMP_REDS(c_p, ERTS_PORT_REDS_EXIT);
return res;
}
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
@@ -2434,6 +2440,8 @@ erts_port_connect(Process *c_p,
try_call_state.state,
connect_id);
finalize_imm_drv_call(&try_call_state);
+ if (res == ERTS_PORT_OP_DONE)
+ BUMP_REDS(c_p, ERTS_PORT_REDS_CONNECT);
return res;
}
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
@@ -2492,6 +2500,7 @@ erts_port_unlink(Process *c_p, Port *prt, Eterm from, Eterm *refp)
case ERTS_TRY_IMM_DRV_CALL_OK:
port_unlink(prt, from);
finalize_imm_drv_call(&try_call_state);
+ BUMP_REDS(c_p, ERTS_PORT_REDS_UNLINK);
return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
return ERTS_PORT_OP_DROPPED;
@@ -2579,6 +2588,7 @@ erts_port_link(Process *c_p, Port *prt, Eterm to, Eterm *refp)
case ERTS_TRY_IMM_DRV_CALL_OK:
port_link(prt, try_call_state.state, to);
finalize_imm_drv_call(&try_call_state);
+ BUMP_REDS(c_p, ERTS_PORT_REDS_LINK);
return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
return ERTS_PORT_OP_BADARG;
@@ -3944,6 +3954,7 @@ erts_port_control(Process* c_p,
&hp,
NULL,
&c_p->off_heap);
+ BUMP_REDS(c_p, ERTS_PORT_REDS_CONTROL);
return ERTS_PORT_OP_DONE;
}
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
@@ -4244,6 +4255,7 @@ erts_port_call(Process* c_p,
if (resp_buf != &resp_buf[0]
&& !(ret_flags & DRIVER_CALL_KEEP_BUFFER))
driver_free(resp_buf);
+ BUMP_REDS(c_p, ERTS_PORT_REDS_CALL);
return ERTS_PORT_OP_DONE;
}
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
@@ -4423,6 +4435,7 @@ erts_port_info(Process* c_p,
*retvalp = copy_struct(value, used_h_size, &hp, &MSO(c_p));
free_message_buffer(bp);
}
+ BUMP_REDS(c_p, ERTS_PORT_REDS_INFO);
return ERTS_PORT_OP_DONE;
}
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
@@ -4509,6 +4522,7 @@ erts_port_set_data(Process* c_p,
prt->bp = bp;
prt->data = set_data;
finalize_imm_drv_call(&try_call_state);
+ BUMP_REDS(c_p, ERTS_PORT_REDS_SET_DATA);
return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
return ERTS_PORT_OP_DROPPED;
@@ -4641,6 +4655,7 @@ erts_port_get_data(Process* c_p,
free_message_buffer(bp);
}
*retvalp = TUPLE2(hp, am_ok, data);
+ BUMP_REDS(c_p, ERTS_PORT_REDS_GET_DATA);
return ERTS_PORT_OP_DONE;
}
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT: