aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/io.c
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2013-02-14 17:43:21 +0100
committerRickard Green <[email protected]>2013-02-14 17:43:21 +0100
commitb708bf2064513e524eec1d5de1a9e76e97a20131 (patch)
treedeb7304828ad2cde93b120bfc866a39b45100768 /erts/emulator/beam/io.c
parent85775c504842e669d0bca9c62909366990954ed2 (diff)
parent953a4bd91e471126370bf5a70956ad233fda189a (diff)
downloadotp-b708bf2064513e524eec1d5de1a9e76e97a20131.tar.gz
otp-b708bf2064513e524eec1d5de1a9e76e97a20131.tar.bz2
otp-b708bf2064513e524eec1d5de1a9e76e97a20131.zip
Merge branch 'rickard/erl_drv_consume_timeslice/OTP-10810'
* rickard/erl_drv_consume_timeslice/OTP-10810: Implement erl_drv_consume_timeslice()
Diffstat (limited to 'erts/emulator/beam/io.c')
-rw-r--r--erts/emulator/beam/io.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 99766b7997..b73c883658 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1199,6 +1199,7 @@ typedef struct {
int async; /* Asynchronous operation */
int pre_chk_sched_flags; /* Check sched flags before lock? */
int fpe_was_unmasked;
+ int reds_left_in;
} ErtsTryImmDrvCallState;
#define ERTS_INIT_TRY_IMM_DRV_CALL_STATE(C_P, PRT, SFLGS, PTS_FLGS, A, PRT_OP) \
@@ -1213,6 +1214,7 @@ static ERTS_INLINE ErtsTryImmDrvCallResult
try_imm_drv_call(ErtsTryImmDrvCallState *sp)
{
ErtsTryImmDrvCallResult res;
+ int reds_left_in;
erts_aint32_t invalid_state, invalid_sched_flags;
Port *prt = sp->port;
Process *c_p = sp->c_p;
@@ -1246,16 +1248,24 @@ try_imm_drv_call(ErtsTryImmDrvCallState *sp)
goto locked_fail;
}
- if (c_p) {
+
+ if (!c_p)
+ reds_left_in = CONTEXT_REDS/10;
+ else {
if (IS_TRACED_FL(c_p, F_TRACE_SCHED_PROCS))
trace_virtual_sched(c_p, am_out);
if (erts_system_profile_flags.runnable_procs
&& erts_system_profile_flags.exclusive)
profile_runnable_proc(c_p, am_inactive);
+ reds_left_in = ERTS_BIF_REDS_LEFT(c_p);
erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);
}
+ ASSERT(0 <= reds_left_in && reds_left_in <= CONTEXT_REDS);
+ sp->reds_left_in = reds_left_in;
+ prt->reds = CONTEXT_REDS - reds_left_in;
+
ERTS_SMP_CHK_NO_PROC_LOCKS;
if (IS_TRACED_FL(prt, F_TRACE_SCHED_PORTS))
@@ -1276,10 +1286,12 @@ locked_fail:
static ERTS_INLINE void
finalize_imm_drv_call(ErtsTryImmDrvCallState *sp)
{
+ int reds;
Port *prt = sp->port;
Process *c_p = sp->c_p;
- erts_port_driver_callback_epilogue(prt, NULL);
+ reds = prt->reds;
+ reds += erts_port_driver_callback_epilogue(prt, NULL);
erts_unblock_fpe(sp->fpe_was_unmasked);
@@ -1294,6 +1306,12 @@ finalize_imm_drv_call(ErtsTryImmDrvCallState *sp)
if (c_p) {
erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
+ if (reds != (CONTEXT_REDS - sp->reds_left_in)) {
+ int bump_reds = reds - (CONTEXT_REDS - sp->reds_left_in);
+ ASSERT(bump_reds > 0);
+ BUMP_REDS(c_p, bump_reds);
+ }
+
if (IS_TRACED_FL(c_p, F_TRACE_SCHED_PROCS))
trace_virtual_sched(c_p, am_in);
if (erts_system_profile_flags.runnable_procs