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

[wasm-mt] Support async JS interop on threadpool threads #84494

Commits on Apr 21, 2023

  1. [wasm-mt] Full JSInterop on threadpool workers

    [wasm][threads] flip YieldFromDispatchLoop; specialize PortableThreadPool.WorkerThread
    
    [mono] Implement a LifoJSSemaphore
    
    This is a LIFO semaphore with an asynchronous wait that triggers
    callbacks on the JS event loop in case of Release or timeout.
    
    Make managed LowLevelJSSemaphore
    
    copy-paste PortableThreadPool.WorkerThread for threaded WASM
    
    no changes yet. just copying verbatim to a separate file
    
    fixup native code for lifo semaphore
    
    fixup managed code for LowLevelJSSemaphore
    
    Implement PortableThreadPool loop using semaphore callbacks
    
    manage emscripten event loop from PortableThreadPool.WorkerThread
    
    make sure to keep the thread alive after setting up the semaphore
    wait.
    Cleanup the thread when exiting
    
    FIXME: thread equality assertion in timeout callback
    
    XXX REVERT ME - minimal async timeout test
    
    BUGFIX: &wait_entry ===> wait_entry
    
    nit: log thread id as hex in .ts
    
    Match the C logging for easier grepping
    
    XXX minimal sample - fetch on a background thread works
    
    fix non-wasm non-threads builds
    
    Add WebWorkerEventLoop internal class to managed event loop keepalive
    
    Don't explicitly call UnwindToJs as it doesn't know about managed
    code.
    Also avoid mono_thread_exit as that also won't necessarily clean up
    after the interpreter
    
    Start threadpool threads with keepalive checks
    
    Add a flag to mono's thread start wrappers to keep track of threads
    that may not want cleanup to run after the Start function returns.
    
    Use the flag when starting threadpool threads.
    
    HACK: kind of work around the emscripten_runtime_keepalive_push/pop no-op
    
    Keep a thread local counter in mono. that we "know" will be right for
    us and manually call unwind_to_js and thread_exit.
    
    This is super-fragile since we don't know what emscripten internals
    might be trying to manipulate the keepalive count and also we are
    exiting the thread with active managed frames, so we might be skipping
    finally clauses and possibly leaking interpreter memory.
    
    This is mainly meant to keep work going on this branch and not
    something we necessarily want to commit
    
    support JS Semaphore with --print-icall-table cross compiler
    
    fixes smoketest on Release builds
    
    make minimal FetchBackground sample more like a unit test
    
    Share PortableThreadPool.WorkerThread common code
    
    Share the code between non-browser implementations and
    browser+threads.
    
    The differences are just in how the work loop is started and implemented
    
    make both kinds of lifo semaphore share a base struct
    
    Unify LowLevelLifoSemaphore for normal and async waiting
    
    WebWorkerEventLoop: remove dead code, update comments
    
    remove unused arg from async wait semaphore
    
    don't need both user data and a gchandle
    
    rename native semaphore to LifoSemaphoreAsyncWait
    
    prefix functions with mono_lifo_semaphore_asyncwait_
    
    Rename managed file to LowLevelLifoSemaphore.AsyncWait.Browser.Threads.Mono.cs
    
    Remove unnecessary indirections and allocations from managed AsyncWait semaphore
    
    fix non-browser+threads builds
    
    Keep track of unsettled JS interop promises in threadpool workers
    
    Set WorkerThread.IsIOPending when the current thread has unsettled JS
    interop promises.
    
    When IsIOPending is true, the worker will not exit even if it has no
    more work to do.  Instead it will repeatedly wait for more work to
    arrive or for all promises to settle.
    
    change minimal sample's fetch helper to artificially delay
    
    the delay is longer that the threadpool worker's semaphore timeout, in
    order to validate that the worker stays alive while there are
    unsettled promises
    lambdageek committed Apr 21, 2023
    Configuration menu
    Copy the full SHA
    8c3fef3 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    a3db886 View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    847ecd5 View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    dd69c8f View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    451d21b View commit details
    Browse the repository at this point in the history
  6. extend and rationalize the smoke test a bit

    Add a test that just starts a thread and asserts that it has a
    different thread ID than the main thread.  This should allow us to
    rule out accidentally having the test pass on a single-threaded runtime
    lambdageek committed Apr 21, 2023
    Configuration menu
    Copy the full SHA
    2889a1f View commit details
    Browse the repository at this point in the history
  7. Configuration menu
    Copy the full SHA
    92d80a5 View commit details
    Browse the repository at this point in the history
  8. hide some debug output

    lambdageek committed Apr 21, 2023
    Configuration menu
    Copy the full SHA
    5f4acc8 View commit details
    Browse the repository at this point in the history
  9. Configuration menu
    Copy the full SHA
    806b770 View commit details
    Browse the repository at this point in the history
  10. [wasm-mt] make JSHostImplementation.s_csOwnedObjects ThreadStatic

    The integer jsHandles are not global - they are essentially indices
    into a JS array.
    So the mapping from a jsHandle to a JSObject must be per-thread.
    
    This fixes the thread affinity assertions in the smoketest (which were
    false positives - we looked up a worker's jsHandle and got back the
    main thread's JSObject - and then asserted that it was accessed from
    the wrong thread)
    lambdageek committed Apr 21, 2023
    Configuration menu
    Copy the full SHA
    d2811f7 View commit details
    Browse the repository at this point in the history
  11. remove locking on JSHostImplementation.CsOwnedObjects

    In single-threaded wasm, there is no need to lock since there is only
    one caller at a time.
    
    In multi-threaded wasm, the underlying dictionary is thread-static
    lambdageek committed Apr 21, 2023
    Configuration menu
    Copy the full SHA
    48d22ae View commit details
    Browse the repository at this point in the history

Commits on Apr 24, 2023

  1. Merge remote-tracking branch 'origin/main' into pieces-wasm-threadpoo…

    …l-worker-4-async-threadpool-worker
    lambdageek committed Apr 24, 2023
    Configuration menu
    Copy the full SHA
    c813701 View commit details
    Browse the repository at this point in the history

Commits on Apr 27, 2023

  1. Merge remote-tracking branch 'origin/main' into pieces-wasm-threadpoo…

    …l-worker-4-async-threadpool-worker
    lambdageek committed Apr 27, 2023
    Configuration menu
    Copy the full SHA
    0a4dd8c View commit details
    Browse the repository at this point in the history
  2. [threads] make the "external eventloop" platform independent

    It only does something on WASM, but in principle if other platforms
    allow us to run some code after returning from a thread start
    function, we could do it there, too.
    lambdageek committed Apr 27, 2023
    Configuration menu
    Copy the full SHA
    77a54ff View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    fd99953 View commit details
    Browse the repository at this point in the history

Commits on Apr 28, 2023

  1. Add a Thread.HasExternalEventLoop managed property

    Set it from WebWorkerEventLoop.StartExitable.
    In native code, use it to set the
    `MONO_THREAD_CREATE_FLAGS_EXTERNAL_EVENTLOOP` flag when starting the thread.
    lambdageek committed Apr 28, 2023
    Configuration menu
    Copy the full SHA
    4671e03 View commit details
    Browse the repository at this point in the history
  2. rename JSHostImplementation.ThreadCsOwnedObjects

    (used to be CsOwnedObjects)
    
    Rename to make it clear that it's objects owned by the current thread,
    not the runtime globally
    lambdageek committed Apr 28, 2023
    Configuration menu
    Copy the full SHA
    e22ca46 View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    c591501 View commit details
    Browse the repository at this point in the history