Skip to content

Commit

Permalink
alloc-tls: Initial commit
Browse files Browse the repository at this point in the history
- Add alloc-tls crate
  - Supports detecting recursive initialization
  - Supports disabling TLS during dynamic load on Mac
- elfc: Support alloc-tls hooks for dynamic loading on Mac
- elfc: Don't run 'cargo test' in CI
- elfmalloc: Switch to using alloc-tls
- elfmalloc: Remove nightly feature
  • Loading branch information
joshlf committed Nov 16, 2017
1 parent bd10fe9 commit 522ae8d
Show file tree
Hide file tree
Showing 14 changed files with 698 additions and 294 deletions.
14 changes: 14 additions & 0 deletions alloc-tls/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!-- Copyright 2017 the authors. See the 'Copyright and license' section of the
README.md file at the top-level directory of this repository.
Licensed under the Apache License, Version 2.0 (the LICENSE-APACHE file) or
the MIT license (the LICENSE-MIT file) at your option. This file may not be
copied, modified, or distributed except according to those terms. -->

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).

## [Unreleased]
26 changes: 26 additions & 0 deletions alloc-tls/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2017 the authors. See the 'Copyright and license' section of the
# README.md file at the top-level directory of this repository.
#
# Licensed under the Apache License, Version 2.0 (the LICENSE-APACHE file) or
# the MIT license (the LICENSE-MIT file) at your option. This file may not be
# copied, modified, or distributed except according to those terms.

[package]
name = "alloc-tls"
version = "0.1.0"
authors = ["Joshua Liebow-Feeser <hello@joshlf.com>"]
license = "Apache-2.0/MIT"
description = "Thread-local storage that is safe for use in implementing global allocators."

keywords = ["thread-local", "allocator", "tls"]
categories = ["memory-management", "os"]

readme = "README.md"
documentation = "https://docs.rs/alloc-tls"
repository = "https://github.com/ezrosent/allocators-rs/tree/master/alloc-tls"

[features]
dylib = []

[dependencies]
alloc-fmt = { path = "../alloc-fmt" }
47 changes: 47 additions & 0 deletions alloc-tls/DESIGN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!-- Copyright 2017 the authors. See the 'Copyright and license' section of the
README.md file at the top-level directory of this repository.
Licensed under the Apache License, Version 2.0 (the LICENSE-APACHE file) or
the MIT license (the LICENSE-MIT file) at your option. This file may not be
copied, modified, or distributed except according to those terms. -->

Design of alloc-tls
===================

`alloc-tls` provides the `alloc_thread_local!` macro, a near-drop-in replacement
for the standard library's `thread_local!` macro that is safe for use in
implementing a global allocator.

Unlike `thread_local!`, `alloc_thread_local!` address the following issues
unique to implementing a global allocator:
- On platforms that support the `#[thread_local]` attribute, registering
destructors for types that implement `Drop` requires allocation. When a
thread-local is initialized from a call to an allocation function (`malloc`,
`free`, etc), this causes reentrancy. `alloc_thread_local!` can detect this.
- On Mac, it is not safe to access TLS while a dynamic library is being loaded.
When implementing a Mac dynamic library that provides a global allocator,
`alloc_thread_local!` can detect whether the library has been loaded or not,
and can avoid using TLS if `malloc` or other similar calls are made from the
loader itself during loading.

# Reentrancy

Reentrancy is addressed by expanding the number of states that a thread-local
variable can be in. Variables defined using the standard library's
`thread_local!` macro can be in one of three states - Uninitialized, Valid, and
Destroyed. In contrast, variables defined using `alloc_thread_local!` can be in
Uninitialized, Initializing (a new state), Initialized (equivalent to Valid), or
Dropped (equivalent to Destroyed). When a variable is accessed in the
Uninitialized state, it is moved into the Initializing state _before_ any
destructors are registered. This way, if registering destructors causes
allocation, any TLS access in that allocation will find the variable in the
Initializing state, and will thus be able to detect the reentrancy.

# Mac dynamic libraries

On Mac, dynamic libraries can specify library constructors - functions that are
called immediately after the library is loaded. When compiling a dynamic library
for Mac, `alloc-tls` defines a global `DYLD_LOADED` variable that is initialized
to false. A constructor is registered that sets it to true. When a TLS variable
is accessed, if `DYLD_LOADED` is false, the access fails, leaving it up to the
caller to use some slow path that doesn't rely on thread-local values.
29 changes: 29 additions & 0 deletions alloc-tls/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!-- Copyright 2017 the authors. See the 'Copyright and license' section of the
README.md file at the top-level directory of this repository.
Licensed under the Apache License, Version 2.0 (the LICENSE-APACHE file) or
the MIT license (the LICENSE-MIT file) at your option. This file may not be
copied, modified, or distributed except according to those terms. -->

alloc-tls
=========

`alloc-tls` provides the `alloc_thread_local!` macro, a near-drop-in replacement
for the standard library's `thread_local!` macro that is safe for use in
implementing a global allocator.

Unlike `thread_local!`, `alloc_thread_local!` address the following issues
unique to implementing a global allocator:
- On platforms that support the `#[thread_local]` attribute, registering
destructors for types that implement `Drop` requires allocation. When a
thread-local is initialized from a call to an allocation function (`malloc`,
`free`, etc), this causes reentrancy. `alloc_thread_local!` can detect this.
- On Mac, it is not safe to access TLS while a dynamic library is being loaded.
When implementing a Mac dynamic library that provides a global allocator,
`alloc_thread_local!` can detect whether the library has been loaded or not,
and can avoid using TLS if `malloc` or other similar calls are made from the
loader itself during loading.

Known limitations:
- `alloc-tls` does not currently support platforms that do not support the
`#[thread_local]` attribute.
Loading

0 comments on commit 522ae8d

Please sign in to comment.