Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add a scheduler array for BpData at BeamInstr[-4]

To solve the issue of multiple schedulers constantly updating the
head pointer to the bp data wheel, each scheduler now has its own
entrypoint to the wheel. This head pointer can be updated without
a locking being taken. Previously there were no lock ...
  • Loading branch information...
commit ff9531eb5e6aaa5a4802db0db5e0e850f4233702 1 parent 9a5848f
Björn-Egil Dahlberg authored May 06, 2010 RaimoNiskanen committed June 03, 2010
150  erts/emulator/beam/beam_bp.c
@@ -101,6 +101,9 @@ do {                               \
101 101
     (b)->prev = (a);               \
102 102
 } while (0)
103 103
 
  104
+
  105
+
  106
+
104 107
 /* *************************************************************************
105 108
 ** Local prototypes
106 109
 */
@@ -127,7 +130,7 @@ static int clear_function_break(Module *modp, BeamInstr *pc,
127 130
 				BeamInstr break_op);
128 131
 
129 132
 static BpData *is_break(BeamInstr *pc, BeamInstr break_op);
130  
-static BpData *get_break(BeamInstr *pc, BeamInstr break_op);
  133
+static BpData *get_break(Process *p, BeamInstr *pc, BeamInstr break_op);
131 134
 
132 135
 /* bp_hash */
133 136
 #define BP_TIME_ADD(pi0, pi1)                       \
@@ -296,9 +299,12 @@ BeamInstr
296 299
 erts_trace_break(Process *p, BeamInstr *pc, Eterm *args,
297 300
 		 Uint32 *ret_flags, Eterm *tracer_pid) {
298 301
     Eterm tpid1, tpid2;
299  
-    BpDataTrace *bdt = (BpDataTrace *) pc[-4];
  302
+    BpData **bds = (BpData **) (pc)[-4];
  303
+    BpDataTrace *bdt = NULL;
300 304
 
  305
+    ASSERT(bds);
301 306
     ASSERT(pc[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
  307
+    bdt = (BpDataTrace *) bds[bp_sched2ix_proc(p)];
302 308
     ASSERT(bdt);
303 309
     bdt = (BpDataTrace *) bdt->next;
304 310
     ASSERT(bdt);
@@ -317,7 +323,7 @@ erts_trace_break(Process *p, BeamInstr *pc, Eterm *args,
317 323
 	bdt->tracer_pid = tpid2;
318 324
 	ErtsSmpBPUnlock(bdt);
319 325
     }
320  
-    pc[-4] = (BeamInstr) bdt;
  326
+    bds[bp_sched2ix_proc(p)] = (BpData *) bdt;
321 327
     return bdt->orig_instr;
322 328
 }
323 329
 
@@ -329,12 +335,15 @@ erts_trace_break(Process *p, BeamInstr *pc, Eterm *args,
329 335
 Uint32
330 336
 erts_bif_mtrace(Process *p, BeamInstr *pc, Eterm *args, int local,
331 337
 		Eterm *tracer_pid) {
332  
-    BpDataTrace *bdt = (BpDataTrace *) pc[-4];
  338
+    BpData **bds = (BpData **) (pc)[-4];
  339
+    BpDataTrace *bdt = NULL;
  340
+
333 341
 
334 342
     ASSERT(tracer_pid);
335  
-    if (bdt) {
  343
+    if (bds) {
336 344
 	Eterm tpid1, tpid2;
337 345
 	Uint32 flags;
  346
+	bdt = (BpDataTrace *)bds[bp_sched2ix_proc(p)];
338 347
 
339 348
 	ErtsSmpBPLock(bdt);
340 349
 	tpid1 = tpid2 = bdt->tracer_pid;
@@ -520,7 +529,15 @@ erts_find_local_func(Eterm mfa[3]) {
520 529
 }
521 530
 
522 531
 /* bp_hash */
523  
-
  532
+ERTS_INLINE Uint bp_sched2ix() {
  533
+#ifdef ERTS_SMP
  534
+    ErtsSchedulerData *esdp;
  535
+    esdp = erts_get_scheduler_data();
  536
+    return esdp->no - 1;
  537
+#else
  538
+    return 0;
  539
+#endif
  540
+}
524 541
 static void bp_hash_init(bp_time_hash_t *hash, Uint n) {
525 542
     Uint size = sizeof(bp_data_time_item_t)*n;
526 543
     Uint i;
@@ -528,7 +545,6 @@ static void bp_hash_init(bp_time_hash_t *hash, Uint n) {
528 545
     hash->n    = n;
529 546
     hash->used = 0;
530 547
 
531  
-
532 548
     hash->item = (bp_data_time_item_t *)Alloc(size);
533 549
     sys_memzero(hash->item, size);
534 550
 
@@ -654,7 +670,6 @@ static void bp_time_diff(bp_data_time_item_t *item, /* out */
654 670
 void erts_schedule_time_break(Process *p, Uint schedule) {
655 671
     Uint ms, s, us;
656 672
     process_breakpoint_time_t *pbt = NULL;
657  
-    Uint ix = 0;
658 673
     bp_data_time_item_t sitem, *item = NULL;
659 674
     bp_time_hash_t *h = NULL;
660 675
     BpDataTime *pbdt = NULL;
@@ -663,18 +678,7 @@ void erts_schedule_time_break(Process *p, Uint schedule) {
663 678
 
664 679
     pbt = ERTS_PROC_GET_CALL_TIME(p);
665 680
 
666  
-#ifdef ERTS_SMP
667  
-    ix = p->scheduler_data->no - 1;
668  
-#else
669  
-    ix = 0;
670  
-#endif
671  
-/*
672  
-    ASSERT( (p->status == P_RUNNING) ||
673  
-	    (p->status == P_WAITING) ||
674  
-	    (p->status == P_RUNABLE));
675  
-*/
676 681
     if (pbt) {
677  
-	get_sys_now(&ms,&s,&us);
678 682
 
679 683
 	switch(schedule) {
680 684
 	case ERTS_BP_CALL_TIME_SCHEDULE_EXITING :
@@ -685,13 +689,14 @@ void erts_schedule_time_break(Process *p, Uint schedule) {
685 689
 	     * the previous breakpoint.
686 690
 	     */
687 691
 
688  
-	    pbdt = (BpDataTime *) get_break(pbt->pc, (Uint) BeamOp(op_i_time_breakpoint));
  692
+	    pbdt = (BpDataTime *) get_break(p, pbt->pc, (BeamInstr) BeamOp(op_i_time_breakpoint));
689 693
 	    if (pbdt) {
  694
+		get_sys_now(&ms,&s,&us);
690 695
 		bp_time_diff(&sitem, pbt, ms, s, us);
691 696
 		sitem.pid   = p->id;
692 697
 		sitem.count = 0;
693 698
 
694  
-		h = &(pbdt->hash[ix]);
  699
+		h = &(pbdt->hash[bp_sched2ix_proc(p)]);
695 700
 
696 701
 		ASSERT(h);
697 702
 		ASSERT(h->item);
@@ -709,6 +714,7 @@ void erts_schedule_time_break(Process *p, Uint schedule) {
709 714
 	     * timestamp it and remove the previous
710 715
 	     * timestamp in the psd.
711 716
 	     */
  717
+	    get_sys_now(&ms,&s,&us);
712 718
 	    pbt->ms = ms;
713 719
 	    pbt->s  = s;
714 720
 	    pbt->us = us;
@@ -718,14 +724,6 @@ void erts_schedule_time_break(Process *p, Uint schedule) {
718 724
 		/* will never happen */
719 725
 	    break;
720 726
 	}
721  
-#ifdef DEBUG
722  
-    } else {
723  
-	/* if pbt is null, then the process has just been spawned
724  
-	 * and status should be runnable.
725  
-	 */
726  
-	ASSERT( (p->status == P_RUNABLE) ||
727  
-		(p->status == P_WAITING));
728  
-#endif
729 727
     } /* pbt */
730 728
 }
731 729
 
@@ -745,7 +743,6 @@ void erts_schedule_time_break(Process *p, Uint schedule) {
745 743
 void erts_trace_time_break(Process *p, BeamInstr *pc, BpDataTime *bdt, Uint type) {
746 744
     Uint ms,s,us;
747 745
     process_breakpoint_time_t *pbt = NULL;
748  
-    int ix = 0;
749 746
     bp_data_time_item_t sitem, *item = NULL;
750 747
     bp_time_hash_t *h = NULL;
751 748
     BpDataTime *pbdt = NULL;
@@ -759,12 +756,6 @@ void erts_trace_time_break(Process *p, BeamInstr *pc, BpDataTime *bdt, Uint type
759 756
     pbt = ERTS_PROC_GET_CALL_TIME(p);
760 757
     get_sys_now(&ms,&s,&us);
761 758
 
762  
-#ifdef ERTS_SMP
763  
-    ix = p->scheduler_data->no - 1;
764  
-#else
765  
-    ix = 0;
766  
-#endif
767  
-
768 759
     switch(type) {
769 760
 	    /* get pbt
770 761
 	     * timestamp = t0
@@ -783,11 +774,11 @@ void erts_trace_time_break(Process *p, BeamInstr *pc, BpDataTime *bdt, Uint type
783 774
 		sitem.count = 0;
784 775
 
785 776
 		/* previous breakpoint */
786  
-		pbdt = (BpDataTime *) get_break(pbt->pc, (Uint) BeamOp(op_i_time_breakpoint));
  777
+		pbdt = (BpDataTime *) get_break(p, pbt->pc, (BeamInstr) BeamOp(op_i_time_breakpoint));
787 778
 
788 779
 		/* if null then the breakpoint was removed */
789 780
 		if (pbdt) {
790  
-		    h = &(pbdt->hash[ix]);
  781
+		    h = &(pbdt->hash[bp_sched2ix_proc(p)]);
791 782
 
792 783
 		    ASSERT(h);
793 784
 		    ASSERT(h->item);
@@ -813,7 +804,7 @@ void erts_trace_time_break(Process *p, BeamInstr *pc, BpDataTime *bdt, Uint type
813 804
 
814 805
 	    /* this breakpoint */
815 806
 	    ASSERT(bdt);
816  
-	    h = &(bdt->hash[ix]);
  807
+	    h = &(bdt->hash[bp_sched2ix_proc(p)]);
817 808
 
818 809
 	    ASSERT(h);
819 810
 	    ASSERT(h->item);
@@ -851,11 +842,11 @@ void erts_trace_time_break(Process *p, BeamInstr *pc, BpDataTime *bdt, Uint type
851 842
 		sitem.count = 0;
852 843
 
853 844
 		/* previous breakpoint */
854  
-		pbdt = (BpDataTime *) get_break(pbt->pc, (Uint) BeamOp(op_i_time_breakpoint));
  845
+		pbdt = (BpDataTime *) get_break(p, pbt->pc, (BeamInstr) BeamOp(op_i_time_breakpoint));
855 846
 
  847
+		/* beware, the trace_pattern might have been removed */
856 848
 		if (pbdt) {
857  
-
858  
-		    h = &(pbdt->hash[ix]);
  849
+		    h = &(pbdt->hash[bp_sched2ix_proc(p)]);
859 850
 
860 851
 		    ASSERT(h);
861 852
 		    ASSERT(h->item);
@@ -874,6 +865,10 @@ void erts_trace_time_break(Process *p, BeamInstr *pc, BpDataTime *bdt, Uint type
874 865
 		pbt->us = us;
875 866
 	    }
876 867
 	    break;
  868
+	default :
  869
+	    ASSERT(0);
  870
+		/* will never happen */
  871
+	    break;
877 872
     }
878 873
 }
879 874
 
@@ -946,8 +941,9 @@ static int set_module_break(Module *modp, Eterm mfa[3], int specified,
946 941
 static int set_function_break(Module *modp, BeamInstr *pc,
947 942
 			      Binary *match_spec, BeamInstr break_op,
948 943
 			      enum erts_break_op count_op, Eterm tracer_pid) {
949  
-    BpData *bd, **r;
  944
+    BpData *bd, **r, ***rs;
950 945
     size_t size;
  946
+    Uint ix = 0;
951 947
     BeamInstr **code_base = (BeamInstr **)modp->code;
952 948
     
953 949
     ASSERT(code_base);
@@ -1037,7 +1033,15 @@ static int set_function_break(Module *modp, BeamInstr *pc,
1037 1033
 	    size = sizeof(BpDataDebug);
1038 1034
 	}
1039 1035
     }
1040  
-    r = (BpData **) (pc-4);
  1036
+    rs = (BpData ***) (pc-4);
  1037
+    if (! *rs) {
  1038
+	size_t ssize = sizeof(BeamInstr) * erts_no_schedulers;
  1039
+	*rs = (BpData **) Alloc(ssize);
  1040
+	sys_memzero(*rs, ssize);
  1041
+    }
  1042
+
  1043
+    r = &((*rs)[0]);
  1044
+
1041 1045
     if (! *r) {
1042 1046
 	ASSERT(*pc != (BeamInstr) BeamOp(op_i_trace_breakpoint));
1043 1047
 	ASSERT(*pc != (BeamInstr) BeamOp(op_i_mtrace_breakpoint));
@@ -1058,12 +1062,12 @@ static int set_function_break(Module *modp, BeamInstr *pc,
1058 1062
 	if (*pc == (BeamInstr) BeamOp(op_i_debug_breakpoint)) {
1059 1063
 	    /* Debug bp must be last, so if it is also first; 
1060 1064
 	     * it must be singleton. */
1061  
-	    ASSERT(BpSingleton(*r)); 
  1065
+	    ASSERT(BpSingleton(*r));
1062 1066
 	    /* Insert new bp first in the ring, i.e second to last. */
1063 1067
 	    bd = Alloc(size);
1064 1068
 	    BpInitAndSpliceNext(bd, *pc, *r);
1065 1069
 	    *pc = break_op;
1066  
-	} else if ((*r)->prev->orig_instr 
  1070
+	} else if ((*r)->prev->orig_instr
1067 1071
 		   == (BeamInstr) BeamOp(op_i_debug_breakpoint)) {
1068 1072
 	    /* Debug bp last in the ring; insert new second to last. */
1069 1073
 	    bd = Alloc(size);
@@ -1077,6 +1081,10 @@ static int set_function_break(Module *modp, BeamInstr *pc,
1077 1081
 	    *r = bd;
1078 1082
 	}
1079 1083
     }
  1084
+    for (ix = 1; ix < erts_no_schedulers; ++ix) {
  1085
+	(*rs)[ix] = (*rs)[0];
  1086
+    }
  1087
+
1080 1088
     bd->this_instr = break_op;
1081 1089
     /* Init the bp type specific data */
1082 1090
     if (break_op == (BeamInstr) BeamOp(op_i_trace_breakpoint) ||
@@ -1161,6 +1169,7 @@ static int clear_module_break(Module *m, Eterm mfa[3], int specified,
1161 1169
 
1162 1170
 static int clear_function_break(Module *m, BeamInstr *pc, BeamInstr break_op) {
1163 1171
     BpData *bd;
  1172
+    Uint ix = 0;
1164 1173
     BeamInstr **code_base = (BeamInstr **)m->code;
1165 1174
     
1166 1175
     ASSERT(code_base);
@@ -1178,8 +1187,17 @@ static int clear_function_break(Module *m, BeamInstr *pc, BeamInstr break_op) {
1178 1187
 	 * but break_op may be 0 which matches any type. 
1179 1188
 	 */
1180 1189
 	BeamInstr op;
1181  
-	BpData **r = (BpData **) (pc-4);
  1190
+	BpData ***rs = (BpData ***) (pc - 4);
  1191
+	BpData   **r = NULL;
  1192
+
  1193
+#ifdef DEBUG
  1194
+	for (ix = 1; ix < erts_no_schedulers; ++ix) {
  1195
+	    ASSERT((*rs)[ix] == (*rs)[0]);
  1196
+	}
  1197
+#endif
1182 1198
 	
  1199
+	r = &((*rs)[0]);
  1200
+
1183 1201
 	ASSERT(*r);
1184 1202
 	/* Find opcode for this breakpoint */
1185 1203
 	if (break_op) {
@@ -1195,8 +1213,9 @@ static int clear_function_break(Module *m, BeamInstr *pc, BeamInstr break_op) {
1195 1213
 	if (BpSingleton(bd)) {
1196 1214
 	    ASSERT(*r == bd);
1197 1215
 	    /* Only one breakpoint to remove */
1198  
-	    *r  = NULL;
1199 1216
 	    *pc = bd->orig_instr;
  1217
+	    Free(*rs);
  1218
+	    *rs = NULL;
1200 1219
 	} else {
1201 1220
 	    BpData *bd_prev = bd->prev;
1202 1221
 	    
@@ -1256,7 +1275,12 @@ static int clear_function_break(Module *m, BeamInstr *pc, BeamInstr break_op) {
1256 1275
 	Free(bd);
1257 1276
 	ASSERT(((BeamInstr) code_base[MI_NUM_BREAKPOINTS]) > 0);
1258 1277
 	--(*(BeamInstr*)&code_base[MI_NUM_BREAKPOINTS]);
1259  
-    }
  1278
+	if (*rs) {
  1279
+	    for (ix = 1; ix < erts_no_schedulers; ++ix) {
  1280
+		(*rs)[ix] = (*rs)[0];
  1281
+	    }
  1282
+	}
  1283
+    } /* while bd != NULL */
1260 1284
     return 1;
1261 1285
 }
1262 1286
 
@@ -1272,7 +1296,16 @@ static int clear_function_break(Module *m, BeamInstr *pc, BeamInstr break_op) {
1272 1296
 static BpData *is_break(BeamInstr *pc, BeamInstr break_op) {
1273 1297
     ASSERT(pc[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
1274 1298
     if (! erts_is_native_break(pc)) {
1275  
-	BpData *bd = (BpData *) pc[-4];
  1299
+	BpData **rs = (BpData **) pc[-4];
  1300
+	BpData  *bd = NULL, *ebd = NULL;
  1301
+
  1302
+	if (! rs) {
  1303
+	    return NULL;
  1304
+	}
  1305
+
  1306
+	bd = ebd = rs[bp_sched2ix()];
  1307
+
  1308
+	ASSERT(bd);
1276 1309
 	
1277 1310
 	if (break_op == 0) {
1278 1311
 	    return bd;
@@ -1285,7 +1318,7 @@ static BpData *is_break(BeamInstr *pc, BeamInstr break_op) {
1285 1318
 	    return NULL;
1286 1319
 	}
1287 1320
 	bd = bd->next;
1288  
-	while (bd != (BpData *) pc[-4]) {
  1321
+	while (bd != ebd) {
1289 1322
 	    ASSERT(bd);
1290 1323
 	    if (bd->orig_instr == break_op) {
1291 1324
 		bd = bd->next;
@@ -1298,17 +1331,24 @@ static BpData *is_break(BeamInstr *pc, BeamInstr break_op) {
1298 1331
     }
1299 1332
     return NULL;
1300 1333
 }
1301  
-static BpData *get_break(BeamInstr *pc, BeamInstr break_op) {
  1334
+static BpData *get_break(Process *p, BeamInstr *pc, BeamInstr break_op) {
1302 1335
     ASSERT(pc[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
1303 1336
     if (! erts_is_native_break(pc)) {
1304  
-	BpData *bd = (BpData *) pc[-4];
  1337
+	BpData **rs = (BpData **) pc[-4];
  1338
+	BpData  *bd = NULL, *ebd = NULL;
1305 1339
 
1306  
-	if (! bd){
  1340
+	if (! rs) {
1307 1341
 	    return NULL;
1308 1342
 	}
1309 1343
 
  1344
+	bd = ebd = rs[bp_sched2ix_proc(p)];
  1345
+	ASSERT(bd);
  1346
+	if (bd->this_instr == break_op) {
  1347
+	    return bd;
  1348
+	}
  1349
+
1310 1350
 	bd = bd->next;
1311  
-	while (bd != (BpData *) pc[-4]) {
  1351
+	while (bd != ebd) {
1312 1352
 	    ASSERT(bd);
1313 1353
 	    if (bd->this_instr == break_op) {
1314 1354
 		ASSERT(bd);
108  erts/emulator/beam/beam_bp.h
@@ -27,24 +27,41 @@
27 27
 
28 28
 
29 29
 
30  
-/*
31  
-** Common struct to all bp_data_*
32  
-**
33  
-** Two gotchas: 
34  
-**
35  
-** 1) The type of bp_data structure in the ring is deduced from the 
36  
-**    orig_instr field of the structure _before_ in the ring, except for 
37  
-**    the first structure in the ring that has its instruction in
38  
-**    pc[0] of the code to execute.
39  
-**
40  
-** 2) pc[-4] points to the _last_ structure in the ring before the
41  
-**    breakpoints are being executed.
42  
-**
43  
-** So, as an example, when a breakpointed function starts to execute,
44  
-** the first instruction that is a breakpoint instruction at pc[0] finds
45  
-** its data at ((BpData *) pc[-4])->next and has to cast that pointer 
46  
-** to the correct bp_data type.
  30
+/* A couple of gotchas:
  31
+ *
  32
+ * The breakpoint structure from BeamInstr,
  33
+ * In beam_emu where the instruction counter pointer, I (or pc),
  34
+ * points to the *current* instruction. At that time, if the instruction
  35
+ * is a breakpoint instruction the pc looks like the following,
  36
+ *
  37
+ * I[-5]   | op_i_func_info_IaaI |        scheduler specific entries
  38
+ * I[-4]   |    BpData** bpa     |  --> | BpData * bdas1 | ... | BpData * bdasN |
  39
+ * I[-3]   |  Tagged Module      |            |                    |
  40
+ * I[-2]   |  Tagged Function    |            V                    V
  41
+ * I[-1]   |  Arity              |          BpData -> BpData -> BpData -> BpData
  42
+ * I[0]    | The bp instruction  |            ^       * the bp wheel *      |
  43
+ *                                            |------------------------------
  44
+ *
  45
+ * Common struct to all bp_data_*
  46
+ *
  47
+ * 1) The type of bp_data structure in the ring is deduced from the
  48
+ *    orig_instr field of the structure _before_ in the ring, except for
  49
+ *    the first structure in the ring that has its instruction in
  50
+ *    pc[0] of the code to execute.
  51
+ *    This is valid as long as you don't search for the function while it is
  52
+ *    being executed by something else. Or is in the middle of its rotation for
  53
+ *    any other reason.
  54
+ *    A key, the bp beam instruction, is included for this reason.
  55
+ *
  56
+ * 2) pc[-4][sched_id - 1] points to the _last_ structure in the ring before the
  57
+ *    breakpoints are being executed.
  58
+ *
  59
+ * So, as an example, when a breakpointed function starts to execute,
  60
+ * the first instruction that is a breakpoint instruction at pc[0] finds
  61
+ * its data at ((BpData **) pc[-4][sched_id - 1])->next and has to cast that pointer
  62
+ * to the correct bp_data type.
47 63
 */
  64
+
48 65
 typedef struct bp_data {
49 66
     struct bp_data *next; /* Doubly linked ring pointers */
50 67
     struct bp_data *prev; /* -"-                         */
@@ -127,31 +144,46 @@ extern erts_smp_spinlock_t erts_bp_lock;
127 144
 #define ErtsSmpBPUnlock(BDC)
128 145
 #endif
129 146
 
130  
-#define ErtsCountBreak(pc,instr_result)                     \
131  
-do {                                                        \
132  
-    BpDataCount *bdc = (BpDataCount *) (pc)[-4];            \
133  
-                                                            \
  147
+ERTS_INLINE Uint bp_sched2ix(void);
  148
+
  149
+#ifdef ERTS_SMP
  150
+#define bp_sched2ix_proc(p) ((p)->scheduler_data->no - 1)
  151
+#else
  152
+#define bp_sched2ix_proc(p) (0)
  153
+#endif
  154
+
  155
+#define ErtsCountBreak(pc,instr_result)                          \
  156
+do {                                                             \
  157
+    BpData **bds = (BpData **) (pc)[-4];                         \
  158
+    BpDataCount *bdc = NULL;                                     \
  159
+    Uint ix = bp_sched2ix();                                     \
  160
+                                                                 \
134 161
     ASSERT((pc)[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI)); \
135  
-    ASSERT(bdc);                                            \
136  
-    bdc = (BpDataCount *) bdc->next;                        \
137  
-    ASSERT(bdc);                                            \
138  
-    (pc)[-4] = (BeamInstr) bdc;                                  \
139  
-    ErtsSmpBPLock(bdc);                                     \
140  
-    if (bdc->count >= 0) bdc->count++;                      \
141  
-    ErtsSmpBPUnlock(bdc);                                   \
142  
-    *(instr_result) = bdc->orig_instr;                      \
  162
+    ASSERT(bds);                                                 \
  163
+    bdc = (BpDataCount *) bds[ix];                               \
  164
+    bdc = (BpDataCount *) bdc->next;                             \
  165
+    ASSERT(bdc);                                                 \
  166
+    bds[ix] = (BpData *) bdc;                                    \
  167
+    ErtsSmpBPLock(bdc);                                          \
  168
+    if (bdc->count >= 0) bdc->count++;                           \
  169
+    ErtsSmpBPUnlock(bdc);                                        \
  170
+    *(instr_result) = bdc->orig_instr;                           \
143 171
 } while (0)
144 172
 
145  
-#define ErtsBreakSkip(pc,instr_result)                      \
146  
-do {                                                        \
147  
-    BpData *bd = (BpData *) (pc)[-4];                       \
148  
-                                                            \
  173
+#define ErtsBreakSkip(pc,instr_result)                           \
  174
+do {                                                             \
  175
+    BpData **bds = (BpData **) (pc)[-4];                         \
  176
+    BpData *bd = NULL;                                           \
  177
+    Uint ix = bp_sched2ix();                                     \
  178
+                                                                 \
149 179
     ASSERT((pc)[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI)); \
150  
-    ASSERT(bd);                                             \
151  
-    bd = bd->next;                                          \
152  
-    ASSERT(bd);                                             \
153  
-    (pc)[-4] = (BeamInstr) bd;                                   \
154  
-    *(instr_result) = bd->orig_instr;                       \
  180
+    ASSERT(bds);                                                 \
  181
+    bd = bds[ix];                                                \
  182
+    ASSERT(bd);                                                  \
  183
+    bd = bd->next;                                               \
  184
+    ASSERT(bd);                                                  \
  185
+    bds[ix] = bd;                                                \
  186
+    *(instr_result) = bd->orig_instr;                            \
155 187
 } while (0)
156 188
 
157 189
 enum erts_break_op{
37  erts/emulator/beam/beam_emu.c
@@ -4415,23 +4415,28 @@ void process_main(void)
4415 4415
 
4416 4416
  OpCase(i_time_breakpoint): {
4417 4417
      BeamInstr real_I;
4418  
-     BpDataTime *bdt = (BpDataTime *) (I)[-4];
4419  
-     Uint tail_call = 0;
  4418
+     BpData **bds = (BpData **) (I)[-4];
  4419
+     BpDataTime *bdt = NULL;
  4420
+     Uint ix = 0;
  4421
+#ifdef ERTS_SMP
  4422
+     ix = c_p->scheduler_data->no - 1;
  4423
+#else
  4424
+     ix = 0;
  4425
+#endif
  4426
+     bdt = (BpDataTime *)bds[ix];
4420 4427
 
4421 4428
      ASSERT((I)[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
4422 4429
      ASSERT(bdt);
4423 4430
      bdt = (BpDataTime *) bdt->next;
4424 4431
      ASSERT(bdt);
4425  
-     (I)[-4] = (BeamInstr) bdt;
  4432
+     bds[ix] = (BpData *) bdt;
4426 4433
      real_I = bdt->orig_instr;
4427 4434
      ASSERT(VALID_INSTR(real_I));
4428 4435
 
4429 4436
      if (IS_TRACED_FL(c_p, F_TRACE_CALLS) && !(bdt->pause)) {
4430  
-	 if (*cp_val((Eterm)c_p->cp) == (BeamInstr) OpCode(i_return_time_trace)) {
4431  
-	     tail_call = 1;
4432  
-	 }
4433  
-
4434  
-	 if (tail_call) {
  4437
+	 if (	(*(c_p->cp) == (BeamInstr) OpCode(i_return_time_trace)) ||
  4438
+		(*(c_p->cp) == (BeamInstr) OpCode(return_trace)) ||
  4439
+		(*(c_p->cp) == (BeamInstr) OpCode(i_return_to_trace))) {
4435 4440
 	     /* This _IS_ a tail recursive call */
4436 4441
 	     SWAPOUT;
4437 4442
 	     erts_trace_time_break(c_p, I, bdt, ERTS_BP_CALL_TIME_TAIL_CALL);
@@ -4458,7 +4463,7 @@ void process_main(void)
4458 4463
 	     E -= 2;
4459 4464
 	     E[0] = make_cp(I);
4460 4465
 	     E[1] = make_cp(c_p->cp);     /* original return address */
4461  
-	     c_p->cp = (Eterm *) make_cp(beam_return_time_trace);
  4466
+	     c_p->cp = (BeamInstr *) make_cp(beam_return_time_trace);
4462 4467
 	 }
4463 4468
      }
4464 4469
 
@@ -4488,18 +4493,20 @@ void process_main(void)
4488 4493
      BeamInstr real_I;
4489 4494
      Uint32 flags;
4490 4495
      Eterm tracer_pid;
4491  
-     Uint *cpp;
  4496
+     BeamInstr *cpp;
4492 4497
      int return_to_trace = 0, need = 0;
4493 4498
      flags = 0;
4494 4499
      SWAPOUT;
4495 4500
      reg[0] = r(0);
4496 4501
 
4497 4502
      if (*(c_p->cp) == (BeamInstr) OpCode(return_trace)) {
4498  
-	 cpp = (Uint*)&E[2];
4499  
-     } else if (*(c_p->cp)
4500  
-		== (BeamInstr) OpCode(i_return_to_trace)) {
  4503
+	 cpp = (BeamInstr*)&E[2];
  4504
+     } else if (*(c_p->cp) == (BeamInstr) OpCode(i_return_to_trace)) {
  4505
+	 return_to_trace = !0;
  4506
+	 cpp = (BeamInstr*)&E[0];
  4507
+     } else if (*(c_p->cp) == (BeamInstr) OpCode(i_return_time_trace)) {
4501 4508
 	 return_to_trace = !0;
4502  
-	 cpp = (Uint*)&E[0];
  4509
+	 cpp = (BeamInstr*)&E[0];
4503 4510
      } else {
4504 4511
 	 cpp = NULL;
4505 4512
      }
@@ -4516,6 +4523,8 @@ void process_main(void)
4516 4523
 	     } else if (*cp_val(*cpp) == (BeamInstr) OpCode(i_return_to_trace)) {
4517 4524
 		 return_to_trace = !0;
4518 4525
 		 cpp += 1;
  4526
+	     } else if (*cp_val(*cpp) == (BeamInstr) OpCode(i_return_time_trace)) {
  4527
+		 cpp += 2;
4519 4528
 	     } else
4520 4529
 		 break;
4521 4530
 	 }
3  erts/emulator/beam/erl_nif.c
@@ -1546,7 +1546,8 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
1546 1546
 		code_ptr[5+0] = (BeamInstr) BeamOp(op_call_nif);
1547 1547
 	    }
1548 1548
 	    else { /* Function traced, patch the original instruction word */
1549  
-		BpData* bp = (BpData*) code_ptr[1];
  1549
+		BpData** bps = (BpData**) code_ptr[1];
  1550
+		BpData*  bp  = (BpData*) bps[bp_sched2ix()];
1550 1551
 	        bp->orig_instr = (BeamInstr) BeamOp(op_call_nif);
1551 1552
 	    }	    
1552 1553
 	    code_ptr[5+1] = (BeamInstr) entry->funcs[i].fptr;

0 notes on commit ff9531e

Please sign in to comment.
Something went wrong with that request. Please try again.