Merge patch from JeremyF:
39-lock-prefix
Add a new UInstr LOCK to represent a "lock" prefix in the instruction
stream. This has the same semantics as NOP, but allows a skin to tell
whether a group of UInstrs associated with an x86 instruction are
meant to be locked.
HELGRIND: uses the LOCK UInstr to automatically take and release a
special __BUS_HARDWARE_LOCK__ around locked instructions. This only
works properly if all instructions touching a given address are locked
(even reads).
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1310 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/addrcheck/ac_main.c b/addrcheck/ac_main.c
index 7eb355d..984cc15 100644
--- a/addrcheck/ac_main.c
+++ b/addrcheck/ac_main.c
@@ -1752,7 +1752,7 @@
u_in = &cb_in->instrs[i];
switch (u_in->opcode) {
- case NOP: case CALLM_E: case CALLM_S:
+ case NOP: case LOCK: case CALLM_E: case CALLM_S:
break;
/* For memory-ref instrs, copy the data_addr into a temporary to be
diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c
index c288647..7a93fc2 100644
--- a/cachegrind/cg_main.c
+++ b/cachegrind/cg_main.c
@@ -731,7 +731,7 @@
if (instrumented_Jcond) sk_assert(u_in->opcode == JMP);
switch (u_in->opcode) {
- case NOP: case CALLM_E: case CALLM_S:
+ case NOP: case LOCK: case CALLM_E: case CALLM_S:
break;
/* For memory-ref instrs, copy the data_addr into a temporary to be
diff --git a/coregrind/vg_from_ucode.c b/coregrind/vg_from_ucode.c
index d08c505..769785d 100644
--- a/coregrind/vg_from_ucode.c
+++ b/coregrind/vg_from_ucode.c
@@ -1981,7 +1981,7 @@
old_emitted_code_used = emitted_code_used;
switch (u->opcode) {
- case NOP: case CALLM_S: case CALLM_E: break;
+ case NOP: case LOCK: case CALLM_S: case CALLM_E: break;
case INCEIP: {
/* Note: Redundant INCEIP merging. A potentially useful
diff --git a/coregrind/vg_to_ucode.c b/coregrind/vg_to_ucode.c
index 4912588..99bf7b1 100644
--- a/coregrind/vg_to_ucode.c
+++ b/coregrind/vg_to_ucode.c
@@ -3254,6 +3254,7 @@
/* Skip a LOCK prefix. */
if (getUChar(eip) == 0xF0) {
/* VG_(printf)("LOCK LOCK LOCK LOCK LOCK \n"); */
+ uInstr0(cb, LOCK, 0);
eip++;
}
diff --git a/coregrind/vg_translate.c b/coregrind/vg_translate.c
index 71fbb11..0b6175a 100644
--- a/coregrind/vg_translate.c
+++ b/coregrind/vg_translate.c
@@ -476,6 +476,7 @@
case GETSEG: return LIT0 && SZ2 && CC0 && Se1 && TR2 && N3 && XOTHER;
case USESEG: return LIT0 && SZ0 && CC0 && TR1 && TR2 && N3 && XOTHER;
case NOP: return LIT0 && SZ0 && CC0 && N1 && N2 && N3 && XOTHER;
+ case LOCK: return LIT0 && SZ0 && CC0 && N1 && N2 && N3 && XOTHER;
case GETF: return LIT0 && SZ42 && CCr && TR1 && N2 && N3 && XOTHER;
case PUTF: return LIT0 && SZ42 && CCw && TR1 && N2 && N3 && XOTHER;
case GET: return LIT0 && SZi && CC0 && AS1 && TR2 && N3 && XOTHER;
@@ -799,6 +800,7 @@
case LEA1: return "LEA1";
case LEA2: return "LEA2";
case NOP: return "NOP";
+ case LOCK: return "LOCK";
case GET: return "GET";
case PUT: return "PUT";
case GETF: return "GETF";
@@ -919,7 +921,7 @@
VG_(pp_UOperand)(u, 2, 4, False);
break;
- case NOP:
+ case NOP: case LOCK:
break;
case FPU_W:
@@ -1092,7 +1094,7 @@
case LEA2: RD(1); RD(2); WR(3); break;
case NOP: case FPU: case INCEIP: case CALLM_S: case CALLM_E:
- case CLEAR: case CALLM: break;
+ case CLEAR: case CALLM: case LOCK: break;
case CCALL:
if (u->argc > 0) RD(1);
@@ -1225,6 +1227,7 @@
case LEA1:
case LEA2:
case NOP:
+ case LOCK:
case PUT:
case LOAD:
case STORE:
diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c
index 85dcc80..b9b539b 100644
--- a/helgrind/hg_main.c
+++ b/helgrind/hg_main.c
@@ -1732,6 +1732,9 @@
static void eraser_mem_help_write_4(Addr a, UInt val) REGPARM(2);
static void eraser_mem_help_write_N(Addr a, UInt size) REGPARM(2);
+static void bus_lock(void);
+static void bus_unlock(void);
+
static
void eraser_pre_mem_read(CorePart part, ThreadState* tst,
Char* s, UInt base, UInt size )
@@ -1863,6 +1866,7 @@
Int t_size = INVALID_TEMPREG;
Int ntemps;
Bool *stackref = NULL;
+ Bool locked = False; /* lock prefix */
cb = VG_(alloc_UCodeBlock)();
cb->nextTemp = cb_in->nextTemp;
@@ -1883,6 +1887,21 @@
case NOP: case CALLM_S: case CALLM_E:
break;
+ case LOCK:
+ locked = True;
+ uInstr0(cb, CCALL, 0);
+ uCCall(cb, (Addr)bus_lock, 0, 0, False);
+ break;
+
+ case JMP: case INCEIP:
+ if (locked) {
+ uInstr0(cb, CCALL, 0);
+ uCCall(cb, (Addr)bus_unlock, 0, 0, False);
+ }
+ locked = False;
+ VG_(copy_UInstr)(cb, u_in);
+ break;
+
case GET:
sk_assert(u_in->tag1 == ArchReg);
sk_assert(u_in->tag2 == TempReg);
@@ -2935,6 +2954,21 @@
clearTLS(joinee);
}
+static Int __BUS_HARDWARE_LOCK__;
+
+static void bus_lock(void)
+{
+ ThreadId tid = VG_(get_current_tid)();
+ eraser_pre_mutex_lock(tid, &__BUS_HARDWARE_LOCK__);
+ eraser_post_mutex_lock(tid, &__BUS_HARDWARE_LOCK__);
+}
+
+static void bus_unlock(void)
+{
+ ThreadId tid = VG_(get_current_tid)();
+ eraser_post_mutex_unlock(tid, &__BUS_HARDWARE_LOCK__);
+}
+
/*--------------------------------------------------------------------*/
/*--- Client requests ---*/
/*--------------------------------------------------------------------*/
@@ -3030,6 +3064,9 @@
VG_(register_compact_helper)((Addr) & eraser_mem_help_write_4);
VG_(register_noncompact_helper)((Addr) & eraser_mem_help_write_N);
+ VG_(register_noncompact_helper)((Addr) & bus_lock);
+ VG_(register_noncompact_helper)((Addr) & bus_unlock);
+
for(i = 0; i < LOCKSET_HASH_SZ; i++)
lockset_hash[i] = NULL;
diff --git a/include/vg_skin.h b/include/vg_skin.h
index 540fe5f..10f70e7 100644
--- a/include/vg_skin.h
+++ b/include/vg_skin.h
@@ -492,6 +492,8 @@
enum {
NOP, /* Null op */
+ LOCK, /* Indicate the existance of a LOCK prefix (functionally NOP) */
+
/* Moving values around */
GET, PUT, /* simulated register <--> TempReg */
GETF, PUTF, /* simulated %eflags <--> TempReg */
diff --git a/lackey/lk_main.c b/lackey/lk_main.c
index 896dc18..4b79d9a 100644
--- a/lackey/lk_main.c
+++ b/lackey/lk_main.c
@@ -162,7 +162,7 @@
u = &cb_in->instrs[i];
switch (u->opcode) {
- case NOP: case CALLM_S: case CALLM_E:
+ case NOP: case LOCK: case CALLM_S: case CALLM_E:
break;
case INCEIP:
diff --git a/memcheck/mc_translate.c b/memcheck/mc_translate.c
index f81bde3..657b998 100644
--- a/memcheck/mc_translate.c
+++ b/memcheck/mc_translate.c
@@ -541,6 +541,7 @@
switch (u_in->opcode) {
+ case LOCK:
case NOP:
break;
@@ -1260,6 +1261,7 @@
/* Deal with these quickly. */
case NOP:
+ case LOCK:
case INCEIP:
break;