-
Notifications
You must be signed in to change notification settings - Fork 22
Conversation
Will add the other architectures soon (unfortunately, the |
It seems it does not include implementation for a number of |
Yes. I tried to get the bare-minimum of thread support running, namely: spawning a thread. I didn't manage to on all platforms. I currently do not work on it, so feel free to pick it up if you want. (If you do, I'd suggest you to also only try thread spawning first, do the rest later. It's hard enough. ^^ Inline assembly for architectures you have never heard before.) |
@japaric does this PR look good? Could you please review/merge it before starting work on other |
This still needs support for the rest of the architectures before it can go forward. From looking at my commit list, at least sparc and PowerPC64 are missing. |
☔ The latest upstream changes (presumably f1624e5) made this pull request unmergeable. Please resolve the merge conflicts. |
@homunkulus try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First, sorry for taking so long to review this.
Second, thanks @tbu- for tackling this. This is tricky stuff!
The implementation looks reasonable to me. It's a good starting point. I mainly have nits about creating issues about what still needs to be implemented.
Cargo.toml
Outdated
@@ -6,7 +6,7 @@ name = "std" | |||
version = "0.1.0" | |||
|
|||
[dependencies] | |||
sc = "0.1.5" | |||
sc = { git = "git://github.com/japaric/syscall.rs" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this be switched back to the latest release?
// Save `fn_` and `arg` on the child stack. | ||
stp x0,x3,[x1,#-16]! | ||
|
||
mov x8,#220 // CLONE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't recall if it's possible or not but could NR_CLONE from the sc crate be used here (and on all the other instances) instead hardcoding the value? (I know the value is very unlikely to change; this is just for clarity and to avoid duplication)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know how to do that. (This value won't change, it would break a lot of programs and Linux is commited to backward-compatiblity on the syscall layer.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, that's fine.
src/libc/internal/aarch64.rs
Outdated
#[naked] | ||
#[no_mangle] | ||
unsafe extern "C" fn __steed_clone() { | ||
// Syscall number is passed in x8, syscall arguments in x0, x1, x2, x3, x4. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love these comments ❤️ ❤️ ❤️ . Great work, @tbu-. 👍
Some of the MUSL implementations say very little about what's going on.
} | ||
|
||
pub unsafe fn set_thread_pointer(thread_data: *mut ()) { | ||
let mut user_desc = linux::user_desc { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a note mentioning that the meaning of flags is explained in the asm block above?
src/thread/mod.rs
Outdated
impl ThreadId { | ||
// Generate a new unique thread ID. | ||
fn new() -> ThreadId { | ||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you create an issue and add a TODO about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/libc/mod.rs
Outdated
} | ||
*/ | ||
|
||
pub unsafe fn pthread_join(pthread: pthread_t, retval: *mut *mut c_void) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implementation looks different from the MUSL one, where did it come from? (I checked src/thread/pthread_join.c
). Regardless, it looks reasonable to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a simplified copy of __timedwait_cp
from src/thread/__timedwait.c
, which is called in pthread_join
by MUSL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment mentioning that file and that this is a simplified version?
pub struct Handler(()); | ||
|
||
impl Handler { | ||
pub unsafe fn new() -> Handler { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you create an issue and add a TODO about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -15,6 +15,10 @@ pub fn exit(code: i32) -> ! { | |||
unsafe { linux::exit_group(code) } | |||
} | |||
|
|||
pub fn page_size() -> usize { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you create an issue and add a TODO about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/libc/mod.rs
Outdated
} | ||
*/ | ||
|
||
pub unsafe fn pthread_create(pthread: *mut pthread_t, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implementation looks different from the MUSL one, where did it come from? (I checked src/thread/pthread_create.c
) Perhaps it is a simplified / minimal version of it. In any case, it looks reasonable to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a simplified version of the MUSL one, pthread_create
in src/thread/pthread_create.c
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment mentioning that file and that this is a simplified version, and the rationale behind omitting some parts (like the copy_tls stuff)?
src/sys/linux/thread.rs
Outdated
} | ||
|
||
/* | ||
impl Drop for Thread { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you create an issue and add a TODO about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@homunkulus try |
💔 Test failed - status-travis |
It only failed on tier-2 platforms. |
☔ The latest upstream changes (presumably #126) made this pull request unmergeable. Please resolve the merge conflicts. |
Please open an issue about the targets that are missing thread support. Ideally, we should cfg the thread code on the platforms where it's unimplemented to keep steed compiling and hello would working but panic when the thread API is used. But, if that tedious, feel free to just leave things as they are and put these targets in the allow_failures list |
|
@homunkulus try |
💔 Test failed - status-travis |
@japaric It seems that the parameters to |
If I put it into a different crate and disable LTO, then it works, but if either LTO is enabled or Not sure what to do about this. |
It sounds like I'm invoking UB somewhere. |
Hmmm, the problem could the extern "C" / symbol approach since in LTO there's only one object file. Perhaps you could try something like this: fn syscall_clone(
fn_: extern "C" fn(*mut c_void) -> *mut c_void,
child_stack: *mut c_void,
flags: c_ulong,
arg: *mut c_void,
ptid: *mut pid_t,
newtls: *mut c_void,
ctid: *mut pid_t,
) -> pid_t {
unsafe {
__steed_clone();
}
} the return type is going to be a problem there. Perhaps change the signature of |
Changing the signature of |
Maybe try something like test::black_box? |
It supports `spawn` and `join` so far. Only works on x86_64 so far. CC japaric#13.
I've read "This Week in Rust" and found that they just added the thing I need: @homunkulus try |
💔 Test failed - status-travis |
Oh, nice.
My hunch tells me that adding a |
This allows us to write the whole function in assembly without hacks.
Yep, also thought so. @homunkulus try |
☀️ Test successful - status-travis |
\o/ |
src/libc/internal/aarch64.rs
Outdated
@@ -34,7 +32,10 @@ unsafe extern "C" fn __steed_clone() { | |||
// | |||
// We save `fn_` and `arg` on the child stack. | |||
|
|||
asm!(" | |||
global_asm!(" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could even commit actual .s files, if you're interested, and do global_asm!(include_str!("./asm_file.s"));
// where CLONE and EXIT are the respective syscalls. Because it mangles | ||
// with the stack (in two processes at once), it needs to be written in the | ||
// target's assembly. | ||
#[link_name = "__steed_clone"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if you can achieve what @japaric suggested above with NR_CLONE
by doing this:
#[no_mangle]
extern "C" fn __steed_clone(nr: usize // <-- or whatever correct type is for syscall numbers
fn_: extern "C" fn(*mut c_void) -> *mut c_void,
child_stack: *mut c_void,
flags: c_ulong,
arg: *mut c_void,
ptid: *mut pid_t,
newtls: *mut c_void,
ctid: *mut pid_t) -> pid_t;
#[inline] // or whatever
fn syscall_clone(fn_: extern "C" fn(*mut c_void) -> *mut c_void,
child_stack: *mut c_void,
flags: c_ulong,
arg: *mut c_void,
ptid: *mut pid_t,
newtls: *mut c_void,
ctid: *mut pid_t) -> pid_t {
// assuming the first arg below is correct...
__steed_clone(sc::nr::CLONE, fn_, child_stack, flags, arg, ptid, newtls, ctid)
}
Now, in the assembly, can't you retrieve the syscall number from rax
or whatever the correct register is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that would be possible, but not zero-cost. :) It would actually pass that parameter at runtime in this case.
Excellent work, @tbu-! 💯 |
|
Yes, I do. However, I'm also implementing mutexes, I hope we're not duplicating work. |
tbu-@b1a8b91 :/ How did you do it? I copied the stuff from |
I implemented rwlock/mutex using atomics, somewhat similar to I never used |
I'd personally prefer to use parking-lot's implementation. It's been out there (and been tested) for a while and have quite a few advantages over libc's, like a const-fn constructors and smaller memory usage. |
I guess it it matter of priorities but it makes sense to avoid complexity and start with a simple textbook implementation for synchronization. The simple atomics based solution is widely known and used in many places, including musl. |
It supports
spawn
andjoin
so far.Only works on x86_64 so far.
CC #13.