Skip to content

Implement precise pthread wakeups#26659

Open
sbc100 wants to merge 2 commits intoemscripten-core:mainfrom
sbc100:precise_wakeups
Open

Implement precise pthread wakeups#26659
sbc100 wants to merge 2 commits intoemscripten-core:mainfrom
sbc100:precise_wakeups

Conversation

@sbc100
Copy link
Copy Markdown
Collaborator

@sbc100 sbc100 commented Apr 9, 2026

This change implements the design in docs/design/01-precise-futex-wakeups.md

As part of this change emscripten_futex_wait API now explicitly allows spurious wakeups, much like the corresponding linux syscall. There were a couple of tests that were using emscripten_futex_wait without a loop, so I added loops to them in an abundance of caution.

Fixes: #26633

@sbc100 sbc100 force-pushed the precise_wakeups branch 3 times, most recently from 61f016e to 20d6937 Compare April 9, 2026 16:56
@sbc100 sbc100 requested a review from tlively April 9, 2026 16:56
@tlively
Copy link
Copy Markdown
Member

tlively commented Apr 9, 2026

"implemenat" => "implements" in description.

@sbc100 sbc100 force-pushed the precise_wakeups branch from 20d6937 to 96b8d1e Compare April 9, 2026 20:15
This change implements the design in docs/design/01-precise-futex-wakeups.md

Note: As part of this change the definition of emscripten_futex_wait
was changes to explicitly allow spurious wakeups.

Fixes: emscripten-core#26633
@sbc100 sbc100 force-pushed the precise_wakeups branch 2 times, most recently from cb1c872 to 8dc3c30 Compare April 11, 2026 00:49
@sbc100 sbc100 requested a review from tlively April 11, 2026 00:50

// If the given memory address contains value val, puts the calling thread to
// sleep waiting for that address to be notified.
// Note: Like the Linux futex syscall, this APi *does* allow spurious wakeups.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// Note: Like the Linux futex syscall, this APi *does* allow spurious wakeups.
// Note: Like the Linux futex syscall, this API *does* allow spurious wakeups.

// Note: Like the Linux futex syscall, this APi *does* allow spurious wakeups.
// This differs from the WebAssembly `atomic.wait` instruction itself which
// does *not* allow supurious wakeups and it means that most callers will want
// to wraps this some kind loop.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// to wraps this some kind loop.
// to wrap this in some kind loop.

return 0;
}
#ifdef __EMSCRIPTEN__
// Wake the target thread in case it in emscripten_futex_wait. Normally
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// Wake the target thread in case it in emscripten_futex_wait. Normally
// Wake the target thread in case it is in emscripten_futex_wait. Normally

} else {
DBG("emscripten_futex_wait skipping atomic.wait due to NOTIFY_BIT");
// CAS failed, NOTIFY_BIT must have been set. In this case we don't
// actually wait at all. Instead we behaviour as if we spuriously woke up
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// actually wait at all. Instead we behaviour as if we spuriously woke up
// actually wait at all. Instead we behave as if we spuriously woke up

return -ECANCELED;
}
#else
ret = __builtin_wasm_memory_atomic_wait32((int*)addr, val, max_wait_ns);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be good to add an // __EMSCRIPTEN_PTHREADS__ comment to the above #else. Otherwise the presence of a second wait here is very confusing. Actually, why do we wait when pthreads are not enabled? Is it just in case user code will handle the notify, e.g. from JS? Or is this a Wasm Workers thing?

// Then proxying work to the main thread using the system queue we have
// a very special case in that we need the target thread to wake up from
// `emscripten_futex_wait` to process the queue.
if (rtn && is_system_queue && pthread_equal(target_thread, emscripten_main_runtime_thread_id())) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be good to clang-format this to wrap to 80 columns. At least that's what the rest of the proxying code uses.


return em_task_queue_send(tasks, t);
bool rtn = em_task_queue_send(tasks, t);
// Then proxying work to the main thread using the system queue we have
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// Then proxying work to the main thread using the system queue we have
// When proxying work to the main thread using the system queue we have

}

return em_task_queue_send(tasks, t);
bool rtn = em_task_queue_send(tasks, t);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would have expected ret rather than rtn. Unless there is common precedent for rtn in the code base?

Suggested change
bool rtn = em_task_queue_send(tasks, t);
bool ret = em_task_queue_send(tasks, t);

// since blocking is not allowed there).
int _emscripten_thread_supports_atomics_wait(void);

// Notify a thread that it has new work to do (cancellation or mailbox).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// Notify a thread that it has new work to do (cancellation or mailbox).

All the method does is inject the wakeup, so I would avoid suggesting that it also directly causes the target thread to do anything like check a mailbox.


5.0.6 (in development)
----------------------
- The emscripten_futux_wait API is not document to explicitly allow spurious
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
- The emscripten_futux_wait API is not document to explicitly allow spurious
- The emscripten_futux_wait API is now documented to explicitly allow spurious

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.

Can we avoid continuous wakeups in emscripten_futex_wait?

2 participants