diff options
author | Björn-Egil Dahlberg <[email protected]> | 2010-05-11 20:14:09 +0200 |
---|---|---|
committer | Raimo Niskanen <[email protected]> | 2010-06-03 14:54:21 +0200 |
commit | 96a6c45d081e41dbe2d44a8d07d78b46d0e9f587 (patch) | |
tree | e715d1718e40b0361dd3bac2a4e11d27d84eba8c /erts/emulator/beam/beam_bp.c | |
parent | 9fd1b1794c6e582cccfdb946b225ccf7acc98c9d (diff) | |
download | otp-96a6c45d081e41dbe2d44a8d07d78b46d0e9f587.tar.gz otp-96a6c45d081e41dbe2d44a8d07d78b46d0e9f587.tar.bz2 otp-96a6c45d081e41dbe2d44a8d07d78b46d0e9f587.zip |
Teach call count tracing to use atomics
Call count previously used a global lock for accessing and writing
its counter in the breakpoint. This is now changed to atomics instead.
The change will let call count tracing and cprof to scale better
when increasing the number of schedulers.
Diffstat (limited to 'erts/emulator/beam/beam_bp.c')
-rw-r--r-- | erts/emulator/beam/beam_bp.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c index 79d150c9e2..424e3324f9 100644 --- a/erts/emulator/beam/beam_bp.c +++ b/erts/emulator/beam/beam_bp.c @@ -439,9 +439,7 @@ erts_is_count_break(BeamInstr *pc, Sint *count_ret) { if (bdc) { if (count_ret) { - ErtsSmpBPLock(bdc); - *count_ret = bdc->count; - ErtsSmpBPUnlock(bdc); + *count_ret = (Sint) erts_smp_atomic_read(&bdc->acount); } return !0; } @@ -976,16 +974,23 @@ static int set_function_break(Module *modp, BeamInstr *pc, ASSERT(is_nil(tracer_pid)); if (break_op == (BeamInstr) BeamOp(op_i_count_breakpoint)) { BpDataCount *bdc = (BpDataCount *) bd; + long count = 0; + long res = 0; - ErtsSmpBPLock(bdc); if (count_op == erts_break_stop) { - if (bdc->count >= 0) { - bdc->count = -bdc->count-1; /* Stop call counter */ + count = erts_smp_atomic_read(&bdc->acount); + if (count >= 0) { + while(1) { + res = erts_smp_atomic_cmpxchg(&bdc->acount, -count - 1, count); + if ((res == count) || count < 0) break; + count = res; + } } } else { - bdc->count = 0; /* Reset call counter */ + /* Reset call counter */ + erts_smp_atomic_set(&bdc->acount, 0); } - ErtsSmpBPUnlock(bdc); + } else if (break_op == (Uint) BeamOp(op_i_time_breakpoint)) { BpDataTime *bdt = (BpDataTime *) bd; Uint i = 0; @@ -1015,8 +1020,7 @@ static int set_function_break(Module *modp, BeamInstr *pc, ASSERT(! match_spec); ASSERT(is_nil(tracer_pid)); if (break_op == (BeamInstr) BeamOp(op_i_count_breakpoint)) { - if (count_op == erts_break_reset - || count_op == erts_break_stop) { + if (count_op == erts_break_reset || count_op == erts_break_stop) { /* Do not insert a new breakpoint */ return 1; } @@ -1108,8 +1112,7 @@ static int set_function_break(Module *modp, BeamInstr *pc, } } else if (break_op == (BeamInstr) BeamOp(op_i_count_breakpoint)) { BpDataCount *bdc = (BpDataCount *) bd; - - bdc->count = 0; + erts_smp_atomic_init(&bdc->acount, 0); } ++(*(BeamInstr*)&code_base[MI_NUM_BREAKPOINTS]); return 1; |