Fixed naked function with arguments in green threads example. See https://github.com/cfsamson/example-greenthreads/issues/20 for more information.

This commit is contained in:
Carl Fredrik Samson
2020-12-06 00:44:31 +01:00
parent 3ba348601a
commit 760fd57be3

View File

@@ -149,7 +149,6 @@ _**Press the expand icon in the top right corner to show the example code.**_
```rust, edition2018 ```rust, edition2018
# #![feature(llvm_asm, naked_functions)] # #![feature(llvm_asm, naked_functions)]
# use std::ptr;
# #
# const DEFAULT_STACK_SIZE: usize = 1024 * 1024 * 2; # const DEFAULT_STACK_SIZE: usize = 1024 * 1024 * 2;
# const MAX_THREADS: usize = 4; # const MAX_THREADS: usize = 4;
@@ -172,7 +171,6 @@ _**Press the expand icon in the top right corner to show the example code.**_
# stack: Vec<u8>, # stack: Vec<u8>,
# ctx: ThreadContext, # ctx: ThreadContext,
# state: State, # state: State,
# task: Option<Box<dyn Fn()>>,
# } # }
# #
# #[derive(Debug, Default)] # #[derive(Debug, Default)]
@@ -185,7 +183,6 @@ _**Press the expand icon in the top right corner to show the example code.**_
# r12: u64, # r12: u64,
# rbx: u64, # rbx: u64,
# rbp: u64, # rbp: u64,
# thread_ptr: u64,
# } # }
# #
# impl Thread { # impl Thread {
@@ -195,7 +192,6 @@ _**Press the expand icon in the top right corner to show the example code.**_
# stack: vec![0_u8; DEFAULT_STACK_SIZE], # stack: vec![0_u8; DEFAULT_STACK_SIZE],
# ctx: ThreadContext::default(), # ctx: ThreadContext::default(),
# state: State::Available, # state: State::Available,
# task: None,
# } # }
# } # }
# } # }
@@ -207,11 +203,9 @@ _**Press the expand icon in the top right corner to show the example code.**_
# stack: vec![0_u8; DEFAULT_STACK_SIZE], # stack: vec![0_u8; DEFAULT_STACK_SIZE],
# ctx: ThreadContext::default(), # ctx: ThreadContext::default(),
# state: State::Running, # state: State::Running,
# task: None,
# }; # };
# #
# let mut threads = vec![base_thread]; # let mut threads = vec![base_thread];
# threads[0].ctx.thread_ptr = &threads[0] as *const Thread as u64;
# let mut available_threads: Vec<Thread> = (1..MAX_THREADS).map(|i| Thread::new(i)).collect(); # let mut available_threads: Vec<Thread> = (1..MAX_THREADS).map(|i| Thread::new(i)).collect();
# threads.append(&mut available_threads); # threads.append(&mut available_threads);
# #
@@ -261,46 +255,44 @@ _**Press the expand icon in the top right corner to show the example code.**_
# self.current = pos; # self.current = pos;
# #
# unsafe { # unsafe {
# switch(&mut self.threads[old_pos].ctx, &self.threads[pos].ctx); # let old: *mut ThreadContext = &mut self.threads[old_pos].ctx;
# let new: *const ThreadContext = &self.threads[pos].ctx;
# llvm_asm!(
# "mov $0, %rdi
# mov $1, %rsi"::"r"(old), "r"(new)
# );
# switch();
# } # }
# true # self.threads.len() > 0
# } # }
# #
# pub fn spawn<F: Fn() + 'static>(f: F){ # pub fn spawn(&mut self, f: fn()) {
# let available = self
# .threads
# .iter_mut()
# .find(|t| t.state == State::Available)
# .expect("no available thread.");
#
# let size = available.stack.len();
# unsafe { # unsafe {
# let rt_ptr = RUNTIME as *mut Runtime; # let s_ptr = available.stack.as_mut_ptr().offset(size as isize);
# let available = (*rt_ptr) # let s_ptr = (s_ptr as usize & !15) as *mut u8;
# .threads # std::ptr::write(s_ptr.offset(-16) as *mut u64, guard as u64);
# .iter_mut() # std::ptr::write(s_ptr.offset(-24) as *mut u64, skip as u64);
# .find(|t| t.state == State::Available) # std::ptr::write(s_ptr.offset(-32) as *mut u64, f as u64);
# .expect("no available thread."); # available.ctx.rsp = s_ptr.offset(-32) as u64;
#
# let size = available.stack.len();
# let s_ptr = available.stack.as_mut_ptr();
# available.task = Some(Box::new(f));
# available.ctx.thread_ptr = available as *const Thread as u64;
# ptr::write(s_ptr.offset((size - 8) as isize) as *mut u64, guard as u64);
# ptr::write(s_ptr.offset((size - 16) as isize) as *mut u64, call as u64);
# available.ctx.rsp = s_ptr.offset((size - 16) as isize) as u64;
# available.state = State::Ready;
# } # }
# } # available.state = State::Ready;
# }
#
# fn call(thread: u64) {
# let thread = unsafe { &*(thread as *const Thread) };
# if let Some(f) = &thread.task {
# f();
# } # }
# } # }
# #
# #[naked] # #[naked]
# fn skip() { }
#
# fn guard() { # fn guard() {
# unsafe { # unsafe {
# let rt_ptr = RUNTIME as *mut Runtime; # let rt_ptr = RUNTIME as *mut Runtime;
# let rt = &mut *rt_ptr; # (*rt_ptr).t_return();
# println!("THREAD {} FINISHED.", rt.threads[rt.current].id);
# rt.t_return();
# }; # };
# } # }
# #
@@ -313,30 +305,24 @@ _**Press the expand icon in the top right corner to show the example code.**_
# #
# #[naked] # #[naked]
# #[inline(never)] # #[inline(never)]
# unsafe fn switch(old: *mut ThreadContext, new: *const ThreadContext) { # unsafe fn switch() {
# llvm_asm!(" # llvm_asm!("
# mov %rsp, 0x00($0) # mov %rsp, 0x00(%rdi)
# mov %r15, 0x08($0) # mov %r15, 0x08(%rdi)
# mov %r14, 0x10($0) # mov %r14, 0x10(%rdi)
# mov %r13, 0x18($0) # mov %r13, 0x18(%rdi)
# mov %r12, 0x20($0) # mov %r12, 0x20(%rdi)
# mov %rbx, 0x28($0) # mov %rbx, 0x28(%rdi)
# mov %rbp, 0x30($0) # mov %rbp, 0x30(%rdi)
# #
# mov 0x00($1), %rsp # mov 0x00(%rsi), %rsp
# mov 0x08($1), %r15 # mov 0x08(%rsi), %r15
# mov 0x10($1), %r14 # mov 0x10(%rsi), %r14
# mov 0x18($1), %r13 # mov 0x18(%rsi), %r13
# mov 0x20($1), %r12 # mov 0x20(%rsi), %r12
# mov 0x28($1), %rbx # mov 0x28(%rsi), %rbx
# mov 0x30($1), %rbp # mov 0x30(%rsi), %rbp
# mov 0x38($1), %rdi
# ret
# " # "
# :
# : "r"(old), "r"(new)
# :
# : "alignstack"
# ); # );
# } # }
# #[cfg(not(windows))] # #[cfg(not(windows))]