Skip to content

Commit b162bcb

Browse files
committed
hjert: Added clock object.
1 parent 4ce53ed commit b162bcb

11 files changed

Lines changed: 151 additions & 107 deletions

File tree

src/kernel/hjert/api/types.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,16 @@ export enum struct Mode : u8 {
1616
};
1717

1818
#define FOREACH_TYPE(TYPE) \
19+
TYPE(CHANNEL) \
20+
TYPE(CLOCK) \
1921
TYPE(DOMAIN) \
20-
TYPE(TASK) \
21-
TYPE(SPACE) \
22-
TYPE(VMO) \
2322
TYPE(IOP) \
24-
TYPE(CHANNEL) \
2523
TYPE(IRQ) \
2624
TYPE(LISTENER) \
27-
TYPE(PIPE)
25+
TYPE(PIPE) \
26+
TYPE(SPACE) \
27+
TYPE(TASK) \
28+
TYPE(VMO)
2829

2930
// clang-format off
3031

@@ -296,6 +297,10 @@ export struct PipeProps {
296297
usize bufCap; //< The capacity of the data buffer (in bytes, must be >= 1)
297298
};
298299

300+
export struct ClockProps {
301+
static constexpr Type TYPE = Type::CLOCK;
302+
};
303+
299304
export using _Props = Union<
300305
DomainProps,
301306
TaskProps,
@@ -305,7 +310,8 @@ export using _Props = Union<
305310
ChannelProps,
306311
IrqProps,
307312
ListenerProps,
308-
PipeProps>;
313+
PipeProps,
314+
ClockProps>;
309315

310316
export struct Props : _Props {
311317
using _Props::_Props;

src/kernel/hjert/core/clock.cpp

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,64 @@
1+
module;
2+
3+
#include <hal/mem.h>
4+
#include <hal/pmm.h>
5+
#include <karm/macros>
6+
17
export module Hjert.Core:clock;
28

39
import Karm.Core;
410

11+
import :vmo;
12+
import :object;
13+
import :mem;
14+
515
using namespace Karm;
616

717
namespace Hjert::Core {
818

9-
static Lock _lock{};
10-
static Instant _stamp{};
19+
export struct Clock;
20+
21+
static Lock _clocksLock;
22+
static Vec<Clock*> _clocks = {};
23+
static Instant _monotonicClock{};
24+
25+
export struct Clock : BaseObject<Clock, Hj::Type::CLOCK> {
26+
Arc<Vmo> _vmo;
27+
Atomic<_TimeVal>* _reg = nullptr;
28+
29+
static Res<Arc<Clock>> create() {
30+
auto vmo = try$(Vmo::alloc(Hal::PAGE_SIZE, Hal::PmmFlags::LOWER));
31+
auto addr = try$(kmm().pmm2Kmm(vmo->range())).start;
32+
auto reg = reinterpret_cast<Atomic<Karm::_TimeVal>*>(addr);
33+
return Ok(makeArc<Clock>(vmo, reg));
34+
}
35+
36+
static Instant monotonicInstant() {
37+
LockScope _{_clocksLock};
38+
return _monotonicClock;
39+
}
40+
41+
static void monotonicTick(Duration span) {
42+
LockScope _{_clocksLock};
43+
_monotonicClock += span;
44+
for (auto* clock : _clocks)
45+
clock->tick(span);
46+
}
47+
48+
Clock(Arc<Vmo> vmo, Atomic<_TimeVal>* reg)
49+
: _vmo(vmo), _reg(reg) {
50+
LockScope _{_clocksLock};
51+
_clocks.pushBack(this);
52+
}
1153

12-
export Instant clockNow() {
13-
LockScope _{_lock};
14-
return _stamp;
15-
}
54+
~Clock() {
55+
LockScope _{_clocksLock};
56+
_clocks.removeAll(this);
57+
}
1658

17-
export void clockTick(Duration span) {
18-
LockScope _{_lock};
19-
_stamp += span;
20-
}
59+
void tick(Duration span) {
60+
_reg->fetchAdd(span.val());
61+
}
62+
};
2163

2264
} // namespace Hjert::Core

src/kernel/hjert/core/init.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace Hjert::Core {
2121
Res<Arc<Vmo>> _locateInit(Handover::Payload& payload, Str path) {
2222
logInfo("locating {#}...", path);
2323

24-
auto const* record = payload.fileByName("file:/skift/init.bootfs");
24+
auto const* record = payload.blobByName("file:/skift/init.bootfs");
2525
if (not record) {
2626
logError("handover: could not find bootfs");
2727
return Error::invalidInput("could not find bootfs");
@@ -52,7 +52,7 @@ Res<> enterUserspace(Handover::Payload& payload) {
5252
auto elfVmo = try$(_locateInit(payload, "bundles/strata-cm/bin/strata-cm.elf"));
5353
elfVmo->label("elf-shared");
5454
auto elfRange = try$(kmm().pmm2Kmm(elfVmo->range()));
55-
Elf::ElfObject<Elf::Elf64LeAbi> object{elfRange.bytes()};
55+
Elf::ElfObject<Elf::CurrentAbi> object{elfRange.bytes()};
5656
try$(object.validate());
5757

5858
for (Elf::ElfProgram prog : object.iterProgram()) {

src/kernel/hjert/core/mem.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,8 @@ struct Kmm : Hal::Kmm {
106106
}
107107

108108
Res<Hal::PmmRange> kmm2Pmm(Hal::KmmRange range) override {
109-
if (range.start < Hal::UPPER_HALF) {
109+
if (range.start < Hal::UPPER_HALF)
110110
return Error::invalidInput("Invalid heap range");
111-
}
112111

113112
return Ok(Hal::PmmRange{
114113
range.start - Hal::UPPER_HALF,

src/kernel/hjert/core/object.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ struct BaseObject : Object {
6666
}
6767
};
6868

69-
export struct [[nodiscard]] ObjectLockScope : LockScope<Lock> {
69+
export struct [[nodiscard]] ObjectLockScope : LockScope<> {
7070
ObjectLockScope(Object& obj)
7171
: LockScope(obj._lock) {
7272
}

src/kernel/hjert/core/sched.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct Sched {
4141
void schedule() {
4242
LockScope _{_lock};
4343

44-
auto now = clockNow();
44+
auto now = Clock::monotonicInstant();
4545
_prev = _curr;
4646
_curr->_sliceEnd = now;
4747

src/kernel/hjert/core/syscalls.cpp

Lines changed: 65 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ namespace Hjert::Core {
2525
static constexpr bool DEBUG_SYSCALLS = false;
2626

2727
Res<> doNow(Task& self, User<Instant> ts) {
28-
return ts.store(self.space(), clockNow());
28+
return ts.store(self.space(), Clock::monotonicInstant());
2929
}
3030

3131
Res<> doLog(Task& self, UserSlice<Str> msg) {
@@ -55,70 +55,70 @@ Res<> doCreate(Task& self, Hj::Cap dest, User<Hj::Cap> out, User<Hj::Props> p) {
5555
return Error::invalidInput("invalid props");
5656

5757
auto obj = try$(props.visit(
58-
Visitor{
59-
[&](Hj::DomainProps&) -> Res<Arc<Object>> {
60-
return Ok(try$(Domain::create()));
61-
},
62-
[&](Hj::TaskProps& props) -> Res<Arc<Object>> {
63-
try$(self.ensure(Hj::Pledge::TASK));
64-
65-
auto dom = props.domain.isRoot()
66-
? try$(self._domain)
67-
: try$(self.domain().get<Domain>(props.domain));
68-
69-
auto spa = props.space.isRoot()
70-
? try$(self._space)
71-
: try$(self.domain().get<Space>(props.space));
72-
73-
auto obj = try$(Task::create(Hj::Mode::USER, spa, dom));
74-
75-
auto pledges = self.pledges();
76-
try$(obj->pledge(pledges));
77-
78-
return Ok(obj);
79-
},
80-
[&](Hj::SpaceProps&) -> Res<Arc<Object>> {
81-
try$(self.ensure(Hj::Pledge::MEM));
82-
83-
return Ok(try$(Space::create()));
84-
},
85-
[&](Hj::VmoProps& props) -> Res<Arc<Object>> {
86-
try$(self.ensure(Hj::Pledge::MEM));
87-
88-
if (not props.vmo.isRoot()) {
89-
auto vmo = try$(self.domain().get<Vmo>(props.vmo));
90-
return Ok(try$(Vmo::makeSlice(vmo, {props.phys, props.len})));
91-
}
92-
93-
bool isDma = props.flags.has(Hj::VmoFlags::DMA);
94-
if (isDma) {
95-
try$(self.ensure(Hj::Pledge::HW));
96-
return Ok(try$(Vmo::makeDma({props.phys, props.len})));
97-
}
98-
99-
if (props.len > 2_GiB) {
100-
return Error::invalidInput("Vmo size too large");
101-
}
102-
103-
return Ok(try$(Vmo::alloc(props.len, props.flags)));
104-
},
105-
[&](Hj::IopProps& props) -> Res<Arc<Object>> {
106-
try$(self.ensure(Hj::Pledge::HW));
107-
return Ok(try$(Iop::create({props.base, props.len})));
108-
},
109-
[&](Hj::ChannelProps& props) -> Res<Arc<Object>> {
110-
return Ok(try$(Channel::create(props.bufCap, props.capsCap)));
111-
},
112-
[&](Hj::IrqProps& props) -> Res<Arc<Object>> {
58+
[&](Hj::DomainProps&) -> Res<Arc<Object>> {
59+
return Ok(try$(Domain::create()));
60+
},
61+
[&](Hj::TaskProps& props) -> Res<Arc<Object>> {
62+
try$(self.ensure(Hj::Pledge::TASK));
63+
64+
auto dom = props.domain.isRoot()
65+
? try$(self._domain)
66+
: try$(self.domain().get<Domain>(props.domain));
67+
68+
auto spa = props.space.isRoot()
69+
? try$(self._space)
70+
: try$(self.domain().get<Space>(props.space));
71+
72+
auto obj = try$(Task::create(Hj::Mode::USER, spa, dom));
73+
74+
auto pledges = self.pledges();
75+
try$(obj->pledge(pledges));
76+
77+
return Ok(obj);
78+
},
79+
[&](Hj::SpaceProps&) -> Res<Arc<Object>> {
80+
try$(self.ensure(Hj::Pledge::MEM));
81+
82+
return Space::create();
83+
},
84+
[&](Hj::VmoProps& props) -> Res<Arc<Object>> {
85+
try$(self.ensure(Hj::Pledge::MEM));
86+
87+
if (not props.vmo.isRoot()) {
88+
auto vmo = try$(self.domain().get<Vmo>(props.vmo));
89+
return Vmo::makeSlice(vmo, {props.phys, props.len});
90+
}
91+
92+
bool isDma = props.flags.has(Hj::VmoFlags::DMA);
93+
if (isDma) {
11394
try$(self.ensure(Hj::Pledge::HW));
114-
return Ok(try$(Irq::create(props.irq)));
115-
},
116-
[&](Hj::ListenerProps&) -> Res<Arc<Object>> {
117-
return Ok(try$(Listener::create()));
118-
},
119-
[&](Hj::PipeProps& props) -> Res<Arc<Object>> {
120-
return Ok(try$(Pipe::create(props.bufCap)));
121-
},
95+
return Vmo::makeDma({props.phys, props.len});
96+
}
97+
98+
if (props.len > 2_GiB)
99+
return Error::invalidInput("Vmo size too large");
100+
101+
return Vmo::alloc(props.len, props.flags);
102+
},
103+
[&](Hj::IopProps& props) -> Res<Arc<Object>> {
104+
try$(self.ensure(Hj::Pledge::HW));
105+
return Iop::create({props.base, props.len});
106+
},
107+
[&](Hj::ChannelProps& props) -> Res<Arc<Object>> {
108+
return Channel::create(props.bufCap, props.capsCap);
109+
},
110+
[&](Hj::IrqProps& props) -> Res<Arc<Object>> {
111+
try$(self.ensure(Hj::Pledge::HW));
112+
return Irq::create(props.irq);
113+
},
114+
[&](Hj::ListenerProps&) -> Res<Arc<Object>> {
115+
return Listener::create();
116+
},
117+
[&](Hj::PipeProps& props) -> Res<Arc<Object>> {
118+
return Pipe::create(props.bufCap);
119+
},
120+
[&](Hj::ClockProps&) -> Res<Arc<Object>> {
121+
return Clock::create();
122122
}
123123
));
124124

@@ -141,9 +141,8 @@ Res<> doDrop(Task& self, Hj::Cap cap) {
141141
}
142142

143143
Res<> doPledge(Task& self, Hj::Cap cap, Flags<Hj::Pledge> pledges) {
144-
if (cap.isRoot()) {
144+
if (cap.isRoot())
145145
return self.pledge(pledges);
146-
}
147146

148147
auto obj = try$(self.domain().get<Task>(cap));
149148
return obj->pledge(pledges);

src/kernel/hjert/core/task.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export struct Task : BaseObject<Task, Hj::Type::TASK> {
9595

9696
Res<> block(Blocker blocker) {
9797
// NOTE: If the blocker is already expired, don't block.
98-
if (blocker() <= clockNow())
98+
if (blocker() <= Clock::monotonicInstant())
9999
return Ok();
100100

101101
// NOTE: Can't use ObjectLockScope here because

src/kernel/hjert/core/vmo.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,15 @@ export struct Vmo : BaseObject<Vmo, Hj::Type::VMO> {
5353

5454
Hal::PmmRange range() const {
5555
return _mem.visit(
56-
Visitor{
57-
[](Hal::PmmMem const& mem) {
58-
return mem.range();
59-
},
60-
[](Hal::DmaRange const& range) {
61-
return range.into<Hal::PmmRange>();
62-
},
63-
[](_Slice const& slice) {
64-
auto range = slice.range.into<Hal::PmmRange>();
65-
return slice.vmo->range().slice(range);
66-
}
56+
[](Hal::PmmMem const& mem) {
57+
return mem.range();
58+
},
59+
[](Hal::DmaRange const& range) {
60+
return range.into<Hal::PmmRange>();
61+
},
62+
[](_Slice const& slice) {
63+
auto range = slice.range.into<Hal::PmmRange>();
64+
return slice.vmo->range().slice(range);
6765
}
6866
);
6967
}

src/kernel/hjert/x86_64/arch.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ void backtrace(usize rbp) {
174174

175175
void switchTask(Duration span, Frame& frame) {
176176
Core::globalSched().currentTask().save(frame);
177-
Core::clockTick(span);
177+
Core::Clock::monotonicTick(span);
178178
Core::globalSched().schedule();
179179
Core::globalSched().currentTask().load(frame);
180180
}

0 commit comments

Comments
 (0)