@@ -60,7 +60,21 @@ Several modules in `core` are clients of `rt`:
60
60
#[ deny( unused_variable) ] ;
61
61
62
62
use cell:: Cell ;
63
+ use clone:: Clone ;
64
+ use container:: Container ;
65
+ use from_str:: FromStr ;
66
+ use iterator:: IteratorUtil ;
67
+ use option:: { Some , None } ;
68
+ use os;
63
69
use ptr:: RawPtr ;
70
+ use uint;
71
+ use rt:: sched:: { Scheduler , Coroutine , Shutdown } ;
72
+ use rt:: sleeper_list:: SleeperList ;
73
+ use rt:: task:: Task ;
74
+ use rt:: thread:: Thread ;
75
+ use rt:: work_queue:: WorkQueue ;
76
+ use rt:: uv:: uvio:: UvEventLoop ;
77
+ use vec:: { OwnedVector , MutableVector } ;
64
78
65
79
/// The global (exchange) heap.
66
80
pub mod global_heap;
@@ -159,23 +173,8 @@ pub mod util;
159
173
/// The return value is used as the process return code. 0 on success, 101 on error.
160
174
pub fn start ( _argc : int , _argv : * * u8 , crate_map : * u8 , main : ~fn ( ) ) -> int {
161
175
162
- use self :: sched:: { Scheduler , Coroutine } ;
163
- use self :: work_queue:: WorkQueue ;
164
- use self :: uv:: uvio:: UvEventLoop ;
165
- use self :: sleeper_list:: SleeperList ;
166
-
167
176
init ( crate_map) ;
168
-
169
- let loop_ = ~UvEventLoop :: new ( ) ;
170
- let work_queue = WorkQueue :: new ( ) ;
171
- let sleepers = SleeperList :: new ( ) ;
172
- let mut sched = ~Scheduler :: new ( loop_, work_queue, sleepers) ;
173
- sched. no_sleep = true ;
174
- let main_task = ~Coroutine :: new_root ( & mut sched. stack_pool , main) ;
175
-
176
- sched. enqueue_task ( main_task) ;
177
- sched. run ( ) ;
178
-
177
+ run ( main) ;
179
178
cleanup ( ) ;
180
179
181
180
return 0 ;
@@ -191,6 +190,67 @@ pub fn cleanup() {
191
190
global_heap:: cleanup ( ) ;
192
191
}
193
192
193
+ pub fn run( main : ~fn ( ) ) {
194
+ let nthreads = match os:: getenv ( "RUST_THREADS" ) {
195
+ Some ( nstr) => FromStr :: from_str ( nstr) . get ( ) ,
196
+ None => unsafe {
197
+ // Using more threads than cores in test code
198
+ // to force the OS to preempt them frequently.
199
+ // Assuming that this help stress test concurrent types.
200
+ util:: num_cpus ( ) * 2
201
+ }
202
+ } ;
203
+
204
+ let sleepers = SleeperList :: new ( ) ;
205
+ let work_queue = WorkQueue :: new ( ) ;
206
+
207
+ let mut handles = ~[ ] ;
208
+ let mut scheds = ~[ ] ;
209
+
210
+ for uint:: range( 0 , nthreads) |_| {
211
+ let loop_ = ~UvEventLoop :: new ( ) ;
212
+ let mut sched = ~Scheduler :: new ( loop_, work_queue. clone ( ) , sleepers. clone ( ) ) ;
213
+ let handle = sched. make_handle ( ) ;
214
+
215
+ handles. push ( handle) ;
216
+ scheds. push ( sched) ;
217
+ }
218
+
219
+ let main_cell = Cell :: new ( main) ;
220
+ let handles = Cell :: new ( handles) ;
221
+ let mut new_task = ~Task :: new_root ( ) ;
222
+ let on_exit: ~fn ( bool ) = |exit_status| {
223
+
224
+ let mut handles = handles. take ( ) ;
225
+ // Tell schedulers to exit
226
+ for handles. mut_iter( ) . advance |handle| {
227
+ handle. send( Shutdown ) ;
228
+ }
229
+
230
+ rtassert ! ( exit_status) ;
231
+ } ;
232
+ new_task. on_exit = Some ( on_exit) ;
233
+ let main_task = ~Coroutine :: with_task( & mut scheds[ 0 ] . stack_pool,
234
+ new_task, main_cell. take( ) ) ;
235
+ scheds[ 0 ] . enqueue_task( main_task) ;
236
+
237
+ let mut threads = ~[ ] ;
238
+
239
+ while !scheds. is_empty( ) {
240
+ let sched = scheds. pop( ) ;
241
+ let sched_cell = Cell :: new( sched) ;
242
+ let thread = do Thread :: start {
243
+ let sched = sched_cell. take( ) ;
244
+ sched. run( ) ;
245
+ } ;
246
+
247
+ threads. push( thread) ;
248
+ }
249
+
250
+ // Wait for schedulers
251
+ let _threads = threads;
252
+ }
253
+
194
254
/// Possible contexts in which Rust code may be executing.
195
255
/// Different runtime services are available depending on context.
196
256
/// Mostly used for determining if we're using the new scheduler
0 commit comments