compiler/
kernel/
lib/
scripts/
seed/
sublime/
test/
acceptance/
boot/
bootstrap/
cycles/
kernel/
job.rad
651 B
machine.ras
817 B
run
2.2 KiB
spin.rad
3.7 KiB
support.rad
242 B
dispatch/
loader/
mmio/
modules/
native/
packages/
pages/
runtime/
scheduling/
shared/
slots/
smp/
sync/
termination/
tests/
trap/
run
2.7 KiB
runner.rad
10.3 KiB
vim/
.gitignore
336 B
.gitsigners
112 B
CONTRIBUTING
2.1 KiB
LICENSE
1.1 KiB
Makefile
10.2 KiB
README
2.5 KiB
STYLE
2.5 KiB
std.lib
1.5 KiB
std.lib.test
551 B
test/cycles/spin.rad
raw
| 1 | //! Concurrent load, spawn, yield, fault, and teardown cycles. |
| 2 | use support; |
| 3 | export mod abi; |
| 4 | export mod sys; |
| 5 | export mod mmio; |
| 6 | |
| 7 | /// Ordered shared-memory access boundary for the single event consumer. |
| 8 | @intrinsic fn memoryFence(); |
| 9 | |
| 10 | /// Controller resources and retained completion metadata. |
| 11 | record Arguments: Copy { |
| 12 | /// Readable binary worker package. |
| 13 | source: abi::Handle, |
| 14 | /// Exact package byte length. |
| 15 | length: u64, |
| 16 | /// Read-only clock capability. |
| 17 | clock: abi::Handle, |
| 18 | /// Page that owns this argument record. |
| 19 | page: abi::Handle, |
| 20 | /// Reserved worker interval in clock ticks. |
| 21 | quantum: u64, |
| 22 | /// Shared worker code base reported to the checker. |
| 23 | codeBase: u64, |
| 24 | /// Number of fully checked worker lifetimes. |
| 25 | completed: u64, |
| 26 | } |
| 27 | |
| 28 | /// Published event wire record. |
| 29 | record Event: Copy { |
| 30 | /// Notification kind. |
| 31 | kind: u16, |
| 32 | /// Reserved zero bits. |
| 33 | reserved: u16, |
| 34 | /// Terminal status or fault code. |
| 35 | code: u32, |
| 36 | /// Generation-bearing child identity. |
| 37 | value: u64, |
| 38 | } |
| 39 | |
| 40 | /// Shared single-consumer event ring. |
| 41 | record Ring: Copy { |
| 42 | /// Published event slots. |
| 43 | data: [Event; 256], |
| 44 | /// Consumer progress. |
| 45 | head: u32, |
| 46 | /// Producer progress. |
| 47 | tail: u32, |
| 48 | /// Ring index mask. |
| 49 | mask: u32, |
| 50 | } |
| 51 | |
| 52 | /// Kernel startup pointers for one controller. |
| 53 | record Env: Copy { |
| 54 | /// Writable arguments retained by the parent. |
| 55 | argsPointer: *unsafe mut Arguments, |
| 56 | /// Argument record byte size. |
| 57 | argsSize: u64, |
| 58 | /// Installed event capability. |
| 59 | eventsHandle: u64, |
| 60 | /// Shared event-ring pointer. |
| 61 | eventsPointer: *unsafe mut Ring, |
| 62 | } |
| 63 | |
| 64 | /// Repeat publication lookup and private worker lifetimes on this hart. |
| 65 | @default unsafe fn main(env: *Env) { |
| 66 | assert env.argsSize == @sizeOf(Arguments) as u64; |
| 67 | let mut args = env.argsPointer; |
| 68 | let initial = sys::currentContext(); |
| 69 | for turn in 0..4 { |
| 70 | assert support::advance() == turn as u64 + 1; |
| 71 | let mut image = abi::Handle(0); |
| 72 | while image == abi::Handle(0) { |
| 73 | set image = try sys::imageLoad(abi::Handle(0), args.source, 0, args.length) catch error { |
| 74 | assert error == abi::Error::Busy; |
| 75 | continue; |
| 76 | }; |
| 77 | } |
| 78 | let loaded = try! sys::queryImage(image); |
| 79 | if turn == 0 { set args.codeBase = loaded.codeBase; } |
| 80 | assert loaded.codeBase == args.codeBase; |
| 81 | let child = try! sys::domainCreate(abi::Handle(0), image); |
| 82 | let identity = sys::queryDomain(child).id; |
| 83 | let stack = try! sys::pageAllocate(abi::Handle(0), 4); |
| 84 | let extent = sys::queryPage(stack); |
| 85 | let moved = try! sys::capabilityTransfer(stack, child, abi::RIGHTS_MASK as u64); |
| 86 | let shared = try! sys::capabilityGrant(args.page, child, abi::READ as u64); |
| 87 | try! sys::domainActivate(child, extent.base + extent.count * 4096, args as *unsafe opaque, (turn % 2) as u64); |
| 88 | let current = sys::currentContext(); |
| 89 | assert current.context == initial.context and current.hart == initial.hart; |
| 90 | let later = try! sys::budgetSplit(abi::Handle(current.budget), mmio::read64(args.clock, 0) + args.quantum); |
| 91 | try! sys::yield(child); |
| 92 | assert sys::currentContext().budget == *later; |
| 93 | let mut ring = env.eventsPointer; |
| 94 | let head = ring.head; |
| 95 | let tail = ring.tail; |
| 96 | memoryFence(); |
| 97 | assert head <> tail and ring.mask == 255; |
| 98 | let event = ring.data[head & ring.mask]; |
| 99 | assert event.value == identity and event.reserved == 0; |
| 100 | if turn % 2 == 0 { assert event.kind == 4 and event.code == 9; } |
| 101 | else { assert event.kind == 3 and event.code == 3; } |
| 102 | memoryFence(); |
| 103 | set ring.head = head + 1; |
| 104 | try! sys::capabilityDrop(image); |
| 105 | set args.completed = turn as u64 + 1; |
| 106 | } |
| 107 | sys::exit(68); |
| 108 | } |