diff --git a/kernel/src/arch/hosted/mod.rs b/kernel/src/arch/hosted/mod.rs index 82ebe4e19..856d8a29b 100644 --- a/kernel/src/arch/hosted/mod.rs +++ b/kernel/src/arch/hosted/mod.rs @@ -95,12 +95,6 @@ fn handle_connection( chn: Sender, should_exit: std::sync::Arc, ) { - // enum ServerMessage { - // Exit, - // ServerPacket(Box), - // ServerPacketWithData([usize; 9], Vec), - // } - fn conn_thread(mut conn: TcpStream, sender: Sender, pid: PID) { loop { let mut raw_data = [0u8; 9 * std::mem::size_of::()]; @@ -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); diff --git a/kernel/src/arch/hosted/process.rs b/kernel/src/arch/hosted/process.rs index 57c7dbdd4..a0880bd9c 100644 --- a/kernel/src/arch/hosted/process.rs +++ b/kernel/src/arch/hosted/process.rs @@ -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!"); } diff --git a/kernel/src/services.rs b/kernel/src/services.rs index 92a1449cb..209e95bcf 100644 --- a/kernel/src/services.rs +++ b/kernel/src/services.rs @@ -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: {:?}", diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index e48952069..29b1da64a 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -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| {