111
117
static int set_break(Eterm mfa[3], int specified,
112
Binary *match_spec, Uint break_op,
118
Binary *match_spec, BeamInstr break_op,
113
119
enum erts_break_op count_op, Eterm tracer_pid);
114
120
static int set_module_break(Module *modp, Eterm mfa[3], int specified,
115
Binary *match_spec, Uint break_op,
121
Binary *match_spec, BeamInstr break_op,
116
122
enum erts_break_op count_op, Eterm tracer_pid);
117
static int set_function_break(Module *modp, Uint *pc,
118
Binary *match_spec, Uint break_op,
123
static int set_function_break(Module *modp, BeamInstr *pc, int bif,
124
Binary *match_spec, BeamInstr break_op,
119
125
enum erts_break_op count_op, Eterm tracer_pid);
121
127
static int clear_break(Eterm mfa[3], int specified,
123
129
static int clear_module_break(Module *modp, Eterm mfa[3], int specified,
125
static int clear_function_break(Module *modp, Uint *pc,
128
static BpData *is_break(Uint *pc, Uint break_op);
131
static int clear_function_break(Module *modp, BeamInstr *pc, int bif,
134
static BpData *is_break(BeamInstr *pc, BeamInstr break_op);
135
static BpData *get_break(Process *p, BeamInstr *pc, BeamInstr break_op);
138
#define BP_TIME_ADD(pi0, pi1) \
141
(pi0)->count += (pi1)->count; \
142
(pi0)->s_time += (pi1)->s_time; \
143
(pi0)->us_time += (pi1)->us_time; \
144
r = (pi0)->us_time / 1000000; \
145
(pi0)->s_time += r; \
146
(pi0)->us_time = (pi0)->us_time % 1000000; \
149
static void bp_hash_init(bp_time_hash_t *hash, Uint n);
150
static void bp_hash_rehash(bp_time_hash_t *hash, Uint n);
151
static ERTS_INLINE bp_data_time_item_t * bp_hash_get(bp_time_hash_t *hash, bp_data_time_item_t *sitem);
152
static ERTS_INLINE bp_data_time_item_t * bp_hash_put(bp_time_hash_t *hash, bp_data_time_item_t *sitem);
153
static void bp_hash_delete(bp_time_hash_t *hash);
132
156
/* *************************************************************************
153
177
Eterm tracer_pid) {
154
178
ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
155
179
return set_break(mfa, specified, match_spec,
156
(Uint) BeamOp(op_i_mtrace_breakpoint), 0, tracer_pid);
180
(BeamInstr) BeamOp(op_i_mtrace_breakpoint), 0, tracer_pid);
183
/* set breakpoint data for on exported bif entry */
160
erts_set_mtrace_bif(Uint *pc, Binary *match_spec, Eterm tracer_pid) {
186
erts_set_mtrace_bif(BeamInstr *pc, Binary *match_spec, Eterm tracer_pid) {
162
187
ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
164
bdt = (BpDataTrace *) pc[-4];
166
MatchSetUnref(bdt->match_spec);
167
MatchSetRef(match_spec);
168
bdt->match_spec = match_spec;
169
bdt->tracer_pid = tracer_pid;
171
bdt = Alloc(sizeof(BpDataTrace));
172
BpInit((BpData *) bdt, 0);
173
MatchSetRef(match_spec);
174
bdt->match_spec = match_spec;
175
bdt->tracer_pid = tracer_pid;
188
set_function_break(NULL, pc, BREAK_IS_BIF, match_spec, (BeamInstr) BeamOp(op_i_mtrace_breakpoint), 0, tracer_pid);
191
void erts_set_time_trace_bif(BeamInstr *pc, enum erts_break_op count_op) {
192
set_function_break(NULL, pc, BREAK_IS_BIF, NULL, (BeamInstr) BeamOp(op_i_time_breakpoint), count_op, NIL);
195
void erts_clear_time_trace_bif(BeamInstr *pc) {
196
clear_function_break(NULL, pc, BREAK_IS_BIF, (BeamInstr) BeamOp(op_i_time_breakpoint));
181
200
erts_set_debug_break(Eterm mfa[3], int specified) {
182
201
ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
183
202
return set_break(mfa, specified, NULL,
184
(Uint) BeamOp(op_i_debug_breakpoint), 0, NIL);
203
(BeamInstr) BeamOp(op_i_debug_breakpoint), 0, NIL);
188
207
erts_set_count_break(Eterm mfa[3], int specified, enum erts_break_op count_op) {
189
208
ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
190
209
return set_break(mfa, specified, NULL,
191
(Uint) BeamOp(op_i_count_breakpoint), count_op, NIL);
210
(BeamInstr) BeamOp(op_i_count_breakpoint), count_op, NIL);
214
erts_set_time_break(Eterm mfa[3], int specified, enum erts_break_op count_op) {
215
ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
216
return set_break(mfa, specified, NULL,
217
(BeamInstr) BeamOp(op_i_time_breakpoint), count_op, NIL);
197
221
erts_clear_trace_break(Eterm mfa[3], int specified) {
198
222
ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
199
223
return clear_break(mfa, specified,
200
(Uint) BeamOp(op_i_trace_breakpoint));
224
(BeamInstr) BeamOp(op_i_trace_breakpoint));
204
228
erts_clear_mtrace_break(Eterm mfa[3], int specified) {
205
229
ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
206
230
return clear_break(mfa, specified,
207
(Uint) BeamOp(op_i_mtrace_breakpoint));
231
(BeamInstr) BeamOp(op_i_mtrace_breakpoint));
211
erts_clear_mtrace_bif(Uint *pc) {
213
ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
215
bdt = (BpDataTrace *) pc[-4];
217
if (bdt->match_spec) {
218
MatchSetUnref(bdt->match_spec);
222
pc[-4] = (Uint) NULL;
235
erts_clear_mtrace_bif(BeamInstr *pc) {
236
clear_function_break(NULL, pc, BREAK_IS_BIF, (BeamInstr) BeamOp(op_i_mtrace_breakpoint));
226
240
erts_clear_debug_break(Eterm mfa[3], int specified) {
227
241
ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
228
242
return clear_break(mfa, specified,
229
(Uint) BeamOp(op_i_debug_breakpoint));
243
(BeamInstr) BeamOp(op_i_debug_breakpoint));
233
247
erts_clear_count_break(Eterm mfa[3], int specified) {
234
248
ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
235
249
return clear_break(mfa, specified,
236
(Uint) BeamOp(op_i_count_breakpoint));
250
(BeamInstr) BeamOp(op_i_count_breakpoint));
254
erts_clear_time_break(Eterm mfa[3], int specified) {
255
ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
256
return clear_break(mfa, specified,
257
(BeamInstr) BeamOp(op_i_time_breakpoint));
348
erts_is_mtrace_break(Uint *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) {
375
erts_is_mtrace_break(BeamInstr *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) {
349
376
BpDataTrace *bdt =
350
(BpDataTrace *) is_break(pc, (Uint) BeamOp(op_i_mtrace_breakpoint));
353
if (match_spec_ret) {
354
*match_spec_ret = bdt->match_spec;
356
if (tracer_pid_ret) {
358
*tracer_pid_ret = bdt->tracer_pid;
359
ErtsSmpBPUnlock(bdt);
367
erts_is_mtrace_bif(Uint *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) {
368
BpDataTrace *bdt = (BpDataTrace *) pc[-4];
371
if (match_spec_ret) {
372
*match_spec_ret = bdt->match_spec;
374
if (tracer_pid_ret) {
376
*tracer_pid_ret = bdt->tracer_pid;
377
ErtsSmpBPUnlock(bdt);
385
erts_is_native_break(Uint *pc) {
377
(BpDataTrace *) is_break(pc, (BeamInstr) BeamOp(op_i_mtrace_breakpoint));
380
if (match_spec_ret) {
381
*match_spec_ret = bdt->match_spec;
383
if (tracer_pid_ret) {
385
*tracer_pid_ret = bdt->tracer_pid;
386
ErtsSmpBPUnlock(bdt);
394
erts_is_native_break(BeamInstr *pc) {
387
ASSERT(pc[-5] == (Uint) BeamOp(op_i_func_info_IaaI));
388
return pc[0] == (Uint) BeamOp(op_hipe_trap_call)
389
|| pc[0] == (Uint) BeamOp(op_hipe_trap_call_closure);
396
ASSERT(pc[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
397
return pc[0] == (BeamInstr) BeamOp(op_hipe_trap_call)
398
|| pc[0] == (BeamInstr) BeamOp(op_hipe_trap_call_closure);
396
erts_is_count_break(Uint *pc, Sint *count_ret) {
405
erts_is_count_break(BeamInstr *pc, Sint *count_ret) {
397
406
BpDataCount *bdc =
398
(BpDataCount *) is_break(pc, (Uint) BeamOp(op_i_count_breakpoint));
407
(BpDataCount *) is_break(pc, (BeamInstr) BeamOp(op_i_count_breakpoint));
403
*count_ret = bdc->count;
404
ErtsSmpBPUnlock(bdc);
411
*count_ret = (Sint) erts_smp_atomic_read(&bdc->acount);
418
int erts_is_time_break(Process *p, BeamInstr *pc, Eterm *retval) {
423
bp_data_time_item_t *item = NULL;
424
BpDataTime *bdt = (BpDataTime *) is_break(pc, (BeamInstr) BeamOp(op_i_time_breakpoint));
428
/* collect all hashes to one hash */
429
bp_hash_init(&hash, 64);
430
/* foreach threadspecific hash */
431
for (i = 0; i < bdt->n; i++) {
432
bp_data_time_item_t *sitem;
434
/* foreach hash bucket not NIL*/
435
for(ix = 0; ix < bdt->hash[i].n; ix++) {
436
item = &(bdt->hash[i].item[ix]);
437
if (item->pid != NIL) {
438
sitem = bp_hash_get(&hash, item);
440
BP_TIME_ADD(sitem, item);
442
bp_hash_put(&hash, item);
447
/* *retval should be NIL or term from previous bif in export entry */
450
size = (5 + 2)*hash.used;
451
hp = HAlloc(p, size);
453
for(ix = 0; ix < hash.n; ix++) {
454
item = &(hash.item[ix]);
455
if (item->pid != NIL) {
456
t = TUPLE4(hp, item->pid,
457
make_small(item->count),
458
make_small(item->s_time),
459
make_small(item->us_time));
461
*retval = CONS(hp, t, *retval); hp += 2;
465
bp_hash_delete(&hash);
412
475
erts_find_local_func(Eterm mfa[3]) {
477
BeamInstr** code_base;
418
481
if ((modp = erts_get_module(mfa[0])) == NULL)
420
if ((code_base = (Uint **) modp->code) == NULL)
483
if ((code_base = (BeamInstr **) modp->code) == NULL)
422
n = (Uint) code_base[MI_NUM_FUNCTIONS];
485
n = (BeamInstr) code_base[MI_NUM_FUNCTIONS];
423
486
for (i = 0; i < n; ++i) {
424
487
code_ptr = code_base[MI_FUNCTIONS+i];
425
ASSERT(((Uint) BeamOp(op_i_func_info_IaaI)) == code_ptr[0]);
488
ASSERT(((BeamInstr) BeamOp(op_i_func_info_IaaI)) == code_ptr[0]);
426
489
ASSERT(mfa[0] == ((Eterm) code_ptr[2]));
427
490
if (mfa[1] == ((Eterm) code_ptr[3]) &&
428
((Uint) mfa[2]) == code_ptr[4]) {
491
((BeamInstr) mfa[2]) == code_ptr[4]) {
429
492
return code_ptr + 5;
499
ERTS_INLINE Uint bp_sched2ix() {
501
ErtsSchedulerData *esdp;
502
esdp = erts_get_scheduler_data();
508
static void bp_hash_init(bp_time_hash_t *hash, Uint n) {
509
Uint size = sizeof(bp_data_time_item_t)*n;
515
hash->item = (bp_data_time_item_t *)Alloc(size);
516
sys_memzero(hash->item, size);
518
for(i = 0; i < n; ++i) {
519
hash->item[i].pid = NIL;
523
static void bp_hash_rehash(bp_time_hash_t *hash, Uint n) {
524
bp_data_time_item_t *item = NULL;
525
Uint size = sizeof(bp_data_time_item_t)*n;
529
item = (bp_data_time_item_t *)Alloc(size);
530
sys_memzero(item, size);
532
for( ix = 0; ix < n; ++ix) {
536
/* rehash, old hash -> new hash */
538
for( ix = 0; ix < hash->n; ix++) {
539
if (hash->item[ix].pid != NIL) {
541
hval = ((hash->item[ix].pid) >> 4) % n; /* new n */
543
while (item[hval].pid != NIL) {
544
hval = (hval + 1) % n;
546
item[hval].pid = hash->item[ix].pid;
547
item[hval].count = hash->item[ix].count;
548
item[hval].s_time = hash->item[ix].s_time;
549
item[hval].us_time = hash->item[ix].us_time;
557
static ERTS_INLINE bp_data_time_item_t * bp_hash_get(bp_time_hash_t *hash, bp_data_time_item_t *sitem) {
558
Eterm pid = sitem->pid;
559
Uint hval = (pid >> 4) % hash->n;
560
bp_data_time_item_t *item = NULL;
564
while (item[hval].pid != pid) {
565
if (item[hval].pid == NIL) return NULL;
566
hval = (hval + 1) % hash->n;
569
return &(item[hval]);
572
static ERTS_INLINE bp_data_time_item_t * bp_hash_put(bp_time_hash_t *hash, bp_data_time_item_t* sitem) {
575
bp_data_time_item_t *item;
577
/* make sure that the hash is not saturated */
578
/* if saturated, rehash it */
580
r = hash->used / (float) hash->n;
583
bp_hash_rehash(hash, hash->n * 2);
585
/* Do hval after rehash */
586
hval = (sitem->pid >> 4) % hash->n;
591
while (item[hval].pid != NIL) {
592
hval = (hval + 1) % hash->n;
594
item = &(hash->item[hval]);
596
item->pid = sitem->pid;
597
item->s_time = sitem->s_time;
598
item->us_time = sitem->us_time;
599
item->count = sitem->count;
605
static void bp_hash_delete(bp_time_hash_t *hash) {
612
static void bp_time_diff(bp_data_time_item_t *item, /* out */
613
process_breakpoint_time_t *pbt, /* in */
614
Uint ms, Uint s, Uint us) {
621
/* get_sys_now may return zero difftime,
625
ASSERT(dms >= 0 || ds >= 0 || dus >= 0);
639
void erts_schedule_time_break(Process *p, Uint schedule) {
641
process_breakpoint_time_t *pbt = NULL;
642
bp_data_time_item_t sitem, *item = NULL;
643
bp_time_hash_t *h = NULL;
644
BpDataTime *pbdt = NULL;
648
pbt = ERTS_PROC_GET_CALL_TIME(p);
653
case ERTS_BP_CALL_TIME_SCHEDULE_EXITING :
655
case ERTS_BP_CALL_TIME_SCHEDULE_OUT :
656
/* When a process is scheduled _out_,
657
* timestamp it and add its delta to
658
* the previous breakpoint.
661
pbdt = (BpDataTime *) get_break(p, pbt->pc, (BeamInstr) BeamOp(op_i_time_breakpoint));
663
get_sys_now(&ms,&s,&us);
664
bp_time_diff(&sitem, pbt, ms, s, us);
668
h = &(pbdt->hash[bp_sched2ix_proc(p)]);
673
item = bp_hash_get(h, &sitem);
675
item = bp_hash_put(h, &sitem);
677
BP_TIME_ADD(item, &sitem);
681
case ERTS_BP_CALL_TIME_SCHEDULE_IN :
682
/* When a process is scheduled _in_,
683
* timestamp it and remove the previous
684
* timestamp in the psd.
686
get_sys_now(&ms,&s,&us);
693
/* will never happen */
699
/* call_time breakpoint
700
* Accumulated times are added to the previous bp,
701
* not the current one. The current one is saved
702
* for future reference.
703
* The previous breakpoint is stored in the process it self, the psd.
704
* We do not need to store in a stack frame.
705
* There is no need for locking, each thread has its own
706
* area in each bp to save data.
707
* Since we need to diffrentiate between processes for each bp,
708
* every bp has a hash (per thread) to process-bp statistics.
712
void erts_trace_time_break(Process *p, BeamInstr *pc, BpDataTime *bdt, Uint type) {
714
process_breakpoint_time_t *pbt = NULL;
715
bp_data_time_item_t sitem, *item = NULL;
716
bp_time_hash_t *h = NULL;
717
BpDataTime *pbdt = NULL;
720
ASSERT(p->status == P_RUNNING);
722
/* get previous timestamp and breakpoint
723
* from the process psd */
725
pbt = ERTS_PROC_GET_CALL_TIME(p);
726
get_sys_now(&ms,&s,&us);
731
* lookup bdt from code
733
* add call count here?
735
case ERTS_BP_CALL_TIME_CALL:
736
case ERTS_BP_CALL_TIME_TAIL_CALL:
740
/* add time to previous code */
741
bp_time_diff(&sitem, pbt, ms, s, us);
745
/* previous breakpoint */
746
pbdt = (BpDataTime *) get_break(p, pbt->pc, (BeamInstr) BeamOp(op_i_time_breakpoint));
748
/* if null then the breakpoint was removed */
750
h = &(pbdt->hash[bp_sched2ix_proc(p)]);
755
item = bp_hash_get(h, &sitem);
757
item = bp_hash_put(h, &sitem);
759
BP_TIME_ADD(item, &sitem);
764
/* first call of process to instrumented function */
765
pbt = Alloc(sizeof(process_breakpoint_time_t));
766
(void *) ERTS_PROC_SET_CALL_TIME(p, ERTS_PROC_LOCK_MAIN, pbt);
768
/* add count to this code */
774
/* this breakpoint */
776
h = &(bdt->hash[bp_sched2ix_proc(p)]);
781
item = bp_hash_get(h, &sitem);
783
item = bp_hash_put(h, &sitem);
785
BP_TIME_ADD(item, &sitem);
794
case ERTS_BP_CALL_TIME_RETURN:
796
* lookup bdt from code
799
* get item from bdt->hash[bp_hash(p->id)]
800
* ack diff (t1, t0) to item
804
/* might have been removed due to
805
* trace_pattern(false)
809
bp_time_diff(&sitem, pbt, ms, s, us);
813
/* previous breakpoint */
814
pbdt = (BpDataTime *) get_break(p, pbt->pc, (BeamInstr) BeamOp(op_i_time_breakpoint));
816
/* beware, the trace_pattern might have been removed */
818
h = &(pbdt->hash[bp_sched2ix_proc(p)]);
823
item = bp_hash_get(h, &sitem);
825
item = bp_hash_put(h, &sitem);
827
BP_TIME_ADD(item, &sitem);
839
/* will never happen */
437
845
/* *************************************************************************
472
880
static int set_module_break(Module *modp, Eterm mfa[3], int specified,
473
Binary *match_spec, Uint break_op,
881
Binary *match_spec, BeamInstr break_op,
474
882
enum erts_break_op count_op, Eterm tracer_pid) {
883
BeamInstr** code_base;
477
885
int num_processed = 0;
480
888
ASSERT(break_op);
482
code_base = (Uint **) modp->code;
890
code_base = (BeamInstr **) modp->code;
483
891
if (code_base == NULL) {
486
n = (Uint) code_base[MI_NUM_FUNCTIONS];
894
n = (BeamInstr) code_base[MI_NUM_FUNCTIONS];
487
895
for (i = 0; i < n; ++i) {
488
896
code_ptr = code_base[MI_FUNCTIONS+i];
489
ASSERT(code_ptr[0] == (Uint) BeamOp(op_i_func_info_IaaI));
897
ASSERT(code_ptr[0] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
490
898
if ((specified < 2 || mfa[1] == ((Eterm) code_ptr[3])) &&
491
899
(specified < 3 || ((int) mfa[2]) == ((int) code_ptr[4]))) {
492
Uint *pc = code_ptr+5;
900
BeamInstr *pc = code_ptr+5;
495
set_function_break(modp, pc, match_spec,
903
set_function_break(modp, pc, BREAK_IS_ERL, match_spec,
496
904
break_op, count_op, tracer_pid);
499
907
return num_processed;
502
static int set_function_break(Module *modp, Uint *pc,
503
Binary *match_spec, Uint break_op,
910
static int set_function_break(Module *modp, BeamInstr *pc, int bif,
911
Binary *match_spec, BeamInstr break_op,
504
912
enum erts_break_op count_op, Eterm tracer_pid) {
914
BeamInstr **code_base = NULL;
915
BpData *bd, **r, ***rs;
507
Uint **code_base = (Uint **)modp->code;
510
ASSERT(code_base <= (Uint **)pc);
511
ASSERT((Uint **)pc < code_base + (modp->code_length/sizeof(Uint *)));
919
if (bif == BREAK_IS_ERL) {
920
code_base = (BeamInstr **)modp->code;
922
ASSERT(code_base <= (BeamInstr **)pc);
923
ASSERT((BeamInstr **)pc < code_base + (modp->code_length/sizeof(BeamInstr *)));
925
ASSERT(*pc == (BeamInstr) em_apply_bif);
926
ASSERT(modp == NULL);
513
930
* Currently no trace support for native code.
531
949
ErtsSmpBPUnlock(bdt);
532
950
MatchSetUnref(old_match_spec);
952
BpDataCount *bdc = (BpDataCount *) bd;
953
erts_aint_t count = 0;
534
956
ASSERT(! match_spec);
535
957
ASSERT(is_nil(tracer_pid));
536
if (break_op == (Uint) BeamOp(op_i_count_breakpoint)) {
537
BpDataCount *bdc = (BpDataCount *) bd;
540
if (count_op == erts_break_stop) {
541
if (bdc->count >= 0) {
542
bdc->count = -bdc->count-1; /* Stop call counter */
545
bdc->count = 0; /* Reset call counter */
547
ErtsSmpBPUnlock(bdc);
959
if (break_op == (BeamInstr) BeamOp(op_i_count_breakpoint)) {
960
if (count_op == erts_break_stop) {
961
count = erts_smp_atomic_read(&bdc->acount);
964
res = erts_smp_atomic_cmpxchg(&bdc->acount, -count - 1, count);
965
if ((res == count) || count < 0) break;
970
/* Reset call counter */
971
erts_smp_atomic_set(&bdc->acount, 0);
974
} else if (break_op == (BeamInstr) BeamOp(op_i_time_breakpoint)) {
975
BpDataTime *bdt = (BpDataTime *) bd;
978
ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
980
if (count_op == erts_break_stop) {
984
for (i = 0; i < bdt->n; i++) {
985
bp_hash_delete(&(bdt->hash[i]));
986
bp_hash_init(&(bdt->hash[i]), 32);
549
991
ASSERT (! count_op);
554
if (break_op == (Uint) BeamOp(op_i_trace_breakpoint) ||
555
break_op == (Uint) BeamOp(op_i_mtrace_breakpoint)) {
996
if (break_op == (BeamInstr) BeamOp(op_i_trace_breakpoint) ||
997
break_op == (BeamInstr) BeamOp(op_i_mtrace_breakpoint)) {
556
998
size = sizeof(BpDataTrace);
558
1000
ASSERT(! match_spec);
559
1001
ASSERT(is_nil(tracer_pid));
560
if (break_op == (Uint) BeamOp(op_i_count_breakpoint)) {
561
if (count_op == erts_break_reset
562
|| count_op == erts_break_stop) {
1002
if (break_op == (BeamInstr) BeamOp(op_i_count_breakpoint)) {
1003
if (count_op == erts_break_reset || count_op == erts_break_stop) {
563
1004
/* Do not insert a new breakpoint */
566
1007
size = sizeof(BpDataCount);
1008
} else if (break_op == (BeamInstr) BeamOp(op_i_time_breakpoint)) {
1009
if (count_op == erts_break_reset || count_op == erts_break_stop) {
1010
/* Do not insert a new breakpoint */
1013
size = sizeof(BpDataTime);
568
1015
ASSERT(! count_op);
569
ASSERT(break_op == (Uint) BeamOp(op_i_debug_breakpoint));
1016
ASSERT(break_op == (BeamInstr) BeamOp(op_i_debug_breakpoint));
570
1017
size = sizeof(BpDataDebug);
573
r = (BpData **) (pc-4);
1020
rs = (BpData ***) (pc-4);
1022
size_t ssize = sizeof(BeamInstr) * erts_no_schedulers;
1023
*rs = (BpData **) Alloc(ssize);
1024
sys_memzero(*rs, ssize);
575
ASSERT(*pc != (Uint) BeamOp(op_i_trace_breakpoint));
576
ASSERT(*pc != (Uint) BeamOp(op_i_mtrace_breakpoint));
577
ASSERT(*pc != (Uint) BeamOp(op_i_debug_breakpoint));
578
ASSERT(*pc != (Uint) BeamOp(op_i_count_breakpoint));
1030
ASSERT(*pc != (BeamInstr) BeamOp(op_i_trace_breakpoint));
1031
ASSERT(*pc != (BeamInstr) BeamOp(op_i_mtrace_breakpoint));
1032
ASSERT(*pc != (BeamInstr) BeamOp(op_i_debug_breakpoint));
1033
ASSERT(*pc != (BeamInstr) BeamOp(op_i_count_breakpoint));
1034
ASSERT(*pc != (BeamInstr) BeamOp(op_i_time_breakpoint));
579
1035
/* First breakpoint; create singleton ring */
580
1036
bd = Alloc(size);
581
1037
BpInit(bd, *pc);
1039
if (bif == BREAK_IS_ERL) {
585
ASSERT(*pc == (Uint) BeamOp(op_i_trace_breakpoint) ||
586
*pc == (Uint) BeamOp(op_i_mtrace_breakpoint) ||
587
*pc == (Uint) BeamOp(op_i_debug_breakpoint) ||
588
*pc == (Uint) BeamOp(op_i_count_breakpoint));
589
if (*pc == (Uint) BeamOp(op_i_debug_breakpoint)) {
1043
ASSERT(*pc == (BeamInstr) BeamOp(op_i_trace_breakpoint) ||
1044
*pc == (BeamInstr) BeamOp(op_i_mtrace_breakpoint) ||
1045
*pc == (BeamInstr) BeamOp(op_i_debug_breakpoint) ||
1046
*pc == (BeamInstr) BeamOp(op_i_time_breakpoint) ||
1047
*pc == (BeamInstr) BeamOp(op_i_count_breakpoint) ||
1048
*pc == (BeamInstr) em_apply_bif);
1049
if (*pc == (BeamInstr) BeamOp(op_i_debug_breakpoint)) {
590
1050
/* Debug bp must be last, so if it is also first;
591
1051
* it must be singleton. */
592
ASSERT(BpSingleton(*r));
1052
ASSERT(BpSingleton(*r));
593
1053
/* Insert new bp first in the ring, i.e second to last. */
594
1054
bd = Alloc(size);
595
1055
BpInitAndSpliceNext(bd, *pc, *r);
597
} else if ((*r)->prev->orig_instr
598
== (Uint) BeamOp(op_i_debug_breakpoint)) {
1056
if (bif == BREAK_IS_ERL) {
1059
} else if ((*r)->prev->orig_instr
1060
== (BeamInstr) BeamOp(op_i_debug_breakpoint)) {
599
1061
/* Debug bp last in the ring; insert new second to last. */
600
1062
bd = Alloc(size);
601
1063
BpInitAndSplicePrev(bd, (*r)->prev->orig_instr, *r);
654
1134
static int clear_module_break(Module *m, Eterm mfa[3], int specified,
1135
BeamInstr break_op) {
1136
BeamInstr** code_base;
1137
BeamInstr* code_ptr;
658
1138
int num_processed = 0;
662
code_base = (Uint **) m->code;
1143
code_base = (BeamInstr **) m->code;
663
1144
if (code_base == NULL) {
666
n = (Uint) code_base[MI_NUM_FUNCTIONS];
1147
n = (BeamInstr) code_base[MI_NUM_FUNCTIONS];
667
1148
for (i = 0; i < n; ++i) {
668
1149
code_ptr = code_base[MI_FUNCTIONS+i];
669
1150
if ((specified < 2 || mfa[1] == ((Eterm) code_ptr[3])) &&
670
1151
(specified < 3 || ((int) mfa[2]) == ((int) code_ptr[4]))) {
671
Uint *pc = code_ptr + 5;
1152
BeamInstr *pc = code_ptr + 5;
673
1154
num_processed +=
674
clear_function_break(m, pc, break_op);
1155
clear_function_break(m, pc, BREAK_IS_ERL, break_op);
677
1158
return num_processed;
680
static int clear_function_break(Module *m, Uint *pc, Uint break_op) {
1161
static int clear_function_break(Module *m, BeamInstr *pc, int bif, BeamInstr break_op) {
682
Uint **code_base = (Uint **)m->code;
685
ASSERT(code_base <= (Uint **)pc);
686
ASSERT((Uint **)pc < code_base + (m->code_length/sizeof(Uint *)));
1164
BeamInstr **code_base = NULL;
1166
if (bif == BREAK_IS_ERL) {
1167
code_base = (BeamInstr **)m->code;
1169
ASSERT(code_base <= (BeamInstr **)pc);
1170
ASSERT((BeamInstr **)pc < code_base + (m->code_length/sizeof(BeamInstr *)));
1172
ASSERT(*pc == (BeamInstr) em_apply_bif);
688
1177
* Currently no trace support for native code.
690
1179
if (erts_is_native_break(pc)) {
693
1183
while ( (bd = is_break(pc, break_op))) {
694
1184
/* Remove all breakpoints of this type.
695
1185
* There should be only one of each type,
696
1186
* but break_op may be 0 which matches any type.
699
BpData **r = (BpData **) (pc-4);
1189
BpData ***rs = (BpData ***) (pc - 4);
1193
for (ix = 1; ix < erts_no_schedulers; ++ix) {
1194
ASSERT((*rs)[ix] == (*rs)[0]);
702
1201
/* Find opcode for this breakpoint */