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

feat: implement memory.atomic.notify,wait32,wait64 #5255

Merged

Conversation

haraldh
Copy link
Contributor

@haraldh haraldh commented Nov 11, 2022

Added the parking_spot crate, which provides the needed registry for the operations.

Tests include:

  • wait32 doesn't block if the values don't match
  • wait32 eventually times out if the values match
  • wait32 traps on unshared memories
  • notify returns 0 on unshared memories
  • notify returns 0 with 0 waiters
  • notify returns the number woken (this one you can't precisely test for but you could add a sleep for ~100ms and otherwise retry the test N times until it works)
  • wait32 and notify require in-bounds and aligned addresses

@haraldh haraldh force-pushed the feature/atomic_wait_notify branch 2 times, most recently from 1e277e7 to 860d9aa Compare November 11, 2022 14:27
@bjorn3
Copy link
Contributor

bjorn3 commented Nov 11, 2022

The rustix crate wasmtime already uses has futex support. memory.atomic.{notify,wait32,wait64} are modeled after the futex model afaik, not the thread parking model that parking_lot_core exposes. In addition parking_lot_core is modelled on top of futex on Linux. As such using rustix::thread::futex will likely require less code and be more efficient.

@haraldh
Copy link
Contributor Author

haraldh commented Nov 11, 2022

@bjorn3
I had a futex solution here, but we need a solution for other OSes and AtomicU64, too.

@haraldh
Copy link
Contributor Author

haraldh commented Nov 11, 2022

@bjorn3 see also this comment

@bjorn3
Copy link
Contributor

bjorn3 commented Nov 11, 2022

Didn't think of wait64. That is indeed an issue.

Copy link
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

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

Thanks for the PR here! Would it be possible to add tests with this as well? I'd ideally like to grow the threads test suite to be as comprehensive as we can reasonably get it as features land.

Internally I think there's a few things about the wasm semantics to touch up. You mention i64 vs u64, and in these intrinsics you'll want to cast timeout: u64 to timeout: i64 since the spec says that it's treated as a signed number. Additionally I think you'll want to handle timeout == 0 differently where it looks like now that equates to now deadline but with the spec that equates to a zero deadline.

For error handling I think it's ok to avoid TrapReason::user_with_backtrace since all of the error conditions here should be infallible, so I think they'd best be replaced with a .unwrap() where necessary.

Finally, for the low level implementation, I personally do not want to use parking-lot internally here. I reviewed it historically and I don't think it's suitable for Wasmtime where any mistake is a security issue. I think it would be better to build this with condvars/mutexes/etc within the SharedMemory structure for state management. That furthermore removes the need for global state management here and additionally enables a more flexible implementation that takes into account async one day, if necessary.

@haraldh haraldh force-pushed the feature/atomic_wait_notify branch from 860d9aa to 95df1a8 Compare November 16, 2022 15:17
@haraldh
Copy link
Contributor Author

haraldh commented Nov 16, 2022

Implemented parking_spot as a parking_lot_core replacement.

@haraldh haraldh requested a review from alexcrichton November 16, 2022 15:18
@haraldh
Copy link
Contributor Author

haraldh commented Nov 16, 2022

Err... SIGKILL is hard in the CI :)
edit: maybe a timeout killer?

Copy link
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

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

Looks reasonable to me, thanks!

One thing that we'll want to add is embedder APIs to interact with these instructions as well. For eample I think we'll want SharedMemory::{notify,wait32,wait64} which are basically the same wasm instructions but callable by wasmtime embedders, allowing programmatic interactions with threads as well. That doesn't need to be added necessarily in this PR, however, but it might motivate movement of the implementation of these instructions into wasmtime_runtime::SharedMemory instead of keeping it in libcalls in the long run.

crates/parking_spot/LICENSE-APACHE Outdated Show resolved Hide resolved
crates/parking_spot/Cargo.toml Outdated Show resolved Hide resolved
Cargo.toml Outdated Show resolved Hide resolved
Cargo.lock Outdated Show resolved Hide resolved
crates/runtime/src/libcalls.rs Outdated Show resolved Hide resolved
crates/runtime/src/memory.rs Outdated Show resolved Hide resolved
crates/runtime/src/memory.rs Outdated Show resolved Hide resolved
crates/parking_spot/src/lib.rs Outdated Show resolved Hide resolved
crates/parking_spot/src/lib.rs Outdated Show resolved Hide resolved
crates/parking_spot/src/lib.rs Outdated Show resolved Hide resolved
@alexcrichton
Copy link
Member

Oh, and to reiterate, this will require tests to merge.

@haraldh
Copy link
Contributor Author

haraldh commented Nov 16, 2022

Oh, and to reiterate, this will require tests to merge.

@alexcrichton wouldn't that need threading support first, to test it in full action?

@alexcrichton
Copy link
Member

It would indeed, and everything necessary should be implemented in Wasmtime today. There are, for example, already tests with threads.

@haraldh haraldh force-pushed the feature/atomic_wait_notify branch from 74003f8 to eb5bc23 Compare November 17, 2022 08:44
@haraldh
Copy link
Contributor Author

haraldh commented Nov 17, 2022

Addressed some of the issues, working on the others. Now tested with my real pthread example.

@haraldh haraldh force-pushed the feature/atomic_wait_notify branch 2 times, most recently from 35dadcf to b06836f Compare November 17, 2022 09:00
@haraldh
Copy link
Contributor Author

haraldh commented Nov 17, 2022

So, I setup the aarch64 cross compile locally and it passes... just takes some time:

wasmtime/crates/parking_spot on  feature/atomic_wait_notify via 🦀 v1.65.0 took 42s 
[debian-toolbox:latest] ❯ cargo test --target aarch64-unknown-linux-gnu  --locked -p wasmtime-parking_spot --lib
   Compiling wasmtime-parking_spot v4.0.0 (/home/harald/git/wasmtime/crates/parking_spot)
    Finished test [optimized + debuginfo] target(s) in 0.78s
     Running unittests src/lib.rs (/home/harald/git/wasmtime/target/aarch64-unknown-linux-gnu/debug/deps/wasmtime_parking_spot-91a65de835bf666b)

running 13 tests
test tests::atomic_wait_notify ... ok
test tests::parking_lot::hundred_unpark_all_one ... ok
test tests::parking_lot::unpark_one_fifty ... ok
test tests::parking_lot::unpark_all_one ... ok
test tests::parking_lot::unpark_one_one ... ok
test tests::parking_lot::unpark_one_fifty_then_fifty_all ... ok
test tests::parking_lot::unpark_one_hundred_fast ... ok
test tests::parking_lot::unpark_one_one_fast ... ok
test tests::parking_lot::unpark_one_fifty_then_fifty_all_fast ... ok
test tests::parking_lot::unpark_all_hundred ... ok
test tests::parking_lot::unpark_all_hundred_fast ... ok
test tests::parking_lot::hundred_unpark_all_one_fast has been running for over 60 seconds
test tests::parking_lot::unpark_all_one_fast has been running for over 60 seconds
test tests::parking_lot::hundred_unpark_all_one_fast ... ok
test tests::parking_lot::unpark_all_one_fast ... ok

test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 98.13s

@haraldh haraldh force-pushed the feature/atomic_wait_notify branch from 3bd3fb6 to c5d9a29 Compare November 17, 2022 15:10
@haraldh
Copy link
Contributor Author

haraldh commented Nov 17, 2022

Oh, and to reiterate, this will require tests to merge.

@alexcrichton added one basic test... more to follow

@haraldh haraldh force-pushed the feature/atomic_wait_notify branch from c5d9a29 to 20a2e37 Compare November 17, 2022 15:45
@haraldh haraldh requested a review from alexcrichton November 17, 2022 15:46
@haraldh haraldh force-pushed the feature/atomic_wait_notify branch from 20a2e37 to 91e2e72 Compare November 17, 2022 15:54
Copy link
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

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

The test you added looks good, thanks! I think it might be also good to perhaps have a small mutex-like implementation with 2-4 threads incrementing a shared counter perhaps and ensure that the final count is as expected as well.

Otherwise others tests to add would be the basic single-threaded operational semantics of these instructions in the face of no threads. You may want to check the test suite but IIRC it's not very comprehensive (and we're almost certainly not running it at this time). Anything missing there can be added as a manual *.wast test or similar. I'm thinking things like:

  • wait32 doesn't block if the values don't match
  • wait32 eventually times out if the values match
  • wait32 traps on unshared memories
  • notify returns 0 on unshared memories
  • notify returns 0 with 0 waiters
  • notify returns the number woken (this one you can't precisely test for but you could add a sleep for ~100ms and otherwise retry the test N times until it works)
  • wait32 and notify require in-bounds and aligned addresses

Much of this can be expressed with a *.wast test I think. It all should theoretically be covered by the upstream test suite but you'd need to check to make sure it is. I can help out with this if you're having trouble.

crates/runtime/src/libcalls.rs Outdated Show resolved Hide resolved
crates/runtime/src/lib.rs Outdated Show resolved Hide resolved
crates/runtime/src/libcalls.rs Outdated Show resolved Hide resolved
crates/runtime/src/parking_spot.rs Outdated Show resolved Hide resolved
crates/runtime/src/parking_spot.rs Outdated Show resolved Hide resolved
crates/runtime/src/memory.rs Outdated Show resolved Hide resolved
@github-actions github-actions bot added the wasmtime:api Related to the API of the `wasmtime` crate itself label Nov 18, 2022
@github-actions
Copy link

Subscribe to Label Action

cc @peterhuene

This issue or pull request has been labeled: "wasmtime:api"

Thus the following users have been cc'd because of the following labels:

  • peterhuene: wasmtime:api

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

@haraldh
Copy link
Contributor Author

haraldh commented Nov 18, 2022

Looks reasonable to me, thanks!

One thing that we'll want to add is embedder APIs to interact with these instructions as well. For eample I think we'll want SharedMemory::{notify,wait32,wait64} which are basically the same wasm instructions but callable by wasmtime embedders, allowing programmatic interactions with threads as well. That doesn't need to be added necessarily in this PR, however, but it might motivate movement of the implementation of these instructions into wasmtime_runtime::SharedMemory instead of keeping it in libcalls in the long run.

added Shared::Memory::atomic_* methods.

@haraldh haraldh force-pushed the feature/atomic_wait_notify branch from 1b680f2 to 8c0b176 Compare November 18, 2022 14:42
crates/runtime/src/vmcontext.rs Outdated Show resolved Hide resolved
crates/runtime/src/memory.rs Show resolved Hide resolved
crates/runtime/src/memory.rs Outdated Show resolved Hide resolved
crates/runtime/src/vmcontext.rs Outdated Show resolved Hide resolved
crates/runtime/src/memory.rs Show resolved Hide resolved
@haraldh haraldh force-pushed the feature/atomic_wait_notify branch 3 times, most recently from ad8c894 to 24d61bb Compare November 18, 2022 16:22
@haraldh haraldh marked this pull request as draft November 18, 2022 16:28
build.rs Outdated Show resolved Hide resolved
build.rs Outdated Show resolved Hide resolved
crates/runtime/src/memory.rs Outdated Show resolved Hide resolved
@haraldh haraldh force-pushed the feature/atomic_wait_notify branch from 24d61bb to a04786d Compare November 20, 2022 06:06
@github-actions github-actions bot added the fuzzing Issues related to our fuzzing infrastructure label Nov 20, 2022
@github-actions
Copy link

Subscribe to Label Action

cc @fitzgen

This issue or pull request has been labeled: "fuzzing"

Thus the following users have been cc'd because of the following labels:

  • fitzgen: fuzzing

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

Added the parking_spot crate, which provides the needed registry for the
operations.

Signed-off-by: Harald Hoyer <[email protected]>
The threads spec test wants "unaligned atomic"
instead of "misaligned memory access".

Signed-off-by: Harald Hoyer <[email protected]>
without pooling and reference types.
Also "shared_memory" is added to the "spectest" interface.

Signed-off-by: Harald Hoyer <[email protected]>
checking that notify with 0 waiters returns 0 on shared and non-shared
memory.

Signed-off-by: Harald Hoyer <[email protected]>
@haraldh haraldh force-pushed the feature/atomic_wait_notify branch from 05efbe4 to b6a485e Compare November 21, 2022 07:58
- return 2 - timeout for 0
- return 2 - timeout for 1000ns
- return 1 - invalid value

Signed-off-by: Harald Hoyer <[email protected]>
@haraldh haraldh marked this pull request as ready for review November 21, 2022 17:01
@haraldh haraldh requested a review from alexcrichton November 21, 2022 17:01
Copy link
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

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

Ok this all looks good to me so I'm going to mark this for merging. Thanks again @haraldh for your work here!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fuzzing Issues related to our fuzzing infrastructure wasmtime:api Related to the API of the `wasmtime` crate itself
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants