Skip to content

Move implementation for threads to Rust #10290

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 5, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion mk/rt.mk
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ endif

RUNTIME_CXXS_$(1)_$(2) := \
rt/sync/lock_and_signal.cpp \
rt/sync/rust_thread.cpp \
rt/rust_builtin.cpp \
rt/rust_upcall.cpp \
rt/miniz.cpp \
Expand Down
63 changes: 56 additions & 7 deletions src/libstd/libc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,10 @@ pub mod types {
pub mod common {
pub mod posix01 {
use libc::types::common::c95::{c_void};
use libc::types::os::arch::c95::{c_char, size_t};
use libc::types::os::arch::c95::{c_char, c_ulong, size_t};

pub type pthread_t = c_ulong;

pub struct glob_t {
gl_pathc: size_t,
gl_pathv: **c_char,
Expand Down Expand Up @@ -294,7 +297,7 @@ pub mod types {
}
#[cfg(target_arch = "x86")]
pub mod posix01 {
use libc::types::os::arch::c95::{c_short, c_long, time_t};
use libc::types::os::arch::c95::{c_char, c_short, c_long, time_t};
use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
use libc::types::os::arch::posix88::{mode_t, off_t};
use libc::types::os::arch::posix88::{uid_t};
Expand Down Expand Up @@ -325,10 +328,14 @@ pub mod types {
__unused4: c_long,
__unused5: c_long,
}

pub struct pthread_attr_t {
__size: [c_char, ..36]
}
}
#[cfg(target_arch = "arm")]
pub mod posix01 {
use libc::types::os::arch::c95::{c_uchar, c_uint, c_ulong, time_t};
use libc::types::os::arch::c95::{c_char, c_uchar, c_uint, c_ulong, time_t};
use libc::types::os::arch::c99::{c_longlong, c_ulonglong};
use libc::types::os::arch::posix88::{uid_t, gid_t, ino_t};

Expand Down Expand Up @@ -357,10 +364,14 @@ pub mod types {
st_ctime_nsec: c_ulong,
st_ino: c_ulonglong
}

pub struct pthread_attr_t {
__size: [c_char, ..36]
}
}
#[cfg(target_arch = "mips")]
pub mod posix01 {
use libc::types::os::arch::c95::{c_long, c_ulong, time_t};
use libc::types::os::arch::c95::{c_char, c_long, c_ulong, time_t};
use libc::types::os::arch::posix88::{gid_t, ino_t};
use libc::types::os::arch::posix88::{mode_t, off_t};
use libc::types::os::arch::posix88::{uid_t};
Expand Down Expand Up @@ -391,6 +402,10 @@ pub mod types {
st_blocks: blkcnt_t,
st_pad5: [c_long, ..14],
}

pub struct pthread_attr_t {
__size: [c_char, ..36]
}
}
pub mod posix08 {}
pub mod bsd44 {}
Expand Down Expand Up @@ -435,7 +450,7 @@ pub mod types {
pub type ssize_t = i64;
}
pub mod posix01 {
use libc::types::os::arch::c95::{c_int, c_long, time_t};
use libc::types::os::arch::c95::{c_char, c_int, c_long, time_t};
use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
use libc::types::os::arch::posix88::{mode_t, off_t};
use libc::types::os::arch::posix88::{uid_t};
Expand Down Expand Up @@ -463,6 +478,10 @@ pub mod types {
st_ctime_nsec: c_long,
__unused: [c_long, ..3],
}

pub struct pthread_attr_t {
__size: [c_char, ..56]
}
}
pub mod posix08 {
}
Expand All @@ -479,6 +498,10 @@ pub mod types {
pub mod posix01 {
use libc::types::common::c95::{c_void};
use libc::types::os::arch::c95::{c_char, c_int, size_t};
use libc::types::os::arch::c99::{uintptr_t};

pub type pthread_t = uintptr_t;

pub struct glob_t {
gl_pathc: size_t,
__unused1: size_t,
Expand Down Expand Up @@ -535,6 +558,7 @@ pub mod types {
pub type ssize_t = i64;
}
pub mod posix01 {
use libc::types::common::c95::{c_void};
use libc::types::common::c99::{uint8_t, uint32_t, int32_t};
use libc::types::os::arch::c95::{c_long, time_t};
use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
Expand Down Expand Up @@ -569,6 +593,8 @@ pub mod types {
st_birthtime_nsec: c_long,
__unused: [uint8_t, ..2],
}

pub type pthread_attr_t = *c_void;
}
pub mod posix08 {
}
Expand Down Expand Up @@ -945,6 +971,10 @@ pub mod types {
pub mod posix01 {
use libc::types::common::c95::{c_void};
use libc::types::os::arch::c95::{c_char, c_int, size_t};
use libc::types::os::arch::c99::{uintptr_t};

pub type pthread_t = uintptr_t;

pub struct glob_t {
gl_pathc: size_t,
__unused1: c_int,
Expand Down Expand Up @@ -1002,7 +1032,7 @@ pub mod types {
}
pub mod posix01 {
use libc::types::common::c99::{int32_t, int64_t, uint32_t};
use libc::types::os::arch::c95::{c_long, time_t};
use libc::types::os::arch::c95::{c_char, c_long, time_t};
use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t,
mode_t, off_t, uid_t};

Expand Down Expand Up @@ -1034,6 +1064,11 @@ pub mod types {
st_lspare: int32_t,
st_qspare: [int64_t, ..2],
}

pub struct pthread_attr_t {
__sig: c_long,
__opaque: [c_char, ..36]
}
}
pub mod posix08 {
}
Expand Down Expand Up @@ -1083,7 +1118,7 @@ pub mod types {
pub mod posix01 {
use libc::types::common::c99::{int32_t, int64_t};
use libc::types::common::c99::{uint32_t};
use libc::types::os::arch::c95::{c_long, time_t};
use libc::types::os::arch::c95::{c_char, c_long, time_t};
use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
use libc::types::os::arch::posix88::{mode_t, off_t, uid_t};

Expand Down Expand Up @@ -1115,6 +1150,11 @@ pub mod types {
st_lspare: int32_t,
st_qspare: [int64_t, ..2],
}

pub struct pthread_attr_t {
__sig: c_long,
__opaque: [c_char, ..56]
}
}
pub mod posix08 {
}
Expand Down Expand Up @@ -1800,6 +1840,9 @@ pub mod consts {
pub static _SC_XOPEN_LEGACY : c_int = 129;
pub static _SC_XOPEN_REALTIME : c_int = 130;
pub static _SC_XOPEN_REALTIME_THREADS : c_int = 131;

pub static PTHREAD_CREATE_JOINABLE: c_int = 0;
pub static PTHREAD_CREATE_DETACHED: c_int = 1;
}
pub mod posix08 {
}
Expand Down Expand Up @@ -2207,6 +2250,9 @@ pub mod consts {
pub static _SC_XOPEN_UNIX : c_int = 115;
pub static _SC_XOPEN_VERSION : c_int = 116;
pub static _SC_XOPEN_XCU_VERSION : c_int = 117;

pub static PTHREAD_CREATE_JOINABLE: c_int = 0;
pub static PTHREAD_CREATE_DETACHED: c_int = 1;
}
pub mod posix08 {
}
Expand Down Expand Up @@ -2560,6 +2606,9 @@ pub mod consts {
pub static _SC_XOPEN_UNIX : c_int = 115;
pub static _SC_XOPEN_VERSION : c_int = 116;
pub static _SC_XOPEN_XCU_VERSION : c_int = 121;

pub static PTHREAD_CREATE_JOINABLE: c_int = 1;
pub static PTHREAD_CREATE_DETACHED: c_int = 2;
}
pub mod posix08 {
}
Expand Down
127 changes: 97 additions & 30 deletions src/libstd/rt/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,74 +8,141 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[allow(non_camel_case_types)];

use cast;
use libc;
use ops::Drop;
use unstable::raw;
use uint;
use ptr;

#[cfg(windows)]
use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T,
LPVOID, DWORD, LPDWORD, HANDLE};

#[allow(non_camel_case_types)] // runtime type
type raw_thread = libc::c_void;
#[cfg(windows)] type rust_thread = HANDLE;
#[cfg(unix)] type rust_thread = libc::pthread_t;

pub struct Thread {
priv main: ~fn(),
priv raw_thread: *raw_thread,
priv native: rust_thread,
priv joined: bool
}

static DEFAULT_STACK_SIZE: libc::size_t = 1024*1024;

#[cfg(windows)] type rust_thread_return = DWORD;
#[cfg(unix)] type rust_thread_return = *libc::c_void;

impl Thread {
#[fixed_stack_segment] #[inline(never)]

pub fn start(main: ~fn()) -> Thread {
// This is the starting point of rust os threads. The first thing we do
// is make sure that we don't trigger __morestack (also why this has a
// no_split_stack annotation), and then we re-build the main function
// and invoke it from there.
// no_split_stack annotation), and then we extract the main function
// and invoke it.
#[no_split_stack]
extern "C" fn thread_start(code: *(), env: *()) {
extern "C" fn thread_start(trampoline: *libc::c_void) -> rust_thread_return {
use rt::context;
unsafe {
context::record_stack_bounds(0, uint::max_value);
let f: &fn() = cast::transmute(raw::Closure {
code: code,
env: env,
});
f();
let f: ~~fn() = cast::transmute(trampoline);
(*f)();
}
unsafe { cast::transmute(0) }
}

let raw_thread = unsafe {
let c: raw::Closure = cast::transmute_copy(&main);
let raw::Closure { code, env } = c;
rust_raw_thread_start(thread_start, code, env)
};
let native = native_thread_create(thread_start, ~main);
Thread {
main: main,
raw_thread: raw_thread,
native: native,
joined: false,
}
}

pub fn join(mut self) {
#[fixed_stack_segment]; #[inline(never)];

assert!(!self.joined);
unsafe { rust_raw_thread_join(self.raw_thread); }
native_thread_join(self.native);
self.joined = true;
}
}

#[cfg(windows)]
fn native_thread_create(thread_start: extern "C" fn(*libc::c_void) -> rust_thread_return,
tramp: ~~fn()) -> rust_thread {
#[fixed_stack_segment];

unsafe {
let ptr: *mut libc::c_void = cast::transmute(tramp);
CreateThread(ptr::mut_null(), DEFAULT_STACK_SIZE, thread_start, ptr, 0, ptr::mut_null())
}
}

#[cfg(windows)]
fn native_thread_join(native: rust_thread) {
#[fixed_stack_segment];
use libc::consts::os::extra::INFINITE;
unsafe { WaitForSingleObject(native, INFINITE); }
}

#[cfg(unix)]
fn native_thread_create(thread_start: extern "C" fn(*libc::c_void) -> rust_thread_return,
tramp: ~~fn()) -> rust_thread {
#[fixed_stack_segment];

use unstable::intrinsics;
let mut native: libc::pthread_t = unsafe { intrinsics::uninit() };

unsafe {
use libc::consts::os::posix01::PTHREAD_CREATE_JOINABLE;

let mut attr: libc::pthread_attr_t = intrinsics::uninit();
assert!(pthread_attr_init(&mut attr) == 0);
assert!(pthread_attr_setstacksize(&mut attr, DEFAULT_STACK_SIZE) == 0);
assert!(pthread_attr_setdetachstate(&mut attr, PTHREAD_CREATE_JOINABLE) == 0);

let ptr: *libc::c_void = cast::transmute(tramp);
assert!(pthread_create(&mut native, &attr, thread_start, ptr) == 0);
}
native
}

#[cfg(unix)]
fn native_thread_join(native: rust_thread) {
#[fixed_stack_segment];
unsafe { assert!(pthread_join(native, ptr::null()) == 0) }
}

impl Drop for Thread {
fn drop(&mut self) {
#[fixed_stack_segment]; #[inline(never)];

assert!(self.joined);
unsafe { rust_raw_thread_delete(self.raw_thread) }
}
}

#[cfg(windows, target_arch = "x86")]
extern "stdcall" {
fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T,
lpStartAddress: extern "C" fn(*libc::c_void) -> rust_thread_return,
lpParameter: LPVOID, dwCreationFlags: DWORD, lpThreadId: LPDWORD) -> HANDLE;
fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
}

#[cfg(windows, target_arch = "x86_64")]
extern {
fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T,
lpStartAddress: extern "C" fn(*libc::c_void) -> rust_thread_return,
lpParameter: LPVOID, dwCreationFlags: DWORD, lpThreadId: LPDWORD) -> HANDLE;
fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
}

#[cfg(unix)]
extern {
fn rust_raw_thread_start(f: extern "C" fn(*(), *()),
code: *(), env: *()) -> *raw_thread;
fn rust_raw_thread_join(thread: *raw_thread);
fn rust_raw_thread_delete(thread: *raw_thread);
fn pthread_create(native: *mut libc::pthread_t, attr: *libc::pthread_attr_t,
f: extern "C" fn(*libc::c_void) -> rust_thread_return,
value: *libc::c_void) -> libc::c_int;
fn pthread_join(native: libc::pthread_t, value: **libc::c_void) -> libc::c_int;
fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
stack_size: libc::size_t) -> libc::c_int;
fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
state: libc::c_int) -> libc::c_int;
}
Loading