[][src]Module sunrise_libuser::thread_local_storage

Thread Local Storage on x86

Usage

You declare a thread-local using the #[thread_local] attribute :

#![feature(thread_local)]
#[thread_local]
static MY_THREAD_LOCAL: core::cell::Cell<u8> = core::cell::Cell::new(42);

and access it as if it was a regular static, only that each thread will have its own view of the static.

The compiler is responsible for generating code that will access the right address, provided we configured TLS correctly.

Early startup

Note that you can't access a thread-local static before init_main_thread is called, because the thread-local area for the main thread isn't initialized yet, and this will likely result to a page fault or UB.

Inner workings

We implement the TLS according to conventions laid out by Ulrich Drepper's paper on TLS which is followed by LLVM and most compilers.

Since we're running on i386, we're following variant II.

Each thread's gs segment points to a thread local memory area where thread-local statics live. thread-local statics are simply accessed through an offset from gs.

The linker is in charge of creating an ELF segment of type PT_TLS where an initialization image for cpu local regions can be found, and is meant to be copy-pasted for every thread we create.

on SunriseOS

On Surnise, the area where gs points to is per-thread and user-controlled, we set it at the startup of every thread with the set_thread_area syscall.

The TLS initialisation image is supposed to be retrieved from our own program headers, which is a really weird design. Since we don't have access to our program headers, we instead use the linker to expose the following symbols:

Those symbols are the addresses of the initialization in our .tdata, so it can directly be copied.

dtv and __tls_get_addr

Since we don't do dynamic loading (yet ?), we know our TLS model will be static (either Initial Exec or Local Exec). Those models always access thread-locals directly via gs, and always short-circuit the dtv.

So we don't even bother allocating a dtv array at all. Neither do we define a __tls_get_addr function.

This might change in the future when we will want to support dynamic loading.

Structs

ThreadControlBlock

Elf TLS TCB

ThreadLocalStaticRegion

Represents an allocated thread local static region.

TlsElf

The Thread Local Storage manager for a thread

Statics

__tls_align__

The alignment of the TLS segment.

__tls_file_size__

The size of the TLS initialisation image in our .tdata.

__tls_init_image_addr__

The address of the start of the TLS initialisation image in our .tdata.

__tls_mem_size__

The total memsize of the TLS segment: .tdata + .tbss

Functions

tls_align_up

The round function, as defined in section 3.0: