Lines 37-42
use rustc_target::spec::{MergeFunctions, SanitizerSet};
Link Here
|
37 |
use std::any::Any; |
37 |
use std::any::Any; |
38 |
use std::fs; |
38 |
use std::fs; |
39 |
use std::io; |
39 |
use std::io; |
|
|
40 |
use std::marker::PhantomData; |
40 |
use std::mem; |
41 |
use std::mem; |
41 |
use std::path::{Path, PathBuf}; |
42 |
use std::path::{Path, PathBuf}; |
42 |
use std::str; |
43 |
use std::str; |
Lines 473-482
pub fn start_async_codegen<B: ExtraBackendMethods>(
Link Here
|
473 |
metadata_module, |
474 |
metadata_module, |
474 |
crate_info, |
475 |
crate_info, |
475 |
|
476 |
|
476 |
coordinator_send, |
|
|
477 |
codegen_worker_receive, |
477 |
codegen_worker_receive, |
478 |
shared_emitter_main, |
478 |
shared_emitter_main, |
479 |
future: coordinator_thread, |
479 |
coordinator: Coordinator { |
|
|
480 |
sender: coordinator_send, |
481 |
future: Some(coordinator_thread), |
482 |
phantom: PhantomData, |
483 |
}, |
480 |
output_filenames: tcx.output_filenames(()).clone(), |
484 |
output_filenames: tcx.output_filenames(()).clone(), |
481 |
} |
485 |
} |
482 |
} |
486 |
} |
Lines 1245-1250
fn start_executing_work<B: ExtraBackendMethods>(
Link Here
|
1245 |
// work to be done. |
1249 |
// work to be done. |
1246 |
while !codegen_done |
1250 |
while !codegen_done |
1247 |
|| running > 0 |
1251 |
|| running > 0 |
|
|
1252 |
|| main_thread_worker_state == MainThreadWorkerState::LLVMing |
1248 |
|| (!codegen_aborted |
1253 |
|| (!codegen_aborted |
1249 |
&& !(work_items.is_empty() |
1254 |
&& !(work_items.is_empty() |
1250 |
&& needs_fat_lto.is_empty() |
1255 |
&& needs_fat_lto.is_empty() |
Lines 1464-1470
fn start_executing_work<B: ExtraBackendMethods>(
Link Here
|
1464 |
assert!(!codegen_aborted); |
1469 |
assert!(!codegen_aborted); |
1465 |
codegen_done = true; |
1470 |
codegen_done = true; |
1466 |
codegen_aborted = true; |
1471 |
codegen_aborted = true; |
1467 |
assert_eq!(main_thread_worker_state, MainThreadWorkerState::Codegenning); |
|
|
1468 |
} |
1472 |
} |
1469 |
Message::Done { result: Ok(compiled_module), worker_id } => { |
1473 |
Message::Done { result: Ok(compiled_module), worker_id } => { |
1470 |
free_worker(worker_id); |
1474 |
free_worker(worker_id); |
Lines 1511-1516
fn start_executing_work<B: ExtraBackendMethods>(
Link Here
|
1511 |
} |
1515 |
} |
1512 |
} |
1516 |
} |
1513 |
|
1517 |
|
|
|
1518 |
if codegen_aborted { |
1519 |
return Err(()); |
1520 |
} |
1521 |
|
1514 |
let needs_link = mem::take(&mut needs_link); |
1522 |
let needs_link = mem::take(&mut needs_link); |
1515 |
if !needs_link.is_empty() { |
1523 |
if !needs_link.is_empty() { |
1516 |
assert!(compiled_modules.is_empty()); |
1524 |
assert!(compiled_modules.is_empty()); |
Lines 1800-1815
impl SharedEmitterMain {
Link Here
|
1800 |
} |
1808 |
} |
1801 |
} |
1809 |
} |
1802 |
|
1810 |
|
|
|
1811 |
pub struct Coordinator<B: ExtraBackendMethods> { |
1812 |
pub sender: Sender<Box<dyn Any + Send>>, |
1813 |
future: Option<thread::JoinHandle<Result<CompiledModules, ()>>>, |
1814 |
// Only used for the Message type. |
1815 |
phantom: PhantomData<B>, |
1816 |
} |
1817 |
|
1818 |
impl<B: ExtraBackendMethods> Coordinator<B> { |
1819 |
fn join(mut self) -> std::thread::Result<Result<CompiledModules, ()>> { |
1820 |
self.future.take().unwrap().join() |
1821 |
} |
1822 |
} |
1823 |
|
1824 |
impl<B: ExtraBackendMethods> Drop for Coordinator<B> { |
1825 |
fn drop(&mut self) { |
1826 |
if let Some(future) = self.future.take() { |
1827 |
// If we haven't joined yet, signal to the coordinator that it should spawn no more |
1828 |
// work, and wait for worker threads to finish. |
1829 |
drop(self.sender.send(Box::new(Message::CodegenAborted::<B>))); |
1830 |
drop(future.join()); |
1831 |
} |
1832 |
} |
1833 |
} |
1834 |
|
1803 |
pub struct OngoingCodegen<B: ExtraBackendMethods> { |
1835 |
pub struct OngoingCodegen<B: ExtraBackendMethods> { |
1804 |
pub backend: B, |
1836 |
pub backend: B, |
1805 |
pub metadata: EncodedMetadata, |
1837 |
pub metadata: EncodedMetadata, |
1806 |
pub metadata_module: Option<CompiledModule>, |
1838 |
pub metadata_module: Option<CompiledModule>, |
1807 |
pub crate_info: CrateInfo, |
1839 |
pub crate_info: CrateInfo, |
1808 |
pub coordinator_send: Sender<Box<dyn Any + Send>>, |
|
|
1809 |
pub codegen_worker_receive: Receiver<Message<B>>, |
1840 |
pub codegen_worker_receive: Receiver<Message<B>>, |
1810 |
pub shared_emitter_main: SharedEmitterMain, |
1841 |
pub shared_emitter_main: SharedEmitterMain, |
1811 |
pub future: thread::JoinHandle<Result<CompiledModules, ()>>, |
|
|
1812 |
pub output_filenames: Arc<OutputFilenames>, |
1842 |
pub output_filenames: Arc<OutputFilenames>, |
|
|
1843 |
pub coordinator: Coordinator<B>, |
1813 |
} |
1844 |
} |
1814 |
|
1845 |
|
1815 |
impl<B: ExtraBackendMethods> OngoingCodegen<B> { |
1846 |
impl<B: ExtraBackendMethods> OngoingCodegen<B> { |
Lines 1817-1824
impl<B: ExtraBackendMethods> OngoingCodegen<B> {
Link Here
|
1817 |
let _timer = sess.timer("finish_ongoing_codegen"); |
1848 |
let _timer = sess.timer("finish_ongoing_codegen"); |
1818 |
|
1849 |
|
1819 |
self.shared_emitter_main.check(sess, true); |
1850 |
self.shared_emitter_main.check(sess, true); |
1820 |
let future = self.future; |
1851 |
let compiled_modules = sess.time("join_worker_thread", || match self.coordinator.join() { |
1821 |
let compiled_modules = sess.time("join_worker_thread", || match future.join() { |
|
|
1822 |
Ok(Ok(compiled_modules)) => compiled_modules, |
1852 |
Ok(Ok(compiled_modules)) => compiled_modules, |
1823 |
Ok(Err(())) => { |
1853 |
Ok(Err(())) => { |
1824 |
sess.abort_if_errors(); |
1854 |
sess.abort_if_errors(); |
Lines 1866-1891
impl<B: ExtraBackendMethods> OngoingCodegen<B> {
Link Here
|
1866 |
|
1896 |
|
1867 |
// These are generally cheap and won't throw off scheduling. |
1897 |
// These are generally cheap and won't throw off scheduling. |
1868 |
let cost = 0; |
1898 |
let cost = 0; |
1869 |
submit_codegened_module_to_llvm(&self.backend, &self.coordinator_send, module, cost); |
1899 |
submit_codegened_module_to_llvm(&self.backend, &self.coordinator.sender, module, cost); |
1870 |
} |
1900 |
} |
1871 |
|
1901 |
|
1872 |
pub fn codegen_finished(&self, tcx: TyCtxt<'_>) { |
1902 |
pub fn codegen_finished(&self, tcx: TyCtxt<'_>) { |
1873 |
self.wait_for_signal_to_codegen_item(); |
1903 |
self.wait_for_signal_to_codegen_item(); |
1874 |
self.check_for_errors(tcx.sess); |
1904 |
self.check_for_errors(tcx.sess); |
1875 |
drop(self.coordinator_send.send(Box::new(Message::CodegenComplete::<B>))); |
1905 |
drop(self.coordinator.sender.send(Box::new(Message::CodegenComplete::<B>))); |
1876 |
} |
|
|
1877 |
|
1878 |
/// Consumes this context indicating that codegen was entirely aborted, and |
1879 |
/// we need to exit as quickly as possible. |
1880 |
/// |
1881 |
/// This method blocks the current thread until all worker threads have |
1882 |
/// finished, and all worker threads should have exited or be real close to |
1883 |
/// exiting at this point. |
1884 |
pub fn codegen_aborted(self) { |
1885 |
// Signal to the coordinator it should spawn no more work and start |
1886 |
// shutdown. |
1887 |
drop(self.coordinator_send.send(Box::new(Message::CodegenAborted::<B>))); |
1888 |
drop(self.future.join()); |
1889 |
} |
1906 |
} |
1890 |
|
1907 |
|
1891 |
pub fn check_for_errors(&self, sess: &Session) { |
1908 |
pub fn check_for_errors(&self, sess: &Session) { |