Domain schedules#445
Conversation
Having the extra configs doesn't scale well, it already is a bit out of hand with the SMP ones, I think the domain functionality should be part of the existing configurations. |
If you're always running with NUM_DOMAINS > 1 and don't set up a schedule, you will get the default schedule that wraps around once 2^56-1 ticks have passed. On a 1 GHz timer tick that's after about 833 days. Impact is negligible, just wanted to point out that if you are using this for a very long-term deployment with super precise time requirements you would see a blip every few years. |
8c458dd to
a3b6e88
Compare
|
Some comments:
When we move to a clock based MCS API instead of time based, we'll run into the same issues as for domains. For x86, the timing info is passed on via bootinfo. The problem of that is that it's hard to use by stand-alone or library code, as it depends on the system how to get that information. That's why I proposed a new syscall to get the same info (it could take either a domain cap, or an SchedContext/SchedControl cap). Even on Arm and RISC-V it depends on the system used whether those kernel configs are passed on or not. |
The max number of domains has no performance impact at all as long as it fits 8 bits. You can have NUM_DOMAINS=256 and only use 4 of them. I do agree that you don't want to actually use 256 domains, that would indeed have a performance impact, but there is no reason to pick a particular low number for the maximum.
That is the only one that actually does cost a little. The kernel default is 100, but I don't think 256 is a problem.
I agree, people have been asking for a shorter minimum duration for non-MCS as well. |
That's not true, all the scheduling queues are duplicated per-domain, and they're often some of the largest data in the kernel image aside from kernel page table structures. Though it's probably not a performance impact but more just a memory usage one. (But yes, I broadly agree with you). |
You're right, there is indeed a memory impact. |
I do explicitly mention just below the xml snippet: And I also mention something similar in the |
|
I've switched the default maximums to 64 domains, and 128 domain schedule entries. Would this be sufficient? |
a791ef9 to
ed650e1
Compare
1085b8d to
887c554
Compare
64 is still way too many, especially considering Microkit practically has a limit of about 64 PDs and already uses MCS, which reduces the need for domains. I also strongly recommend reducing the number of priorities to something sane. E.g.
and the same is true for If you reduce the number of priorities to 64 and have a default number of domains of 4, then you don't use much more memory than now without domains enabled. |
I'm not so sure that MCS has much to do with reducing the need for domains. The main use case we have now is supporting ARINC like systems where domains represent independent subsystems that we want to temporally isolate from each other. We want to define a fixed schedule for these subsystems, MCS doesn't provide us that.
I won't comment on the reduction of priorities here as it's out of scope for this PR, but as said before the main current use case is using domains to represent independent subsystems, 4 is too limiting for that. KSU's simple examples already use ~11 domains. I'll reduce the defaults to 32 domains and 64 domain schedule entries |
054ec74 to
ba3f824
Compare
Indanz
left a comment
There was a problem hiding this comment.
Wouldn't it make more sense to make idx_shift and domain_start attributes of domain_schedule instead? Adding it as an attribute to an entry makes no sense.
And I would also make it standard integers, not some custom weird hexadecimal format (assuming that's supported) which can't easily defined with XSD and is less user friendly anyway. If you don't support that already, then perhaps don't use characters that would be valid within hexadecimal, it's ambiguous now.
3b992bb to
d0ff46d
Compare
|
I'm inclined to leave the number of domains at the verification default of 16. (The verification is generic over the number of domains, right, though?) |
Yes, it can be configured to anything <=255. |
In the work on [RFC-20] it was proposed that it would make sense to remove the (micro)seconds-to-ticks conversions from seL4 and migrate all of (MCS) userspace APIs to be in ticks, to make dealing with these calculations and their trickiness to instead be done at user-level - and the tradeoffs one has to make to be no longer kernel policy. This PR demonstrates implements this for the capDL initialiser. For other cases supported by the capDL specification, such (MCS) budgets and periods currently specified in microseconds, the capDL initialiser should be able to paper over the change in kernel APIs without the users needing to deal with this distinction. These changes are motivated by the [Domain schedules] PR to the seL4 Microkit, which creates a capDL specification for the (Rust version) of the capDL initialiser to use. At the moment, this PR is unable to be consistent about the values exposed to the user for the units of the domain schedule: whilst we can statically determine the us->ticks conversion for ARM/RISC-V platforms, on x86 this is a runtime-known value only. Since the spec is packed at system-build-time, we cannot therefore specify x86 domain schedules in a consistent set of units. The concrete specification changes from this PR is the addition of a 'unit' suffix inside the domain schedule syntax. The initialiser can then support either ticks (the default without any units) or microseconds, and it performs a runtime conversion of this value to ticks for the domain scheduler API. Canonically, the end marker is left without units as (0, 0), but we permit inputs of (0, 0 ticks) or (0, 0 us) for consistency. Note: the meaning of a kernel tick is different between MCS and non-MCS configurations. One consequence of taking input in 'us' is that there are cases where the input is unrepresentable in 'ticks'; and so this introduces the possiblity of failure in the initialiser that is unchecked at build-time. For non-MCS, as kernel ticks are an integer multiple of 1 ms, the conversion from us to ticks will fail if the conversion is not exact. This is easy to avoid, one has to specify a 'us' value that is a multiple of (CONFIG_TIMER_TICK_MS * 1000), something which does not differ per platform. For MCS, the kernel tick reflects the underlying timer frequency (for the domain scheduler). Thus, there exists many frequencies for which it is impossible to be exact in the conversion from us to ticks. (those frequencies above 1 MHz, which is most of them on modern 64-bit platforms). We guarantee a conversion that is accurate to the nearest tick value, or failure otherwise. This can be ±1 timer period. If you want to specify durations of length close to the period between timer ticks, please use ticks exactly. However, depending on kernel WCET domains of this duration may not be schedulable. [RFC-20]: seL4/rfcs#33 [Domain schedules]: seL4/microkit#445 Signed-off-by: Julia Vassiliki <julia.vassiliki@unsw.edu.au>
In the work on [RFC-20] it was proposed that it would make sense to remove the (micro)seconds-to-ticks conversions from seL4 and migrate all of (MCS) userspace APIs to be in ticks, to make dealing with these calculations and their trickiness to instead be done at user-level - and the tradeoffs one has to make to be no longer kernel policy. This PR demonstrates implements this for the capDL initialiser. For other cases supported by the capDL specification, such (MCS) budgets and periods currently specified in microseconds, the capDL initialiser should be able to paper over the change in kernel APIs without the users needing to deal with this distinction. These changes are motivated by the [Domain schedules] PR to the seL4 Microkit, which creates a capDL specification for the (Rust version) of the capDL initialiser to use. At the moment, this PR is unable to be consistent about the values exposed to the user for the units of the domain schedule: whilst we can statically determine the us->ticks conversion for ARM/RISC-V platforms, on x86 this is a runtime-known value only. Since the spec is packed at system-build-time, we cannot therefore specify x86 domain schedules in a consistent set of units. The concrete specification changes from this PR is the addition of a 'unit' suffix inside the domain schedule syntax. The initialiser can then support either ticks (the default without any units) or microseconds, and it performs a runtime conversion of this value to ticks for the domain scheduler API. Canonically, the end marker is left without units as (0, 0), but we permit inputs of (0, 0 ticks) or (0, 0 us) for consistency. Note: the meaning of a kernel tick is different between MCS and non-MCS configurations. One consequence of taking input in 'us' is that there are cases where the input is unrepresentable in 'ticks'; and so this introduces the possiblity of failure in the initialiser that is unchecked at build-time. For non-MCS, as kernel ticks are an integer multiple of 1 ms, the conversion from us to ticks will fail if the conversion is not exact. This is easy to avoid, one has to specify a 'us' value that is a multiple of (CONFIG_TIMER_TICK_MS * 1000), something which does not differ per platform. For MCS, the kernel tick reflects the underlying timer frequency (for the domain scheduler). Thus, there exists many frequencies for which it is impossible to be exact in the conversion from us to ticks. (those frequencies above 1 MHz, which is most of them on modern 64-bit platforms). We guarantee a conversion that is accurate to the nearest tick value, or failure otherwise. This can be ±1 timer period. If you want to specify durations of length close to the period between timer ticks, please use ticks exactly. However, depending on kernel WCET domains of this duration may not be schedulable. [RFC-20]: seL4/rfcs#33 [Domain schedules]: seL4/microkit#445 Signed-off-by: Julia Vassiliki <julia.vassiliki@unsw.edu.au>
In the work on [RFC-20] it was proposed that it would make sense to remove the (micro)seconds-to-ticks conversions from seL4 and migrate all of (MCS) userspace APIs to be in ticks, to make dealing with these calculations and their trickiness to instead be done at user-level - and the tradeoffs one has to make to be no longer kernel policy. This PR demonstrates implements this for the capDL initialiser. For other cases supported by the capDL specification, such (MCS) budgets and periods currently specified in microseconds, the capDL initialiser should be able to paper over the change in kernel APIs without the users needing to deal with this distinction. These changes are motivated by the [Domain schedules] PR to the seL4 Microkit, which creates a capDL specification for the (Rust version) of the capDL initialiser to use. At the moment, this PR is unable to be consistent about the values exposed to the user for the units of the domain schedule: whilst we can statically determine the us->ticks conversion for ARM/RISC-V platforms, on x86 this is a runtime-known value only. Since the spec is packed at system-build-time, we cannot therefore specify x86 domain schedules in a consistent set of units. The concrete specification changes from this PR is the addition of a 'unit' suffix inside the domain schedule syntax. The initialiser can then support either ticks (the default without any units) or microseconds, and it performs a runtime conversion of this value to ticks for the domain scheduler API. Canonically, the end marker is left without units as (0, 0), but we permit inputs of (0, 0 ticks) or (0, 0 us) for consistency. Note: the meaning of a kernel tick is different between MCS and non-MCS configurations. One consequence of taking input in 'us' is that there are cases where the input is unrepresentable in 'ticks'; and so this introduces the possiblity of failure in the initialiser that is unchecked at build-time. For non-MCS, as kernel ticks are an integer multiple of 1 ms, the conversion from us to ticks will fail if the conversion is not exact. This is easy to avoid, one has to specify a 'us' value that is a multiple of (CONFIG_TIMER_TICK_MS * 1000), something which does not differ per platform. For MCS, the kernel tick reflects the underlying timer frequency (for the domain scheduler). Thus, there exists many frequencies for which it is impossible to be exact in the conversion from us to ticks. (those frequencies above 1 MHz, which is most of them on modern 64-bit platforms). We guarantee a conversion that is accurate to the nearest tick value, or failure otherwise. This can be ±1 timer period. If you want to specify durations of length close to the period between timer ticks, please use ticks exactly. However, depending on kernel WCET domains of this duration may not be schedulable. [RFC-20]: seL4/rfcs#33 [Domain schedules]: seL4/microkit#445 Signed-off-by: Julia Vassiliki <julia.vassiliki@unsw.edu.au>
882cba4 to
d0ff46d
Compare
|
The original branch is here: https://github.com/au-ts/microkit/tree/archive/krishan-runtime-domains I'm going to restart this branch and reorder a lot of the commits here, because upstream has changed enough it's annoying to rebase now. |
This is confusing with seL4 domains. Signed-off-by: Julia Vassiliki <julia.vassiliki@unsw.edu.au>
Having a domain scheduler causes no issues if the domain scheduler is unused, so we can turn it on on non-smp configurations. (seL4 does not support SMP domain-scheduler). Signed-off-by: Julia Vassiliki <julia.vassiliki@unsw.edu.au>
d0ff46d to
6883235
Compare
These will be useful later. Signed-off-by: Julia Vassiliki <julia.vassiliki@unsw.edu.au>
6883235 to
03185c4
Compare
This adds a new syntax which looks like this:
<domains>
<domain name="monitor" id="0" />
<domain name="emitter" id="1" />
<domain name="collector" />
<domain_schedule start_index="3" index_shift="0" >
<schedule_entry domain="monitor" duration="3000 us" />
<schedule_entry domain="emitter" duration="8000 us" />
<schedule_entry domain="collector" duration="2000 us" />
<schedule_entry domain="monitor" duration="3000 us" />
</domain_schedule>
</domains>
Co-authored-by: Krishnan Winter <krishnan.winter@unsw.edu.au>
Signed-off-by: Julia Vassiliki <julia.vassiliki@unsw.edu.au>
When we have a domain schedule specified, this is also required. Co-authored-by: Krishnan Winter <krishnan.winter@unsw.edu.au> Signed-off-by: Julia Vassiliki <julia.vassiliki@unsw.edu.au>
This is equivalent to the CAmkES domains example which has an emitter and collector. Signed-off-by: Julia Vassiliki <julia.vassiliki@unsw.edu.au>
Mostly just error cases :) Plus some extra cases in the code. Co-authored-by: Krishnan Winter <krishnan.winter@unsw.edu.au> Signed-off-by: Julia Vassiliki <julia.vassiliki@unsw.edu.au>
We describe the syntax and the reference separately. Co-authored-by: Krishnan Winter <krishnan.winter@unsw.edu.au> Signed-off-by: Julia Vassiliki <julia.vassiliki@unsw.edu.au>
03185c4 to
54c9476
Compare
This adds support for domain schedules to the Microkit. It defines syntax that looks like:
The standard, non-SMP config is changed to always have the domain schedule configured. This is only a minor memory cost to users who do not want to use domains.
Depends on seL4/rust-sel4#360 being merged.
Original description
This PR adds support for defining domain schedules in Microkit, and relies on the run-time domain scheduler changes due to be merged into seL4.
It also depends on the following branch of rust-sel4: https://github.com/au-ts/rust-sel4/tree/domain_set?branch=domain_set
Changes for users
In
build_sdk.pywe define two new configurations,debug_domainsandrelease_domains. These configurations build the kernel with a max of 256 domains, and 256 entries into the domain schedule. The user can change this to values as they see fit. I have separated these from the regular configs as the users may not wish to have the extra memory overhead (although mostly negligible). I can merge these configs into one if its more desirable.A domain schedule is defined in the sdf as:
The length is defined in milliseconds, and reads the
TIMER_FREQUENCYfrom the kernel config to covert to timer ticks that the kernel requires. This is the case for aarch64 and riscv64. However, on x86, we don't have a static definition of the timer frequency, and is instead set at runtime by the kernel. I'm not sure of the best way to do it here, whether we should do this conversion in the capDL initialiser instead.The above will insert the schedule using the new
DomainSetinvocations, beginning at index 0 by default. We also provide capDL a start index of 0 by default.The users can optionally set these values like so:
The start index is relative to the schedule list that the user provides not an absolute index. It must be in bounds of the length of schedule that the user defines. We also can have a domain shift, which means that will start inserting the schedule at that shifted index (in the above case 10). The shift + length of the schedule must be less than the kernel configured max number of domain schedules.
We also now build one monitor per domain. The monitor is responsible for handling faults, and also making threads passive if requested. The decision to create a monitor per domain was that these faults/requests can be serviced within that domains timeslice, and not have to wait for a singular domain to be scheduled again.