Nothing to see here, move along meow
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 16 kB View raw
1use crate::cap::pool::POOL; 2use crate::ipc::{AlwaysBlocked, IpcOutcome, endpoint, message}; 3use crate::proc::context::{CpuContext, IpcMessage}; 4use crate::proc::{BlockedReason, PROCESSES, ProcessState}; 5use crate::tests::helpers::alloc_endpoint_cap; 6use lancer_core::object_layout::EndpointObject; 7 8crate::kernel_test!( 9 fn send_blocks_when_no_receiver() { 10 let (id, generation, cap) = alloc_endpoint_cap(); 11 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 12 let mut ptable = PROCESSES.lock(); 13 14 let created = ptable.allocate(&mut allocator).expect("alloc"); 15 ptable.start(created).expect("start"); 16 let pid = created.pid(); 17 ptable.simulate_dispatch(pid); 18 19 ptable.exec_mut(pid).unwrap().ipc_message = IpcMessage::from_regs([1, 2, 3, 4, 5, 6]); 20 let result = endpoint::do_send(&cap, pid, &mut ptable); 21 match result { 22 Ok(IpcOutcome::Blocked) => { 23 assert!(ptable[pid].state() == ProcessState::Blocked); 24 assert!(matches!( 25 ptable[pid].blocked_reason(), 26 Some(BlockedReason::Sending(eid, _)) if eid == id 27 )); 28 } 29 _ => panic!("expected Blocked when no receiver"), 30 } 31 32 ptable.destroy(pid, &mut allocator); 33 let _ = POOL.lock().dec_ref_phys(id, generation); 34 } 35); 36 37crate::kernel_test!( 38 fn multiple_senders_fifo_order() { 39 let (id, generation, cap) = alloc_endpoint_cap(); 40 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 41 let mut ptable = PROCESSES.lock(); 42 43 let a_created = ptable.allocate(&mut allocator).expect("alloc A"); 44 let b_created = ptable.allocate(&mut allocator).expect("alloc B"); 45 let recv_created = ptable.allocate(&mut allocator).expect("alloc recv"); 46 ptable.start(a_created).expect("start A"); 47 ptable.start(b_created).expect("start B"); 48 ptable.start(recv_created).expect("start recv"); 49 let a_pid = a_created.pid(); 50 let b_pid = b_created.pid(); 51 let recv_pid = recv_created.pid(); 52 53 ptable.exec_mut(a_pid).unwrap().ipc_message = 54 IpcMessage::from_regs([0xAAAA, 0, 0, 0, 0, 0]); 55 ptable.simulate_dispatch(a_pid); 56 let _ = endpoint::do_send(&cap, a_pid, &mut ptable); 57 58 ptable.exec_mut(b_pid).unwrap().ipc_message = 59 IpcMessage::from_regs([0xBBBB, 0, 0, 0, 0, 0]); 60 ptable.simulate_dispatch(b_pid); 61 let _ = endpoint::do_send(&cap, b_pid, &mut ptable); 62 63 let result = endpoint::do_recv(&cap, recv_pid, &mut ptable); 64 match result { 65 Ok(IpcOutcome::Done(sender)) => { 66 assert!(sender == a_pid, "first recv should get sender A (FIFO)"); 67 } 68 _ => panic!("expected Done from recv"), 69 } 70 71 let result2 = endpoint::do_recv(&cap, recv_pid, &mut ptable); 72 match result2 { 73 Ok(IpcOutcome::Done(sender)) => { 74 assert!(sender == b_pid, "second recv should get sender B (FIFO)"); 75 } 76 _ => panic!("expected Done from second recv"), 77 } 78 79 ptable.destroy(a_pid, &mut allocator); 80 ptable.destroy(b_pid, &mut allocator); 81 ptable.destroy(recv_pid, &mut allocator); 82 let _ = POOL.lock().dec_ref_phys(id, generation); 83 } 84); 85 86crate::kernel_test!( 87 fn recv_blocks_when_no_sender() { 88 let (id, generation, cap) = alloc_endpoint_cap(); 89 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 90 let mut ptable = PROCESSES.lock(); 91 92 let created = ptable.allocate(&mut allocator).expect("alloc"); 93 ptable.start(created).expect("start"); 94 let pid = created.pid(); 95 ptable.simulate_dispatch(pid); 96 97 let result = endpoint::do_recv(&cap, pid, &mut ptable); 98 match result { 99 Ok(IpcOutcome::Blocked) => { 100 assert!(ptable[pid].state() == ProcessState::Blocked); 101 assert!(matches!( 102 ptable[pid].blocked_reason(), 103 Some(BlockedReason::Receiving(eid, _)) if eid == id 104 )); 105 } 106 _ => panic!("expected Blocked when no sender"), 107 } 108 109 ptable.destroy(pid, &mut allocator); 110 let _ = POOL.lock().dec_ref_phys(id, generation); 111 } 112); 113 114crate::kernel_test!( 115 fn call_blocks_caller() { 116 let (id, generation, cap) = alloc_endpoint_cap(); 117 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 118 let mut ptable = PROCESSES.lock(); 119 120 let created = ptable.allocate(&mut allocator).expect("alloc"); 121 ptable.start(created).expect("start"); 122 let pid = created.pid(); 123 ptable.simulate_dispatch(pid); 124 125 ptable.exec_mut(pid).unwrap().ipc_message = IpcMessage::from_regs([0xCA11, 0, 0, 0, 0, 0]); 126 let result = endpoint::do_call(&cap, pid, &mut ptable); 127 match result { 128 Ok(AlwaysBlocked) => { 129 assert!(ptable[pid].state() == ProcessState::Blocked); 130 assert!(matches!( 131 ptable[pid].blocked_reason(), 132 Some(BlockedReason::Calling(eid, _)) if eid == id 133 )); 134 } 135 _ => panic!("expected Blocked from call with no receiver"), 136 } 137 138 ptable.destroy(pid, &mut allocator); 139 let _ = POOL.lock().dec_ref_phys(id, generation); 140 } 141); 142 143crate::kernel_test!( 144 fn endpoint_holder_set_on_recv() { 145 let (id, generation, cap) = alloc_endpoint_cap(); 146 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 147 let mut ptable = PROCESSES.lock(); 148 149 let sender_created = ptable.allocate(&mut allocator).expect("alloc sender"); 150 let recv_created = ptable.allocate(&mut allocator).expect("alloc recv"); 151 ptable.start(sender_created).expect("start sender"); 152 ptable.start(recv_created).expect("start recv"); 153 let sender_pid = sender_created.pid(); 154 let recv_pid = recv_created.pid(); 155 156 ptable.exec_mut(sender_pid).unwrap().ipc_message = 157 IpcMessage::from_regs([0, 0, 0, 0, 0, 0]); 158 ptable.simulate_dispatch(sender_pid); 159 let _ = endpoint::do_send(&cap, sender_pid, &mut ptable); 160 161 let _ = endpoint::do_recv(&cap, recv_pid, &mut ptable); 162 163 let pool = POOL.lock(); 164 let ep = pool.read_as::<EndpointObject>(id, generation).unwrap(); 165 assert!( 166 endpoint::load_holder(ep) == Some(recv_pid), 167 "endpoint holder should be set to receiver after do_recv" 168 ); 169 drop(pool); 170 171 ptable.destroy(sender_pid, &mut allocator); 172 ptable.destroy(recv_pid, &mut allocator); 173 let _ = POOL.lock().dec_ref_phys(id, generation); 174 } 175); 176 177crate::kernel_test!( 178 fn dequeue_genuine_receiver_skips_callers() { 179 let (id, generation, cap) = alloc_endpoint_cap(); 180 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 181 let mut ptable = PROCESSES.lock(); 182 183 let caller_created = ptable.allocate(&mut allocator).expect("alloc caller"); 184 let recv_created = ptable.allocate(&mut allocator).expect("alloc recv"); 185 let sender_created = ptable.allocate(&mut allocator).expect("alloc sender"); 186 ptable.start(caller_created).expect("start caller"); 187 ptable.start(recv_created).expect("start recv"); 188 ptable.start(sender_created).expect("start sender"); 189 let caller_pid = caller_created.pid(); 190 let recv_pid = recv_created.pid(); 191 let sender_pid = sender_created.pid(); 192 193 ptable.simulate_dispatch(recv_pid); 194 let blocked_recv = ptable[recv_pid] 195 .block_on(BlockedReason::Receiving(id, generation)) 196 .expect("block recv"); 197 198 { 199 let mut pool = POOL.lock(); 200 let ep = pool.write_as::<EndpointObject>(id, generation).unwrap(); 201 let mut receivers = endpoint::load_receivers(ep); 202 endpoint::enqueue(&mut receivers, blocked_recv, &mut ptable).expect("enqueue recv"); 203 let ep = pool.write_as::<EndpointObject>(id, generation).unwrap(); 204 endpoint::store_receivers(ep, &receivers); 205 } 206 207 ptable.exec_mut(caller_pid).unwrap().ipc_message = 208 IpcMessage::from_regs([0xCA11, 0, 0, 0, 0, 0]); 209 ptable.simulate_dispatch(caller_pid); 210 let result = endpoint::do_call(&cap, caller_pid, &mut ptable); 211 assert!(matches!(result, Ok(AlwaysBlocked))); 212 213 assert!( 214 ptable[recv_pid].state() == ProcessState::Ready, 215 "genuine receiver should be unblocked by call" 216 ); 217 218 ptable.exec_mut(sender_pid).unwrap().ipc_message = 219 IpcMessage::from_regs([0x5E4D, 0, 0, 0, 0, 0]); 220 ptable.simulate_dispatch(sender_pid); 221 let send_result = endpoint::do_send(&cap, sender_pid, &mut ptable); 222 assert!( 223 matches!(send_result, Ok(IpcOutcome::Blocked)), 224 "send should block because only caller (not genuine recv) is in queue" 225 ); 226 227 ptable.destroy(caller_pid, &mut allocator); 228 ptable.destroy(recv_pid, &mut allocator); 229 ptable.destroy(sender_pid, &mut allocator); 230 let _ = POOL.lock().dec_ref_phys(id, generation); 231 } 232); 233 234crate::kernel_test!( 235 fn send_delivers_all_six_registers() { 236 let (id, generation, cap) = alloc_endpoint_cap(); 237 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 238 let mut ptable = PROCESSES.lock(); 239 240 let sender_created = ptable.allocate(&mut allocator).expect("alloc sender"); 241 let recv_created = ptable.allocate(&mut allocator).expect("alloc recv"); 242 ptable.start(sender_created).expect("start sender"); 243 ptable.start(recv_created).expect("start recv"); 244 let sender_pid = sender_created.pid(); 245 let recv_pid = recv_created.pid(); 246 247 let regs = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66]; 248 ptable.exec_mut(sender_pid).unwrap().ipc_message = IpcMessage::from_regs(regs); 249 ptable.simulate_dispatch(sender_pid); 250 let _ = endpoint::do_send(&cap, sender_pid, &mut ptable); 251 252 let result = endpoint::do_recv(&cap, recv_pid, &mut ptable); 253 match result { 254 Ok(IpcOutcome::Done(sender)) => assert!(sender == sender_pid), 255 _ => panic!("expected Done from recv"), 256 } 257 258 let recv_msg = ptable.exec(recv_pid).unwrap().ipc_message; 259 let mut ctx = CpuContext::zero(); 260 message::inject_into_context(&mut ctx, &recv_msg); 261 ctx.rax = sender_pid.raw() as u64; 262 263 assert!(ctx.rsi == 0x11, "reg[0] mismatch"); 264 assert!(ctx.rdx == 0x22, "reg[1] mismatch"); 265 assert!(ctx.r10 == 0x33, "reg[2] mismatch"); 266 assert!(ctx.r8 == 0x44, "reg[3] mismatch"); 267 assert!(ctx.r9 == 0x55, "reg[4] mismatch"); 268 assert!(ctx.r12 == 0x66, "reg[5] mismatch"); 269 270 ptable.destroy(sender_pid, &mut allocator); 271 ptable.destroy(recv_pid, &mut allocator); 272 let _ = POOL.lock().dec_ref_phys(id, generation); 273 } 274); 275 276crate::kernel_test!( 277 fn try_recv_returns_would_block_when_empty() { 278 let (id, generation, cap) = alloc_endpoint_cap(); 279 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 280 let mut ptable = PROCESSES.lock(); 281 282 let created = ptable.allocate(&mut allocator).expect("alloc"); 283 ptable.start(created).expect("start"); 284 let pid = created.pid(); 285 ptable.simulate_dispatch(pid); 286 287 let result = endpoint::do_try_recv(&cap, pid, &mut ptable); 288 assert!( 289 matches!(result, Err(crate::error::KernelError::WouldBlock)), 290 "try_recv with no senders should return WouldBlock" 291 ); 292 assert!( 293 ptable[pid].state() == ProcessState::Running, 294 "process should remain Running after WouldBlock" 295 ); 296 297 ptable.destroy(pid, &mut allocator); 298 let _ = POOL.lock().dec_ref_phys(id, generation); 299 } 300); 301 302crate::kernel_test!( 303 fn try_recv_delivers_when_sender_waiting() { 304 let (id, generation, cap) = alloc_endpoint_cap(); 305 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 306 let mut ptable = PROCESSES.lock(); 307 308 let sender_created = ptable.allocate(&mut allocator).expect("alloc sender"); 309 let recv_created = ptable.allocate(&mut allocator).expect("alloc recv"); 310 ptable.start(sender_created).expect("start sender"); 311 ptable.start(recv_created).expect("start recv"); 312 let sender_pid = sender_created.pid(); 313 let recv_pid = recv_created.pid(); 314 315 ptable.exec_mut(sender_pid).unwrap().ipc_message = 316 IpcMessage::from_regs([0xABCD, 0, 0, 0, 0, 0]); 317 ptable.simulate_dispatch(sender_pid); 318 let _ = endpoint::do_send(&cap, sender_pid, &mut ptable); 319 320 assert!( 321 ptable[sender_pid].state() == ProcessState::Blocked, 322 "sender should be blocked after send with no receiver" 323 ); 324 325 let result = endpoint::do_try_recv(&cap, recv_pid, &mut ptable); 326 match result { 327 Ok(IpcOutcome::Done(from)) => { 328 assert!(from == sender_pid, "should receive from sender"); 329 } 330 _ => panic!("expected Done from try_recv"), 331 } 332 333 assert!( 334 ptable[sender_pid].state() != ProcessState::Blocked, 335 "sender should be unblocked after try_recv delivers" 336 ); 337 338 let recv_msg = ptable.exec(recv_pid).unwrap().ipc_message; 339 assert!( 340 recv_msg.regs[0] == 0xABCD, 341 "message content should be delivered" 342 ); 343 344 ptable.destroy(sender_pid, &mut allocator); 345 ptable.destroy(recv_pid, &mut allocator); 346 let _ = POOL.lock().dec_ref_phys(id, generation); 347 } 348); 349 350crate::kernel_test!( 351 fn recv_caller_reenqueue_sets_reply_target() { 352 let (ep_id, ep_gen, cap) = alloc_endpoint_cap(); 353 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 354 let mut ptable = PROCESSES.lock(); 355 356 let caller_created = ptable.allocate(&mut allocator).expect("alloc caller"); 357 let server_created = ptable.allocate(&mut allocator).expect("alloc server"); 358 ptable.start(caller_created).expect("start caller"); 359 ptable.start(server_created).expect("start server"); 360 let caller_pid = caller_created.pid(); 361 let server_pid = server_created.pid(); 362 363 ptable.simulate_dispatch(caller_pid); 364 ptable.exec_mut(caller_pid).unwrap().ipc_message = 365 IpcMessage::from_regs([0xCA, 0, 0, 0, 0, 0]); 366 let blocked_caller = ptable[caller_pid] 367 .block_on(BlockedReason::Calling(ep_id, ep_gen)) 368 .expect("block caller"); 369 370 { 371 let mut pool = POOL.lock(); 372 let ep = pool 373 .write_as::<EndpointObject>(ep_id, ep_gen) 374 .expect("get ep"); 375 let mut senders = endpoint::load_senders(ep); 376 endpoint::enqueue(&mut senders, blocked_caller, &mut ptable) 377 .expect("enqueue caller as sender"); 378 let ep = pool 379 .write_as::<EndpointObject>(ep_id, ep_gen) 380 .expect("get ep"); 381 endpoint::store_senders(ep, &senders); 382 } 383 384 ptable.simulate_dispatch(server_pid); 385 386 let result = endpoint::do_recv(&cap, server_pid, &mut ptable); 387 assert!( 388 matches!(result, Ok(IpcOutcome::Done(_))), 389 "server should receive caller's message" 390 ); 391 392 assert!( 393 ptable.exec(server_pid).unwrap().reply_target == Some(caller_pid), 394 "server should have reply_target pointing to caller" 395 ); 396 397 let _ = POOL.lock().dec_ref_phys(ep_id, ep_gen); 398 ptable.destroy(caller_pid, &mut allocator); 399 ptable.destroy(server_pid, &mut allocator); 400 } 401);