aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/beam_bp.c
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2010-04-30 15:03:56 +0200
committerRaimo Niskanen <[email protected]>2010-06-03 14:54:20 +0200
commit5bd5aa849475b505a5b0798295511a6a0b4885a4 (patch)
tree9e14f1cdc0872ca07d586973e06bc15a27ac6ff9 /erts/emulator/beam/beam_bp.c
parent891682094bf1db038cdf9addffe0b107f40ab6ec (diff)
downloadotp-5bd5aa849475b505a5b0798295511a6a0b4885a4.tar.gz
otp-5bd5aa849475b505a5b0798295511a6a0b4885a4.tar.bz2
otp-5bd5aa849475b505a5b0798295511a6a0b4885a4.zip
Teach call_time trace to use intruction pointers
call_time trace will use instruction pointers instead of breakpoint data pointers. More costly lookup but the bdt structure might be deallocated, we do not want that. Remove unnecessary pattern lock.
Diffstat (limited to 'erts/emulator/beam/beam_bp.c')
-rw-r--r--erts/emulator/beam/beam_bp.c190
1 files changed, 104 insertions, 86 deletions
diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c
index 48e7b6675a..3e776fa951 100644
--- a/erts/emulator/beam/beam_bp.c
+++ b/erts/emulator/beam/beam_bp.c
@@ -549,6 +549,8 @@ static void bp_hash_rehash(bp_time_hash_t *hash, Uint n) {
item[ix].pid = NIL;
}
+ /* rehash, old hash -> new hash */
+
for( ix = 0; ix < hash->n; ix++) {
if (hash->item[ix].pid != NIL) {
@@ -654,45 +656,51 @@ void erts_schedule_time_break(Process *p, Uint schedule) {
Uint ix = 0;
bp_data_time_item_t sitem, *item = NULL;
bp_time_hash_t *h = NULL;
+ BpDataTime *pbdt = NULL;
ASSERT(p);
pbt = ERTS_PROC_GET_CALL_TIME(p);
+#ifdef ERTS_SMP
+ ix = p->scheduler_data->no - 1;
+#else
+ ix = 0;
+#endif
+/*
ASSERT( (p->status == P_RUNNING) ||
(p->status == P_WAITING) ||
(p->status == P_RUNABLE));
-
+*/
if (pbt) {
get_sys_now(&ms,&s,&us);
switch(schedule) {
case ERTS_BP_CALL_TIME_SCHEDULE_EXITING :
+ break;
case ERTS_BP_CALL_TIME_SCHEDULE_OUT :
/* When a process is scheduled _out_,
* timestamp it and add its delta to
* the previous breakpoint.
*/
-#ifdef ERTS_SMP
- ix = p->scheduler_data->no - 1;
-#else
- ix = 0;
-#endif
- bp_time_diff(&sitem, pbt, ms, s, us);
- sitem.pid = p->id;
- sitem.count = 1;
- /*count is set to 0 if out and 1 if exiting */
+ pbdt = (BpDataTime *) is_break(pbt->pc, (Uint) BeamOp(op_i_time_breakpoint));
+ if (pbdt) {
+ bp_time_diff(&sitem, pbt, ms, s, us);
+ sitem.pid = p->id;
+ sitem.count = 0;
- h = &(pbt->bdt->hash[ix]);
+ h = &(pbdt->hash[ix]);
- ASSERT(h->item);
+ ASSERT(h);
+ ASSERT(h->item);
- item = bp_hash_get(h, &sitem);
- if (!item) {
- item = bp_hash_put(h, &sitem);
- } else {
- BP_TIME_ADD(item, &sitem);
+ item = bp_hash_get(h, &sitem);
+ if (!item) {
+ item = bp_hash_put(h, &sitem);
+ } else {
+ BP_TIME_ADD(item, &sitem);
+ }
}
break;
case ERTS_BP_CALL_TIME_SCHEDULE_IN :
@@ -700,21 +708,6 @@ void erts_schedule_time_break(Process *p, Uint schedule) {
* timestamp it and remove the previous
* timestamp in the psd.
*/
- sitem.pid = p->id;
- sitem.count = -1;
- sitem.us_time = 0;
- sitem.s_time = 0;
-
- h = &(pbt->bdt->hash[ix]);
-
- ASSERT(h->item);
-
- item = bp_hash_get(h, &sitem);
- if (!item) {
- item = bp_hash_put(h, &sitem);
- } else {
- BP_TIME_ADD(item, &sitem);
- }
pbt->ms = ms;
pbt->s = s;
pbt->us = us;
@@ -748,15 +741,15 @@ void erts_schedule_time_break(Process *p, Uint schedule) {
* - egil
*/
-void erts_do_time_break(Process *p, BpDataTime *bdt, Uint type) {
+void erts_trace_time_break(Process *p, BeamInstr *pc, BpDataTime *bdt, Uint type) {
Uint ms,s,us;
process_breakpoint_time_t *pbt = NULL;
int ix = 0;
bp_data_time_item_t sitem, *item = NULL;
bp_time_hash_t *h = NULL;
+ BpDataTime *pbdt = NULL;
ASSERT(p);
- ASSERT(bdt);
ASSERT(p->status == P_RUNNING);
/* get previous timestamp and breakpoint
@@ -765,61 +758,81 @@ void erts_do_time_break(Process *p, BpDataTime *bdt, Uint type) {
pbt = ERTS_PROC_GET_CALL_TIME(p);
get_sys_now(&ms,&s,&us);
+#ifdef ERTS_SMP
+ ix = p->scheduler_data->no - 1;
+#else
+ ix = 0;
+#endif
+
switch(type) {
- case ERTS_BP_CALL_TIME_CALL:
/* get pbt
* timestamp = t0
+ * lookup bdt from code
* set ts0 to pbt
* add call count here?
*/
- if (!pbt) {
- pbt = Alloc(sizeof(process_breakpoint_time_t));
- (void *) ERTS_PROC_SET_CALL_TIME(p, ERTS_PROC_LOCK_MAIN, pbt);
- }
-
- pbt->bdt = bdt; /* needed for schedule? */
-
- pbt->ms = ms;
- pbt->s = s;
- pbt->us = us;
-
-
- break;
+ case ERTS_BP_CALL_TIME_CALL:
case ERTS_BP_CALL_TIME_TAIL_CALL:
- ASSERT(pbt);
-
-#ifdef ERTS_SMP
- ix = p->scheduler_data->no - 1;
-#else
- ix = 0;
-#endif
+ if (pbt) {
+ ASSERT(pbt->pc);
+ /* add time to previous code */
bp_time_diff(&sitem, pbt, ms, s, us);
sitem.pid = p->id;
- sitem.count = 1;
+ sitem.count = 0;
- h = &(bdt->hash[ix]);
+ /* previous breakpoint */
+ pbdt = (BpDataTime *) is_break(pbt->pc, (Uint) BeamOp(op_i_time_breakpoint));
- ASSERT(h->item);
+ /* if null then the breakpoint was removed */
+ if (pbdt) {
+ h = &(pbdt->hash[ix]);
- item = bp_hash_get(h, &sitem);
- if (!item) {
- item = bp_hash_put(h, &sitem);
- } else {
- BP_TIME_ADD(item, &sitem);
+ ASSERT(h);
+ ASSERT(h->item);
+
+ item = bp_hash_get(h, &sitem);
+ if (!item) {
+ item = bp_hash_put(h, &sitem);
+ } else {
+ BP_TIME_ADD(item, &sitem);
+ }
}
+ } else {
+ /* first call of process to instrumented function */
+ pbt = Alloc(sizeof(process_breakpoint_time_t));
+ (void *) ERTS_PROC_SET_CALL_TIME(p, ERTS_PROC_LOCK_MAIN, pbt);
+ }
+ /* add count to this code */
+ sitem.pid = p->id;
+ sitem.count = 1;
+ sitem.s_time = 0;
+ sitem.us_time = 0;
- pbt->bdt = bdt; /* needed for schedule? */
+ /* this breakpoint */
+ ASSERT(bdt);
+ h = &(bdt->hash[ix]);
- pbt->ms = ms;
- pbt->s = s;
- pbt->us = us;
- break;
+ ASSERT(h);
+ ASSERT(h->item);
+ item = bp_hash_get(h, &sitem);
+ if (!item) {
+ item = bp_hash_put(h, &sitem);
+ } else {
+ BP_TIME_ADD(item, &sitem);
+ }
+
+ pbt->pc = pc;
+ pbt->ms = ms;
+ pbt->s = s;
+ pbt->us = us;
+ break;
case ERTS_BP_CALL_TIME_RETURN:
/* get pbt
+ * lookup bdt from code
* timestamp = t1
* get ts0 from pbt
* get item from bdt->hash[bp_hash(p->id)]
@@ -830,30 +843,34 @@ void erts_do_time_break(Process *p, BpDataTime *bdt, Uint type) {
/* might have been removed due to
* trace_pattern(false)
*/
-#ifdef ERTS_SMP
- ix = p->scheduler_data->no - 1;
-#else
- ix = 0;
-#endif
+ ASSERT(pbt->pc);
+
bp_time_diff(&sitem, pbt, ms, s, us);
sitem.pid = p->id;
- sitem.count = 1;
+ sitem.count = 0;
- h = &(bdt->hash[ix]);
+ /* previous breakpoint */
+ pbdt = (BpDataTime *) is_break(pbt->pc, (Uint) BeamOp(op_i_time_breakpoint));
- ASSERT(h->item);
+ if (pbdt) {
- item = bp_hash_get(h, &sitem);
- if (!item) {
- item = bp_hash_put(h, &sitem);
- } else {
- BP_TIME_ADD(item, &sitem);
+ h = &(pbdt->hash[ix]);
+
+ ASSERT(h);
+ ASSERT(h->item);
+
+ item = bp_hash_get(h, &sitem);
+ if (!item) {
+ item = bp_hash_put(h, &sitem);
+ } else {
+ BP_TIME_ADD(item, &sitem);
+ }
}
- pbt->bdt = NULL;
- pbt->ms = ms;
- pbt->s = s;
- pbt->us = us;
+ pbt->pc = pc;
+ pbt->ms = ms;
+ pbt->s = s;
+ pbt->us = us;
}
break;
}
@@ -976,7 +993,8 @@ static int set_function_break(Module *modp, BeamInstr *pc,
BpDataTime *bdt = (BpDataTime *) bd;
Uint i = 0;
- /*XXX: must block system */
+ ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+
if (count_op == erts_break_stop) {
bdt->pause = 1;
} else {