class ThreadStorage

Defined at line 47 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

ThreadStorage handles the memory allocation and ownership for Thread. It's

responsible for allocating all the various kinds of stacks, and the thread

area that underlies both the implementation's private Thread Control Block

(TCB) as well as the public Fuchsia Compiler ABI and ELF TLS. ThreadStorage

initializes only the parts of the TCB that are part of the public ABI

(including all of ELF Initial Exec TLS) and then leaves the rest of the TCB

zero-initialized for later use by libc internals.

Initially it's used at process startup and thread creation. It owns those

allocations and cleans them up on destruction e.g. if thread creation fails.

During the thread's lifetime, the ThreadStorage is moved into its Thread.

This is a bit tricky, as the Thread object's own memory resides in one of

the blocks that ThreadStorage owns. So to destroy Thread, its ThreadStorage

must be moved back out before explicitly calling ~Thread().

ThreadStorage can only be default-constructed or moved. Before Allocate()

has returned successfully (or after it fails), it should only be destroyed

and no other methods used (except for moves).

Public Methods

void ~ThreadStorage ()

Defined at line 36 of file ../../sdk/lib/c/threads/thread-storage.cc

void ThreadStorage ()

Defined at line 49 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

void ThreadStorage (ThreadStorage && other)

Defined at line 50 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

ThreadStorage & operator= (ThreadStorage && other)

Defined at line 52 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

zx::result<Thread *> Allocate (thrd_zx_create_handles_t allocate_from, std::string_view vmo_name, PageRoundedSize stack, PageRoundedSize guard)

This allocates everything and holds ownership in this object. If it

returns an error, some resources may now be owned but nothing more should

be done with the object but to destroy it (and thus reclaim them).

When this returns success, the remaining methods return useful values.

The machine stack, unsafe stack (for the SafeStack ABI, enabled on all

machines), and shadow call stack (enabled on some machines), are all

allocated with guard pages and all-zeroes contents. In the thread area:

* The unsafe stack pointer at $tp + ZX_TLS_UNSAFE_SP_OFFSET is set to

the top of the unsafe stack.

* If the machine's TLS ABI has *$tp = $tp (like x86), that is set.

* The ZX_TLS_STACK_GUARD_OFFSET word still must be set. For the initial

thread, the caller will choose random bits; for new threads, the caller

will copy the value found via its own $tp.

* All the ELF Initial Exec TLS data (static TLS) is initialized.

* The DTV for the dynamic TLS implementation is allocated and filled in.

TODO(https://fxbug.dev/397084454): The new //sdk/lib/dl TLS runtime

does not require a bespoke ABI contract for a DTV.

The name string will become the ZX_PROP_NAME used for the VMO, and must

not be empty. The VMAR handles are saved and used for destruction, so

they must remain valid for the lifetime of the object.

The returned Thread* points somewhere inside the thread area block owned

by this ThreadStorage object, which also contains the static TLS area

already initialized with all the Initial Exec TLS data. The ABI rules

govern where that is in relation to the thread pointer ($tp) and thereby,

indirectly, where the TCB lies relative to $tp. (Note that here we

consider the Fuchsia Compiler ABI

<zircon

/tls.h> fixed slots, as well as

the $tp->self pointer on x86, to be part of the TCB--at one end of it or

the other--though nothing else about the TCB is part of any public ABI.)

Defined at line 314 of file ../../sdk/lib/c/threads/thread-storage-allocate.cc

void FreeStacks ()

This frees just the blocks for all the stacks, leaving the thread block

(where the Thread object itself resides) intact until destruction.

Defined at line 29 of file ../../sdk/lib/c/threads/thread-storage.cc

ThreadStorage FromThread (Thread & thread, bool take_thread_block)

This moves ownership of the ThreadStorage out of the Thread, making it

possible to destroy the Thread before destroying the ThreadStorage makes

its memory inaccessible. (When Thread becomes a true C++ type, this will

be replaced with plain move-construction from its ThreadStorage member.)

If take_thread_block is false, leave the thread block intact.

Defined at line 50 of file ../../sdk/lib/c/threads/thread-storage.cc

void ToThread (Thread & thread)

This moves ownership from this ThreadStorage into the Thread. (When

Thread becomes a true C++ type, this will be replaced with plain

move-assignment to its ThreadStorage member.)

Defined at line 90 of file ../../sdk/lib/c/threads/thread-storage.cc

void AssertLive ()

Assert that this ThreadStorage looks like the result of a successful

Allocate(), possibly after FreeStacks() has been called.

Defined at line 109 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

std::span<uint64_t> ThreadMachineStack (const Thread & thread)

These recover those spans from a Thread without modifying it. (When

Thread becomes a true C++ type, these can be removed in favor of just

using the methods above on the ThreadStorage member in Thread.)

Defined at line 112 of file ../../sdk/lib/c/threads/thread-storage.cc

std::span<uint64_t> ThreadUnsafeStack (const Thread & thread)

Defined at line 117 of file ../../sdk/lib/c/threads/thread-storage.cc

std::span<uint64_t> ThreadShadowCallstack (const Thread & thread)

Defined at line 125 of file ../../sdk/lib/c/threads/thread-storage.cc

uint64_t * machine_sp ()

This returns the initial value for the machine SP. This is always the

limit of the stack, where a push (`*--sp = ...`) will be the first thing

done. This makes it appropriate for a call site, and on most machines for

the entry to a C function. But on x86 it needs a return address pushed

before it can be used at a C function's entry point.

Defined at line 131 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

std::span<std::byte> ThreadThreadBlock (const Thread & thread)

Defined at line 133 of file ../../sdk/lib/c/threads/thread-storage.cc

uint64_t * unsafe_sp ()

This returns the initial value for the unsafe SP. This is always the

limit of the stack, which is always the protocol for function entry.

(This is already stored at $tp + ZX_TLS_UNSAFE_SP_OFFSET, too.)

Defined at line 136 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

uint64_t * shadow_call_sp ()

This returns the initial value for the shadow call stack pointer.

That stack grows up, so the next operation will be `*sp++ = ...`.

Defined at line 140 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

std::span<uint64_t> machine_stack ()

These return each entire stack as a span.

Defined at line 144 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

std::span<uint64_t> unsafe_stack ()

Defined at line 148 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

std::span<uint64_t> shadow_call_stack ()

Defined at line 152 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

std::span<std::byte> thread_block ()

Defined at line 156 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

PageRoundedSize stack_size ()

Defined at line 172 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

PageRoundedSize guard_size ()

Defined at line 173 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

template <auto&& block>
void CommitBlock (auto && block)

This is only used inside the Allocate() implementation, but it's public so

it can be used in a concept.

Defined at line 177 of file ../../sdk/lib/c/startup/../threads/thread-storage.h

Records