-
Notifications
You must be signed in to change notification settings - Fork 4
I194 deadlock in pagemap #198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
dd416b6
13611a5
9d43fb7
418ba45
9d9c9d7
9be6916
7da68f2
74f3bcc
7e8d78a
efc4ade
9b24ea6
ae1bfc3
9469d8b
0cb2143
ece2d00
21e6d93
c7c08d7
e528bb9
abed1d9
73abdd6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,11 +32,14 @@ namespace mythos { | |
|
|
||
| void CapEntry::initRoot(Cap c) | ||
| { | ||
| MLOG_ERROR(mlog::cap, __PRETTY_FUNCTION__, DVAR(this)); | ||
| ASSERT(isKernelAddress(this)); | ||
| ASSERT(c.isUsable()); | ||
| ASSERT(cap().isEmpty()); | ||
| Link loopLink(this); | ||
| MLOG_ERROR(mlog::cap, "this unlocks _next"); | ||
| _next.store(loopLink.value()); | ||
| MLOG_ERROR(mlog::cap, "this unlocks _prev"); | ||
| _prev.store(loopLink.value()); | ||
| _cap.store(c.value()); | ||
| } | ||
|
|
@@ -62,6 +65,7 @@ namespace mythos { | |
|
|
||
| void CapEntry::reset() | ||
| { | ||
| MLOG_ERROR(mlog::cap, __PRETTY_FUNCTION__, DVAR(this)); | ||
| ASSERT(isUnlinked() || cap().isAllocated()); | ||
| _prev.store(Link().value()); | ||
| _next.store(Link().value()); | ||
|
|
@@ -80,32 +84,40 @@ namespace mythos { | |
|
|
||
| optional<void> CapEntry::moveTo(CapEntry& other) | ||
| { | ||
| MLOG_ERROR(mlog::cap, __PRETTY_FUNCTION__, DVAR(this), DVAR(other)); | ||
| ASSERT(other.cap().isAllocated()); | ||
| ASSERT(!other.isLinked()); | ||
| lock_cap(); | ||
| if (!lock_prev()) { | ||
| unlock_cap(); | ||
| other.reset(); | ||
| THROW(Error::GENERIC_ERROR); | ||
| } | ||
| lock(); | ||
| lock_next(); | ||
| auto thisCap = cap(); | ||
| if (isRevoking() || !thisCap.isUsable()) { | ||
| other.reset(); | ||
| unlock(); | ||
| unlock_next(); | ||
| unlock_prev(); | ||
| unlock_cap(); | ||
| THROW(Error::INVALID_CAPABILITY); | ||
| } | ||
|
|
||
| // using these values removes lock | ||
| auto next= Link(_next).withoutFlags(); | ||
| auto prev= Link(_prev).withoutFlags(); | ||
|
|
||
| next->setPrevPreserveFlags(&other); | ||
| other._next.store(next.value()); | ||
| // deleted or revoking can not be set in other._prev | ||
| // deletion, deleted or revoking can not be set in other._prev | ||
| // as we allocated other for moving | ||
| other._prev.store(prev.value()); | ||
| MLOG_ERROR(mlog::cap, "this unlocks prev"); | ||
| prev->_next.store(Link(&other).value()); | ||
| other.commit(thisCap); | ||
| MLOG_ERROR(mlog::cap, "this unlocks cap"); | ||
| _prev.store(Link().value()); | ||
| MLOG_ERROR(mlog::cap, "this unlocks next"); | ||
| _next.store(Link().value()); | ||
| _cap.store(Cap().value()); | ||
| RETURN(Error::SUCCESS); | ||
|
|
@@ -125,31 +137,42 @@ namespace mythos { | |
| return true; | ||
| } | ||
|
|
||
| optional<void> CapEntry::unlink() | ||
| // fails if cap was changed concurrently | ||
| bool CapEntry::try_kill(Cap expected) | ||
| { | ||
| auto next = Link(_next).withoutFlags(); | ||
| auto prev = Link(_prev).withoutFlags(); | ||
| next->_prev.store(prev.value()); | ||
| prev->_next.store(next.value()); | ||
| _prev.store(Link().value()); | ||
| CapValue expectedValue = expected.value(); | ||
| MLOG_DETAIL(mlog::cap, this, ".try_kill", DVAR(expected)); | ||
| if (!_cap.compare_exchange_strong(expectedValue, expected.asZombie().value())) { | ||
| // if the cap was just zombified by sb. else, thats okay | ||
| return (Cap(expectedValue).asZombie() == expected.asZombie()); | ||
| } else return true; | ||
| } | ||
|
|
||
|
|
||
| optional<void> CapEntry::unlinkAndUnlockLinks() | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would be good to do all required locking here or in CapEntry's code instead of the external revoke operation.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Splitting into locking and an ending operation (similar to a commit) allows us to use locked values to implement higher level operation. We can check if this is possible move locking into Also, the external revoke operation is not just any operation and is bound to now details about the
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we apply this acquire-commit design to the insertAfter operation as well? This might remove this one callback function via template argument in CapEntry.hh |
||
| { | ||
| MLOG_ERROR(mlog::cap, __PRETTY_FUNCTION__, DVAR(this)); | ||
| auto next = Link(_next); | ||
| auto prev = Link(_prev); | ||
| next->setPrevPreserveFlags(prev.ptr()); | ||
| MLOG_ERROR(mlog::cap, "this unlocks _next of predecessor"); | ||
| prev->_next.store(next.withoutFlags().value()); | ||
| _prev.store(Link().withoutPtr().value()); | ||
| MLOG_ERROR(mlog::cap, "this unlocks _next"); | ||
| _next.store(Link().value()); | ||
| RETURN(Error::SUCCESS); | ||
| } | ||
|
|
||
| Error CapEntry::try_lock_prev() | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should return the predecessor's address because we will need it anyway, see comments on CapEntry class documentation below. |
||
| { | ||
| auto prev = Link(_prev).ptr(); | ||
| MLOG_ERROR(mlog::cap, __PRETTY_FUNCTION__, DVAR(this), DVAR(prev)); | ||
| if (!prev) { | ||
| return Error::GENERIC_ERROR; | ||
| } | ||
| if (prev->try_lock()) { | ||
| if (Link(_prev.load()).ptr() == prev) { | ||
| return Error::SUCCESS; | ||
| } else { // my _prev has changed in the mean time | ||
| prev->unlock(); | ||
| return Error::RETRY; | ||
| } | ||
| } else return Error::RETRY; | ||
| auto success = prev->try_lock_next(this); | ||
| ASSERT(Link(_prev.load()).ptr() == prev); | ||
| return success ? Error::SUCCESS : Error::RETRY; | ||
| } | ||
|
|
||
| bool CapEntry::lock_prev() | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.