Nothing to see here, move along
1use crate::cap::cnode;
2use crate::cap::object::{
3 EndpointData, NotificationData, ObjectData, ObjectTag, ProcessObjectData, SchedContextData,
4};
5use crate::cap::ops;
6use crate::cap::pool::POOL;
7use crate::cap::table::{CapRef, Rights};
8use crate::error::KernelError;
9use crate::ipc::endpoint;
10use crate::proc::{BlockedReason, PROCESSES, ProcessState};
11use crate::types::{Pid, Priority};
12
13fn bootstrap_test_cnode(pid: Pid, ptable: &mut crate::proc::ProcessManager) {
14 let size_bits = crate::proc::ROOT_CNODE_SIZE_BITS;
15 let allocator = &crate::mem::phys::BitmapFrameAllocator;
16 let cnode_data = crate::cap::cnode::create_cnode(size_bits, allocator).expect("create cnode");
17 let frame_count = cnode_data.frame_count;
18 let (cnode_id, cnode_gen) = crate::cap::pool::POOL
19 .lock()
20 .allocate(crate::cap::object::ObjectData::CNode(cnode_data))
21 .expect("alloc cnode");
22 let proc = ptable.get_mut(pid).expect("get proc");
23 proc.root_cnode = Some((cnode_id, cnode_gen));
24 proc.cnode_depth = size_bits;
25 proc.charge_frames(frame_count as u16).expect("charge frames");
26}
27
28crate::kernel_test!(
29 fn create_endpoint_inserts_cap() {
30 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
31 let mut ptable = PROCESSES.lock();
32 let created = ptable.allocate(&mut allocator).expect("alloc");
33 ptable.start(created).expect("start");
34 let pid = created.pid();
35 bootstrap_test_cnode(pid, &mut ptable);
36
37 let address = 10u64;
38 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(pid, &ptable).expect("coords");
39 let oid = {
40 let mut pool = POOL.lock_after(&ptable);
41 ops::create_via_cnode(&mut pool, cnode_id, cnode_gen, address, depth, ObjectTag::Endpoint)
42 .expect("create endpoint")
43 };
44
45 {
46 let pool = POOL.lock_after(&ptable);
47 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, address, depth)
48 .expect("read slot");
49 assert!(cap.tag() == ObjectTag::Endpoint);
50 assert!(cap.rights().contains(Rights::ALL));
51 assert!(cap.object_id() == oid);
52 }
53
54 ptable.destroy(pid, &mut allocator);
55 }
56);
57
58crate::kernel_test!(
59 fn create_notification_inserts_cap() {
60 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
61 let mut ptable = PROCESSES.lock();
62 let created = ptable.allocate(&mut allocator).expect("alloc");
63 ptable.start(created).expect("start");
64 let pid = created.pid();
65 bootstrap_test_cnode(pid, &mut ptable);
66
67 let address = 11u64;
68 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(pid, &ptable).expect("coords");
69 let oid = {
70 let mut pool = POOL.lock_after(&ptable);
71 ops::create_via_cnode(&mut pool, cnode_id, cnode_gen, address, depth, ObjectTag::Notification)
72 .expect("create notification")
73 };
74
75 {
76 let pool = POOL.lock_after(&ptable);
77 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, address, depth)
78 .expect("read slot");
79 assert!(cap.tag() == ObjectTag::Notification);
80 assert!(cap.object_id() == oid);
81 }
82
83 ptable.destroy(pid, &mut allocator);
84 }
85);
86
87crate::kernel_test!(
88 fn create_memory_region_rejected() {
89 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
90 let mut ptable = PROCESSES.lock();
91 let created = ptable.allocate(&mut allocator).expect("alloc");
92 ptable.start(created).expect("start");
93 let pid = created.pid();
94 bootstrap_test_cnode(pid, &mut ptable);
95
96 let address = 12u64;
97 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(pid, &ptable).expect("coords");
98 let result = {
99 let mut pool = POOL.lock_after(&ptable);
100 ops::create_via_cnode(&mut pool, cnode_id, cnode_gen, address, depth, ObjectTag::MemoryRegion)
101 };
102 assert!(
103 matches!(result, Err(KernelError::InvalidType)),
104 "creating a MemoryRegion cap via create_via_cnode must fail"
105 );
106
107 ptable.destroy(pid, &mut allocator);
108 }
109);
110
111crate::kernel_test!(
112 fn create_invalid_tag_rejected() {
113 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
114 let mut ptable = PROCESSES.lock();
115 let created = ptable.allocate(&mut allocator).expect("alloc");
116 ptable.start(created).expect("start");
117 let pid = created.pid();
118 bootstrap_test_cnode(pid, &mut ptable);
119
120 let address = 13u64;
121 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(pid, &ptable).expect("coords");
122 let result = {
123 let mut pool = POOL.lock_after(&ptable);
124 ops::create_via_cnode(&mut pool, cnode_id, cnode_gen, address, depth, ObjectTag::Process)
125 };
126 assert!(
127 matches!(result, Err(KernelError::InvalidType)),
128 "creating a Process cap via ops::create must fail"
129 );
130
131 ptable.destroy(pid, &mut allocator);
132 }
133);
134
135crate::kernel_test!(
136 fn create_occupied_slot_rolls_back() {
137 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
138 let mut ptable = PROCESSES.lock();
139 let created = ptable.allocate(&mut allocator).expect("alloc");
140 ptable.start(created).expect("start");
141 let pid = created.pid();
142 bootstrap_test_cnode(pid, &mut ptable);
143
144 let address = 14u64;
145 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(pid, &ptable).expect("coords");
146 {
147 let mut pool = POOL.lock_after(&ptable);
148 ops::create_via_cnode(&mut pool, cnode_id, cnode_gen, address, depth, ObjectTag::Endpoint)
149 .expect("first create");
150 }
151
152 let result = {
153 let mut pool = POOL.lock_after(&ptable);
154 ops::create_via_cnode(&mut pool, cnode_id, cnode_gen, address, depth, ObjectTag::Notification)
155 };
156 assert!(
157 matches!(result, Err(KernelError::SlotOccupied)),
158 "second create into occupied slot must fail"
159 );
160
161 {
162 let pool = POOL.lock_after(&ptable);
163 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, address, depth)
164 .expect("read slot");
165 assert!(
166 cap.tag() == ObjectTag::Endpoint,
167 "original cap should still be in the slot"
168 );
169 }
170
171 ptable.destroy(pid, &mut allocator);
172 }
173);
174
175crate::kernel_test!(
176 fn derive_attenuates_rights() {
177 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
178 let mut ptable = PROCESSES.lock();
179 let created = ptable.allocate(&mut allocator).expect("alloc");
180 ptable.start(created).expect("start");
181 let pid = created.pid();
182 bootstrap_test_cnode(pid, &mut ptable);
183
184 let src_addr = 20u64;
185 let dest_addr = 21u64;
186 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(pid, &ptable).expect("coords");
187
188 {
189 let mut pool = POOL.lock_after(&ptable);
190 ops::create_via_cnode(&mut pool, cnode_id, cnode_gen, src_addr, depth, ObjectTag::Endpoint)
191 .expect("create source");
192 }
193
194 {
195 let mut pool = POOL.lock_after(&ptable);
196 ops::derive_via_cnode(&mut pool, cnode_id, cnode_gen, src_addr, dest_addr, depth, Rights::READ)
197 .expect("derive");
198 }
199
200 {
201 let pool = POOL.lock_after(&ptable);
202 let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, dest_addr, depth)
203 .expect("read derived slot");
204 assert!(cap.rights().contains(Rights::READ));
205 assert!(!cap.rights().contains(Rights::WRITE));
206 assert!(!cap.rights().contains(Rights::REVOKE));
207 }
208
209 ptable.destroy(pid, &mut allocator);
210 }
211);
212
213crate::kernel_test!(
214 fn derive_without_grant_fails() {
215 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
216 let mut ptable = PROCESSES.lock();
217 let created = ptable.allocate(&mut allocator).expect("alloc");
218 ptable.start(created).expect("start");
219 let pid = created.pid();
220 bootstrap_test_cnode(pid, &mut ptable);
221
222 let src_addr = 30u64;
223 let dest_addr = 31u64;
224 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(pid, &ptable).expect("coords");
225
226 {
227 let mut pool = POOL.lock_after(&ptable);
228 ops::create_via_cnode(&mut pool, cnode_id, cnode_gen, src_addr, depth, ObjectTag::Endpoint)
229 .expect("create source");
230 }
231
232 {
233 let pool = POOL.lock_after(&ptable);
234 let old_cap = cnode::resolve_and_clear(&pool, cnode_id, cnode_gen, src_addr, depth)
235 .expect("clear slot");
236 let new_cap = old_cap.with_rights(Rights::READ | Rights::WRITE);
237 cnode::resolve_and_insert(&pool, cnode_id, cnode_gen, src_addr, depth, new_cap)
238 .expect("reinsert cap");
239 }
240
241 let result = {
242 let mut pool = POOL.lock_after(&ptable);
243 ops::derive_via_cnode(&mut pool, cnode_id, cnode_gen, src_addr, dest_addr, depth, Rights::READ)
244 };
245 assert!(
246 matches!(result, Err(KernelError::InsufficientRights)),
247 "derive without GRANT right must fail"
248 );
249
250 ptable.destroy(pid, &mut allocator);
251 }
252);
253
254crate::kernel_test!(
255 fn identify_returns_tag_and_rights() {
256 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
257 let mut ptable = PROCESSES.lock();
258 let created = ptable.allocate(&mut allocator).expect("alloc");
259 ptable.start(created).expect("start");
260 let pid = created.pid();
261 bootstrap_test_cnode(pid, &mut ptable);
262
263 let address = 40u64;
264 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(pid, &ptable).expect("coords");
265
266 {
267 let mut pool = POOL.lock_after(&ptable);
268 ops::create_via_cnode(&mut pool, cnode_id, cnode_gen, address, depth, ObjectTag::Notification)
269 .expect("create notification");
270 }
271
272 let (tag, rights) = {
273 let pool = POOL.lock_after(&ptable);
274 ops::identify_via_cnode(&pool, cnode_id, cnode_gen, address, depth)
275 .expect("identify")
276 };
277
278 assert!(tag == ObjectTag::Notification);
279 assert!(rights.contains(Rights::ALL));
280
281 ptable.destroy(pid, &mut allocator);
282 }
283);
284
285crate::kernel_test!(
286 fn endpoint_revoke_unblocks_senders() {
287 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
288 let mut ptable = PROCESSES.lock();
289
290 let owner_created = ptable.allocate(&mut allocator).expect("alloc owner");
291 let sender_created = ptable.allocate(&mut allocator).expect("alloc sender");
292 ptable.start(owner_created).expect("start owner");
293 ptable.start(sender_created).expect("start sender");
294 let owner_pid = owner_created.pid();
295 let sender_pid = sender_created.pid();
296 bootstrap_test_cnode(owner_pid, &mut ptable);
297
298 let (ep_id, ep_gen) = POOL
299 .lock_after(&ptable)
300 .allocate(ObjectData::Endpoint(EndpointData::new()))
301 .expect("alloc ep");
302
303 let cap = CapRef::new(ObjectTag::Endpoint, ep_id, Rights::ALL, ep_gen);
304 let address = 0u64;
305 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(owner_pid, &ptable).expect("coords");
306 {
307 let pool = POOL.lock_after(&ptable);
308 cnode::resolve_and_insert(&pool, cnode_id, cnode_gen, address, depth, cap)
309 .expect("insert cap");
310 }
311
312 ptable[sender_pid]
313 .transition_to(ProcessState::Running)
314 .expect("sender -> Running");
315 let blocked = ptable[sender_pid]
316 .block_on(BlockedReason::Sending(ep_id, ep_gen))
317 .expect("block sender");
318
319 {
320 let mut pool = POOL.lock_after(&ptable);
321 let ep = pool
322 .get_mut(ep_id, ep_gen)
323 .and_then(|d| d.as_endpoint_mut())
324 .expect("get ep");
325 endpoint::enqueue(&mut ep.senders, blocked, &mut ptable).expect("enqueue");
326 }
327
328 ops::revoke_via_cnode(owner_pid, address, &mut ptable).expect("revoke");
329
330 assert!(
331 ptable[sender_pid].state() == ProcessState::Ready,
332 "sender should be unblocked after endpoint revoke"
333 );
334 assert!(
335 ptable[sender_pid].saved_context.rax == KernelError::InvalidObject.to_errno() as u64,
336 "sender's rax should contain InvalidObject errno after endpoint revoke"
337 );
338
339 ptable.destroy(owner_pid, &mut allocator);
340 ptable.destroy(sender_pid, &mut allocator);
341 }
342);
343
344crate::kernel_test!(
345 fn notification_revoke_unblocks_waiters() {
346 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
347 let mut ptable = PROCESSES.lock();
348
349 let owner_created = ptable.allocate(&mut allocator).expect("alloc owner");
350 let waiter_created = ptable.allocate(&mut allocator).expect("alloc waiter");
351 ptable.start(owner_created).expect("start owner");
352 ptable.start(waiter_created).expect("start waiter");
353 let owner_pid = owner_created.pid();
354 let waiter_pid = waiter_created.pid();
355 bootstrap_test_cnode(owner_pid, &mut ptable);
356
357 let (notif_id, notif_gen) = POOL
358 .lock_after(&ptable)
359 .allocate(ObjectData::Notification(NotificationData::new()))
360 .expect("alloc notif");
361
362 let cap = CapRef::new(ObjectTag::Notification, notif_id, Rights::ALL, notif_gen);
363 let address = 0u64;
364 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(owner_pid, &ptable).expect("coords");
365 {
366 let pool = POOL.lock_after(&ptable);
367 cnode::resolve_and_insert(&pool, cnode_id, cnode_gen, address, depth, cap)
368 .expect("insert cap");
369 }
370
371 ptable[waiter_pid]
372 .transition_to(ProcessState::Running)
373 .expect("waiter -> Running");
374 let _ = ptable[waiter_pid]
375 .block_on(BlockedReason::WaitingNotification(notif_id, notif_gen))
376 .expect("block waiter");
377
378 {
379 let mut pool = POOL.lock_after(&ptable);
380 let notif = pool
381 .get_mut(notif_id, notif_gen)
382 .and_then(|d| d.as_notification_mut())
383 .expect("get notif");
384 let _ = notif.waiters.push(waiter_pid);
385 }
386
387 ops::revoke_via_cnode(owner_pid, address, &mut ptable).expect("revoke");
388
389 assert!(
390 ptable[waiter_pid].state() == ProcessState::Ready,
391 "waiter should be unblocked after notification revoke"
392 );
393 assert!(
394 ptable[waiter_pid].saved_context.rax == KernelError::InvalidObject.to_errno() as u64,
395 "waiter's rax should contain InvalidObject errno after notification revoke"
396 );
397
398 ptable.destroy(owner_pid, &mut allocator);
399 ptable.destroy(waiter_pid, &mut allocator);
400 }
401);
402
403crate::kernel_test!(
404 fn proc_destroy_decrements_pool_refcount() {
405 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
406 let mut ptable = PROCESSES.lock();
407
408 let parent_created = ptable.allocate(&mut allocator).expect("alloc parent");
409 let child_created = ptable.allocate(&mut allocator).expect("alloc child");
410 ptable.start(parent_created).expect("start parent");
411 ptable.start(child_created).expect("start child");
412 let parent_pid = parent_created.pid();
413 let child_pid = child_created.pid();
414 bootstrap_test_cnode(parent_pid, &mut ptable);
415
416 let data = ObjectData::Process(ProcessObjectData { pid: child_pid });
417 let tag = ObjectTag::Process;
418 let (obj_id, generation) = POOL.lock_after(&ptable).allocate(data).expect("alloc process object");
419 let cap = CapRef::new(tag, obj_id, Rights::ALL, generation);
420 let address = 0u64;
421 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(parent_pid, &ptable).expect("coords");
422 {
423 let pool = POOL.lock_after(&ptable);
424 cnode::resolve_and_insert(&pool, cnode_id, cnode_gen, address, depth, cap)
425 .expect("insert cap");
426 }
427
428 POOL.lock_after(&ptable).inc_ref(obj_id, generation).expect("inc_ref");
429 let refcount_before = POOL.lock_after(&ptable).get(obj_id, generation).is_ok();
430 assert!(refcount_before, "object should be alive before destroy");
431
432 ptable.destroy(child_pid, &mut allocator);
433
434 POOL.lock_after(&ptable).dec_ref(obj_id, generation);
435 {
436 let pool = POOL.lock_after(&ptable);
437 let _ = cnode::resolve_and_clear(&pool, cnode_id, cnode_gen, address, depth);
438 }
439
440 ptable.destroy(parent_pid, &mut allocator);
441 }
442);
443
444crate::kernel_test!(
445 fn sched_context_revoke_detaches_process() {
446 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
447 let mut ptable = PROCESSES.lock();
448
449 let owner_created = ptable.allocate(&mut allocator).expect("alloc owner");
450 ptable.start(owner_created).expect("start owner");
451 let owner_pid = owner_created.pid();
452 bootstrap_test_cnode(owner_pid, &mut ptable);
453
454 let sc_data =
455 ObjectData::SchedContext(SchedContextData::new(1000, 10000, Priority::new(100)));
456 let (sc_id, sc_gen) = POOL.lock_after(&ptable).allocate(sc_data).expect("alloc sched context");
457
458 {
459 let mut pool = POOL.lock_after(&ptable);
460 let sc = pool
461 .get_mut(sc_id, sc_gen)
462 .and_then(|d| d.as_sched_context_mut())
463 .expect("get sc");
464 sc.attached_pid = Some(owner_pid);
465 }
466
467 let cap = CapRef::new(ObjectTag::SchedContext, sc_id, Rights::ALL, sc_gen);
468 let address = 0u64;
469 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(owner_pid, &ptable).expect("coords");
470 {
471 let pool = POOL.lock_after(&ptable);
472 cnode::resolve_and_insert(&pool, cnode_id, cnode_gen, address, depth, cap)
473 .expect("insert cap");
474 }
475
476 ptable[owner_pid].attach_sched_context(sc_id, sc_gen, Priority::new(100));
477 assert!(
478 ptable[owner_pid].sched_context().is_some(),
479 "sched_context should be attached before revoke"
480 );
481
482 ops::revoke_via_cnode(owner_pid, address, &mut ptable).expect("revoke sched context");
483
484 assert!(
485 ptable[owner_pid].sched_context().is_none(),
486 "sched_context must be detached after SchedContext revoke"
487 );
488
489 ptable.destroy(owner_pid, &mut allocator);
490 }
491);
492
493crate::kernel_test!(
494 fn sched_context_revoke_prevents_scheduling() {
495 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
496 let mut ptable = PROCESSES.lock();
497
498 let owner_created = ptable.allocate(&mut allocator).expect("alloc owner");
499 ptable.start(owner_created).expect("start owner");
500 let owner_pid = owner_created.pid();
501 bootstrap_test_cnode(owner_pid, &mut ptable);
502
503 let sc_data =
504 ObjectData::SchedContext(SchedContextData::new(1000, 10000, Priority::new(200)));
505 let address = 0u64;
506 let (sc_id, sc_gen) = POOL.lock_after(&ptable).allocate(sc_data).expect("alloc sc");
507
508 {
509 let mut pool = POOL.lock_after(&ptable);
510 let sc = pool
511 .get_mut(sc_id, sc_gen)
512 .and_then(|d| d.as_sched_context_mut())
513 .expect("get sc");
514 sc.attached_pid = Some(owner_pid);
515 }
516
517 let cap = CapRef::new(ObjectTag::SchedContext, sc_id, Rights::ALL, sc_gen);
518 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(owner_pid, &ptable).expect("coords");
519 {
520 let pool = POOL.lock_after(&ptable);
521 cnode::resolve_and_insert(&pool, cnode_id, cnode_gen, address, depth, cap)
522 .expect("insert cap");
523 }
524 ptable[owner_pid].attach_sched_context(sc_id, sc_gen, Priority::new(200));
525
526 assert!(
527 ptable[owner_pid].is_runnable(),
528 "process should be runnable before revoke"
529 );
530
531 ops::revoke_via_cnode(owner_pid, address, &mut ptable).expect("revoke");
532
533 assert!(
534 ptable[owner_pid].sched_context().is_none(),
535 "sched_context detached after revoke"
536 );
537
538 ptable.destroy(owner_pid, &mut allocator);
539 }
540);
541
542crate::kernel_test!(
543 fn cleanup_sched_context_with_no_attached_process() {
544 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
545 let mut ptable = PROCESSES.lock();
546
547 let owner_created = ptable.allocate(&mut allocator).expect("alloc owner");
548 ptable.start(owner_created).expect("start owner");
549 let owner_pid = owner_created.pid();
550 bootstrap_test_cnode(owner_pid, &mut ptable);
551
552 let sc_data = ObjectData::SchedContext(SchedContextData::new(500, 5000, Priority::new(50)));
553 let address = 0u64;
554 let (sc_id, sc_gen) = POOL.lock_after(&ptable).allocate(sc_data).expect("alloc sc");
555 let cap = CapRef::new(ObjectTag::SchedContext, sc_id, Rights::ALL, sc_gen);
556 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(owner_pid, &ptable).expect("coords");
557 {
558 let pool = POOL.lock_after(&ptable);
559 cnode::resolve_and_insert(&pool, cnode_id, cnode_gen, address, depth, cap)
560 .expect("insert cap");
561 }
562
563 ops::revoke_via_cnode(owner_pid, address, &mut ptable).expect("revoke unattached sc");
564
565 ptable.destroy(owner_pid, &mut allocator);
566 }
567);
568
569crate::kernel_test!(
570 fn sched_context_cleanup_different_holder_and_attached() {
571 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
572 let mut ptable = PROCESSES.lock();
573
574 let holder_created = ptable.allocate(&mut allocator).expect("alloc holder");
575 let target_created = ptable.allocate(&mut allocator).expect("alloc target");
576 ptable.start(holder_created).expect("start holder");
577 ptable.start(target_created).expect("start target");
578 let holder_pid = holder_created.pid();
579 let target_pid = target_created.pid();
580 bootstrap_test_cnode(holder_pid, &mut ptable);
581
582 let sc_data =
583 ObjectData::SchedContext(SchedContextData::new(1000, 10000, Priority::new(100)));
584 let (sc_id, sc_gen) = POOL.lock_after(&ptable).allocate(sc_data).expect("alloc sc");
585
586 {
587 let mut pool = POOL.lock_after(&ptable);
588 let sc = pool
589 .get_mut(sc_id, sc_gen)
590 .and_then(|d| d.as_sched_context_mut())
591 .expect("get sc");
592 sc.attached_pid = Some(target_pid);
593 }
594
595 ptable[target_pid].attach_sched_context(sc_id, sc_gen, Priority::new(100));
596 assert!(
597 ptable[target_pid].sched_context().is_some(),
598 "target should have sched context"
599 );
600
601 let cap = CapRef::new(ObjectTag::SchedContext, sc_id, Rights::ALL, sc_gen);
602 let address = 0u64;
603 let (cnode_id, cnode_gen, depth) = cnode::cnode_coords(holder_pid, &ptable).expect("coords");
604 {
605 let pool = POOL.lock_after(&ptable);
606 cnode::resolve_and_insert(&pool, cnode_id, cnode_gen, address, depth, cap)
607 .expect("insert cap");
608 }
609
610 ops::revoke_via_cnode(holder_pid, address, &mut ptable).expect("revoke");
611
612 assert!(
613 ptable[target_pid].sched_context().is_none(),
614 "target's sched_context must be cleared when holder revokes the SchedContext"
615 );
616
617 ptable.destroy(holder_pid, &mut allocator);
618 ptable.destroy(target_pid, &mut allocator);
619 }
620);