Nothing to see here, move along
at main 182 lines 6.2 kB view raw
1use crate::cap::object::{NotificationData, ObjectData, ObjectTag}; 2use crate::cap::pool::POOL; 3use crate::cap::table::{CapRef, Rights}; 4use crate::ipc::IpcOutcome; 5use crate::ipc::notification; 6use crate::proc::{PROCESSES, ProcessState}; 7 8fn alloc_notification() -> (crate::types::ObjectId, crate::types::Generation, CapRef) { 9 let (id, generation) = POOL 10 .lock() 11 .allocate(ObjectData::Notification(NotificationData::new())) 12 .expect("alloc notification"); 13 let cap = CapRef::new(ObjectTag::Notification, id, Rights::ALL, generation); 14 (id, generation, cap) 15} 16 17crate::kernel_test!( 18 fn signal_sets_word_bits() { 19 let (id, generation, cap) = alloc_notification(); 20 let mut ptable = PROCESSES.lock(); 21 notification::do_signal(&cap, 0x0F, &mut ptable).expect("signal"); 22 23 let mut pool = POOL.lock(); 24 let notif = pool 25 .get_mut(id, generation) 26 .unwrap() 27 .as_notification_mut() 28 .unwrap(); 29 assert!(notif.word == 0x0F, "word should have bits set"); 30 drop(pool); 31 drop(ptable); 32 let _ = POOL.lock().dec_ref(id, generation); 33 } 34); 35 36crate::kernel_test!( 37 fn signal_accumulates_bits() { 38 let (id, generation, cap) = alloc_notification(); 39 let mut ptable = PROCESSES.lock(); 40 notification::do_signal(&cap, 0x01, &mut ptable).expect("signal 1"); 41 notification::do_signal(&cap, 0x02, &mut ptable).expect("signal 2"); 42 43 let mut pool = POOL.lock(); 44 let notif = pool 45 .get_mut(id, generation) 46 .unwrap() 47 .as_notification_mut() 48 .unwrap(); 49 assert!(notif.word == 0x03, "bits should accumulate via OR"); 50 drop(pool); 51 drop(ptable); 52 let _ = POOL.lock().dec_ref(id, generation); 53 } 54); 55 56crate::kernel_test!( 57 fn poll_returns_word_and_clears() { 58 let (id, generation, cap) = alloc_notification(); 59 { 60 let mut pool = POOL.lock(); 61 pool.get_mut(id, generation) 62 .unwrap() 63 .as_notification_mut() 64 .unwrap() 65 .word = 0xFF; 66 } 67 let val = notification::do_poll(&cap).expect("poll"); 68 assert!(val == 0xFF, "poll should return accumulated word"); 69 70 let val2 = notification::do_poll(&cap).expect("poll again"); 71 assert!(val2 == 0, "second poll should return 0 after clear"); 72 73 let _ = POOL.lock().dec_ref(id, generation); 74 } 75); 76 77crate::kernel_test!( 78 fn wait_with_pending_returns_immediately() { 79 let (id, generation, cap) = alloc_notification(); 80 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 81 let mut ptable = PROCESSES.lock(); 82 83 let created = ptable.allocate(&mut allocator).expect("alloc"); 84 ptable.start(created).expect("start"); 85 let pid = created.pid(); 86 ptable[pid] 87 .transition_to(ProcessState::Running) 88 .expect("-> Running"); 89 90 { 91 let mut pool = POOL.lock(); 92 pool.get_mut(id, generation) 93 .unwrap() 94 .as_notification_mut() 95 .unwrap() 96 .word = 0xAB; 97 } 98 99 let result = notification::do_wait(&cap, pid, &mut ptable).expect("wait"); 100 match result { 101 IpcOutcome::Done(bits) => assert!(bits == 0xAB, "should return pending word"), 102 IpcOutcome::Blocked => panic!("should not block when word is pending"), 103 } 104 105 ptable.destroy(pid, &mut allocator); 106 let _ = POOL.lock().dec_ref(id, generation); 107 } 108); 109 110crate::kernel_test!( 111 fn wait_without_pending_blocks() { 112 let (id, generation, cap) = alloc_notification(); 113 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 114 let mut ptable = PROCESSES.lock(); 115 116 let created = ptable.allocate(&mut allocator).expect("alloc"); 117 ptable.start(created).expect("start"); 118 let pid = created.pid(); 119 ptable[pid] 120 .transition_to(ProcessState::Running) 121 .expect("-> Running"); 122 123 let result = notification::do_wait(&cap, pid, &mut ptable).expect("wait"); 124 match result { 125 IpcOutcome::Blocked => { 126 assert!( 127 ptable[pid].state() == ProcessState::Blocked, 128 "process should be Blocked" 129 ); 130 } 131 IpcOutcome::Done(_) => panic!("should block when no word pending"), 132 } 133 134 ptable.destroy(pid, &mut allocator); 135 let _ = POOL.lock().dec_ref(id, generation); 136 } 137); 138 139crate::kernel_test!( 140 fn signal_wakes_blocked_waiter() { 141 let (id, generation, cap) = alloc_notification(); 142 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 143 let mut ptable = PROCESSES.lock(); 144 145 let created = ptable.allocate(&mut allocator).expect("alloc"); 146 ptable.start(created).expect("start"); 147 let pid = created.pid(); 148 ptable[pid] 149 .transition_to(ProcessState::Running) 150 .expect("-> Running"); 151 152 let result = notification::do_wait(&cap, pid, &mut ptable).expect("wait"); 153 assert!(matches!(result, IpcOutcome::Blocked)); 154 155 notification::do_signal(&cap, 0xDEAD, &mut ptable).expect("signal"); 156 157 assert!( 158 ptable[pid].state() == ProcessState::Ready, 159 "waiter should be unblocked after signal" 160 ); 161 assert!( 162 ptable[pid].saved_context.rdx == 0xDEAD, 163 "waiter's rdx should hold the signaled word" 164 ); 165 assert!( 166 ptable[pid].saved_context.rax == 0, 167 "waiter's rax should be 0 (success)" 168 ); 169 170 ptable.destroy(pid, &mut allocator); 171 let _ = POOL.lock().dec_ref(id, generation); 172 } 173); 174 175crate::kernel_test!( 176 fn poll_on_empty_returns_zero() { 177 let (id, generation, cap) = alloc_notification(); 178 let val = notification::do_poll(&cap).expect("poll"); 179 assert!(val == 0, "poll on fresh notification should return 0"); 180 let _ = POOL.lock().dec_ref(id, generation); 181 } 182);