MCPcopy Create free account
hub / github.com/chyyuu/os_kernel_lab / spawn

Method spawn

user/src/bin/stackful_coroutine.rs:181–205  ·  view source on GitHub ↗

While `yield` is the logically interesting function I think this the technically most interesting. When we spawn a new task we first check if there are any available tasks (tasks in `Parked` state). If we run out of tasks we panic in this scenario but there are several (better) ways to handle that. We keep things simple for now. When we find an available task we get the stack length and a pointe

(&mut self, f: fn())

Source from the content-addressed store, hash-verified

179 ///
180 /// Lastly we set the state as `Ready` which means we have work to do and is ready to do it.
181 pub fn spawn(&mut self, f: fn()) {
182 let available = self
183 .tasks
184 .iter_mut()
185 .find(|t| t.state == State::Available)
186 .expect("no available task.");
187
188 println!("RUNTIME: spawning task {}\n", available.id);
189 let size = available.stack.len();
190 unsafe {
191 let s_ptr = available.stack.as_mut_ptr().offset(size as isize);
192
193 // make sure our stack itself is 8 byte aligned - it will always
194 // offset to a lower memory address. Since we know we're at the "high"
195 // memory address of our allocated space, we know that offsetting to
196 // a lower one will be a valid address (given that we actually allocated)
197 // enough space to actually get an aligned pointer in the first place).
198 let s_ptr = (s_ptr as usize & !7) as *mut u8;
199
200 available.ctx.x1 = guard as u64; //ctx.x1 is old return address
201 available.ctx.nx1 = f as u64; //ctx.nx2 is new return address
202 available.ctx.x2 = s_ptr.offset(-32) as u64; //cxt.x2 is sp
203 }
204 available.state = State::Ready;
205 }
206}
207
208/// This is our guard function that we place on top of the stack. All this function does is set the

Callers 1

mainFunction · 0.80

Calls 2

findMethod · 0.80
lenMethod · 0.80

Tested by

no test coverage detected