init: explicit response to resource requests

This patch removes the formerly built-in policy of responding to
resource requests with handing out slack quota. Instead, resource
requests have to be answered by an update of the init configuration with
adjusted quota values.

Note that this patch may break run scripts that depend on init's
original policy. Those run scripts may be adjusted by increasing the
quota for the components that use to inflate their RAM usage during
runtime such that the specified quota suffices for the entire lifetime
of the component.
This commit is contained in:
Norman Feske 2017-03-06 18:04:10 +01:00 committed by Christian Helmuth
parent d227db4574
commit 1489791d5e
3 changed files with 81 additions and 20 deletions

View File

@ -651,7 +651,7 @@ append config {
</init_config>
<expect_log string="[init -> test] config 7: consume 2 MiB"/>
<expect_log string="[init -> test] consume 2M bytes of memory"/>
<sleep ms="500"/>
<sleep ms="300"/>
<expect_init_state>
<node name="child"> <attribute name="name" value="test"/>
<node name="ram">
@ -662,7 +662,7 @@ append config {
<!-- reduce child quota by 2M, triggering a resource-yield request -->
<init_config>
<report init_ram="yes" child_ram="yes" delay_ms="250"/>
<report init_ram="yes" child_ram="yes"/>
<parent-provides>
<service name="ROM"/> <service name="RAM"/>
<service name="CPU"/> <service name="PD"/>
@ -687,16 +687,64 @@ append config {
</node>
</expect_init_state>
<sleep ms="500"/>
<!-- let child issue a resource request -->
<init_config>
<report init_ram="yes" child_ram="yes" delay_ms="250"/>
<parent-provides>
<service name="ROM"/> <service name="RAM"/>
<service name="CPU"/> <service name="PD"/>
<service name="LOG"/>
</parent-provides>
<start name="test">
<binary name="dummy"/>
<resource name="RAM" quantum="2M"/>
<config version="request more quota than avail">
<consume_ram amount="4M"/>
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
</init_config>
<expect_log string="[init -> test] config 8: request more quota than avail"/>
<sleep ms="300"/>
<expect_init_state>
<node name="child"> <attribute name="name" value="test"/>
<node name="ram">
<attribute name="assigned" value="2M"/>
<attribute name="quota" lower="2M"/>
<attribute name="assigned" value="2M"/>
<attribute name="requested" higher="4000K"/>
</node>
</node>
</expect_init_state>
<!-- respond to resource request-->
<init_config>
<report init_ram="yes" child_ram="yes"/>
<parent-provides>
<service name="ROM"/> <service name="RAM"/>
<service name="CPU"/> <service name="PD"/>
<service name="LOG"/>
</parent-provides>
<start name="test">
<binary name="dummy"/>
<resource name="RAM" quantum="6M"/>
<config version="request more quota than avail">
<consume_ram amount="4M"/>
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
</init_config>
<sleep ms="150"/>
<expect_init_state>
<node name="child"> <attribute name="name" value="test"/>
<node name="ram">
<attribute name="assigned" value="6M"/>
<attribute name="quota" higher="5M"/>
</node>
</node>
</expect_init_state>
<message string="test complete"/>
</config>
<route>
<service name="Report"> <child name="report_rom"/> </service>

View File

@ -203,6 +203,12 @@ void Init::Child::apply_ram_upgrade()
_check_resource_constraints(_ram_limit_accessor.ram_limit());
ref_ram().transfer_quota(_child.ram_session_cap(), transfer);
/* wake up child that blocks on a resource request */
if (_requested_resources.constructed()) {
_child.notify_resource_avail();
_requested_resources.destruct();
}
}
}
@ -288,6 +294,10 @@ void Init::Child::report_state(Xml_generator &xml, Report_detail const &detail)
*/
auto &nonconst_child = const_cast<Genode::Child &>(_child);
generate_ram_info(xml, nonconst_child.ram());
if (_requested_resources.constructed())
xml.attribute("requested", String<32> {
Number_of_bytes(_requested_resources->ram.value) });
});
}
@ -592,22 +602,10 @@ void Init::Child::announce_service(Service::Name const &service_name)
void Init::Child::resource_request(Parent::Resource_args const &args)
{
log("child \"", name(), "\" requests resources: ", args.string());
log("child \"", name(), "\" requests resources: ", args);
size_t const requested_ram_quota =
Arg_string::find_arg(args.string(), "ram_quota")
.ulong_value(0);
if (_ram_limit_accessor.ram_limit().value < requested_ram_quota) {
warning("cannot respond to resource request - out of memory");
return;
}
_env.ram().transfer_quota(_child.ram_session_cap(),
requested_ram_quota);
/* wake up child that was starved for resources */
_child.notify_resource_avail();
_requested_resources.construct(args);
_report_update_trigger.trigger_report_update();
}

View File

@ -250,6 +250,21 @@ class Init::Child : Child_policy, Child_service::Wakeup
*/
bool const _constrain_phys { _resources.constrain_phys };
/**
* Resource request initiated by the child
*/
struct Requested_resources
{
Ram_quota const ram;
Requested_resources(Parent::Resource_args const &args)
:
ram(Ram_quota { Arg_string::find_arg(args.string(), "ram_quota")
.ulong_value(0) })
{ }
};
Constructible<Requested_resources> _requested_resources;
Genode::Child _child { _env.rm(), _env.ep().rpc_ep(), *this };
struct Ram_accessor : Routed_service::Ram_accessor