Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are foreign thread-local global variables accessed in Rust?

For each of the following thread-local storage implementations, how can an external thread-local variable be accessed in Rust programs using the standard ffi mechanisms as exposed by the compiler or standard library?

  • C11
  • gcc's tls extension
  • pthreads
  • Windows TLS API
like image 259
Doe Avatar asked Feb 17 '17 04:02

Doe


People also ask

Can threads access global variables?

But to answer your question, any thread can access any global variable currently in scope. There is no notion of passing variables to a thread. It has a single global variable with a getter and setter function, any thread can call either the getter or setter at any time.

Can global variables be shared between threads?

But: No, threads do not share real local variables.

What is thread local rust?

This library provides the ThreadLocal type which allows a separate copy of an object to be used for each thread. This allows for per-object thread-local storage, unlike the standard library's thread_local! macro which only allows static thread-local storage. Per-thread objects are not destroyed when a thread exits.


1 Answers

Rust has a nightly feature, which allows linking to external thread local variables. The stabilization of the feature is tracked here.

C11 / GCC TLS extension

C11 defines the _Thread_local keyword to define thread-storage duration for an object. There also exists a thread_local macro alias.

GCC also implements a Thread Local extension which uses __thread as a keyword.

Linking to both an external C11 _Thread_local and a gcc __thread variable is possible using nightly (tested with rustc 1.17.0-nightly (0e7727795 2017-02-19) and gcc 5.4)

#![feature(thread_local)]

extern crate libc;

use libc::c_int;

#[link(name="test", kind="static")]
extern {
    #[thread_local]
    static mut test_global: c_int;
}

fn main() {
    let mut threads = vec![];
    for _ in 0..5 {
        let thread = std::thread::spawn(|| {
            unsafe {
                test_global += 1;
                println!("{}", test_global);
                test_global += 1;
            }
        });
        threads.push(thread);
    }

    for thread in threads {
        thread.join().unwrap();
    }
}

This allows get access to a variable declared as either of the following:

_Thread_local extern int test_global;
extern __local int test_global;

The output of the above Rust code will be:

1
1
1
1
1

Which is expected, when the variable is defined as thread local.

like image 157
rnstlr Avatar answered Nov 04 '22 01:11

rnstlr