@@ -425,8 +425,27 @@ mod call_thread_state {
425425 use super :: * ;
426426 use crate :: runtime:: vm:: Unwind ;
427427
428- /// Temporary state stored on the stack which is registered in the `tls` module
429- /// below for calls into wasm.
428+ /// Temporary state stored on the stack which is registered in the `tls`
429+ /// module below for calls into wasm.
430+ ///
431+ /// This structure is stored on the stack and allocated during the
432+ /// `catch_traps` function above. The purpose of this structure is to track
433+ /// the state of an "activation" or a sequence of 0-or-more contiguous
434+ /// WebAssembly call frames. A `CallThreadState` always lives on the stack
435+ /// and additionally maintains pointers to previous states to form a linked
436+ /// list of activations.
437+ ///
438+ /// One of the primary goals of `CallThreadState` is to store the state of
439+ /// various fields in `VMStoreContext` when it was created. This is done
440+ /// because calling WebAssembly will clobber these fields otherwise.
441+ ///
442+ /// Another major purpose of `CallThreadState` is to assist with unwinding
443+ /// and track state necessary when an unwind happens for the original
444+ /// creator of `CallThreadState` to determine why the unwind happened.
445+ ///
446+ /// Note that this structure is pointed-to from TLS, hence liberal usage of
447+ /// interior mutability here since that only gives access to
448+ /// `&CallThreadState`.
430449 pub struct CallThreadState {
431450 pub ( super ) unwind : Cell < Option < ( UnwindReason , Option < Backtrace > , Option < CoreDumpStack > ) > > ,
432451 pub ( super ) jmp_buf : Cell < * const u8 > ,
@@ -525,12 +544,31 @@ mod call_thread_state {
525544 self . prev . get ( )
526545 }
527546
547+ /// Pushes this `CallThreadState` activation on to the linked list
548+ /// stored in TLS.
549+ ///
550+ /// This method will take the current head of the linked list, stored in
551+ /// our TLS pointer, and move it into `prev`. The TLS pointer is then
552+ /// updated to `self`.
553+ ///
554+ /// # Panics
555+ ///
556+ /// Panics if this activation is already in a linked list (e.g.
557+ /// `self.prev` is set).
528558 #[ inline]
529559 pub ( crate ) unsafe fn push ( & self ) {
530560 assert ! ( self . prev. get( ) . is_null( ) ) ;
531561 self . prev . set ( tls:: raw:: replace ( self ) ) ;
532562 }
533563
564+ /// Pops this `CallThreadState` from the linked list stored in TLS.
565+ ///
566+ /// This method will restore `self.prev` into the head of the linked
567+ /// list stored in TLS and will additionally null-out `self.prev`.
568+ ///
569+ /// # Panics
570+ ///
571+ /// Panics if this activation isn't the head of the list.
534572 #[ inline]
535573 pub ( crate ) unsafe fn pop ( & self ) {
536574 let prev = self . prev . replace ( ptr:: null ( ) ) ;
@@ -734,11 +772,84 @@ impl CallThreadState {
734772 }
735773}
736774
737- // A private inner module for managing the TLS state that we require across
738- // calls in wasm. The WebAssembly code is called from C++ and then a trap may
739- // happen which requires us to read some contextual state to figure out what to
740- // do with the trap. This `tls` module is used to persist that information from
741- // the caller to the trap site.
775+ /// A private inner module managing the state of Wasmtime's thread-local storage
776+ /// (TLS) state.
777+ ///
778+ /// Wasmtime at this time has a single pointer of TLS. This single pointer of
779+ /// TLS is the totality of all TLS required by Wasmtime. By keeping this as
780+ /// small as possible it generally makes it easier to integrate with external
781+ /// systems and implement features such as fiber context switches. This single
782+ /// TLS pointer is declared in platform-specific modules to handle platform
783+ /// differences, so this module here uses getters/setters which delegate to
784+ /// platform-specific implementations.
785+ ///
786+ /// The single TLS pointer used by Wasmtime is morally
787+ /// `Option<&CallThreadState>` meaning that it's a possibly-present pointer to
788+ /// some state. This pointer is a pointer to the most recent (youngest)
789+ /// `CallThreadState` activation, or the most recent call into WebAssembly.
790+ ///
791+ /// This TLS pointer is additionally the head of a linked list of activations
792+ /// that are all stored on the stack for the current thread. Each time
793+ /// WebAssembly is recursively invoked by an embedder will push a new entry into
794+ /// this linked list. This singly-linked list is maintained with its head in TLS
795+ /// node pointers are stored in `CallThreadState::prev`.
796+ ///
797+ /// An example stack might look like this:
798+ ///
799+ /// ```text
800+ /// ┌─────────────────────┐◄───── highest, or oldest, stack address
801+ /// │ native stack frames │
802+ /// │ ... │
803+ /// │ ┌───────────────┐◄─┼──┐
804+ /// │ │CallThreadState│ │ │
805+ /// │ └───────────────┘ │ p
806+ /// ├─────────────────────┤ r
807+ /// │ wasm stack frames │ e
808+ /// │ ... │ v
809+ /// ├─────────────────────┤ │
810+ /// │ native stack frames │ │
811+ /// │ ... │ │
812+ /// │ ┌───────────────┐◄─┼──┼── TLS pointer
813+ /// │ │CallThreadState├──┼──┘
814+ /// │ └───────────────┘ │
815+ /// ├─────────────────────┤
816+ /// │ wasm stack frames │
817+ /// │ ... │
818+ /// ├─────────────────────┤
819+ /// │ native stack frames │
820+ /// │ ... │
821+ /// └─────────────────────┘◄───── smallest, or youngest, stack address
822+ /// ```
823+ ///
824+ /// # Fibers and async
825+ ///
826+ /// Wasmtime supports stack-switching with fibers to implement async. This means
827+ /// that Wasmtime will temporarily execute code on a separate stack and then
828+ /// suspend from this stack back to the embedder for async operations. Doing
829+ /// this safely requires manual management of the TLS pointer updated by
830+ /// Wasmtime.
831+ ///
832+ /// For example when a fiber is suspended that means that the TLS pointer needs
833+ /// to be restored to whatever it was when the fiber was resumed. Additionally
834+ /// this may need to pop multiple `CallThreadState` activations, one for each
835+ /// one located on the fiber stack itself.
836+ ///
837+ /// The `AsyncWasmCallState` and `PreviousAsyncWasmCallState` structures in this
838+ /// module are used to manage this state, namely:
839+ ///
840+ /// * The `AsyncWasmCallState` structure represents the state of a suspended
841+ /// fiber. This is a linked list, in reverse order, from oldest activation on
842+ /// the fiber to youngest activation on the fiber.
843+ ///
844+ /// * The `PreviousAsyncWasmCallState` structure represents a pointer within our
845+ /// thread's TLS linked list of activations when a fiber was resumed. This
846+ /// pointer is used during fiber suspension to know when to stop popping
847+ /// activations from the thread's linked list.
848+ ///
849+ /// Note that this means that the directionality of linked list links is
850+ /// opposite when stored in TLS vs when stored for a suspended fiber. The
851+ /// thread's current list pointed to by TLS is youngest-to-oldest links, while a
852+ /// suspended fiber stores oldest-to-youngest links.
742853pub ( crate ) mod tls {
743854 use super :: CallThreadState ;
744855
@@ -830,6 +941,9 @@ pub(crate) mod tls {
830941 //
831942 // When pushed onto a thread this linked list is traversed to get pushed
832943 // onto the current thread at the time.
944+ //
945+ // If this pointer is null then that means that the fiber this state is
946+ // associated with has no activations.
833947 state : raw:: Ptr ,
834948 }
835949
@@ -883,7 +997,7 @@ pub(crate) mod tls {
883997 ///
884998 /// This is used when exiting a future in Wasmtime to assert that the
885999 /// current CallThreadState pointer does not point within the stack
886- /// we're leaving (e.g. allocated for a fiber).
1000+ /// we're leaving (e.g. allocated for a fiber).
8871001 pub fn assert_current_state_not_in_range ( range : core:: ops:: Range < usize > ) {
8881002 let p = raw:: get ( ) as usize ;
8891003 assert ! ( p < range. start || range. end < p) ;
@@ -892,14 +1006,15 @@ pub(crate) mod tls {
8921006
8931007 /// Opaque state used to help control TLS state across stack switches for
8941008 /// async support.
1009+ ///
1010+ /// This structure is returned from [`AsyncWasmCallState::push`] and
1011+ /// represents the state of this thread's TLS variable prior to the push
1012+ /// operation.
8951013 #[ cfg( feature = "async" ) ]
8961014 pub struct PreviousAsyncWasmCallState {
897- // The head of a linked list, similar to the TLS state. Note though that
898- // this list is stored in reverse order to assist with `push` and `pop`
899- // below.
900- //
901- // After a `push` call this stores the previous head for the current
902- // thread so we know when to stop popping during a `pop`.
1015+ // The raw value of this thread's TLS pointer when this structure was
1016+ // created. This is not dereferenced or inspected but is used to halt
1017+ // linked list traversal in [`PreviousAsyncWasmCallState::restore`].
9031018 state : raw:: Ptr ,
9041019 }
9051020
@@ -909,8 +1024,8 @@ pub(crate) mod tls {
9091024 /// `AsyncWasmCallState`.
9101025 ///
9111026 /// This will pop the top activation of this current thread continuously
912- /// until it reaches whatever the current activation was when `push` was
913- /// originally called.
1027+ /// until it reaches whatever the current activation was when
1028+ /// [`AsyncWasmCallState::push`] was originally called.
9141029 ///
9151030 /// # Unsafety
9161031 ///
0 commit comments