[vmkit-commits] FatLock assertion failure?
Nicolas Geoffray
nicolas.geoffray at gmail.com
Fri Dec 2 09:58:35 PST 2011
Hi Will,
On Thu, Dec 1, 2011 at 11:50 PM, Will Dietz <wdietz2 at illinois.edu> wrote:
> On Thu, Dec 1, 2011 at 3:19 PM, Nicolas Geoffray
> <nicolas.geoffray at gmail.com> wrote:
> > Thanks Will for debugging the problem! Indeed, I commented the releasing
> of
> > the fat lock and it worked without any crashes. That's great news
> because it
> > looks like we nailed it. The bad news though is that if we don't release
> a
> > fat lock, it will never be able to get used again. Even worst is if we
> need
> > to keep a pointer to the associated object. The lock will just keep that
> > object alive forever.
> > If it helps, I'm ok with submitting a change that basically comments out
> the
> > release of a FatLock. When I'll have time, I'll investigate more at which
> > point do we have a race.
> > Cheers,
> > Nicolas
> >
>
> Welcome, I was very glad at how well that fixes it myself :).
>
> There are two issues you mention--one is worrying about consuming Lock
> resources, and I think that's not really a concern. Looking at this:
>
>
> http://www.research.ibm.com/people/d/dfb/thinlocks-publications.html#Bacon03Retrospective
>
> They claim it never happens in practice, and only theoretically
> happens in pathological cases. They also describe the difficulty of
> deflation a tad (but not as well as others) including brief mentions
> of solutions that might be of interest to VMKit. Anyway I don't think
> we should worry about running out of space for locks.
>
I need to read the paper, but inflating a lock in a multi-threaded
environment does not look pathological to me.
>
> The other issue you mention is miscalculating the liveness of an
> object through its lock. I agree this is something we should fix but
> I'm okay postponing it for now.
>
Yes, that's a bigger issue. I'd be fine not reallocating the lock, if I was
assured the associated object could be GC'ed.
>
> FWIW inlined below is a sample patch that's been working for me. If
> you prefer we can comment out the code instead of removing it, I'm
> fine either way. Removing the spinlocks/thread counts is a nice
> bonus.
>
I'd rather comment it out. It's been a long time I haven't touched that
code, and these fields were needed for a proper (modulo the bugs we're
currently seeing :)) implementation.
Nicolas
>
> ~Will
>
> From f4bf1be53feaa8b419fea8654c34fb04f735f61d Mon Sep 17 00:00:00 2001
> From: Will Dietz <w at wdtz.org>
> Date: Tue, 29 Nov 2011 14:24:44 -0600
> Subject: [PATCH] Remove code that deflates fat locks, due to races it
> doesn't
> work on SMP.
>
> Fixes bug where multithreaded code would occasionally assert out with:
> j3: /home/will/vmkit-svn/lib/vmkit/CommonThread/ObjectLocks.cpp:305:
> bool vmkit::FatLock::acquire(gc *): Assertion `obj->header &
> ThinLock::FatMask' failed.
> ---
> include/vmkit/ObjectLocks.h | 9 +------
> lib/vmkit/CommonThread/ObjectLocks.cpp | 43
> +------------------------------
> 2 files changed, 3 insertions(+), 49 deletions(-)
>
> diff --git a/include/vmkit/ObjectLocks.h b/include/vmkit/ObjectLocks.h
> index 1b0b4d3..7409e80 100644
> --- a/include/vmkit/ObjectLocks.h
> +++ b/include/vmkit/ObjectLocks.h
> @@ -68,9 +68,6 @@ public:
> class FatLock : public vmkit::PermanentObject {
> private:
> vmkit::LockRecursive internalLock;
> - vmkit::SpinLock spinLock;
> - uint32_t waitingThreads;
> - uint32_t lockingThreads;
> LockingThread* firstThread;
> gc* associatedObject;
> uint32_t index;
> @@ -171,14 +168,10 @@ public:
> static const uint64_t ThinCountShift = NonLockBits;
> static const uint64_t ThinCountAdd = 1LL << NonLockBits;
>
> - /// initialise - Initialise the value of the lock.
> - ///
> - static void removeFatLock(FatLock* fatLock, LockSystem& table);
> -
> /// overflowThinlock - Change the lock of this object to a fat lock
> because
> /// we have reached the maximum number of locks.
> static void overflowThinLock(gc* object, LockSystem& table);
> -
> +
> /// changeToFatlock - Change the lock of this object to a fat lock. The
> lock
> /// may be in a thin lock or fat lock state.
> static FatLock* changeToFatlock(gc* object, LockSystem& table);
> diff --git a/lib/vmkit/CommonThread/ObjectLocks.cpp
> b/lib/vmkit/CommonThread/ObjectLocks.cpp
> index 9456045..cd99492 100644
> --- a/lib/vmkit/CommonThread/ObjectLocks.cpp
> +++ b/lib/vmkit/CommonThread/ObjectLocks.cpp
> @@ -39,27 +39,7 @@ void ThinLock::overflowThinLock(gc* object,
> LockSystem& table) {
> } while (((object->header) & ~NonLockBitsMask) != ID);
> assert(obj->associatedObject == object);
> }
> -
> -/// initialise - Initialise the value of the lock.
> -///
> -void ThinLock::removeFatLock(FatLock* fatLock, LockSystem& table) {
> - gc* object = fatLock->associatedObject;
> - llvm_gcroot(object, 0);
> - word_t ID;
> - word_t oldValue = 0;
> - word_t newValue = 0;
> - word_t yieldedValue = 0;
>
> - ID = fatLock->getID();
> - do {
> - oldValue = object->header;
> - newValue = oldValue & NonLockBitsMask;
> - yieldedValue = __sync_val_compare_and_swap(&object->header,
> oldValue, newValue);
> - } while (oldValue != yieldedValue);
> - assert((oldValue & NonLockBitsMask) != ID);
> - fatLock->associatedObject = NULL;
> -}
> -
> FatLock* ThinLock::changeToFatlock(gc* object, LockSystem& table) {
> llvm_gcroot(object, 0);
> if (!(object->header & FatMask)) {
> @@ -262,8 +242,6 @@ FatLock::FatLock(uint32_t i, gc* a) {
> firstThread = NULL;
> index = i;
> setAssociatedObject(a);
> - waitingThreads = 0;
> - lockingThreads = 0;
> nextFreeLock = NULL;
> }
>
> @@ -275,11 +253,6 @@ void FatLock::release(gc* obj, LockSystem& table) {
> llvm_gcroot(obj, 0);
> assert(associatedObject && "No associated object when releasing");
> assert(associatedObject == obj && "Mismatch object in lock");
> - if (!waitingThreads && !lockingThreads &&
> - internalLock.recursionCount() == 1) {
> - vmkit::ThinLock::removeFatLock(this, table);
> - table.deallocate(this);
> - }
> internalLock.unlock();
> }
>
> @@ -287,16 +260,8 @@ void FatLock::release(gc* obj, LockSystem& table) {
> ///
> bool FatLock::acquire(gc* obj) {
> llvm_gcroot(obj, 0);
> -
> - spinLock.lock();
> - lockingThreads++;
> - spinLock.unlock();
> -
> +
> internalLock.lock();
> -
> - spinLock.lock();
> - lockingThreads--;
> - spinLock.unlock();
>
> if (associatedObject != obj) {
> internalLock.unlock();
> @@ -421,8 +386,6 @@ bool LockingThread::wait(
>
> bool timeout = false;
>
> - l->waitingThreads++;
> -
> while (!this->interruptFlag && this->nextWaiting) {
> if (timed) {
> timeout = varcondThread.timedWait(&l->internalLock, info);
> @@ -432,9 +395,7 @@ bool LockingThread::wait(
> }
> }
> assert(vmkit::ThinLock::owner(self, table) && "Not owner after wait");
> -
> - l->waitingThreads--;
> -
> +
> assert((!l->firstThread || (l->firstThread->prevWaiting &&
> l->firstThread->nextWaiting)) && "Inconsistent list");
>
> --
> 1.7.5.1
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/vmkit-commits/attachments/20111202/15442cf5/attachment.html>
More information about the vmkit-commits
mailing list