Skip to content
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

Split flags in struct MVMCollectable to avoid data races when setting MVM_CF_HAS_OBJECT_ID and MVM_CF_REF_FROM_GEN2 #1336

Merged
merged 2 commits into from
Aug 13, 2020

Conversation

nwc10
Copy link
Contributor

@nwc10 nwc10 commented Aug 11, 2020

"paranoia" checks added as part of work on the new hash tables reveal that there is a nasty data race when setting flag bits in MVMCollectable

Specifically, if one thread calls MVM_gc_object_id for an object that does not yet have an ID, and another thread calls MVM_gc_write_barrier_hit_by for the same object, then each function needs to perform a read, modify, write on the object's flags. If the data race is hit, then the setting of one of the flags bits is lost. If MVM_CF_HAS_OBJECT_ID fails to be set, then we simply leak a little memory in the gen2 pools. If MVM_CF_REF_FROM_GEN2 fails to be set, then the GC doesn't function properly.

A solution to this is to split the flags from a single MVMuint16 into two MVMuint8s and partition the flags bits across the two, so that these two hot flags are not in the same byte. This way, each can be updated without causing a data race with the other. The proposed split turns out to be quite easily memorable - other than MVM_CF_HAS_OBJECT_ID, all "gen2", "nursery" and GC related flags go into flags2, all others into flags1.

Unfortunately rakudo's extension ops have an unhealthy amount of tight coupling with MoarVM, including (ab)using a free bit in the flags for FIRST handling. Hence rakudo needs to be changed before it can build with these changes. The proposed patch to rakudo makes it build with both MoarVM master and this branch

Suggested actions

  1. review this branch for sanity. test with NQP
  2. review the necessary rakudo changes at https://github.com/nwc10/rakudo/tree/flags-split
  3. push the rakudo changes to master
  4. push the MoarVM changes to master

(intersperse with testing as necessary)(as expected, the automatic tests here fail currently, because Rakudo has not been patched)

Problem found by @dogbert17, cause diagnosed by @niner

This permits us to avoid a data race when one thread needs to set
MVM_CF_HAS_OBJECT_ID and a second needs to set MVM_CF_REF_FROM_GEN2.

For now, don't change the flag bit values used in the two new members.
Change the values of the MVM_CF_* flags to sit in the range 1-128.
@nwc10 nwc10 requested review from jnthn and niner August 11, 2020 12:27
@nwc10 nwc10 marked this pull request as draft August 11, 2020 12:39
nwc10 added a commit to nwc10/rakudo that referenced this pull request Aug 11, 2020
As part of the fix for the data race described in MoarVM/MoarVM#1336
the flags member of struct MVMCollectable needs to be changed from a
single MVMuint16 to two MVMuint8 values. As `p6setfirstflag` and
`p6takefirstflag` directly manipulate this struct, they need to be
updated to reflect the changes.

Implemented with conditional compilation so that it will work with MoarVM
before and after these changes. Once MoarVM is updated, the conditional
compilation can be removed.
@nwc10 nwc10 marked this pull request as ready for review August 11, 2020 12:51
Copy link
Member

@jnthn jnthn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In hindsight, static inline functions to test/set flags would have made this change rather easier to perform and review. Perhaps an LHF for somebody with interest...in the meantime, this PR seems cromulent to me.

@jnthn jnthn merged commit 9a52033 into master Aug 13, 2020
@jnthn jnthn deleted the flags-split branch August 13, 2020 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants