mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-04 04:27:34 +00:00
kernel: fix hosted mode
The process scheduler changed in subtle ways taht completely broke hosted mode. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
ca2a47e67f
commit
fc8d78c2ec
4 changed files with 82 additions and 47 deletions
|
|
@ -95,12 +95,6 @@ fn handle_connection(
|
|||
chn: Sender<ThreadMessage>,
|
||||
should_exit: std::sync::Arc<core::sync::atomic::AtomicBool>,
|
||||
) {
|
||||
// enum ServerMessage {
|
||||
// Exit,
|
||||
// ServerPacket(Box<SysCall>),
|
||||
// ServerPacketWithData([usize; 9], Vec<u8>),
|
||||
// }
|
||||
|
||||
fn conn_thread(mut conn: TcpStream, sender: Sender<ThreadMessage>, pid: PID) {
|
||||
loop {
|
||||
let mut raw_data = [0u8; 9 * std::mem::size_of::<usize>()];
|
||||
|
|
@ -184,8 +178,6 @@ fn handle_connection(
|
|||
}
|
||||
}
|
||||
|
||||
// let (sender, receiver) = unbounded();
|
||||
// let conn_sender = sender.clone();
|
||||
let conn_sender = chn.clone();
|
||||
let conn_thread = std::thread::Builder::new()
|
||||
.name(format!("PID {}: client connection thread", pid))
|
||||
|
|
@ -267,7 +259,6 @@ fn listen_thread(
|
|||
let NewPidMessage::NewPid(new_pid) = new_pid_channel
|
||||
.recv()
|
||||
.expect("couldn't receive message from main thread");
|
||||
// println!("KERNEL({}): New client connected from {}", new_pid, _addr);
|
||||
let conn_copy = conn.try_clone().expect("couldn't duplicate connection");
|
||||
let should_exit = should_exit.clone();
|
||||
let jh = std::thread::Builder::new()
|
||||
|
|
@ -506,6 +497,17 @@ pub fn idle() -> bool {
|
|||
// println!("KERNEL: Done sending");
|
||||
}
|
||||
|
||||
{
|
||||
let current_process = crate::arch::process::Process::current();
|
||||
if current_process.thread_exists(thread_id) {
|
||||
SystemServices::with_mut(|ss| {
|
||||
ss.switch_to_thread(pid, Some(thread_id))
|
||||
})
|
||||
.unwrap();
|
||||
crate::arch::process::Process::current().set_tid(thread_id).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the syscall within the Xous kernel
|
||||
let response = crate::syscall::handle(pid, thread_id, false, call)
|
||||
.unwrap_or_else(Result::Error);
|
||||
|
|
|
|||
|
|
@ -222,35 +222,22 @@ impl Process {
|
|||
PROCESS_TABLE.with(|pt| {
|
||||
let process_table = &mut *pt.borrow_mut();
|
||||
Self::setup_thread_inner(thread, process_table);
|
||||
// println!(
|
||||
// "KERNEL({}): self.contexts[{}].allocated = {}",
|
||||
// current_pid_idx,
|
||||
// context - 1,
|
||||
// process.contexts[context - 1].allocated
|
||||
// );
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn current_thread(&mut self) -> TID {
|
||||
// PROCESS_TABLE.with(|pt| {
|
||||
// let mut process_table = pt.borrow_mut();
|
||||
// let current_pid_idx = process_table.current.get() as usize - 1;
|
||||
// let process = &mut process_table.table[current_pid_idx].as_mut().unwrap();
|
||||
// process.current_context
|
||||
// })
|
||||
// }
|
||||
|
||||
/// Set the current context number.
|
||||
/// Set the current thread ID.
|
||||
pub fn set_tid(&mut self, thread: TID) -> Result<(), xous_kernel::Error> {
|
||||
assert!(thread > 0);
|
||||
PROCESS_TABLE.with(|pt| {
|
||||
let mut process_table = pt.borrow_mut();
|
||||
let current_pid_idx = process_table.current.get() as usize - 1;
|
||||
let current_pid = process_table.current.get();
|
||||
let current_pid_idx = current_pid as usize - 1;
|
||||
let process = &mut process_table.table[current_pid_idx].as_mut().unwrap();
|
||||
assert!(
|
||||
process.threads[thread - 1].allocated,
|
||||
"tried to switch to thread {} which wasn't allocated",
|
||||
"process {} tried to switch to thread {} which wasn't allocated",
|
||||
current_pid,
|
||||
thread
|
||||
);
|
||||
process.current_thread = thread;
|
||||
|
|
@ -273,8 +260,20 @@ impl Process {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn thread_exists(&self, _tid: TID) -> bool {
|
||||
false
|
||||
pub fn thread_exists(&self, tid: TID) -> bool {
|
||||
if tid == 0 {
|
||||
return false;
|
||||
}
|
||||
PROCESS_TABLE.with(|pt| {
|
||||
let process_table = pt.borrow();
|
||||
let current_pid = process_table.current.get();
|
||||
let current_pid_idx = current_pid as usize - 1;
|
||||
if let Some(Some(process)) = process_table.table.get(current_pid_idx) {
|
||||
process.threads.get(tid - 1).map(|t| t.allocated).unwrap_or(false)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_thread_result(&mut self, tid: TID, result: xous_kernel::Result) {
|
||||
|
|
@ -283,11 +282,11 @@ impl Process {
|
|||
let mut process_table = pt.borrow_mut();
|
||||
let current_pid_idx = process_table.current.get() as usize - 1;
|
||||
let process = &mut process_table.table[current_pid_idx].as_mut().unwrap();
|
||||
assert!(
|
||||
process.threads[tid - 1].allocated,
|
||||
"thread {} is not allocated",
|
||||
tid,
|
||||
);
|
||||
// assert!(
|
||||
// process.threads[tid - 1].allocated,
|
||||
// "thread {} is not allocated",
|
||||
// tid,
|
||||
// );
|
||||
|
||||
let mut response = vec![];
|
||||
// Add the destination thread ID to the start of the packet.
|
||||
|
|
@ -305,7 +304,11 @@ impl Process {
|
|||
}
|
||||
|
||||
// If there is memory to return for this thread, also return that.
|
||||
if let Some(buf) = process.memory_to_return[tid - 1].take() {
|
||||
if let Some(buf) = process
|
||||
.memory_to_return
|
||||
.get_mut(tid - 1)
|
||||
.and_then(|v| v.take())
|
||||
{
|
||||
if result.memory().is_some() {
|
||||
panic!("Result has memory and we're also returning memory!");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -698,6 +698,7 @@ impl SystemServices {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub fn find_next_thread(thread_mask: usize, current_thread: usize) -> usize {
|
||||
// From https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
|
||||
// This platform has a multiplier, so this is fast
|
||||
|
|
@ -727,6 +728,23 @@ impl SystemServices {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_pointer_width = "32"))]
|
||||
pub fn find_next_thread(thread_mask: usize, current_thread: usize) -> usize {
|
||||
if thread_mask == 0 {
|
||||
panic!("no threads were available to run");
|
||||
}
|
||||
if thread_mask.is_power_of_two() {
|
||||
thread_mask.trailing_zeros() as usize
|
||||
} else {
|
||||
let upper_bits = thread_mask & !((2usize << current_thread) - 1);
|
||||
if upper_bits != 0 {
|
||||
upper_bits.trailing_zeros() as usize
|
||||
} else {
|
||||
thread_mask.trailing_zeros() as usize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark the current process as "Ready to run".
|
||||
///
|
||||
/// # Panics
|
||||
|
|
@ -815,6 +833,8 @@ impl SystemServices {
|
|||
}
|
||||
|
||||
// Activate this process on this CPU
|
||||
#[cfg(not(target_os = "xous"))]
|
||||
process.activate()?;
|
||||
ArchProcess::current().set_tid(new_thread)?;
|
||||
process.current_thread = new_thread as _;
|
||||
ProcessState::Running(ready_threads & !(1 << new_thread))
|
||||
|
|
@ -1549,7 +1569,6 @@ impl SystemServices {
|
|||
|
||||
// println!("KERNEL({}): Created new thread {}", pid, new_tid);
|
||||
|
||||
// let old_state = process.state;
|
||||
// Queue the thread to run
|
||||
process.state = match process.state {
|
||||
ProcessState::Running(x) => ProcessState::Running(x | (1 << new_tid)),
|
||||
|
|
@ -1825,15 +1844,21 @@ impl SystemServices {
|
|||
// existing connection
|
||||
for (connection_idx, server_idx) in process_inner.connection_map.iter().enumerate() {
|
||||
// If we find an empty slot, use it
|
||||
if server_idx.is_none() {
|
||||
let Some(server_idx) = server_idx else {
|
||||
if slot_idx.is_none() {
|
||||
slot_idx = Some(connection_idx);
|
||||
}
|
||||
continue;
|
||||
};
|
||||
let server_idx = server_idx.get() as usize;
|
||||
|
||||
// Tombstone or unallocated server index
|
||||
if server_idx < 2 {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If a connection to this server ID exists already, return it.
|
||||
let server_idx = (server_idx.unwrap().get() as usize) - 2;
|
||||
let server_idx = server_idx - 2;
|
||||
if let Some(allocated_server) = &self.servers[server_idx] {
|
||||
if allocated_server.sid == sid {
|
||||
// println!("KERNEL({}): Existing connection to SID {:?} found in this process @ {}, process connection map is: {:?}",
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@ fn send_message(pid: PID, tid: TID, cid: CID, message: Message) -> SysCallResult
|
|||
|
||||
// Mark the server's context as "Ready". If this fails, return the context
|
||||
// to the blocking list.
|
||||
#[cfg(target_os = "xous")]
|
||||
ss.ready_thread(server_pid, server_tid).map_err(|e| {
|
||||
ss.server_from_sidx_mut(sidx)
|
||||
.expect("server couldn't be located")
|
||||
|
|
@ -366,6 +367,7 @@ fn return_memory(
|
|||
if !cfg!(baremetal) || in_irq || !client_is_runnable {
|
||||
// Send a message to the client, in order to wake it up
|
||||
// print!(" [waking up PID {}:{}]", client_pid, client_tid);
|
||||
#[cfg(baremetal)]
|
||||
ss.ready_thread(client_pid, client_tid)?;
|
||||
#[cfg(not(baremetal))]
|
||||
ss.switch_to_thread(client_pid, Some(client_tid))?;
|
||||
|
|
@ -724,7 +726,7 @@ fn reply_and_receive_next(
|
|||
.unwrap_or(Err(xous_kernel::Error::ProcessNotFound))
|
||||
} else {
|
||||
// Switch to the client and return the result
|
||||
ss.ready_thread(response.pid, response.tid)?;
|
||||
//ss.ready_thread(response.pid, response.tid)?;
|
||||
ss.switch_to_thread(response.pid, Some(response.tid))?;
|
||||
ss.set_thread_result(response.pid, response.tid, response.result)?;
|
||||
|
||||
|
|
@ -1057,16 +1059,19 @@ pub fn handle_inner(pid: PID, tid: TID, in_irq: bool, call: SysCall) -> SysCallR
|
|||
}),
|
||||
SysCall::CreateThread(thread_init) => SystemServices::with_mut(|ss| {
|
||||
ss.create_thread(pid, thread_init).map(|new_tid| {
|
||||
// Immediately switch to the new thread
|
||||
ss.switch_to_thread(pid, Some(new_tid))
|
||||
.expect("couldn't activate new thread");
|
||||
|
||||
// Set the return value of the existing thread to be the new thread ID
|
||||
ss.set_thread_result(pid, tid, xous_kernel::Result::ThreadID(new_tid))
|
||||
.expect("couldn't set new thread ID");
|
||||
if cfg!(target_os = "xous") {
|
||||
// Immediately switch to the new thread
|
||||
ss.switch_to_thread(pid, Some(new_tid))
|
||||
.expect("couldn't activate new thread");
|
||||
ss.set_thread_result(pid, tid, xous_kernel::Result::ThreadID(new_tid))
|
||||
.expect("couldn't set new thread ID");
|
||||
|
||||
// Return `ResumeProcess` since we're switching threads
|
||||
xous_kernel::Result::ResumeProcess
|
||||
// Return `ResumeProcess` since we're switching threads
|
||||
xous_kernel::Result::ResumeProcess
|
||||
} else {
|
||||
xous_kernel::Result::ThreadID(new_tid)
|
||||
}
|
||||
})
|
||||
}),
|
||||
SysCall::CreateProcess(process_init) => SystemServices::with_mut(|ss| {
|
||||
|
|
|
|||
Loading…
Reference in a new issue