diff options
author | Rickard Green <[email protected]> | 2012-06-04 20:47:08 +0200 |
---|---|---|
committer | Rickard Green <[email protected]> | 2012-12-03 21:18:04 +0100 |
commit | 3b523c25af0df45fbf68ab3cf50c0556f1d4e0a1 (patch) | |
tree | f930df53411010192f32f351e922ea195f28d84f /erts/emulator/beam/bif.c | |
parent | 6da93c20472f5d13b34a40ca53cba4fe6f352d24 (diff) | |
download | otp-3b523c25af0df45fbf68ab3cf50c0556f1d4e0a1.tar.gz otp-3b523c25af0df45fbf68ab3cf50c0556f1d4e0a1.tar.bz2 otp-3b523c25af0df45fbf68ab3cf50c0556f1d4e0a1.zip |
Atomic port state
Diffstat (limited to 'erts/emulator/beam/bif.c')
-rw-r--r-- | erts/emulator/beam/bif.c | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 89a8f839db..10dcba565b 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -1899,30 +1899,34 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend) { ERTS_SMP_LC_ASSERT(!pt || erts_lc_is_port_locked(pt)); /* We have waited for locks, trace schedule ports */ - if (pt && IS_TRACED_FL(pt, F_TRACE_SCHED_PORTS)) { - trace_sched_ports_where(pt, am_in, am_command); - } - if (pt && erts_system_profile_flags.runnable_ports && !erts_port_is_scheduled(pt)) { - profile_runnable_port(pt, am_active); - } - - /* XXX let port_command handle the busy stuff !!! */ - if (pt && (pt->status & ERTS_PORT_SFLG_PORT_BUSY)) { - if (suspend) { - erts_suspend(p, ERTS_PROC_LOCK_MAIN, pt); - if (erts_system_monitor_flags.busy_port) { - monitor_generic(p, am_busy_port, portid); - } - } - /* Virtually schedule out the port before releasing */ + if (pt) { + erts_aint32_t state; if (IS_TRACED_FL(pt, F_TRACE_SCHED_PORTS)) { - trace_sched_ports_where(pt, am_out, am_command); + trace_sched_ports_where(pt, am_in, am_command); } if (erts_system_profile_flags.runnable_ports && !erts_port_is_scheduled(pt)) { - profile_runnable_port(pt, am_inactive); + profile_runnable_port(pt, am_active); + } + + state = erts_smp_atomic32_read_nob(&pt->state); + /* XXX let port_command handle the busy stuff !!! */ + if (state & ERTS_PORT_SFLG_PORT_BUSY) { + if (suspend) { + erts_suspend(p, ERTS_PROC_LOCK_MAIN, pt); + if (erts_system_monitor_flags.busy_port) { + monitor_generic(p, am_busy_port, portid); + } + } + /* Virtually schedule out the port before releasing */ + if (IS_TRACED_FL(pt, F_TRACE_SCHED_PORTS)) { + trace_sched_ports_where(pt, am_out, am_command); + } + if (erts_system_profile_flags.runnable_ports && !erts_port_is_scheduled(pt)) { + profile_runnable_port(pt, am_inactive); + } + erts_port_release(pt); + return SEND_YIELD; } - erts_port_release(pt); - return SEND_YIELD; } if (IS_TRACED(p)) /* trace once only !! */ @@ -3534,14 +3538,17 @@ BIF_RETTYPE ports_0(BIF_ALIST_0) for (i = erts_max_ports-1; i >= 0; i--) { Port* prt = &erts_port[i]; - erts_smp_port_state_lock(prt); - if (!(prt->status & ERTS_PORT_SFLGS_DEAD) - && prt->snapshot != next_ss) { - ASSERT(prt->snapshot == next_ss - 1); - *pp++ = prt->id; - prt->snapshot = next_ss; /* Consumed by this snapshot */ + erts_aint32_t state = erts_smp_atomic32_read_acqb(&prt->state); + if (!(state & ERTS_PORT_SFLGS_DEAD)) { + erts_smp_port_minor_lock(prt); + state = erts_smp_atomic32_read_nob(&prt->state); + if (!(state & ERTS_PORT_SFLGS_DEAD) && prt->snapshot != next_ss) { + ASSERT(prt->snapshot == next_ss - 1); + *pp++ = prt->id; + prt->snapshot = next_ss; /* Consumed by this snapshot */ + } + erts_smp_port_minor_unlock(prt); } - erts_smp_port_state_unlock(prt); } dead_ports = (Eterm*)erts_smp_atomic_xchg_nob(&erts_dead_ports_ptr, |