Creating Our Own Fibers 118 Let's present the function before we go on to explain the last part of it: #[inline(never)] fn t_yield(&mut self)-> bool { let mut pos = self. current; while self. threads[pos]. state != State::Ready { pos += 1; if pos == self. threads. len() { pos = 0; } if pos == self. current { return false; } } if self. threads[self. current]. state != State::Available { self. threads[self. current]. state = State::Ready; } self. threads[pos]. state = State::Running; let old_pos = self. current; self. current = pos; unsafe { let old: *mut Thread Context = &mut self. threads[old_pos]. ctx; let new: *const Thread Context = &self. threads[pos]. ctx; asm!("call switch", in("rdi") old, in("rsi") new, clobber_abi("C")); } self. threads. len() > 0 } The next thing we do is to call the function switch, which will save the current context (the old context) and load the new context into the CPU. The new context is either a new task or all the information the CPU needs to resume work on an existing task. Our switch function, which we will cover a little further down, takes two arguments and is marked as #[naked]. Naked functions are not like normal functions. They don't accept formal arguments, for example, so we can't simply call it in Rust as a normal function like switch(old, new). Y ou see, usually, when we call a function with two arguments, the compiler will place each argument in a register described by the calling convention for the platform. However, when we call a #[naked] function, we need to take care of this ourselves. Therefore, we pass in the address to our old and new Thread Context using assembly. rdi is the register for the first argument in the System V ABI calling convention and rsi is the register used for the second argument. The #[inline(never)] attribute prevents the compiler from simply substituting a call to our function with a copy of the function content wherever it's called (this is what inlining means). This is 