]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/util.rs
Merge pull request #20510 from tshepang/patch-6
[rust.git] / src / libstd / rt / util.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 //
11 // ignore-lexer-test FIXME #15677
12
13 use prelude::v1::*;
14
15 use cmp;
16 use fmt;
17 use intrinsics;
18 use libc::{self, uintptr_t};
19 use os;
20 use slice;
21 use str;
22 use sync::atomic::{mod, Ordering};
23
24 /// Dynamically inquire about whether we're running under V.
25 /// You should usually not use this unless your test definitely
26 /// can't run correctly un-altered. Valgrind is there to help
27 /// you notice weirdness in normal, un-doctored code paths!
28 pub fn running_on_valgrind() -> bool {
29     extern {
30         fn rust_running_on_valgrind() -> uintptr_t;
31     }
32     unsafe { rust_running_on_valgrind() != 0 }
33 }
34
35 /// Valgrind has a fixed-sized array (size around 2000) of segment descriptors
36 /// wired into it; this is a hard limit and requires rebuilding valgrind if you
37 /// want to go beyond it. Normally this is not a problem, but in some tests, we
38 /// produce a lot of threads casually.  Making lots of threads alone might not
39 /// be a problem _either_, except on OSX, the segments produced for new threads
40 /// _take a while_ to get reclaimed by the OS. Combined with the fact that libuv
41 /// schedulers fork off a separate thread for polling fsevents on OSX, we get a
42 /// perfect storm of creating "too many mappings" for valgrind to handle when
43 /// running certain stress tests in the runtime.
44 pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool {
45     (cfg!(target_os="macos")) && running_on_valgrind()
46 }
47
48 pub fn min_stack() -> uint {
49     static MIN: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT;
50     match MIN.load(Ordering::SeqCst) {
51         0 => {}
52         n => return n - 1,
53     }
54     let amt = os::getenv("RUST_MIN_STACK").and_then(|s| s.parse());
55     let amt = amt.unwrap_or(2 * 1024 * 1024);
56     // 0 is our sentinel value, so ensure that we'll never see 0 after
57     // initialization has run
58     MIN.store(amt + 1, Ordering::SeqCst);
59     return amt;
60 }
61
62 /// Get's the number of scheduler threads requested by the environment
63 /// either `RUST_THREADS` or `num_cpus`.
64 pub fn default_sched_threads() -> uint {
65     match os::getenv("RUST_THREADS") {
66         Some(nstr) => {
67             let opt_n: Option<uint> = nstr.parse();
68             match opt_n {
69                 Some(n) if n > 0 => n,
70                 _ => panic!("`RUST_THREADS` is `{}`, should be a positive integer", nstr)
71             }
72         }
73         None => {
74             if limit_thread_creation_due_to_osx_and_valgrind() {
75                 1
76             } else {
77                 os::num_cpus()
78             }
79         }
80     }
81 }
82
83 // Indicates whether we should perform expensive sanity checks, including rtassert!
84 //
85 // FIXME: Once the runtime matures remove the `true` below to turn off rtassert,
86 //        etc.
87 pub const ENFORCE_SANITY: bool = true || !cfg!(rtopt) || cfg!(rtdebug) ||
88                                   cfg!(rtassert);
89
90 #[allow(missing_copy_implementations)]
91 pub struct Stdio(libc::c_int);
92
93 #[allow(non_upper_case_globals)]
94 pub const Stdout: Stdio = Stdio(libc::STDOUT_FILENO);
95 #[allow(non_upper_case_globals)]
96 pub const Stderr: Stdio = Stdio(libc::STDERR_FILENO);
97
98 impl Stdio {
99     pub fn write_bytes(&mut self, data: &[u8]) {
100         #[cfg(unix)]
101         type WriteLen = libc::size_t;
102         #[cfg(windows)]
103         type WriteLen = libc::c_uint;
104         unsafe {
105             let Stdio(fd) = *self;
106             libc::write(fd,
107                         data.as_ptr() as *const libc::c_void,
108                         data.len() as WriteLen);
109         }
110     }
111 }
112
113 impl fmt::Writer for Stdio {
114     fn write_str(&mut self, data: &str) -> fmt::Result {
115         self.write_bytes(data.as_bytes());
116         Ok(()) // yes, we're lying
117     }
118 }
119
120 pub fn dumb_print(args: fmt::Arguments) {
121     let _ = Stderr.write_fmt(args);
122 }
123
124 pub fn abort(args: fmt::Arguments) -> ! {
125     use fmt::Writer;
126
127     struct BufWriter<'a> {
128         buf: &'a mut [u8],
129         pos: uint,
130     }
131     impl<'a> fmt::Writer for BufWriter<'a> {
132         fn write_str(&mut self, bytes: &str) -> fmt::Result {
133             let left = self.buf.slice_from_mut(self.pos);
134             let to_write = bytes.as_bytes()[..cmp::min(bytes.len(), left.len())];
135             slice::bytes::copy_memory(left, to_write);
136             self.pos += to_write.len();
137             Ok(())
138         }
139     }
140
141     // Convert the arguments into a stack-allocated string
142     let mut msg = [0u8; 512];
143     let mut w = BufWriter { buf: &mut msg, pos: 0 };
144     let _ = write!(&mut w, "{}", args);
145     let msg = str::from_utf8(w.buf[mut ..w.pos]).unwrap_or("aborted");
146     let msg = if msg.is_empty() {"aborted"} else {msg};
147
148     // Give some context to the message
149     let hash = msg.bytes().fold(0, |accum, val| accum + (val as uint) );
150     let quote = match hash % 10 {
151         0 => "
152 It was from the artists and poets that the pertinent answers came, and I
153 know that panic would have broken loose had they been able to compare notes.
154 As it was, lacking their original letters, I half suspected the compiler of
155 having asked leading questions, or of having edited the correspondence in
156 corroboration of what he had latently resolved to see.",
157         1 => "
158 There are not many persons who know what wonders are opened to them in the
159 stories and visions of their youth; for when as children we listen and dream,
160 we think but half-formed thoughts, and when as men we try to remember, we are
161 dulled and prosaic with the poison of life. But some of us awake in the night
162 with strange phantasms of enchanted hills and gardens, of fountains that sing
163 in the sun, of golden cliffs overhanging murmuring seas, of plains that stretch
164 down to sleeping cities of bronze and stone, and of shadowy companies of heroes
165 that ride caparisoned white horses along the edges of thick forests; and then
166 we know that we have looked back through the ivory gates into that world of
167 wonder which was ours before we were wise and unhappy.",
168         2 => "
169 Instead of the poems I had hoped for, there came only a shuddering blackness
170 and ineffable loneliness; and I saw at last a fearful truth which no one had
171 ever dared to breathe before — the unwhisperable secret of secrets — The fact
172 that this city of stone and stridor is not a sentient perpetuation of Old New
173 York as London is of Old London and Paris of Old Paris, but that it is in fact
174 quite dead, its sprawling body imperfectly embalmed and infested with queer
175 animate things which have nothing to do with it as it was in life.",
176         3 => "
177 The ocean ate the last of the land and poured into the smoking gulf, thereby
178 giving up all it had ever conquered. From the new-flooded lands it flowed
179 again, uncovering death and decay; and from its ancient and immemorial bed it
180 trickled loathsomely, uncovering nighted secrets of the years when Time was
181 young and the gods unborn. Above the waves rose weedy remembered spires. The
182 moon laid pale lilies of light on dead London, and Paris stood up from its damp
183 grave to be sanctified with star-dust. Then rose spires and monoliths that were
184 weedy but not remembered; terrible spires and monoliths of lands that men never
185 knew were lands...",
186         4 => "
187 There was a night when winds from unknown spaces whirled us irresistibly into
188 limitless vacuum beyond all thought and entity. Perceptions of the most
189 maddeningly untransmissible sort thronged upon us; perceptions of infinity
190 which at the time convulsed us with joy, yet which are now partly lost to my
191 memory and partly incapable of presentation to others.",
192         _ => "You've met with a terrible fate, haven't you?"
193     };
194     rterrln!("{}", "");
195     rterrln!("{}", quote);
196     rterrln!("{}", "");
197     rterrln!("fatal runtime error: {}", msg);
198     unsafe { intrinsics::abort(); }
199 }
200
201 pub unsafe fn report_overflow() {
202     use thread::Thread;
203
204     // See the message below for why this is not emitted to the
205     // ^ Where did the message below go?
206     // task's logger. This has the additional conundrum of the
207     // logger may not be initialized just yet, meaning that an FFI
208     // call would happen to initialized it (calling out to libuv),
209     // and the FFI call needs 2MB of stack when we just ran out.
210
211     rterrln!("\nthread '{}' has overflowed its stack",
212              Thread::current().name().unwrap_or("<unknown>"));
213 }