Thread* thr;
/* The first 4 fields describe the previously observed
(should-be) ordering. */
- Addr shouldbe_earlier_ga;
- Addr shouldbe_later_ga;
+ Lock* shouldbe_earlier_lk;
+ Lock* shouldbe_later_lk;
ExeContext* shouldbe_earlier_ec;
ExeContext* shouldbe_later_ec;
/* In principle we need to record two more stacks, from
void HG_(record_error_LockOrder)(
Thread* thr,
- Addr shouldbe_earlier_ga,
- Addr shouldbe_later_ga,
+ Lock* shouldbe_earlier_lk,
+ Lock* shouldbe_later_lk,
ExeContext* shouldbe_earlier_ec,
ExeContext* shouldbe_later_ec,
ExeContext* actual_earlier_ec
init_XError(&xe);
xe.tag = XE_LockOrder;
xe.XE.LockOrder.thr = thr;
- xe.XE.LockOrder.shouldbe_earlier_ga = shouldbe_earlier_ga;
+ xe.XE.LockOrder.shouldbe_earlier_lk
+ = mk_LockP_from_LockN(shouldbe_earlier_lk,
+ False/*!allowed_to_be_invalid*/);
xe.XE.LockOrder.shouldbe_earlier_ec = shouldbe_earlier_ec;
- xe.XE.LockOrder.shouldbe_later_ga = shouldbe_later_ga;
+ xe.XE.LockOrder.shouldbe_later_lk
+ = mk_LockP_from_LockN(shouldbe_later_lk,
+ False/*!allowed_to_be_invalid*/);
xe.XE.LockOrder.shouldbe_later_ec = shouldbe_later_ec;
xe.XE.LockOrder.actual_earlier_ec = actual_earlier_ec;
// FIXME: tid vs thr
tl_assert(lk->magic == LockP_MAGIC);
if (VG_(clo_xml)) {
- /* fixme: add announcement */
+ if (lk->appeared_at) {
+ emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
+ (void*)lk );
+ VG_(pp_ExeContext)( lk->appeared_at );
+ }
+
} else {
if (lk->appeared_at) {
- VG_(umsg)( "Lock at %p was first observed\n",
+ VG_(umsg)( " Lock at %p was first observed\n",
(void*)lk->guestaddr );
VG_(pp_ExeContext)( lk->appeared_at );
} else {
- VG_(umsg)( "Lock at %p : no stacktrace for first observation\n",
+ VG_(umsg)( " Lock at %p : no stacktrace for first observation\n",
(void*)lk->guestaddr );
}
HG_(get_and_pp_addrdescr) (lk->guestaddr);
emit( " <text>Thread #%d: lock order \"%p before %p\" "
"violated</text>\n",
(Int)xe->XE.LockOrder.thr->errmsg_index,
- (void*)xe->XE.LockOrder.shouldbe_earlier_ga,
- (void*)xe->XE.LockOrder.shouldbe_later_ga );
+ (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr,
+ (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
emit( " <hthreadid>%d</hthreadid>\n",
(Int)xe->XE.LockOrder.thr->errmsg_index );
emit( " </xwhat>\n" );
&& xe->XE.LockOrder.shouldbe_later_ec) {
emit( " <auxwhat>Required order was established by "
"acquisition of lock at %p</auxwhat>\n",
- (void*)xe->XE.LockOrder.shouldbe_earlier_ga );
+ (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr );
VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
emit( " <auxwhat>followed by a later acquisition "
"of lock at %p</auxwhat>\n",
- (void*)xe->XE.LockOrder.shouldbe_later_ga );
+ (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
}
+ announce_LockP ( xe->XE.LockOrder.shouldbe_earlier_lk );
+ announce_LockP ( xe->XE.LockOrder.shouldbe_later_lk );
} else {
emit( "Thread #%d: lock order \"%p before %p\" violated\n",
(Int)xe->XE.LockOrder.thr->errmsg_index,
- (void*)xe->XE.LockOrder.shouldbe_earlier_ga,
- (void*)xe->XE.LockOrder.shouldbe_later_ga );
+ (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr,
+ (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
emit( "\n" );
emit( "Observed (incorrect) order is: "
"acquisition of lock at %p\n",
- (void*)xe->XE.LockOrder.shouldbe_later_ga);
+ (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr);
if (xe->XE.LockOrder.actual_earlier_ec) {
VG_(pp_ExeContext)(xe->XE.LockOrder.actual_earlier_ec);
} else {
}
emit( "\n" );
emit(" followed by a later acquisition of lock at %p\n",
- (void*)xe->XE.LockOrder.shouldbe_earlier_ga);
+ (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr);
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
if (xe->XE.LockOrder.shouldbe_earlier_ec
&& xe->XE.LockOrder.shouldbe_later_ec) {
emit("\n");
emit( "Required order was established by "
"acquisition of lock at %p\n",
- (void*)xe->XE.LockOrder.shouldbe_earlier_ga );
+ (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr );
VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
emit( "\n" );
emit( " followed by a later acquisition of lock at %p\n",
- (void*)xe->XE.LockOrder.shouldbe_later_ga );
+ (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
}
+ emit("\n");
+ announce_LockP ( xe->XE.LockOrder.shouldbe_earlier_lk );
+ announce_LockP ( xe->XE.LockOrder.shouldbe_later_lk );
}
(Int)xe->XE.UnlockForeign.owner->errmsg_index );
emit( " </xwhat>\n" );
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-
- if (xe->XE.UnlockForeign.lock->appeared_at) {
- emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
- (void*)xe->XE.UnlockForeign.lock->guestaddr );
- VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
- }
+ announce_LockP ( xe->XE.UnlockForeign.lock );
} else {
(void*)xe->XE.UnlockForeign.lock->guestaddr,
(Int)xe->XE.UnlockForeign.owner->errmsg_index );
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
- if (xe->XE.UnlockForeign.lock->appeared_at) {
- emit( " Lock at %p was first observed\n",
- (void*)xe->XE.UnlockForeign.lock->guestaddr );
- VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
- }
+ announce_LockP ( xe->XE.UnlockForeign.lock );
}
(Int)xe->XE.UnlockUnlocked.thr->errmsg_index );
emit( " </xwhat>\n" );
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
- if (xe->XE.UnlockUnlocked.lock->appeared_at) {
- emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
- (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
- VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
- }
+ announce_LockP ( xe->XE.UnlockUnlocked.lock);
} else {
(Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
(void*)xe->XE.UnlockUnlocked.lock->guestaddr );
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
- if (xe->XE.UnlockUnlocked.lock->appeared_at) {
- emit( " Lock at %p was first observed\n",
- (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
- VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
- }
+ announce_LockP ( xe->XE.UnlockUnlocked.lock);
}
const HChar* );
/* see the implementation for meaning of these params */
-void HG_(record_error_LockOrder) ( Thread*, Addr, Addr,
+void HG_(record_error_LockOrder) ( Thread*, Lock*, Lock*,
ExeContext*, ExeContext*,
ExeContext* );
tl_assert(found->src_ec);
tl_assert(found->dst_ec);
HG_(record_error_LockOrder)(
- thr, lk->guestaddr, other->guestaddr,
+ thr, lk, other,
found->src_ec, found->dst_ec, other->acquired_at );
} else {
/* Hmm. This can't happen (can it?) */
held by this thread, with its 'acquired_at'. */
HG_(record_error_LockOrder)(
- thr, lk->guestaddr, other->guestaddr,
+ thr, lk, other,
NULL, NULL, other->acquired_at );
}
}
----------------------------------------------------------------
-Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: rwlock_init (annotate_rwlock.c:54)
by 0x........: main (annotate_rwlock.c:161)
Address 0x........ is 0 bytes inside data symbol "s_rwlock"
by 0x........: mythread_wrapper (hg_intercepts.c:...)
...
+ Lock at 0x........ was first observed
+ at 0x........: pthread_mutex_lock (hg_intercepts.c:...)
+ by 0x........: main (hg02_deadlock.c:32)
+ Address 0x........ is 0 bytes inside data symbol "m1"
+
+ Lock at 0x........ was first observed
+ at 0x........: pthread_mutex_lock (hg_intercepts.c:...)
+ by 0x........: t1 (hg02_deadlock.c:10)
+ by 0x........: mythread_wrapper (hg_intercepts.c:...)
+ ...
+ Address 0x........ is 0 bytes inside data symbol "m2"
+
+
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
----------------------------------------------------------------
-Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_mutex_lock (hg_intercepts.c:...)
by 0x........: child_fn (locked_vs_unlocked1.c:18)
by 0x........: mythread_wrapper (hg_intercepts.c:...)
----------------------------------------------------------------
-Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_mutex_lock (hg_intercepts.c:...)
by 0x........: child_fn (locked_vs_unlocked1.c:18)
by 0x........: mythread_wrapper (hg_intercepts.c:...)
----------------------------------------------------------------
-Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_mutex_init (hg_intercepts.c:...)
by 0x........: main (locked_vs_unlocked2.c:58)
Address 0x........ is 0 bytes inside data symbol "mx2a"
-Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_mutex_init (hg_intercepts.c:...)
by 0x........: main (locked_vs_unlocked2.c:59)
Address 0x........ is 0 bytes inside data symbol "mx2b"
-Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_mutex_init (hg_intercepts.c:...)
by 0x........: main (locked_vs_unlocked2.c:57)
Address 0x........ is 0 bytes inside data symbol "mx1b"
----------------------------------------------------------------
-Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_mutex_init (hg_intercepts.c:...)
by 0x........: main (locked_vs_unlocked3.c:51)
Address 0x........ is 0 bytes inside data symbol "mx"
at 0x........: pthread_mutex_unlock (hg_intercepts.c:...)
by 0x........: nearly_main (tc09_bad_unlock.c:27)
by 0x........: main (tc09_bad_unlock.c:49)
- Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_mutex_init (hg_intercepts.c:...)
by 0x........: nearly_main (tc09_bad_unlock.c:23)
by 0x........: main (tc09_bad_unlock.c:49)
+ Address 0x........ is on thread #x's stack
+ in frame #x, created by nearly_main (tc09_bad_unlock.c:16)
+
---Thread-Announcement------------------------------------------
by 0x........: child_fn (tc09_bad_unlock.c:11)
by 0x........: mythread_wrapper (hg_intercepts.c:...)
...
- Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_mutex_init (hg_intercepts.c:...)
by 0x........: nearly_main (tc09_bad_unlock.c:31)
by 0x........: main (tc09_bad_unlock.c:49)
+ Address 0x........ is on thread #x's stack
+ in frame #x, created by nearly_main (tc09_bad_unlock.c:16)
+
----------------------------------------------------------------
at 0x........: pthread_mutex_unlock (hg_intercepts.c:...)
by 0x........: nearly_main (tc09_bad_unlock.c:27)
by 0x........: main (tc09_bad_unlock.c:50)
- Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_mutex_init (hg_intercepts.c:...)
by 0x........: nearly_main (tc09_bad_unlock.c:23)
by 0x........: main (tc09_bad_unlock.c:49)
+ Address 0x........ is on thread #x's stack
+ in frame #x, created by nearly_main (tc09_bad_unlock.c:16)
+
----------------------------------------------------------------
by 0x........: child_fn (tc09_bad_unlock.c:11)
by 0x........: mythread_wrapper (hg_intercepts.c:...)
...
- Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_mutex_init (hg_intercepts.c:...)
by 0x........: nearly_main (tc09_bad_unlock.c:31)
by 0x........: main (tc09_bad_unlock.c:49)
+ Address 0x........ is on thread #x's stack
+ in frame #x, created by nearly_main (tc09_bad_unlock.c:16)
+
----------------------------------------------------------------
at 0x........: pthread_mutex_unlock (hg_intercepts.c:...)
by 0x........: nearly_main (tc10_rec_lock.c:42)
by 0x........: main (tc10_rec_lock.c:47)
- Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_mutex_init (hg_intercepts.c:...)
by 0x........: nearly_main (tc10_rec_lock.c:24)
by 0x........: main (tc10_rec_lock.c:47)
+ Address 0x........ is on thread #x's stack
+ in frame #x, created by nearly_main (tc10_rec_lock.c:15)
+
----------------------------------------------------------------
at 0x........: pthread_rwlock_unlock_WRK (hg_intercepts.c:...)
by 0x........: pthread_rwlock_unlock (hg_intercepts.c:...)
by 0x........: main (tc12_rwl_trivial.c:35)
- Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_rwlock_init_WRK (hg_intercepts.c:...)
by 0x........: pthread_rwlock_init (hg_intercepts.c:...)
by 0x........: main (tc12_rwl_trivial.c:24)
+ Address 0x........ is on thread #x's stack
+ in frame #x, created by main (tc12_rwl_trivial.c:20)
+
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
at 0x........: pthread_mutex_lock (hg_intercepts.c:...)
by 0x........: main (tc13_laog1.c:18)
+ Lock at 0x........ was first observed
+ at 0x........: pthread_mutex_init (hg_intercepts.c:...)
+ by 0x........: main (tc13_laog1.c:14)
+ Address 0x........ is on thread #x's stack
+ in frame #x, created by main (tc13_laog1.c:11)
+
+ Lock at 0x........ was first observed
+ at 0x........: pthread_mutex_init (hg_intercepts.c:...)
+ by 0x........: main (tc13_laog1.c:15)
+ Address 0x........ is on thread #x's stack
+ in frame #x, created by main (tc13_laog1.c:11)
+
+
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
-
+#include <assert.h>
/* Naive dining philosophers with inconsistent lock acquisition
ordering. */
static pthread_t phil[5];
-static pthread_mutex_t chop[5];
+static struct {
+ pthread_mutex_t m;
+ char pad[120 - sizeof(pthread_mutex_t)];
+} chop[5];
void* dine ( void* arg )
{
long left = (long)arg;
long right = (left + 1) % 5;
for (i = 0; i < 1000/*arbitrary*/; i++) {
- pthread_mutex_lock(&chop[left]);
- pthread_mutex_lock(&chop[right]);
+ pthread_mutex_lock(&chop[left].m);
+ pthread_mutex_lock(&chop[right].m);
/* eating */
- pthread_mutex_unlock(&chop[left]);
- pthread_mutex_unlock(&chop[right]);
+ pthread_mutex_unlock(&chop[left].m);
+ pthread_mutex_unlock(&chop[right].m);
}
return NULL;
}
int main ( void )
{
long i;
+ assert(sizeof(pthread_mutex_t) <= 120);
+
for (i = 0; i < 5; i++)
- pthread_mutex_init( &chop[i], NULL);
+ pthread_mutex_init( &chop[i].m, NULL);
for (i = 0; i < 5; i++)
pthread_create(&phil[i], NULL, dine, (void*)i );
Thread #x was created
...
by 0x........: pthread_create@* (hg_intercepts.c:...)
- by 0x........: main (tc14_laog_dinphils.c:34)
+ by 0x........: main (tc14_laog_dinphils.c:39)
----------------------------------------------------------------
Observed (incorrect) order is: acquisition of lock at 0x........
at 0x........: pthread_mutex_lock (hg_intercepts.c:...)
- by 0x........: dine (tc14_laog_dinphils.c:18)
+ by 0x........: dine (tc14_laog_dinphils.c:21)
by 0x........: mythread_wrapper (hg_intercepts.c:...)
...
followed by a later acquisition of lock at 0x........
at 0x........: pthread_mutex_lock (hg_intercepts.c:...)
- by 0x........: dine (tc14_laog_dinphils.c:19)
+ by 0x........: dine (tc14_laog_dinphils.c:22)
by 0x........: mythread_wrapper (hg_intercepts.c:...)
...
+ Lock at 0x........ was first observed
+ at 0x........: pthread_mutex_init (hg_intercepts.c:...)
+ by 0x........: main (tc14_laog_dinphils.c:36)
+ Address 0x........ is 0 bytes inside data symbol "chop"
+
+ Lock at 0x........ was first observed
+ at 0x........: pthread_mutex_init (hg_intercepts.c:...)
+ by 0x........: main (tc14_laog_dinphils.c:36)
+ Address 0x........ is 480 bytes inside data symbol "chop"
+
+
ERROR SUMMARY: 1000 errors from 1 contexts (suppressed: 0 from 0)
{
int r;
pthread_mutex_t *mx1, *mx2;
-
- mx1 = malloc(sizeof(pthread_mutex_t));
- mx2 = malloc(sizeof(pthread_mutex_t));
+ assert (sizeof(pthread_mutex_t) <= 120);
+ mx1 = malloc(120 + sizeof(pthread_mutex_t) - sizeof(pthread_mutex_t));
+ mx2 = malloc(120 + sizeof(pthread_mutex_t) - sizeof(pthread_mutex_t));
assert(mx1);
assert(mx2);
at 0x........: pthread_mutex_lock (hg_intercepts.c:...)
by 0x........: main (tc15_laog_lockdel.c:28)
+ Lock at 0x........ was first observed
+ at 0x........: pthread_mutex_init (hg_intercepts.c:...)
+ by 0x........: main (tc15_laog_lockdel.c:22)
+ Address 0x........ is 0 bytes inside a block of size 120 alloc'd
+ at 0x........: malloc (vg_replace_malloc.c:...)
+ by 0x........: main (tc15_laog_lockdel.c:16)
+ Block was alloc'd by thread #x
+
+ Lock at 0x........ was first observed
+ at 0x........: pthread_mutex_init (hg_intercepts.c:...)
+ by 0x........: main (tc15_laog_lockdel.c:23)
+ Address 0x........ is 0 bytes inside a block of size 120 alloc'd
+ at 0x........: malloc (vg_replace_malloc.c:...)
+ by 0x........: main (tc15_laog_lockdel.c:17)
+ Block was alloc'd by thread #x
+
+
Free 2 and re-allocate it. This gives it a new identity,
so a second locking sequence 2 -> 1 should now be OK.
done
at 0x........: pthread_rwlock_unlock_WRK (hg_intercepts.c:...)
by 0x........: pthread_rwlock_unlock (hg_intercepts.c:...)
by 0x........: main (tc20_verifywrap.c:179)
- Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_rwlock_init_WRK (hg_intercepts.c:...)
by 0x........: pthread_rwlock_init (hg_intercepts.c:...)
by 0x........: main (tc20_verifywrap.c:178)
+ Location 0x........ is 0 bytes inside local var "rwl"
+ declared at tc20_verifywrap.c:47, in frame #x of thread x
+
(1) no error on next line
(2) no error on next line
at 0x........: pthread_rwlock_unlock_WRK (hg_intercepts.c:...)
by 0x........: pthread_rwlock_unlock (hg_intercepts.c:...)
by 0x........: main (tc20_verifywrap.c:196)
- Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_rwlock_init_WRK (hg_intercepts.c:...)
by 0x........: pthread_rwlock_init (hg_intercepts.c:...)
by 0x........: main (tc20_verifywrap.c:186)
+ Location 0x........ is 0 bytes inside local var "rwl2"
+ declared at tc20_verifywrap.c:48, in frame #x of thread x
+
(4) no error on next line
(5) no error on next line
at 0x........: pthread_rwlock_unlock_WRK (hg_intercepts.c:...)
by 0x........: pthread_rwlock_unlock (hg_intercepts.c:...)
by 0x........: main (tc20_verifywrap.c:212)
- Lock at 0x........ was first observed
+ Lock at 0x........ was first observed
at 0x........: pthread_rwlock_init_WRK (hg_intercepts.c:...)
by 0x........: pthread_rwlock_init (hg_intercepts.c:...)
by 0x........: main (tc20_verifywrap.c:186)
+ Location 0x........ is 0 bytes inside local var "rwl2"
+ declared at tc20_verifywrap.c:48, in frame #x of thread x
+
---------------- sem_* ----------------