Skip to content

Commit d3e0a06

Browse files
Bleibrson
authored andcommitted
V2: now with more locks!
1 parent 68e755b commit d3e0a06

File tree

6 files changed

+43
-33
lines changed

6 files changed

+43
-33
lines changed

src/libcore/task.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,8 +1661,8 @@ extern mod rustrt {
16611661

16621662
fn rust_get_sched_id() -> sched_id;
16631663
fn rust_new_sched(num_threads: libc::uintptr_t) -> sched_id;
1664-
fn rust_max_sched_threads() -> libc::size_t;
16651664
fn rust_sched_threads() -> libc::size_t;
1665+
fn rust_sched_current_nonlazy_threads() -> libc::size_t;
16661666
fn rust_num_threads() -> libc::uintptr_t;
16671667

16681668
fn get_task_id() -> task_id;
@@ -2436,7 +2436,7 @@ fn test_sched_thread_per_core() {
24362436

24372437
do spawn_sched(ThreadPerCore) {
24382438
let cores = rustrt::rust_num_threads();
2439-
let reported_threads = rustrt::rust_max_sched_threads();
2439+
let reported_threads = rustrt::rust_sched_threads();
24402440
assert(cores as uint == reported_threads as uint);
24412441
chan.send(());
24422442
}
@@ -2449,9 +2449,9 @@ fn test_spawn_thread_on_demand() {
24492449
let (chan, port) = pipes::stream();
24502450

24512451
do spawn_sched(ManualThreads(2)) {
2452-
let max_threads = rustrt::rust_max_sched_threads();
2452+
let max_threads = rustrt::rust_sched_threads();
24532453
assert(max_threads as int == 2);
2454-
let running_threads = rustrt::rust_sched_threads();
2454+
let running_threads = rustrt::rust_sched_current_nonlazy_threads();
24552455
assert(running_threads as int == 1);
24562456

24572457
let (chan2, port2) = pipes::stream();
@@ -2460,7 +2460,7 @@ fn test_spawn_thread_on_demand() {
24602460
chan2.send(());
24612461
}
24622462

2463-
let running_threads2 = rustrt::rust_sched_threads();
2463+
let running_threads2 = rustrt::rust_sched_current_nonlazy_threads();
24642464
assert(running_threads2 as int == 2);
24652465

24662466
port2.recv();

src/libstd/test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export run_tests_console;
2626

2727
#[abi = "cdecl"]
2828
extern mod rustrt {
29-
fn rust_max_sched_threads() -> libc::size_t;
29+
fn rust_sched_threads() -> libc::size_t;
3030
}
3131

3232
// The name of a test. By convention this follows the rules for rust
@@ -327,7 +327,7 @@ const sched_overcommit : uint = 1u;
327327
const sched_overcommit : uint = 4u;
328328
329329
fn get_concurrency() -> uint {
330-
let threads = rustrt::rust_max_sched_threads() as uint;
330+
let threads = rustrt::rust_sched_threads() as uint;
331331
if threads == 1u { 1u }
332332
else { threads * sched_overcommit }
333333
}

src/rt/rust_builtin.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -627,13 +627,13 @@ start_task(rust_task *target, fn_env_pair *f) {
627627
}
628628

629629
extern "C" CDECL size_t
630-
rust_sched_threads() {
630+
rust_sched_current_nonlazy_threads() {
631631
rust_task *task = rust_get_current_task();
632632
return task->sched->number_of_threads();
633633
}
634634

635635
extern "C" CDECL size_t
636-
rust_max_sched_threads() {
636+
rust_sched_threads() {
637637
rust_task *task = rust_get_current_task();
638638
return task->sched->max_number_of_threads();
639639
}

src/rt/rust_scheduler.cpp

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ rust_scheduler::rust_scheduler(rust_kernel *kernel,
2323
id(id)
2424
{
2525
// Create the first thread
26+
scoped_lock with(lock);
2627
threads.push(create_task_thread(0));
2728
}
2829

@@ -34,6 +35,7 @@ void rust_scheduler::delete_this() {
3435

3536
rust_sched_launcher *
3637
rust_scheduler::create_task_thread(int id) {
38+
lock.must_have_lock();
3739
live_threads++;
3840
rust_sched_launcher *thread = launchfac->create(this, id, killed);
3941
KLOG(kernel, kern, "created task thread: " PTR
@@ -50,6 +52,7 @@ rust_scheduler::destroy_task_thread(rust_sched_launcher *thread) {
5052

5153
void
5254
rust_scheduler::destroy_task_threads() {
55+
scoped_lock with(lock);
5356
for(size_t i = 0; i < threads.size(); ++i) {
5457
destroy_task_thread(threads[i]);
5558
}
@@ -58,6 +61,7 @@ rust_scheduler::destroy_task_threads() {
5861
void
5962
rust_scheduler::start_task_threads()
6063
{
64+
scoped_lock with(lock);
6165
for(size_t i = 0; i < threads.size(); ++i) {
6266
rust_sched_launcher *thread = threads[i];
6367
thread->start();
@@ -67,6 +71,7 @@ rust_scheduler::start_task_threads()
6771
void
6872
rust_scheduler::join_task_threads()
6973
{
74+
scoped_lock with(lock);
7075
for(size_t i = 0; i < threads.size(); ++i) {
7176
rust_sched_launcher *thread = threads[i];
7277
thread->join();
@@ -75,8 +80,16 @@ rust_scheduler::join_task_threads()
7580

7681
void
7782
rust_scheduler::kill_all_tasks() {
78-
for(size_t i = 0; i < threads.size(); ++i) {
79-
rust_sched_launcher *thread = threads[i];
83+
array_list<rust_sched_launcher *> copied_threads;
84+
{
85+
scoped_lock with(lock);
86+
killed = true;
87+
for (size_t i = 0; i < threads.size(); ++i) {
88+
copied_threads.push(threads[i]);
89+
}
90+
}
91+
for(size_t i = 0; i < copied_threads.size(); ++i) {
92+
rust_sched_launcher *thread = copied_threads[i];
8093
thread->get_loop()->kill_all_tasks();
8194
}
8295
}
@@ -88,26 +101,16 @@ rust_scheduler::create_task(rust_task *spawner, const char *name) {
88101
scoped_lock with(lock);
89102
live_tasks++;
90103

91-
// Find unoccupied thread
92-
for (thread_no = 0; thread_no < threads.size(); ++thread_no) {
93-
if (threads[thread_no]->get_loop()->number_of_live_tasks() == 0)
94-
break;
95-
}
96-
97-
if (thread_no == threads.size()) {
98-
if (threads.size() < max_num_threads) {
99-
// Else create new thread
100-
thread_no = threads.size();
101-
rust_sched_launcher *thread = create_task_thread(thread_no);
102-
thread->start();
103-
threads.push(thread);
104-
} else {
105-
// Or use round robin allocation
106-
thread_no = cur_thread++;
107-
if (cur_thread >= max_num_threads)
108-
cur_thread = 0;
109-
}
104+
if (cur_thread < threads.size()) {
105+
thread_no = cur_thread;
106+
} else {
107+
assert(threads.size() < max_num_threads);
108+
thread_no = threads.size();
109+
rust_sched_launcher *thread = create_task_thread(thread_no);
110+
thread->start();
111+
threads.push(thread);
110112
}
113+
cur_thread = (thread_no + 1) % max_num_threads;
111114
}
112115
KLOG(kernel, kern, "Creating task %s, on thread %d.", name, thread_no);
113116
kernel->register_task();
@@ -135,6 +138,12 @@ void
135138
rust_scheduler::exit() {
136139
// Take a copy of the number of threads. After the last thread exits this
137140
// scheduler will get destroyed, and our fields will cease to exist.
141+
//
142+
// This is also the reason we can't use the lock here (as in the other
143+
// cases when accessing `threads`), after the loop the lock won't exist
144+
// anymore. This is safe because this method is only called when all the
145+
// task are dead, so there is no chance of a task trying to create new
146+
// threads.
138147
size_t current_num_threads = threads.size();
139148
for(size_t i = 0; i < current_num_threads; ++i) {
140149
threads[i]->get_loop()->exit();
@@ -148,6 +157,7 @@ rust_scheduler::max_number_of_threads() {
148157

149158
size_t
150159
rust_scheduler::number_of_threads() {
160+
scoped_lock with(lock);
151161
return threads.size();
152162
}
153163

src/rt/rustrt.def.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ rand_new_seeded
3030
rand_next
3131
rand_seed
3232
rust_get_sched_id
33-
rust_max_sched_threads
3433
rust_new_sched
3534
rust_new_task_in_sched
3635
rust_num_threads
@@ -49,6 +48,7 @@ rust_port_size
4948
rust_process_wait
5049
rust_ptr_eq
5150
rust_run_program
51+
rust_sched_current_nonlazy_threads
5252
rust_sched_threads
5353
rust_set_exit_status
5454
rust_start

src/test/run-pass/morestack6.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ extern mod rustrt {
88
fn last_os_error() -> ~str;
99
fn rust_getcwd() -> ~str;
1010
fn get_task_id() -> libc::intptr_t;
11-
fn rust_max_sched_threads();
11+
fn rust_sched_threads();
1212
fn rust_get_task();
1313
}
1414

1515
fn calllink01() { rustrt::rust_get_sched_id(); }
1616
fn calllink02() { rustrt::last_os_error(); }
1717
fn calllink03() { rustrt::rust_getcwd(); }
1818
fn calllink08() { rustrt::get_task_id(); }
19-
fn calllink09() { rustrt::rust_max_sched_threads(); }
19+
fn calllink09() { rustrt::rust_sched_threads(); }
2020
fn calllink10() { rustrt::rust_get_task(); }
2121

2222
fn runtest(f: fn~(), frame_backoff: u32) {

0 commit comments

Comments
 (0)