From 3fa021d7ab36b59e877082d3150d626afabc8454 Mon Sep 17 00:00:00 2001
From: Joe Richey <joerichey@google.com>
Date: Wed, 10 Jul 2019 18:03:24 -0700
Subject: [PATCH] Add libc_thread_local cfg and unstable feature

---
 Cargo.toml                                  |  3 ++-
 README.md                                   |  3 +++
 build.rs                                    | 15 ++++++++++-----
 src/lib.rs                                  |  1 +
 src/unix/bsd/freebsdlike/dragonfly/errno.rs | 12 ++++++++++++
 src/unix/bsd/freebsdlike/dragonfly/mod.rs   | 16 +++++++---------
 6 files changed, 35 insertions(+), 15 deletions(-)
 create mode 100644 src/unix/bsd/freebsdlike/dragonfly/errno.rs

diff --git a/Cargo.toml b/Cargo.toml
index 120fbe19..cf54d45a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -26,8 +26,9 @@ rustc-std-workspace-core = { version = "1.0.0", optional = true }
 default = ["std"]
 std = []
 align = []
-rustc-dep-of-std = ['align', 'rustc-std-workspace-core']
+rustc-dep-of-std = ['align', 'rustc-std-workspace-core', 'unstable']
 extra_traits = []
+unstable = []
 # use_std is deprecated, use `std` instead
 use_std = [ 'std' ]
 
diff --git a/README.md b/README.md
index dc5ff04f..1af0b1c2 100644
--- a/README.md
+++ b/README.md
@@ -35,6 +35,9 @@ libc = "0.2"
 * `extra_traits`: all `struct`s implemented in `libc` are `Copy` and `Clone`.
   This feature derives `Debug`, `Eq`, `Hash`, and `PartialEq`.
 
+* `unstable`: enable currently unstable bindings. Right now, this just allows
+  bindings to `#[thread_local]` statics on certain platforms. Requires nightly.
+
 * **deprecated**: `use_std` is deprecated, and is equivalent to `std`.
 
 ## Rust version support
diff --git a/build.rs b/build.rs
index 84529400..c997e6ac 100644
--- a/build.rs
+++ b/build.rs
@@ -5,18 +5,18 @@ use std::str;
 fn main() {
     let rustc_minor_ver =
         rustc_minor_version().expect("Failed to get rustc version");
-    let rustc_dep_of_std =
-        std::env::var("CARGO_FEATURE_RUSTC_DEP_OF_STD").is_ok();
-    let align_cargo_feature = std::env::var("CARGO_FEATURE_ALIGN").is_ok();
+    let rustc_dep_of_std = env::var("CARGO_FEATURE_RUSTC_DEP_OF_STD").is_ok();
+    let align_cargo_feature = env::var("CARGO_FEATURE_ALIGN").is_ok();
+    let unstable_cargo_feature = env::var("CARGO_FEATURE_UNSTABLE").is_ok();
 
-    if std::env::var("CARGO_FEATURE_USE_STD").is_ok() {
+    if env::var("CARGO_FEATURE_USE_STD").is_ok() {
         println!(
             "cargo:warning=\"libc's use_std cargo feature is deprecated since libc 0.2.55; \
              please consider using the `std` cargo feature instead\""
         );
     }
 
-    if std::env::var("LIBC_CI").is_ok() {
+    if env::var("LIBC_CI").is_ok() {
         if let Some(12) = which_freebsd() {
             println!("cargo:rustc-cfg=freebsd12");
         }
@@ -53,6 +53,11 @@ fn main() {
     if rustc_minor_ver >= 33 || rustc_dep_of_std {
         println!("cargo:rustc-cfg=libc_packedN");
     }
+
+    // #[thread_local] is currently unstable
+    if unstable_cargo_feature || rustc_dep_of_std {
+        println!("cargo:rustc-cfg=libc_thread_local");
+    }
 }
 
 fn rustc_minor_version() -> Option<u32> {
diff --git a/src/lib.rs b/src/lib.rs
index 2dc42702..0f800cea 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -21,6 +21,7 @@
     feature = "rustc-dep-of-std",
     feature(cfg_target_vendor, link_cfg, no_core)
 )]
+#![cfg_attr(libc_thread_local, feature(thread_local))]
 // Enable extra lints:
 #![cfg_attr(feature = "extra_traits", deny(missing_debug_implementations))]
 #![deny(missing_copy_implementations, safe_packed_borrows)]
diff --git a/src/unix/bsd/freebsdlike/dragonfly/errno.rs b/src/unix/bsd/freebsdlike/dragonfly/errno.rs
new file mode 100644
index 00000000..e18036ad
--- /dev/null
+++ b/src/unix/bsd/freebsdlike/dragonfly/errno.rs
@@ -0,0 +1,12 @@
+// DragonFlyBSD's __error function is declared with "static inline", so it must
+// be implemented in the libc crate, as a pointer to a static thread_local.
+f! {
+    pub fn __error() -> *mut ::c_int {
+        &mut errno
+    }
+}
+
+extern {
+    #[thread_local]
+    pub static mut errno: ::c_int;
+}
diff --git a/src/unix/bsd/freebsdlike/dragonfly/mod.rs b/src/unix/bsd/freebsdlike/dragonfly/mod.rs
index d1e0a473..fc94fd3c 100644
--- a/src/unix/bsd/freebsdlike/dragonfly/mod.rs
+++ b/src/unix/bsd/freebsdlike/dragonfly/mod.rs
@@ -1036,18 +1036,9 @@ f! {
         (_CMSG_ALIGN(::mem::size_of::<::cmsghdr>()) +
             _CMSG_ALIGN(length as usize)) as ::c_uint
     }
-
-    #[cfg(libc_thread_local)]
-    pub fn __error() -> *mut ::c_int {
-        &mut errno
-    }
 }
 
 extern {
-    #[cfg(libc_thread_local)]
-    #[thread_local]
-    static mut errno: ::c_int;
-
     pub fn setgrent();
     pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int)
                     -> ::c_int;
@@ -1069,3 +1060,10 @@ extern {
     pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int;
     pub fn uname(buf: *mut ::utsname) -> ::c_int;
 }
+
+cfg_if! {
+    if #[cfg(libc_thread_local)] {
+        mod errno;
+        pub use self::errno::*;
+    }
+}
-- 
GitLab