Use Builtin Atomics for wait/waitAsync/notify#956
Use Builtin Atomics for wait/waitAsync/notify#956komyg wants to merge 20 commits intotrynova:mainfrom
Conversation
4482ead to
4a0935d
Compare
aapoalas
left a comment
There was a problem hiding this comment.
Ok, I've updated the code according to your comment.
Can you take a look if the general idea is good?
Note: it seems that I broke a few tests that were passing, so I still have to fix those.
Yeah, the general idea looks really good to me, excellent stuff! <3
It seems quite likely to me that the reason for the breakage is the too-strict-by-half locking of the mutex, since you're effectively making it so that only one thread can wait or notify concurrently. (I think.) The mutex should only be guarding adding a new waiter and removing an old waiter, but not the waiting itself.
nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs
Outdated
Show resolved
Hide resolved
nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs
Outdated
Show resolved
Hide resolved
nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs
Outdated
Show resolved
Hide resolved
nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs
Outdated
Show resolved
Hide resolved
nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs
Outdated
Show resolved
Hide resolved
nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs
Outdated
Show resolved
Hide resolved
1cfe244 to
3ca1733
Compare
9f4eea6 to
0d39787
Compare
|
Hey @aapoalas, I've addressed your feedback, can you review again, please? |
aapoalas
left a comment
There was a problem hiding this comment.
Still some things I'd like changed; most importantly we want to std functions as much as possible.
nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs
Outdated
Show resolved
Hide resolved
nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs
Outdated
Show resolved
Hide resolved
nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs
Outdated
Show resolved
Hide resolved
| let handle = thread::spawn(move || { | ||
| // SAFETY: buffer is a cloned SharedDataBlock; non-dangling. | ||
| let waiters = unsafe { buffer.get_or_init_waiters() }; | ||
| let waiter_record = Arc::new(WaiterRecord { |
There was a problem hiding this comment.
suggestion: Could create a WaiterRecord::new_shared() helper function that returns Arc<WaiterRecord>.
nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs
Outdated
Show resolved
Hide resolved
nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs
Outdated
Show resolved
Hide resolved
| } else { | ||
| let deadline = Instant::now() + Duration::from_millis(t); | ||
| loop { | ||
| if waiter_record.notified.load(StdOrdering::Acquire) { |
There was a problem hiding this comment.
issue: I think we should be fine using just Relaxed for the notification. Waking up is our synchronisation, we only really care about the value of the bool here and it is atomic on its own.
nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs
Outdated
Show resolved
Hide resolved
|
Oh! I forgot: the ecmascript_futex dependency should be removed. |
|
Hmm... I've been looking at the code and doing some cleanups and whatnot and ... I think we have a somewhat fundamental issue here in that the async side has been just bollixed by me. It's pretty badly mangled from what it ought to be now that we're actually using a real parking lot instead of Futexes directly. Importantly: it seems like the critical section must be entered on the main thread, not on the async thread. eg. the Maybe we can still hack the effect by changing the If we cannot hack it, we have to actually do the spec-things exactly and create a separate timeout job and a separate handler job. Also we'd need to somehow figure out if we're resolving a promise on our own Agent or not... |
I think we can start with the hack by having the By doing that, and addressing your feedback above, I think we will have a solution that is good enough. Then we can see if it is worth it to take the time to re-write this to be more adherent to the spec. What do you think? |
Yeah, I guess that could work. I have something akin to this (without the enum) working locally on my laptop with a lot of cleanups, and I was just running test262 on it when the laptop ran out of battery and it turns out I've left my charger at work! Based on my experience there, I must admit I'm not exactly thrilled about having the critical section effectively entirely on a separate thread with the main thread having to wait for a sync message from the waiter thread to see if the waiter thread's read of the byte index produced a Looking at it from a performance point of view now that we have a proper parking lot futex instead of native OS futexes, it makes sense that we'll avoid spawning a waiter thread unless specifically needed for a timeout (and actually even this should be delegated to the host, so that the host can decide if a timeout thread is needed or if it should instead be some sort of OS timer API that we rely on). For |
0d39787 to
ba58810
Compare
Fix: #899