about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-01-30 12:02:53 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-01-30 12:02:53 -0800
commitb70ec4d9f019c1bd886f2f3dc0cd9da4d95804cb (patch)
tree1e6a2c18864490b00edd497eb326d6e1892d6e13 /src/libstd
parentb446c5b67994bd9822e958e3e26122543086c1bc (diff)
parent9ee972ca32b1f91eb6880e1bc9c8bb5a4faf1f29 (diff)
downloadrust-b70ec4d9f019c1bd886f2f3dc0cd9da4d95804cb.tar.gz
rust-b70ec4d9f019c1bd886f2f3dc0cd9da4d95804cb.zip
rollup merge of #21678: vojtechkral/threads-native-names
Fixes #10302

I really am not sure I'm doing this right, so here goes nothing...

Also testing this isn't easy. I don't have any other *nix boxes besides a Linux one.

Test code:

```rust
use std::thread;
use std::io::timer::sleep;
use std::time::duration::Duration;

fn make_thread<'a>(i: i64) -> thread::JoinGuard<'a, ()>
{
	thread::Builder::new().name(format!("MyThread{}", i).to_string()).scoped(move ||
	{
		println!("Start: {}", i);
		sleep(Duration::seconds(i));
		println!("End: {}", i);
	})
}

fn main()
{
	let mut guards = vec![make_thread(3)];

	for i in 4i64..16
	{
		guards.push(make_thread(i));
	}
}
```

GDB output on my machine:

```
(gdb) info threads
  Id   Target Id         Frame
  15   Thread 0x7fdfbb35f700 (LWP 23575) "MyThread3" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
  14   Thread 0x7fdfba7ff700 (LWP 23576) "MyThread4" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
  13   Thread 0x7fdfba5fe700 (LWP 23577) "MyThread5" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
  12   Thread 0x7fdfba3fd700 (LWP 23578) "MyThread6" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
  11   Thread 0x7fdfb8dfe700 (LWP 23580) "MyThread4" 0x00007fdfbb746193 in select () from /usr/lib/libc.so.6
  10   Thread 0x7fdfb8fff700 (LWP 23579) "MyThread7" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
  9    Thread 0x7fdfb8bfd700 (LWP 23581) "MyThread8" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
  8    Thread 0x7fdfb3fff700 (LWP 23582) "MyThread9" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
  7    Thread 0x7fdfb3dfe700 (LWP 23583) "MyThread10" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
  6    Thread 0x7fdfb3bfd700 (LWP 23584) "MyThread11" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
  5    Thread 0x7fdfb2bff700 (LWP 23585) "MyThread12" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
  4    Thread 0x7fdfb29fe700 (LWP 23586) "MyThread13" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
  3    Thread 0x7fdfb27fd700 (LWP 23587) "MyThread14" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
  2    Thread 0x7fdfb1bff700 (LWP 23588) "MyThread15" 0x00007fdfbbe35a8d in nanosleep () from /usr/lib/libpthread.so.0
* 1    Thread 0x7fdfbc411800 (LWP 23574) "threads" 0x00007fdfbbe2e505 in pthread_join () from /usr/lib/libpthread.so.0
```
(I'm not sure why one of the threads is duplicated, but it does that without my patch too...)
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/sys/common/thread_info.rs4
-rw-r--r--src/libstd/sys/unix/thread.rs43
-rw-r--r--src/libstd/sys/windows/thread.rs7
3 files changed, 52 insertions, 2 deletions
diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs
index 92b936e74f6..7c9758ca924 100644
--- a/src/libstd/sys/common/thread_info.rs
+++ b/src/libstd/sys/common/thread_info.rs
@@ -56,6 +56,10 @@ pub fn stack_guard() -> uint {
 
 pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) {
     THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
+    match thread.name() {
+        Some(name) => unsafe { ::sys::thread::set_name(name.as_slice()); },
+        None => {}
+    }
     THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
         stack_bounds: stack_bounds,
         stack_guard: stack_guard,
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index ac51b68795f..26a450b8599 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -17,6 +17,7 @@ use ptr;
 use libc::consts::os::posix01::{PTHREAD_CREATE_JOINABLE, PTHREAD_STACK_MIN};
 use libc;
 use thunk::Thunk;
+use ffi::CString;
 
 use sys_common::stack::RED_ZONE;
 use sys_common::thread::*;
@@ -206,6 +207,37 @@ pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread {
     native
 }
 
+#[cfg(any(target_os = "linux", target_os = "android"))]
+pub unsafe fn set_name(name: &str) {
+    // pthread_setname_np() since glibc 2.12
+    // availability autodetected via weak linkage
+    let cname = CString::from_slice(name.as_bytes());
+    type F = unsafe extern "C" fn(libc::pthread_t, *const libc::c_char) -> libc::c_int;
+    extern {
+        #[linkage = "extern_weak"]
+        static pthread_setname_np: *const ();
+    }
+    if !pthread_setname_np.is_null() {
+        unsafe {
+            mem::transmute::<*const (), F>(pthread_setname_np)(pthread_self(), cname.as_ptr());
+        }
+    }
+}
+
+#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+pub unsafe fn set_name(name: &str) {
+    // pthread_set_name_np() since almost forever on all BSDs
+    let cname = CString::from_slice(name.as_bytes());
+    pthread_set_name_np(pthread_self(), cname.as_ptr());
+}
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+pub unsafe fn set_name(name: &str) {
+    // pthread_setname_np() since OS X 10.6 and iOS 3.2
+    let cname = CString::from_slice(name.as_bytes());
+    pthread_setname_np(cname.as_ptr());
+}
+
 pub unsafe fn join(native: rust_thread) {
     assert_eq!(pthread_join(native, ptr::null_mut()), 0);
 }
@@ -246,7 +278,7 @@ fn min_stack_size(_: *const libc::pthread_attr_t) -> libc::size_t {
     PTHREAD_STACK_MIN
 }
 
-#[cfg(any(target_os = "linux"))]
+#[cfg(any(target_os = "linux", target_os = "android"))]
 extern {
     pub fn pthread_self() -> libc::pthread_t;
     pub fn pthread_getattr_np(native: libc::pthread_t,
@@ -258,11 +290,18 @@ extern {
                                  stacksize: *mut libc::size_t) -> libc::c_int;
 }
 
-#[cfg(target_os = "macos")]
+#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+extern {
+    pub fn pthread_self() -> libc::pthread_t;
+    fn pthread_set_name_np(tid: libc::pthread_t, name: *const libc::c_char);
+}
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
 extern {
     pub fn pthread_self() -> libc::pthread_t;
     pub fn pthread_get_stackaddr_np(thread: libc::pthread_t) -> *mut libc::c_void;
     pub fn pthread_get_stacksize_np(thread: libc::pthread_t) -> libc::size_t;
+    fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int;
 }
 
 extern {
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index 30707488b30..a94adcb3bc7 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -67,6 +67,13 @@ pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread {
     return ret;
 }
 
+pub unsafe fn set_name(_name: &str) {
+    // Windows threads are nameless
+    // The names in MSVC debugger are obtained using a "magic" exception,
+    // which requires a use of MS C++ extensions.
+    // See https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
+}
+
 pub unsafe fn join(native: rust_thread) {
     use libc::consts::os::extra::INFINITE;
     WaitForSingleObject(native, INFINITE);