Skip to content

Commit e75f6df

Browse files
committed
---
yaml --- r: 147839 b: refs/heads/try2 c: e34b1ea h: refs/heads/master i: 147837: 1320087 147835: f9e15ca 147831: ca78889 147823: 5b7e7f4 147807: 5f093a2 147775: a5a6c9b 147711: 28d05ce v: v3
1 parent 8a576a9 commit e75f6df

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+1792
-809
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 14a01b149a5a273abca9c32588935cb9acf207f9
8+
refs/heads/try2: e34b1eaccec107a76513d227fe4d6f15a6281d29
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/doc/rust.md

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3806,25 +3806,6 @@ As a convenience, the logging spec can also be set to a special pseudo-crate,
38063806
`::help`. In this case, when the application starts, the runtime will
38073807
simply output a list of loaded modules containing log expressions, then exit.
38083808

3809-
The Rust runtime itself generates logging information. The runtime's logs are
3810-
generated for a number of artificial modules in the `::rt` pseudo-crate,
3811-
and can be enabled just like the logs for any standard module. The full list
3812-
of runtime logging modules follows.
3813-
3814-
* `::rt::mem` Memory management
3815-
* `::rt::comm` Messaging and task communication
3816-
* `::rt::task` Task management
3817-
* `::rt::dom` Task scheduling
3818-
* `::rt::trace` Unused
3819-
* `::rt::cache` Type descriptor cache
3820-
* `::rt::upcall` Compiler-generated runtime calls
3821-
* `::rt::timer` The scheduler timer
3822-
* `::rt::gc` Garbage collection
3823-
* `::rt::stdlib` Functions used directly by the standard library
3824-
* `::rt::kern` The runtime kernel
3825-
* `::rt::backtrace` Log a backtrace on task failure
3826-
* `::rt::callback` Unused
3827-
38283809
#### Logging Expressions
38293810

38303811
Rust provides several macros to log information. Here's a simple Rust program

branches/try2/src/driver/driver.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,4 @@ extern mod this = "rustdoc";
1919
#[cfg(rustc)]
2020
extern mod this = "rustc";
2121

22-
#[cfg(rustdoc_ng)]
23-
extern mod this = "rustdoc_ng";
24-
2522
fn main() { this::main() }

branches/try2/src/etc/emacs/rust-mode.el

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@
5454
;; We don't want to indent out to the open bracket if the
5555
;; open bracket ends the line
5656
(when (not (looking-at "[[:blank:]]*\\(?://.*\\)?$"))
57-
(when (looking-at "[[:space:]]") (forward-to-word 1))
57+
(when (looking-at "[[:space:]]")
58+
(forward-word 1)
59+
(backward-word 1))
5860
(current-column))))
5961

6062
(defun rust-mode-indent-line ()

branches/try2/src/libextra/getopts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
//!
3232
//! ~~~{.rust}
3333
//! extern mod extra;
34-
//! use extra::getopts::*;
34+
//! use extra::getopts::{optopt,optflag,getopts,Opt};
3535
//! use std::os;
3636
//!
3737
//! fn do_work(inp: &str, out: Option<~str>) {

branches/try2/src/libextra/time.rs

Lines changed: 96 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,16 @@
1212

1313
use std::io::Reader;
1414
use std::io::mem::BufReader;
15+
use std::libc;
1516
use std::num;
1617
use std::str;
1718

1819
static NSEC_PER_SEC: i32 = 1_000_000_000_i32;
1920

20-
pub mod rustrt {
21+
mod rustrt {
2122
use super::Tm;
2223

2324
extern {
24-
pub fn rust_get_time(sec: &mut i64, nsec: &mut i32);
25-
pub fn rust_precise_time_ns(ns: &mut u64);
2625
pub fn rust_tzset();
2726
pub fn rust_gmtime(sec: i64, nsec: i32, result: &mut Tm);
2827
pub fn rust_localtime(sec: i64, nsec: i32, result: &mut Tm);
@@ -31,6 +30,31 @@ pub mod rustrt {
3130
}
3231
}
3332

33+
#[cfg(unix, not(target_os = "macos"))]
34+
mod imp {
35+
use std::libc::{c_int, timespec};
36+
37+
// Apparently android provides this in some other library?
38+
#[cfg(not(target_os = "android"))]
39+
#[link(name = "rt")]
40+
extern {}
41+
42+
extern {
43+
pub fn clock_gettime(clk_id: c_int, tp: *mut timespec) -> c_int;
44+
}
45+
46+
}
47+
#[cfg(target_os = "macos")]
48+
mod imp {
49+
use std::libc::{timeval, timezone, c_int, mach_timebase_info};
50+
51+
extern {
52+
pub fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int;
53+
pub fn mach_absolute_time() -> u64;
54+
pub fn mach_timebase_info(info: *mut mach_timebase_info) -> c_int;
55+
}
56+
}
57+
3458
/// A record specifying a time value in seconds and nanoseconds.
3559
3660

@@ -64,11 +88,45 @@ impl Ord for Timespec {
6488
*/
6589
pub fn get_time() -> Timespec {
6690
unsafe {
67-
let mut sec = 0i64;
68-
let mut nsec = 0i32;
69-
rustrt::rust_get_time(&mut sec, &mut nsec);
91+
let (sec, nsec) = os_get_time();
7092
return Timespec::new(sec, nsec);
7193
}
94+
95+
#[cfg(windows)]
96+
unsafe fn os_get_time() -> (i64, i32) {
97+
static NANOSECONDS_FROM_1601_TO_1970: u64 = 11644473600000000;
98+
99+
let mut time = libc::FILETIME {
100+
dwLowDateTime: 0,
101+
dwHighDateTime: 0,
102+
};
103+
libc::GetSystemTimeAsFileTime(&mut time);
104+
105+
// A FILETIME contains a 64-bit value representing the number of
106+
// hectonanosecond (100-nanosecond) intervals since 1601-01-01T00:00:00Z.
107+
// http://support.microsoft.com/kb/167296/en-us
108+
let ns_since_1601 = ((time.dwHighDateTime as u64 << 32) |
109+
(time.dwLowDateTime as u64 << 0)) / 10;
110+
let ns_since_1970 = ns_since_1601 - NANOSECONDS_FROM_1601_TO_1970;
111+
112+
((ns_since_1970 / 1000000) as i64,
113+
((ns_since_1970 % 1000000) * 1000) as i32)
114+
}
115+
116+
#[cfg(target_os = "macos")]
117+
unsafe fn os_get_time() -> (i64, i32) {
118+
use std::ptr;
119+
let mut tv = libc::timeval { tv_sec: 0, tv_usec: 0 };
120+
imp::gettimeofday(&mut tv, ptr::mut_null());
121+
(tv.tv_sec as i64, tv.tv_usec * 1000)
122+
}
123+
124+
#[cfg(not(target_os = "macos"), not(windows))]
125+
unsafe fn os_get_time() -> (i64, i32) {
126+
let mut tv = libc::timespec { tv_sec: 0, tv_nsec: 0 };
127+
imp::clock_gettime(libc::CLOCK_REALTIME, &mut tv);
128+
(tv.tv_sec as i64, tv.tv_nsec as i32)
129+
}
72130
}
73131

74132

@@ -77,10 +135,38 @@ pub fn get_time() -> Timespec {
77135
* in nanoseconds since an unspecified epoch.
78136
*/
79137
pub fn precise_time_ns() -> u64 {
80-
unsafe {
81-
let mut ns = 0u64;
82-
rustrt::rust_precise_time_ns(&mut ns);
83-
ns
138+
return os_precise_time_ns();
139+
140+
#[cfg(windows)]
141+
fn os_precise_time_ns() -> u64 {
142+
let mut ticks_per_s = 0;
143+
assert_eq!(unsafe {
144+
libc::QueryPerformanceFrequency(&mut ticks_per_s)
145+
}, 1);
146+
let ticks_per_s = if ticks_per_s == 0 {1} else {ticks_per_s};
147+
let mut ticks = 0;
148+
assert_eq!(unsafe {
149+
libc::QueryPerformanceCounter(&mut ticks)
150+
}, 1);
151+
152+
return (ticks as u64 * 1000000000) / (ticks_per_s as u64);
153+
}
154+
155+
#[cfg(target_os = "macos")]
156+
fn os_precise_time_ns() -> u64 {
157+
let time = unsafe { imp::mach_absolute_time() };
158+
let mut info = libc::mach_timebase_info { numer: 0, denom: 0 };
159+
unsafe { imp::mach_timebase_info(&mut info); }
160+
return time * ((info.numer / info.denom) as u64);
161+
}
162+
163+
#[cfg(not(windows), not(target_os = "macos"))]
164+
fn os_precise_time_ns() -> u64 {
165+
let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0 };
166+
unsafe {
167+
imp::clock_gettime(libc::CLOCK_MONOTONIC, &mut ts);
168+
}
169+
return (ts.tv_sec as u64) * 1000000000 + (ts.tv_nsec as u64)
84170
}
85171
}
86172

branches/try2/src/libgreen/lib.rs

Lines changed: 77 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,20 @@
2525
// NB this does *not* include globs, please keep it that way.
2626
#[feature(macro_rules)];
2727

28+
// Allow check-stage0-green for now
29+
#[cfg(test, stage0)] extern mod green;
30+
2831
use std::os;
2932
use std::rt::crate_map;
30-
use std::rt::local::Local;
3133
use std::rt::rtio;
32-
use std::rt::task::Task;
3334
use std::rt::thread::Thread;
3435
use std::rt;
3536
use std::sync::atomics::{SeqCst, AtomicUint, INIT_ATOMIC_UINT};
3637
use std::sync::deque;
3738
use std::task::TaskOpts;
3839
use std::util;
3940
use std::vec;
41+
use std::sync::arc::UnsafeArc;
4042

4143
use sched::{Shutdown, Scheduler, SchedHandle, TaskFromFriend, NewNeighbor};
4244
use sleeper_list::SleeperList;
@@ -118,14 +120,6 @@ pub fn run(main: proc()) -> int {
118120
os::set_exit_status(rt::DEFAULT_ERROR_CODE);
119121
}
120122

121-
// Once the main task has exited and we've set our exit code, wait for all
122-
// spawned sub-tasks to finish running. This is done to allow all schedulers
123-
// to remain active while there are still tasks possibly running.
124-
unsafe {
125-
let mut task = Local::borrow(None::<Task>);
126-
task.get().wait_for_other_tasks();
127-
}
128-
129123
// Now that we're sure all tasks are dead, shut down the pool of schedulers,
130124
// waiting for them all to return.
131125
pool.shutdown();
@@ -164,6 +158,17 @@ pub struct SchedPool {
164158
priv deque_pool: deque::BufferPool<~task::GreenTask>,
165159
priv sleepers: SleeperList,
166160
priv factory: fn() -> ~rtio::EventLoop,
161+
priv task_state: TaskState,
162+
priv tasks_done: Port<()>,
163+
}
164+
165+
/// This is an internal state shared among a pool of schedulers. This is used to
166+
/// keep track of how many tasks are currently running in the pool and then
167+
/// sending on a channel once the entire pool has been drained of all tasks.
168+
#[deriving(Clone)]
169+
struct TaskState {
170+
cnt: UnsafeArc<AtomicUint>,
171+
done: SharedChan<()>,
167172
}
168173

169174
impl SchedPool {
@@ -182,6 +187,7 @@ impl SchedPool {
182187
assert!(nscheds > 0);
183188

184189
// The pool of schedulers that will be returned from this function
190+
let (p, state) = TaskState::new();
185191
let mut pool = SchedPool {
186192
threads: ~[],
187193
handles: ~[],
@@ -192,6 +198,8 @@ impl SchedPool {
192198
deque_pool: deque::BufferPool::new(),
193199
next_friend: 0,
194200
factory: factory,
201+
task_state: state,
202+
tasks_done: p,
195203
};
196204

197205
// Create a work queue for each scheduler, ntimes. Create an extra
@@ -210,21 +218,30 @@ impl SchedPool {
210218
(pool.factory)(),
211219
worker,
212220
pool.stealers.clone(),
213-
pool.sleepers.clone());
221+
pool.sleepers.clone(),
222+
pool.task_state.clone());
214223
pool.handles.push(sched.make_handle());
215224
let sched = sched;
216-
pool.threads.push(do Thread::start {
217-
sched.bootstrap();
218-
});
225+
pool.threads.push(do Thread::start { sched.bootstrap(); });
219226
}
220227

221228
return pool;
222229
}
223230

231+
/// Creates a new task configured to run inside of this pool of schedulers.
232+
/// This is useful to create a task which can then be sent to a specific
233+
/// scheduler created by `spawn_sched` (and possibly pin it to that
234+
/// scheduler).
224235
pub fn task(&mut self, opts: TaskOpts, f: proc()) -> ~GreenTask {
225236
GreenTask::configure(&mut self.stack_pool, opts, f)
226237
}
227238

239+
/// Spawns a new task into this pool of schedulers, using the specified
240+
/// options to configure the new task which is spawned.
241+
///
242+
/// New tasks are spawned in a round-robin fashion to the schedulers in this
243+
/// pool, but tasks can certainly migrate among schedulers once they're in
244+
/// the pool.
228245
pub fn spawn(&mut self, opts: TaskOpts, f: proc()) {
229246
let task = self.task(opts, f);
230247

@@ -262,7 +279,8 @@ impl SchedPool {
262279
(self.factory)(),
263280
worker,
264281
self.stealers.clone(),
265-
self.sleepers.clone());
282+
self.sleepers.clone(),
283+
self.task_state.clone());
266284
let ret = sched.make_handle();
267285
self.handles.push(sched.make_handle());
268286
let sched = sched;
@@ -271,9 +289,28 @@ impl SchedPool {
271289
return ret;
272290
}
273291

292+
/// Consumes the pool of schedulers, waiting for all tasks to exit and all
293+
/// schedulers to shut down.
294+
///
295+
/// This function is required to be called in order to drop a pool of
296+
/// schedulers, it is considered an error to drop a pool without calling
297+
/// this method.
298+
///
299+
/// This only waits for all tasks in *this pool* of schedulers to exit, any
300+
/// native tasks or extern pools will not be waited on
274301
pub fn shutdown(mut self) {
275302
self.stealers = ~[];
276303

304+
// Wait for everyone to exit. We may have reached a 0-task count
305+
// multiple times in the past, meaning there could be several buffered
306+
// messages on the `tasks_done` port. We're guaranteed that after *some*
307+
// message the current task count will be 0, so we just receive in a
308+
// loop until everything is totally dead.
309+
while self.task_state.active() {
310+
self.tasks_done.recv();
311+
}
312+
313+
// Now that everyone's gone, tell everything to shut down.
277314
for mut handle in util::replace(&mut self.handles, ~[]).move_iter() {
278315
handle.send(Shutdown);
279316
}
@@ -283,6 +320,31 @@ impl SchedPool {
283320
}
284321
}
285322

323+
impl TaskState {
324+
fn new() -> (Port<()>, TaskState) {
325+
let (p, c) = SharedChan::new();
326+
(p, TaskState {
327+
cnt: UnsafeArc::new(AtomicUint::new(0)),
328+
done: c,
329+
})
330+
}
331+
332+
fn increment(&mut self) {
333+
unsafe { (*self.cnt.get()).fetch_add(1, SeqCst); }
334+
}
335+
336+
fn active(&self) -> bool {
337+
unsafe { (*self.cnt.get()).load(SeqCst) != 0 }
338+
}
339+
340+
fn decrement(&mut self) {
341+
let prev = unsafe { (*self.cnt.get()).fetch_sub(1, SeqCst) };
342+
if prev == 1 {
343+
self.done.send(());
344+
}
345+
}
346+
}
347+
286348
impl Drop for SchedPool {
287349
fn drop(&mut self) {
288350
if self.threads.len() > 0 {

0 commit comments

Comments
 (0)