Skip to content
This repository has been archived by the owner on Dec 9, 2018. It is now read-only.

Commit

Permalink
Merge pull request #110 from tbu-/pr_thread_basic
Browse files Browse the repository at this point in the history
Add basic `thread`
  • Loading branch information
japaric authored Apr 22, 2017
2 parents 6f7f55d + 835f2c2 commit 38c9086
Show file tree
Hide file tree
Showing 36 changed files with 1,780 additions and 129 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name = "std"
version = "0.1.0"

[dependencies]
sc = "0.1.5"
sc = "0.2.0"

[dependencies.ralloc]
default-features = false
Expand Down
1 change: 1 addition & 0 deletions ci/script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ main() {
stderr
system-time
tcp_listen_connect
thread
vec
zero
)
Expand Down
21 changes: 21 additions & 0 deletions examples/thread.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#[cfg(not(any(target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "x86",
target_arch = "x86_64")))]
fn main() {
}

#[cfg(any(target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "x86",
target_arch = "x86_64"))]
fn main() {
use std::io::{self, Write};
use std::thread;

thread::spawn(|| {
io::stdout().write_all(b"Hello, world!\n").unwrap();
}).join().unwrap();
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#![feature(dropck_parametricity)]
#![feature(generic_param_attrs)]
#![feature(exact_size_is_empty)]
#![feature(fnbox)]
#![feature(fused)]
#![feature(global_asm)]
#![feature(heap_api)]
#![feature(int_error_internals)]
#![feature(lang_items)]
Expand Down Expand Up @@ -178,6 +180,7 @@ pub mod os;
pub mod path;
// Rust 1.16.0 (incomplete)
pub mod process;
pub mod thread;
// Rust 1.16.0
pub mod time;

Expand Down
124 changes: 0 additions & 124 deletions src/libc.rs

This file was deleted.

70 changes: 70 additions & 0 deletions src/libc/internal/aarch64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#[cfg(not(test))]
mod not_test {
// Syscall number is passed in x8, syscall arguments in x0, x1, x2, x3, x4.
// The arguments are
// (flags: c_ulong, // x0
// child_stack: *mut c_void, // x1
// ptid: *mut c_int, // x2
// newtls: c_ulong, // x3
// ctid: *mut c_int) // x4
//
// No registers are clobbered, x0 gets the return value.
//
// We do not clobber any registers, so we don't need to save any.
//
// The calling convention passes arguments in registers, from x0 to x6.
// (fn_: extern "C" fn(*mut c_void) -> *mut c_void, // x0
// child_stack: *mut c_void, // x1
// flags: c_ulong, // x2
// arg: *mut c_void, // x3
// ptid: *mut pid_t, // x4
// newtls: *mut c_void, // x5
// ctid: *mut pid_t) // x6
//
// Both ABIs return the function result in x0.
//
// This means we need the following moves:
// x2 -> x0 // flags
// x1 -> x1 // child_stack
// x4 -> x2 // ptid
// x5 -> x3 // newtls
// x6 -> x4 // ctid
//
// We save `fn_` and `arg` on the child stack.

global_asm!("
.globl __steed_clone
__steed_clone:
// Align the child stack.
and x1,x1,#-16
// Save `fn_` and `arg` on the child stack.
stp x0,x3,[x1,#-16]!
mov x8,#220 // CLONE
mov x0,x2 // flags
// child_stack
mov x2,x4 // ptid
mov x3,x5 // newtls
mov x4,x6 // ctid
svc #0
cbnz x0,1f
// Restore `fn_` and `arg`.
ldp x1,x0,[sp],#16
blr x1
mov x8,#93 // EXIT
// status
svc #0
1:
ret
");
}

pub unsafe fn set_thread_pointer(thread_data: *mut ()) {
let _ = thread_data; // TODO(steed, #127): Set thread-local pointer.
}
99 changes: 99 additions & 0 deletions src/libc/internal/arm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#[cfg(not(test))]
mod not_test {
// Syscall number is passed in r7, syscall arguments in r0, r1, r2, r3, r4.
// The arguments are
// (flags: c_ulong, // r0
// child_stack: *mut c_void, // r1
// ptid: *mut c_int, // r2
// newtls: c_ulong, // r3
// ctid: *mut c_int) // r4
//
// No registers are clobbered, r0 gets the return value.
//
// Only r0, r1, r2, r3 are caller-saved, so we must restore the value of
// all other registers before returning.
//
// The calling convention passes the first four arguments in r0 to r3 and
// all further arguments on the stack, right to left. Since we push r4 to
// r7 onto the stack in the very beginning, all stack offsets are increased
// by 16. The arguments are
// (fn_: extern "C" fn(*mut c_void) -> *mut c_void, // r0
// child_stack: *mut c_void, // r1
// flags: c_ulong, // r2
// arg: *mut c_void, // r3
// ptid: *mut pid_t, // [sp,#16]
// newtls: *mut c_void, // [sp,#20]
// ctid: *mut pid_t) // [sp,#24]
//
// Both ABIs return the function result in r0.
//
// This means we need the following moves:
// r2 -> r0 // flags
// r1 -> r1 // child_stack
// [sp,#16] -> r2 // ptid
// [sp,#20] -> r3 // newtls
// [sp,#24] -> r4 // ctid
//
// We save `fn_` in r5, `arg` in r6.

global_asm!("
.globl __steed_clone
__steed_clone:
@ Save r4 to r7
stmfd sp!,{r4,r5,r6,r7}
mov r5,r0 @ fn_
mov r6,r3 @ arg
mov r7,#120 @ CLONE
mov r0,r2 @ flags
@ child_stack
ldr r2,[sp,#16] @ ptid
ldr r3,[sp,#20] @ newtls
ldr r4,[sp,#24] @ ctid
and r1,r1,#-16 @ Align the stack
@ Do the syscall
svc 0
@ CLONE returns 0 in the child thread, return if we're the parent.
tst r0,r0
bne 3f
mov r0,r6 @ arg
@ Do we need to execute `fn_` in thumb mode?
tst r5,#1
bne 2f
@ pc (Program Counter) is always 2 instructions ahead.
mov lr,pc
mov pc,r5 @ fn_
@ The function will return here.
__steed_clone_exit:
mov r7,#1 @ EXIT
@ status
svc 0
2:
@ Again, pc is 2 instructions ahead.
mov lr,pc
bx r5 @ Start thumb mode
b 2b
3:
@ Restore r4 to r7
ldmfd sp!,{r4,r5,r6,r7}
@ Return from the function.
mov pc,lr
");
}

pub unsafe fn set_thread_pointer(thread_data: *mut ()) {
let _ = thread_data; // TODO(steed, #127): Set thread-local pointer.
}
3 changes: 3 additions & 0 deletions src/libc/internal/mips.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub unsafe fn set_thread_pointer(thread_data: *mut ()) {
let _ = thread_data; // TODO(steed, #127): Set thread-local pointer.
}
3 changes: 3 additions & 0 deletions src/libc/internal/mips64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub unsafe fn set_thread_pointer(thread_data: *mut ()) {
let _ = thread_data; // TODO(steed, #127): Set thread-local pointer.
}
23 changes: 23 additions & 0 deletions src/libc/internal/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#[cfg(target_arch = "aarch64")] #[path = "aarch64.rs"] mod arch;
#[cfg(target_arch = "arm")] #[path = "arm.rs"] mod arch;
#[cfg(target_arch = "mips")] #[path = "mips.rs"] mod arch;
#[cfg(target_arch = "mips64")] #[path = "mips64.rs"] mod arch;
#[cfg(target_arch = "powerpc")] #[path = "powerpc.rs"] mod arch;
#[cfg(target_arch = "powerpc64")] #[path = "powerpc64.rs"] mod arch;
#[cfg(target_arch = "sparc64")] #[path = "sparc64.rs"] mod arch;
#[cfg(target_arch = "x86")] #[path = "x86.rs"] mod arch;
#[cfg(target_arch = "x86_64")] #[path = "x86_64.rs"] mod arch;

use super::*;
use self::arch::*;

pub struct Buffer(thread);

pub unsafe fn init_main_thread(buffer: *mut Buffer) {
let buffer: *mut thread = &mut (*buffer).0;
*buffer = thread {
this: buffer,
thread_id: -1,
};
set_thread_pointer(buffer as *mut _);
}
Loading

0 comments on commit 38c9086

Please sign in to comment.