summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2021-02-26 15:52:35 +0100
committerGitHub <noreply@github.com>2021-02-26 15:52:35 +0100
commit6b5e141999cc2350c0322cef9a0b569f2908d341 (patch)
tree4fbdae52705b7f7828ff03430c603bb4efd4f8f2 /compiler/rustc_codegen_ssa/src
parent75959fb3566f722dc141d112fab047c4c0dcb5c5 (diff)
parent9d3739d9cefe5ee38d695e8f1eab69a7422d9a21 (diff)
downloadrust-6b5e141999cc2350c0322cef9a0b569f2908d341.tar.gz
rust-6b5e141999cc2350c0322cef9a0b569f2908d341.zip
Rollup merge of #82535 - wesleywiser:wip_codegen_thread_names, r=nagisa
Set codegen thread names

Set names on threads spawned during codegen. Various debugging and profiling tools can take advantage of this to show a more useful identifier for threads.

For example, gdb will show thread names in `info threads`:

```
(gdb) info threads
  Id   Target Id                                          Frame
  1    Thread 0x7fffefa7ec40 (LWP 2905) "rustc"           __pthread_clockjoin_ex (threadid=140737214134016, thread_return=0x0, clockid=<optimized out>, abstime=<optimized out>, block=<optimized out>)
    at pthread_join_common.c:145
  2    Thread 0x7fffefa7b700 (LWP 2957) "rustc"           0x00007ffff125eaa8 in llvm::X86_MC::initLLVMToSEHAndCVRegMapping(llvm::MCRegisterInfo*) ()
   from /home/wesley/.rustup/toolchains/stage1/lib/librustc_driver-f866439e29074957.so
  3    Thread 0x7fffeef0f700 (LWP 3116) "rustc"           futex_wait_cancelable (private=0, expected=0, futex_word=0x7fffe8602ac8) at ../sysdeps/nptl/futex-internal.h:183
* 4    Thread 0x7fffeed0e700 (LWP 3123) "rustc"           rustc_codegen_ssa::back::write::spawn_work (cgcx=..., work=...) at /home/wesley/code/rust/rust/compiler/rustc_codegen_ssa/src/back/write.rs:1573
  6    Thread 0x7fffe113b700 (LWP 3150) "opt foof.7rcbfp" 0x00007ffff2940e62 in llvm::CallGraph::populateCallGraphNode(llvm::CallGraphNode*) ()
   from /home/wesley/.rustup/toolchains/stage1/lib/librustc_driver-f866439e29074957.so
  8    Thread 0x7fffe0d39700 (LWP 3158) "opt foof.7rcbfp" 0x00007fffefe8998e in malloc_consolidate (av=av@entry=0x7ffe2c000020) at malloc.c:4492
  9    Thread 0x7fffe0f3a700 (LWP 3162) "opt foof.7rcbfp" 0x00007fffefef27c4 in __libc_open64 (file=0x7fffe0f38608 "foof.foof.7rcbfp3g-cgu.6.rcgu.o", oflag=524865) at ../sysdeps/unix/sysv/linux/open64.c:48
(gdb)
```

and Windows Performance Analyzer will also show this information when profiling:

![image](https://user-images.githubusercontent.com/831192/109231017-d311f780-7793-11eb-8072-ab836a830e90.png)
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs124
1 files changed, 77 insertions, 47 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index d931c57fba2..7b8ce157fc2 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -712,6 +712,33 @@ impl<B: WriteBackendMethods> WorkItem<B> {
             }
         }
     }
+
+    /// Generate a short description of this work item suitable for use as a thread name.
+    fn short_description(&self) -> String {
+        // `pthread_setname()` on *nix is limited to 15 characters and longer names are ignored.
+        // Use very short descriptions in this case to maximize the space available for the module name.
+        // Windows does not have that limitation so use slightly more descriptive names there.
+        match self {
+            WorkItem::Optimize(m) => {
+                #[cfg(windows)]
+                return format!("optimize module {}", m.name);
+                #[cfg(not(windows))]
+                return format!("opt {}", m.name);
+            }
+            WorkItem::CopyPostLtoArtifacts(m) => {
+                #[cfg(windows)]
+                return format!("copy LTO artifacts for {}", m.name);
+                #[cfg(not(windows))]
+                return format!("copy {}", m.name);
+            }
+            WorkItem::LTO(m) => {
+                #[cfg(windows)]
+                return format!("LTO module {}", m.name());
+                #[cfg(not(windows))]
+                return format!("LTO {}", m.name());
+            }
+        }
+    }
 }
 
 enum WorkItemResult<B: WriteBackendMethods> {
@@ -1609,56 +1636,59 @@ fn start_executing_work<B: ExtraBackendMethods>(
 pub struct WorkerFatalError;
 
 fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>) {
-    thread::spawn(move || {
-        // Set up a destructor which will fire off a message that we're done as
-        // we exit.
-        struct Bomb<B: ExtraBackendMethods> {
-            coordinator_send: Sender<Box<dyn Any + Send>>,
-            result: Option<Result<WorkItemResult<B>, FatalError>>,
-            worker_id: usize,
-        }
-        impl<B: ExtraBackendMethods> Drop for Bomb<B> {
-            fn drop(&mut self) {
-                let worker_id = self.worker_id;
-                let msg = match self.result.take() {
-                    Some(Ok(WorkItemResult::Compiled(m))) => {
-                        Message::Done::<B> { result: Ok(m), worker_id }
-                    }
-                    Some(Ok(WorkItemResult::NeedsLink(m))) => {
-                        Message::NeedsLink::<B> { module: m, worker_id }
-                    }
-                    Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
-                        Message::NeedsFatLTO::<B> { result: m, worker_id }
-                    }
-                    Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
-                        Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
-                    }
-                    Some(Err(FatalError)) => {
-                        Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
-                    }
-                    None => Message::Done::<B> { result: Err(None), worker_id },
-                };
-                drop(self.coordinator_send.send(Box::new(msg)));
+    let builder = thread::Builder::new().name(work.short_description());
+    builder
+        .spawn(move || {
+            // Set up a destructor which will fire off a message that we're done as
+            // we exit.
+            struct Bomb<B: ExtraBackendMethods> {
+                coordinator_send: Sender<Box<dyn Any + Send>>,
+                result: Option<Result<WorkItemResult<B>, FatalError>>,
+                worker_id: usize,
+            }
+            impl<B: ExtraBackendMethods> Drop for Bomb<B> {
+                fn drop(&mut self) {
+                    let worker_id = self.worker_id;
+                    let msg = match self.result.take() {
+                        Some(Ok(WorkItemResult::Compiled(m))) => {
+                            Message::Done::<B> { result: Ok(m), worker_id }
+                        }
+                        Some(Ok(WorkItemResult::NeedsLink(m))) => {
+                            Message::NeedsLink::<B> { module: m, worker_id }
+                        }
+                        Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
+                            Message::NeedsFatLTO::<B> { result: m, worker_id }
+                        }
+                        Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
+                            Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
+                        }
+                        Some(Err(FatalError)) => {
+                            Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
+                        }
+                        None => Message::Done::<B> { result: Err(None), worker_id },
+                    };
+                    drop(self.coordinator_send.send(Box::new(msg)));
+                }
             }
-        }
 
-        let mut bomb = Bomb::<B> {
-            coordinator_send: cgcx.coordinator_send.clone(),
-            result: None,
-            worker_id: cgcx.worker,
-        };
+            let mut bomb = Bomb::<B> {
+                coordinator_send: cgcx.coordinator_send.clone(),
+                result: None,
+                worker_id: cgcx.worker,
+            };
 
-        // Execute the work itself, and if it finishes successfully then flag
-        // ourselves as a success as well.
-        //
-        // Note that we ignore any `FatalError` coming out of `execute_work_item`,
-        // as a diagnostic was already sent off to the main thread - just
-        // surface that there was an error in this worker.
-        bomb.result = {
-            let _prof_timer = work.start_profiling(&cgcx);
-            Some(execute_work_item(&cgcx, work))
-        };
-    });
+            // Execute the work itself, and if it finishes successfully then flag
+            // ourselves as a success as well.
+            //
+            // Note that we ignore any `FatalError` coming out of `execute_work_item`,
+            // as a diagnostic was already sent off to the main thread - just
+            // surface that there was an error in this worker.
+            bomb.result = {
+                let _prof_timer = work.start_profiling(&cgcx);
+                Some(execute_work_item(&cgcx, work))
+            };
+        })
+        .expect("failed to spawn thread");
 }
 
 enum SharedEmitterMessage {