Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ See docs/process.md for more on how version tagging works.

5.0.2 (in development)
----------------------
- Several low level emscripten APIs that return success/failure now return the
C `bool` type rather than `int`. For example `emscripten_proxy_sync` and
`emscripten_is_main_runtime_thread`. (#26316)
- SDL2 port updated from 2.32.8 to 2.32.10. (#26298)
- The remaining launcher scripts (e.g. `emcc.bat`) were removed from the git
repository. These scripts are created by the `./bootstrap` script which
Expand Down
22 changes: 11 additions & 11 deletions site/source/docs/api_reference/proxying.h.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,46 +72,46 @@ Functions

Signal the end of a task proxied with ``emscripten_proxy_sync_with_ctx``.

.. c:function:: int emscripten_proxy_async(em_proxying_queue* q, pthread_t target_thread, void (*func)(void*), void* arg)
.. c:function:: bool emscripten_proxy_async(em_proxying_queue* q, pthread_t target_thread, void (*func)(void*), void* arg)

Enqueue ``func`` to be called with argument ``arg`` on the given queue and
thread then return immediately without waiting for ``func`` to be executed.
Returns 1 if the work was successfully enqueued or 0 otherwise.
Returns true if the work was successfully enqueued or false otherwise.

.. c:function:: int emscripten_proxy_sync(em_proxying_queue* q, pthread_t target_thread, void (*func)(void*), void* arg)
.. c:function:: bool emscripten_proxy_sync(em_proxying_queue* q, pthread_t target_thread, void (*func)(void*), void* arg)

Enqueue ``func`` to be called with argument ``arg`` on the given queue and
thread then wait for ``func`` to be executed synchronously before returning.
Returns 1 if the ``func`` was successfully completed and 0 otherwise,
Returns true if the ``func`` was successfully completed and false otherwise,
including if the target thread is canceled or exits before the work is
completed.

.. c:function:: int emscripten_proxy_sync_with_ctx(em_proxying_queue* q, pthread_t target_thread, void (*func)(em_proxying_ctx*, void*), void* arg)
.. c:function:: bool emscripten_proxy_sync_with_ctx(em_proxying_queue* q, pthread_t target_thread, void (*func)(em_proxying_ctx*, void*), void* arg)

The same as ``emscripten_proxy_sync`` except that instead of waiting for the
proxied function to return, it waits for the proxied task to be explicitly
marked finished with ``emscripten_proxy_finish``. ``func`` need not call
``emscripten_proxy_finish`` itself; it could instead store the context pointer
and call ``emscripten_proxy_finish`` at an arbitrary later time.

.. c:function:: int emscripten_proxy_callback(em_proxying_queue* q, pthread_t target_thread, void (*func)(void*), void (*callback)(void*), void (*cancel)(void*), void* arg)
.. c:function:: bool emscripten_proxy_callback(em_proxying_queue* q, pthread_t target_thread, void (*func)(void*), void (*callback)(void*), void (*cancel)(void*), void* arg)

Enqueue ``func`` on the given queue and thread. Once (and if) it finishes
executing, it will asynchronously proxy ``callback`` back to the current
thread on the same queue, or if the target thread dies before the work can be
completed, ``cancel`` will be proxied back instead. All three function will
receive the same argument, ``arg``. Returns 1 if ``func`` was successfully
enqueued and the target thread notified or 0 otherwise.
receive the same argument, ``arg``. Returns true if ``func`` was successfully
enqueued and the target thread notified or false otherwise.

.. c:function:: int emscripten_proxy_callback_with_ctx(em_proxying_queue* q, pthread_t target_thread, void (*func)(em_proxying_ctx*, void*), void (*callback)(void*), void (*cancel)(void*), void* arg)
.. c:function:: bool emscripten_proxy_callback_with_ctx(em_proxying_queue* q, pthread_t target_thread, void (*func)(em_proxying_ctx*, void*), void (*callback)(void*), void (*cancel)(void*), void* arg)

Enqueue ``func`` on the given queue and thread. Once (and if) it finishes the
task by calling ``emscripten_proxy_finish`` on the given ``em_proxying_ctx``,
it will asynchronously proxy ``callback`` back to the current thread on the
same queue, or if the target thread dies before the work can be completed,
``cancel`` will be proxied back instead. All three function will receive the
same argument, ``arg``. Returns 1 if ``func`` was successfully enqueued and
the target thread notified or 0 otherwise.
same argument, ``arg``. Returns true if ``func`` was successfully enqueued and
the target thread notified or false otherwise.

C++ API
-------
Expand Down
2 changes: 2 additions & 0 deletions system/include/emscripten/emscripten.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ int emscripten_get_worker_queue_size(worker_handle worker);
// misc.

long emscripten_get_compiler_setting(const char *name);

// Returns the value of -sASYNCIFY. Can be 0, 1, or 2 (in the case of JSPI).
int emscripten_has_asyncify(void);

void emscripten_debugger(void);
Expand Down
4 changes: 3 additions & 1 deletion system/include/emscripten/heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#pragma once

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <emscripten/emscripten.h>
Expand All @@ -31,7 +32,8 @@ uintptr_t *emscripten_get_sbrk_ptr(void);
// src/settings.js variables MEMORY_GROWTH_GEOMETRIC_STEP,
// MEMORY_GROWTH_GEOMETRIC_CAP and MEMORY_GROWTH_LINEAR_STEP. This function
// cannot be used to shrink the size of the memory.
int emscripten_resize_heap(size_t requested_size) EM_IMPORT(emscripten_resize_heap);
// Returns true on success, false otherwise.
bool emscripten_resize_heap(size_t requested_size) EM_IMPORT(emscripten_resize_heap);

// Returns the current size of the WebAssembly memory (referred to as heap for
// legacy reason).
Expand Down
71 changes: 36 additions & 35 deletions system/include/emscripten/proxying.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <emscripten/emscripten.h>
#include <emscripten/promise.h>
#include <stdbool.h>
#include <pthread.h>

#ifdef __cplusplus
Expand Down Expand Up @@ -48,60 +49,60 @@ typedef struct em_proxying_ctx em_proxying_ctx;
void emscripten_proxy_finish(em_proxying_ctx* ctx);

// Enqueue `func` on the given queue and thread and return immediately. Returns
// 1 if the work was successfully enqueued and the target thread notified or 0
// otherwise.
int emscripten_proxy_async(em_proxying_queue* q,
// true if the work was successfully enqueued and the target thread notified or
// false otherwise.
bool emscripten_proxy_async(em_proxying_queue* q,
pthread_t target_thread,
void (*func)(void*),
void* arg);

// Enqueue `func` on the given queue and thread and wait for it to finish
// executing before returning. Returns true if the task was successfully
// completed and false otherwise, including if the target thread is canceled or
// exits before the work is completed.
bool emscripten_proxy_sync(em_proxying_queue* q,
pthread_t target_thread,
void (*func)(void*),
void* arg);

// Enqueue `func` on the given queue and thread and wait for it to finish
// executing before returning. Returns 1 if the task was successfully completed
// and 0 otherwise, including if the target thread is canceled or exits before
// the work is completed.
int emscripten_proxy_sync(em_proxying_queue* q,
pthread_t target_thread,
void (*func)(void*),
void* arg);

// Enqueue `func` on the given queue and thread and wait for it to be executed
// and for the task to be marked finished with `emscripten_proxy_finish` before
// returning. `func` need not call `emscripten_proxy_finish` itself; it could
// instead store the context pointer and call `emscripten_proxy_finish` at an
// arbitrary later time. Returns 1 if the task was successfully completed and 0
// otherwise, including if the target thread is canceled or exits before the
// work is completed.
int emscripten_proxy_sync_with_ctx(em_proxying_queue* q,
pthread_t target_thread,
void (*func)(em_proxying_ctx*, void*),
void* arg);
// arbitrary later time. Returns true if the task was successfully completed and
// false otherwise, including if the target thread is canceled or exits before
// the work is completed.
bool emscripten_proxy_sync_with_ctx(em_proxying_queue* q,
pthread_t target_thread,
void (*func)(em_proxying_ctx*, void*),
void* arg);

// Enqueue `func` on the given queue and thread. Once (and if) it finishes
// executing, it will asynchronously proxy `callback` back to the current thread
// on the same queue, or if the target thread dies before the work can be
// completed, `cancel` will be proxied back instead. All three functions will
// receive the same argument, `arg`. Returns 1 if `func` was successfully
// enqueued and the target thread notified or 0 otherwise.
int emscripten_proxy_callback(em_proxying_queue* q,
pthread_t target_thread,
void (*func)(void*),
void (*callback)(void*),
void (*cancel)(void*),
void* arg);
// receive the same argument, `arg`. Returns true if `func` was successfully
// enqueued and the target thread notified or false otherwise.
bool emscripten_proxy_callback(em_proxying_queue* q,
pthread_t target_thread,
void (*func)(void*),
void (*callback)(void*),
void (*cancel)(void*),
void* arg);

// Enqueue `func` on the given queue and thread. Once (and if) it finishes the
// task by calling `emscripten_proxy_finish` on the given `em_proxying_ctx`, it
// will asynchronously proxy `callback` back to the current thread on the same
// queue, or if the target thread dies before the work can be completed,
// `cancel` will be proxied back instead. All three functions will receive the
// same argument, `arg`. Returns 1 if `func` was successfully enqueued and the
// target thread notified or 0 otherwise.
int emscripten_proxy_callback_with_ctx(em_proxying_queue* q,
pthread_t target_thread,
void (*func)(em_proxying_ctx*, void*),
void (*callback)(void*),
void (*cancel)(void*),
void* arg);
// same argument, `arg`. Returns true if `func` was successfully enqueued and
// the target thread notified or false otherwise.
bool emscripten_proxy_callback_with_ctx(em_proxying_queue* q,
pthread_t target_thread,
void (*func)(em_proxying_ctx*, void*),
void (*callback)(void*),
void (*cancel)(void*),
void* arg);

__attribute__((warn_unused_result)) em_promise_t
emscripten_proxy_promise(em_proxying_queue* q,
Expand Down
15 changes: 8 additions & 7 deletions system/include/emscripten/threading.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <inttypes.h>
#include <pthread.h>
#include <stdbool.h>

#include <emscripten/html5.h> // for EMSCRIPTEN_RESULT
#include <emscripten/atomic.h>
Expand All @@ -24,7 +25,7 @@ extern "C" {
// pthread_create(), and the compiled page was built with threading support
// enabled. If this returns 0, calls to pthread_create() will fail with return
// code EAGAIN.
int emscripten_has_threading_support(void);
bool emscripten_has_threading_support(void);

// Returns the number of logical cores on the system.
int emscripten_num_logical_cores(void);
Expand All @@ -39,14 +40,14 @@ int emscripten_futex_wait(volatile void/*uint32_t*/ * _Nonnull addr, uint32_t va
// Returns -EINVAL if addr is null.
int emscripten_futex_wake(volatile void/*uint32_t*/ * _Nonnull addr, int count);

// Returns 1 if the current thread is the thread that hosts the Emscripten
// Returns true if the current thread is the thread that hosts the Emscripten
// runtime.
int emscripten_is_main_runtime_thread(void);
bool emscripten_is_main_runtime_thread(void);

// Returns 1 if the current thread is the main browser thread. In the case that
// the emscripten module is run in a worker there may be no pthread for which
// this returns 1.
int emscripten_is_main_browser_thread(void);
// Returns true if the current thread is the main browser thread. In the case
// that the Emscripten module is started in a worker there will be no thread
// for which this returns true.
bool emscripten_is_main_browser_thread(void);

// A temporary workaround to issue
// https://github.com/emscripten-core/emscripten/issues/3495:
Expand Down
3 changes: 2 additions & 1 deletion system/include/emscripten/wasm_worker.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <emscripten/atomic.h>
Expand Down Expand Up @@ -115,7 +116,7 @@ int emscripten_navigator_hardware_concurrency(void);
// accesses, behavior differs across browsers, see
// - https://bugzil.la/1246139
// - https://bugs.chromium.org/p/chromium/issues/detail?id=1167449
int emscripten_atomics_is_lock_free(int byteWidth);
bool emscripten_atomics_is_lock_free(int byteWidth);

#define emscripten_lock_t volatile uint32_t

Expand Down
24 changes: 12 additions & 12 deletions system/lib/pthread/em_task_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,12 @@ void em_task_queue_destroy(em_task_queue* queue) {
}

// Not thread safe. Returns 1 on success and 0 on failure.
static int em_task_queue_grow(em_task_queue* queue) {
static bool em_task_queue_grow(em_task_queue* queue) {
// Allocate a larger task queue.
int new_capacity = queue->capacity * 2;
task* new_tasks = malloc(sizeof(task) * new_capacity);
if (new_tasks == NULL) {
return 0;
return false;
}
// Copy the tasks such that the head of the queue is at the beginning of the
// buffer. There are two cases to handle: either the queue wraps around the
Expand All @@ -162,7 +162,7 @@ static int em_task_queue_grow(em_task_queue* queue) {
queue->capacity = new_capacity;
queue->head = 0;
queue->tail = queued_tasks;
return 1;
return true;
}

void em_task_queue_execute(em_task_queue* queue) {
Expand Down Expand Up @@ -197,13 +197,13 @@ void em_task_queue_cancel(em_task_queue* queue) {
queue->notification = NOTIFICATION_NONE;
}

int em_task_queue_enqueue(em_task_queue* queue, task t) {
bool em_task_queue_enqueue(em_task_queue* queue, task t) {
if (em_task_queue_is_full(queue) && !em_task_queue_grow(queue)) {
return 0;
return false;
}
queue->tasks[queue->tail] = t;
queue->tail = (queue->tail + 1) % queue->capacity;
return 1;
return true;
}

task em_task_queue_dequeue(em_task_queue* queue) {
Expand All @@ -226,19 +226,19 @@ static void cancel_notification(void* arg) {
em_task_queue_cancel(tasks);
}

int em_task_queue_send(em_task_queue* queue, task t) {
bool em_task_queue_send(em_task_queue* queue, task t) {
// Ensure the target mailbox will remain open or detect that it is already
// closed.
if (!emscripten_thread_mailbox_ref(queue->thread)) {
return 0;
return false;
}

pthread_mutex_lock(&queue->mutex);
int enqueued = em_task_queue_enqueue(queue, t);
bool enqueued = em_task_queue_enqueue(queue, t);
pthread_mutex_unlock(&queue->mutex);
if (!enqueued) {
emscripten_thread_mailbox_unref(queue->thread);
return 0;
return false;
}

// We're done if there is already a pending notification for this task queue.
Expand All @@ -247,13 +247,13 @@ int em_task_queue_send(em_task_queue* queue, task t) {
atomic_exchange(&queue->notification, NOTIFICATION_PENDING);
if (previous == NOTIFICATION_PENDING) {
emscripten_thread_mailbox_unref(queue->thread);
return 1;
return true;
}

emscripten_thread_mailbox_send(queue->thread,
(task){.func = receive_notification,
.cancel = cancel_notification,
.arg = queue});
emscripten_thread_mailbox_unref(queue->thread);
return 1;
return true;
}
15 changes: 8 additions & 7 deletions system/lib/pthread/em_task_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#pragma once

#include <stdbool.h>
#include <pthread.h>

#include "proxying_notification_state.h"
Expand Down Expand Up @@ -58,22 +59,22 @@ void em_task_queue_execute(em_task_queue* queue);
void em_task_queue_cancel(em_task_queue* queue);

// Not thread safe.
static inline int em_task_queue_is_empty(em_task_queue* queue) {
static inline bool em_task_queue_is_empty(em_task_queue* queue) {
return queue->head == queue->tail;
}

// Not thread safe.
static inline int em_task_queue_is_full(em_task_queue* queue) {
static inline bool em_task_queue_is_full(em_task_queue* queue) {
return queue->head == (queue->tail + 1) % queue->capacity;
}

// Not thread safe. Returns 1 on success and 0 on failure.
int em_task_queue_enqueue(em_task_queue* queue, task t);
// Not thread safe. Returns true on success and false on failure.
bool em_task_queue_enqueue(em_task_queue* queue, task t);

// Not thread safe. Assumes the queue is not empty.
task em_task_queue_dequeue(em_task_queue* queue);

// Atomically enqueue the task and schedule the queue to be executed next time
// its owning thread returns to its event loop. Returns 1 on success and 0
// otherwise. Internally locks the queue.
int em_task_queue_send(em_task_queue* queue, task t);
// its owning thread returns to its event loop. Returns true on success and
// false otherwise. Internally locks the queue.
bool em_task_queue_send(em_task_queue* queue, task t);
7 changes: 5 additions & 2 deletions system/lib/pthread/library_pthread_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include <emscripten/threading.h>
#include <emscripten/emscripten.h>

int emscripten_has_threading_support() { return 0; }
bool emscripten_has_threading_support() { return false; }

int emscripten_num_logical_cores() { return 1; }

Expand All @@ -32,7 +32,10 @@ int emscripten_futex_wake(volatile void /*uint32_t*/* addr, int count) {
return 0; // success
}

int emscripten_is_main_runtime_thread() { return 1; }
bool emscripten_is_main_runtime_thread() {
// TODO: We probably shouldn't be returning true here in WASM_WORKERS builds.
return true;
}

void emscripten_main_thread_process_queued_calls() {
// nop
Expand Down
Loading