Skip to content

Commit 47e0bd4

Browse files
committed
Move implementation for threads to Rust
This binds to the appropriate pthreads_* and Windows specific functions and calls them from Rust. This allows for removal of the C++ support code for threads. Fixes #10162
1 parent 92065ce commit 47e0bd4

File tree

7 files changed

+153
-181
lines changed

7 files changed

+153
-181
lines changed

mk/rt.mk

-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ endif
8484

8585
RUNTIME_CXXS_$(1)_$(2) := \
8686
rt/sync/lock_and_signal.cpp \
87-
rt/sync/rust_thread.cpp \
8887
rt/rust_builtin.cpp \
8988
rt/rust_upcall.cpp \
9089
rt/miniz.cpp \

src/libstd/libc.rs

+56-7
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,10 @@ pub mod types {
224224
pub mod common {
225225
pub mod posix01 {
226226
use libc::types::common::c95::{c_void};
227-
use libc::types::os::arch::c95::{c_char, size_t};
227+
use libc::types::os::arch::c95::{c_char, c_ulong, size_t};
228+
229+
pub type pthread_t = c_ulong;
230+
228231
pub struct glob_t {
229232
gl_pathc: size_t,
230233
gl_pathv: **c_char,
@@ -294,7 +297,7 @@ pub mod types {
294297
}
295298
#[cfg(target_arch = "x86")]
296299
pub mod posix01 {
297-
use libc::types::os::arch::c95::{c_short, c_long, time_t};
300+
use libc::types::os::arch::c95::{c_char, c_short, c_long, time_t};
298301
use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
299302
use libc::types::os::arch::posix88::{mode_t, off_t};
300303
use libc::types::os::arch::posix88::{uid_t};
@@ -325,10 +328,14 @@ pub mod types {
325328
__unused4: c_long,
326329
__unused5: c_long,
327330
}
331+
332+
pub struct pthread_attr_t {
333+
__size: [c_char, ..36]
334+
}
328335
}
329336
#[cfg(target_arch = "arm")]
330337
pub mod posix01 {
331-
use libc::types::os::arch::c95::{c_uchar, c_uint, c_ulong, time_t};
338+
use libc::types::os::arch::c95::{c_char, c_uchar, c_uint, c_ulong, time_t};
332339
use libc::types::os::arch::c99::{c_longlong, c_ulonglong};
333340
use libc::types::os::arch::posix88::{uid_t, gid_t, ino_t};
334341

@@ -357,10 +364,14 @@ pub mod types {
357364
st_ctime_nsec: c_ulong,
358365
st_ino: c_ulonglong
359366
}
367+
368+
pub struct pthread_attr_t {
369+
__size: [c_char, ..36]
370+
}
360371
}
361372
#[cfg(target_arch = "mips")]
362373
pub mod posix01 {
363-
use libc::types::os::arch::c95::{c_long, c_ulong, time_t};
374+
use libc::types::os::arch::c95::{c_char, c_long, c_ulong, time_t};
364375
use libc::types::os::arch::posix88::{gid_t, ino_t};
365376
use libc::types::os::arch::posix88::{mode_t, off_t};
366377
use libc::types::os::arch::posix88::{uid_t};
@@ -391,6 +402,10 @@ pub mod types {
391402
st_blocks: blkcnt_t,
392403
st_pad5: [c_long, ..14],
393404
}
405+
406+
pub struct pthread_attr_t {
407+
__size: [c_char, ..36]
408+
}
394409
}
395410
pub mod posix08 {}
396411
pub mod bsd44 {}
@@ -435,7 +450,7 @@ pub mod types {
435450
pub type ssize_t = i64;
436451
}
437452
pub mod posix01 {
438-
use libc::types::os::arch::c95::{c_int, c_long, time_t};
453+
use libc::types::os::arch::c95::{c_char, c_int, c_long, time_t};
439454
use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
440455
use libc::types::os::arch::posix88::{mode_t, off_t};
441456
use libc::types::os::arch::posix88::{uid_t};
@@ -463,6 +478,10 @@ pub mod types {
463478
st_ctime_nsec: c_long,
464479
__unused: [c_long, ..3],
465480
}
481+
482+
pub struct pthread_attr_t {
483+
__size: [c_char, ..56]
484+
}
466485
}
467486
pub mod posix08 {
468487
}
@@ -479,6 +498,10 @@ pub mod types {
479498
pub mod posix01 {
480499
use libc::types::common::c95::{c_void};
481500
use libc::types::os::arch::c95::{c_char, c_int, size_t};
501+
use libc::types::os::arch::c99::{uintptr_t};
502+
503+
pub type pthread_t = uintptr_t;
504+
482505
pub struct glob_t {
483506
gl_pathc: size_t,
484507
__unused1: size_t,
@@ -535,6 +558,7 @@ pub mod types {
535558
pub type ssize_t = i64;
536559
}
537560
pub mod posix01 {
561+
use libc::types::common::c95::{c_void};
538562
use libc::types::common::c99::{uint8_t, uint32_t, int32_t};
539563
use libc::types::os::arch::c95::{c_long, time_t};
540564
use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
@@ -569,6 +593,8 @@ pub mod types {
569593
st_birthtime_nsec: c_long,
570594
__unused: [uint8_t, ..2],
571595
}
596+
597+
pub type pthread_attr_t = *c_void;
572598
}
573599
pub mod posix08 {
574600
}
@@ -945,6 +971,10 @@ pub mod types {
945971
pub mod posix01 {
946972
use libc::types::common::c95::{c_void};
947973
use libc::types::os::arch::c95::{c_char, c_int, size_t};
974+
use libc::types::os::arch::c99::{uintptr_t};
975+
976+
pub type pthread_t = uintptr_t;
977+
948978
pub struct glob_t {
949979
gl_pathc: size_t,
950980
__unused1: c_int,
@@ -1002,7 +1032,7 @@ pub mod types {
10021032
}
10031033
pub mod posix01 {
10041034
use libc::types::common::c99::{int32_t, int64_t, uint32_t};
1005-
use libc::types::os::arch::c95::{c_long, time_t};
1035+
use libc::types::os::arch::c95::{c_char, c_long, time_t};
10061036
use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t,
10071037
mode_t, off_t, uid_t};
10081038

@@ -1034,6 +1064,11 @@ pub mod types {
10341064
st_lspare: int32_t,
10351065
st_qspare: [int64_t, ..2],
10361066
}
1067+
1068+
pub struct pthread_attr_t {
1069+
__sig: c_long,
1070+
__opaque: [c_char, ..36]
1071+
}
10371072
}
10381073
pub mod posix08 {
10391074
}
@@ -1083,7 +1118,7 @@ pub mod types {
10831118
pub mod posix01 {
10841119
use libc::types::common::c99::{int32_t, int64_t};
10851120
use libc::types::common::c99::{uint32_t};
1086-
use libc::types::os::arch::c95::{c_long, time_t};
1121+
use libc::types::os::arch::c95::{c_char, c_long, time_t};
10871122
use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
10881123
use libc::types::os::arch::posix88::{mode_t, off_t, uid_t};
10891124

@@ -1115,6 +1150,11 @@ pub mod types {
11151150
st_lspare: int32_t,
11161151
st_qspare: [int64_t, ..2],
11171152
}
1153+
1154+
pub struct pthread_attr_t {
1155+
__sig: c_long,
1156+
__opaque: [c_char, ..56]
1157+
}
11181158
}
11191159
pub mod posix08 {
11201160
}
@@ -1800,6 +1840,9 @@ pub mod consts {
18001840
pub static _SC_XOPEN_LEGACY : c_int = 129;
18011841
pub static _SC_XOPEN_REALTIME : c_int = 130;
18021842
pub static _SC_XOPEN_REALTIME_THREADS : c_int = 131;
1843+
1844+
pub static PTHREAD_CREATE_JOINABLE: c_int = 0;
1845+
pub static PTHREAD_CREATE_DETACHED: c_int = 1;
18031846
}
18041847
pub mod posix08 {
18051848
}
@@ -2207,6 +2250,9 @@ pub mod consts {
22072250
pub static _SC_XOPEN_UNIX : c_int = 115;
22082251
pub static _SC_XOPEN_VERSION : c_int = 116;
22092252
pub static _SC_XOPEN_XCU_VERSION : c_int = 117;
2253+
2254+
pub static PTHREAD_CREATE_JOINABLE: c_int = 0;
2255+
pub static PTHREAD_CREATE_DETACHED: c_int = 1;
22102256
}
22112257
pub mod posix08 {
22122258
}
@@ -2560,6 +2606,9 @@ pub mod consts {
25602606
pub static _SC_XOPEN_UNIX : c_int = 115;
25612607
pub static _SC_XOPEN_VERSION : c_int = 116;
25622608
pub static _SC_XOPEN_XCU_VERSION : c_int = 121;
2609+
2610+
pub static PTHREAD_CREATE_JOINABLE: c_int = 1;
2611+
pub static PTHREAD_CREATE_DETACHED: c_int = 2;
25632612
}
25642613
pub mod posix08 {
25652614
}

src/libstd/rt/thread.rs

+97-30
Original file line numberDiff line numberDiff line change
@@ -8,74 +8,141 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
#[allow(non_camel_case_types)];
12+
1113
use cast;
1214
use libc;
1315
use ops::Drop;
14-
use unstable::raw;
1516
use uint;
17+
use ptr;
18+
19+
#[cfg(windows)]
20+
use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T,
21+
LPVOID, DWORD, LPDWORD, HANDLE};
1622

17-
#[allow(non_camel_case_types)] // runtime type
18-
type raw_thread = libc::c_void;
23+
#[cfg(windows)] type rust_thread = HANDLE;
24+
#[cfg(unix)] type rust_thread = libc::pthread_t;
1925

2026
pub struct Thread {
21-
priv main: ~fn(),
22-
priv raw_thread: *raw_thread,
27+
priv native: rust_thread,
2328
priv joined: bool
2429
}
2530

31+
static DEFAULT_STACK_SIZE: libc::size_t = 1024*1024;
32+
33+
#[cfg(windows)] type rust_thread_return = DWORD;
34+
#[cfg(unix)] type rust_thread_return = *libc::c_void;
35+
2636
impl Thread {
27-
#[fixed_stack_segment] #[inline(never)]
37+
2838
pub fn start(main: ~fn()) -> Thread {
2939
// This is the starting point of rust os threads. The first thing we do
3040
// is make sure that we don't trigger __morestack (also why this has a
31-
// no_split_stack annotation), and then we re-build the main function
32-
// and invoke it from there.
41+
// no_split_stack annotation), and then we extract the main function
42+
// and invoke it.
3343
#[no_split_stack]
34-
extern "C" fn thread_start(code: *(), env: *()) {
44+
extern "C" fn thread_start(trampoline: *libc::c_void) -> rust_thread_return {
3545
use rt::context;
3646
unsafe {
3747
context::record_stack_bounds(0, uint::max_value);
38-
let f: &fn() = cast::transmute(raw::Closure {
39-
code: code,
40-
env: env,
41-
});
42-
f();
48+
let f: ~~fn() = cast::transmute(trampoline);
49+
(*f)();
4350
}
51+
unsafe { cast::transmute(0) }
4452
}
4553

46-
let raw_thread = unsafe {
47-
let c: raw::Closure = cast::transmute_copy(&main);
48-
let raw::Closure { code, env } = c;
49-
rust_raw_thread_start(thread_start, code, env)
50-
};
54+
let native = native_thread_create(thread_start, ~main);
5155
Thread {
52-
main: main,
53-
raw_thread: raw_thread,
56+
native: native,
5457
joined: false,
5558
}
5659
}
5760

5861
pub fn join(mut self) {
59-
#[fixed_stack_segment]; #[inline(never)];
60-
6162
assert!(!self.joined);
62-
unsafe { rust_raw_thread_join(self.raw_thread); }
63+
native_thread_join(self.native);
6364
self.joined = true;
6465
}
6566
}
6667

68+
#[cfg(windows)]
69+
fn native_thread_create(thread_start: extern "C" fn(*libc::c_void) -> rust_thread_return,
70+
tramp: ~~fn()) -> rust_thread {
71+
#[fixed_stack_segment];
72+
73+
unsafe {
74+
let ptr: *mut libc::c_void = cast::transmute(tramp);
75+
CreateThread(ptr::mut_null(), DEFAULT_STACK_SIZE, thread_start, ptr, 0, ptr::mut_null())
76+
}
77+
}
78+
79+
#[cfg(windows)]
80+
fn native_thread_join(native: rust_thread) {
81+
#[fixed_stack_segment];
82+
use libc::consts::os::extra::INFINITE;
83+
unsafe { WaitForSingleObject(native, INFINITE); }
84+
}
85+
86+
#[cfg(unix)]
87+
fn native_thread_create(thread_start: extern "C" fn(*libc::c_void) -> rust_thread_return,
88+
tramp: ~~fn()) -> rust_thread {
89+
#[fixed_stack_segment];
90+
91+
use unstable::intrinsics;
92+
let mut native: libc::pthread_t = unsafe { intrinsics::uninit() };
93+
94+
unsafe {
95+
use libc::consts::os::posix01::PTHREAD_CREATE_JOINABLE;
96+
97+
let mut attr: libc::pthread_attr_t = intrinsics::uninit();
98+
assert!(pthread_attr_init(&mut attr) == 0);
99+
assert!(pthread_attr_setstacksize(&mut attr, DEFAULT_STACK_SIZE) == 0);
100+
assert!(pthread_attr_setdetachstate(&mut attr, PTHREAD_CREATE_JOINABLE) == 0);
101+
102+
let ptr: *libc::c_void = cast::transmute(tramp);
103+
assert!(pthread_create(&mut native, &attr, thread_start, ptr) == 0);
104+
}
105+
native
106+
}
107+
108+
#[cfg(unix)]
109+
fn native_thread_join(native: rust_thread) {
110+
#[fixed_stack_segment];
111+
unsafe { assert!(pthread_join(native, ptr::null()) == 0) }
112+
}
113+
67114
impl Drop for Thread {
68115
fn drop(&mut self) {
69116
#[fixed_stack_segment]; #[inline(never)];
70-
71117
assert!(self.joined);
72-
unsafe { rust_raw_thread_delete(self.raw_thread) }
73118
}
74119
}
75120

121+
#[cfg(windows, target_arch = "x86")]
122+
extern "stdcall" {
123+
fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T,
124+
lpStartAddress: extern "C" fn(*libc::c_void) -> rust_thread_return,
125+
lpParameter: LPVOID, dwCreationFlags: DWORD, lpThreadId: LPDWORD) -> HANDLE;
126+
fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
127+
}
128+
129+
#[cfg(windows, target_arch = "x86_64")]
130+
extern {
131+
fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T,
132+
lpStartAddress: extern "C" fn(*libc::c_void) -> rust_thread_return,
133+
lpParameter: LPVOID, dwCreationFlags: DWORD, lpThreadId: LPDWORD) -> HANDLE;
134+
fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
135+
}
136+
137+
#[cfg(unix)]
76138
extern {
77-
fn rust_raw_thread_start(f: extern "C" fn(*(), *()),
78-
code: *(), env: *()) -> *raw_thread;
79-
fn rust_raw_thread_join(thread: *raw_thread);
80-
fn rust_raw_thread_delete(thread: *raw_thread);
139+
fn pthread_create(native: *mut libc::pthread_t, attr: *libc::pthread_attr_t,
140+
f: extern "C" fn(*libc::c_void) -> rust_thread_return,
141+
value: *libc::c_void) -> libc::c_int;
142+
fn pthread_join(native: libc::pthread_t, value: **libc::c_void) -> libc::c_int;
143+
fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
144+
fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
145+
stack_size: libc::size_t) -> libc::c_int;
146+
fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
147+
state: libc::c_int) -> libc::c_int;
81148
}

0 commit comments

Comments
 (0)