Skip to content
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

Asm experiments. NOT FOR MERGE #17

Closed
wants to merge 2 commits into from
Closed

Asm experiments. NOT FOR MERGE #17

wants to merge 2 commits into from

Conversation

target-san
Copy link

Note. This PR is incomplete and just shows some raw ideas. Don't accep
Please pay attention to asm/x86_64-linux.S, src/backend.rs
lib/libx86_64-linux.a is built from mentioned ASM file.

  1. backend links against pre-built lib, so no inline asm, GNU tool etc.
  2. Context store is unstructured, and is just a memory buffer; it's size is different for each platform, but is defined via simple constant. So no more multiple Registers definitions
  3. Swap function is multi-purpose; controlled via null-arity of each argument

@zonyitoo
Copy link
Owner

Why should the Swap function accept null pointers?

@zonyitoo
Copy link
Owner

By the way, I was experimenting to use the asm!() to inline all those .S assembly codes inside the .rs file, so that it can be compiled without depending on external C compiler.

But ... Since asm!() is not going to become stable recently, and I also encountered bugs to switch contexts inside a Rust function, I think there is lots work to do.

@target-san
Copy link
Author

Swap: it dedupes code. Because save is first half of swap, and load is the second. I don't like code duping. Less code, less possible typos and errors. Especially in assembly. By this trick we have 3 funcs in 1. If first arg is null, there's no save. If second one is null, there's no load.

Asm: that's why I'm digging into prebuilt binaries. If asm becomes stable, we could try to migrate. As per your troubles, the first one I can see is uncontrollable stack and argument management done by Rust compiler. Like, in swap we need to pick return address from stack. There should be something like #[naked] or #[no_prologue].

Anyway, what do you say? I mean, does this look sound and promising?

@zonyitoo
Copy link
Owner

My experiment is in branch feature-inlineasm and it does not work well. I still trying to find out where is the problem.

The author of Redox OS is pushing the #[naked] attr to go into the rustc. I keep discussing with him and trying to bring green threads as one of a builtin asynchronous facilities.

I suspected that my problem is cause by messing up with the stack frame, but can't find a clue. But the original code in .S files works fine, so I think the #[naked] attr should help.

By the way, the fnstcw and ldmxcsr instructions are so convenient! I am not so familiar with assembly code. Great job!

@target-san
Copy link
Author

I took them from Boost.Context assembly, and stumbled upon some mentions that x87 and MMX control words should be preserved. Also I didn't find any mentions about MMX registers needed to be preserved.

As per your trouble, I suspect it's really around the stack mess. Please note that common function prolog is storing stack base pointer on stack to preserve parent call frame and then setting BP to SP to establish new one. After this, most argument lookup, at least for the ones on stack, is done relative to BP. So the funcs which mess with context should have no such prolog code. But it's established via compiler automatically. That's why I assume asm!() as no-opt to us. At least until #[naked]. But TBH it's then easier to write ASM directly. And know that this particular piece is OUCH and should be approached with care.

So, if you find the proposed way Ok, I'll try to move Rust piece this direction. I'd prefer using ASM from Boost as guidance further. In particular, I don't think we really need segmented stacks support - they look more as leftover from abandoned design.

@zonyitoo
Copy link
Owner

Agree. I personally don't like the segmented stacks, it has obviously overhead on the boundary. By the way, do you know how to let Rust's runtime to print Xxx thread has overflow its stack when coroutines has overflowed its stack rather than just prints Unknown error occurs (Segmentation fault).

@zonyitoo
Copy link
Owner

Here is the _switch function in lthread project: https://github.com/halayli/lthread/blob/master/src/lthread.c#L58.

So tiny and fast.

@target-san
Copy link
Author

Checked lthread. Some issues:

  1. No x87/MMX storing; not the best case if we wanna be universal
  2. Only Linux, since Windows requires more context handling and different order of arguments
  3. No code for other platforms
  4. Almost the same in terms of code size. If x87/MMX stuff is added, mine will be only 2 instructions bigger.
  5. No context switching, or it's in C part
  6. Same as current context-rs, full definition for registers storage, which I'd like to avoid.

So it's barely a subset of what context-rs should be.

@zonyitoo
Copy link
Owner

Agree.

One more thing for the #16 issue, I found that Rust will always generate a function like this

test_function_mangling:
    push %rbp
    mov %rsp, %rbp
    // ... The real function body
    pop %rbp
    ret

So the problem is the %rbp is pushed onto the stack, and poped out after the real function body is exectued. If replace the function body as the context switch function, which will save %rsp but don't pop out %rbp and the return address on the stack, just switch %rsp directly and then let the rest of the generated code to pop out the %rbp and ret.

As what I did in https://github.com/zonyitoo/context-rs/blob/feature-inlineasm/src/detail/x86_64.rs#L125.

If you are interested in bring inline asm into this crate, I am happy to discuss in #16 .

@target-san
Copy link
Author

I'm closing this one from my side for now. Will make PR when I'll have complete solution.

@target-san target-san closed this Oct 23, 2015
@target-san target-san deleted the asm-experiments branch October 29, 2015 22:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants