Apply affinity subspacing to session requests

This commit is contained in:
Norman Feske 2013-08-14 21:19:11 +02:00
parent a4066c358e
commit a652cb5110
5 changed files with 120 additions and 1 deletions

View File

@ -69,6 +69,11 @@ namespace Genode {
unsigned height() const { return _height; }
unsigned total() const { return _width*_height; }
Space multiply(Space const &other) const
{
return Space(_width*other.width(), _height*other.height());
}
/**
* Return location of a single CPU of specified index
*/
@ -110,6 +115,17 @@ namespace Genode {
unsigned width() const { return _width; }
unsigned height() const { return _height; }
bool valid() const { return _width*_height > 0; }
Location multiply_position(Space const &space) const
{
return Location(_xpos*space.width(), _ypos*space.height(),
_width, _height);
}
Location transpose(int dx, int dy) const
{
return Location(_xpos + dx, _ypos + dy, _width, _height);
}
};
private:

View File

@ -73,6 +73,17 @@ namespace Genode {
Server * /*server*/)
{ return false; }
/**
* Apply session affinity policy
*
* \param affinity affinity passed along with a session request
* \return affinity subordinated to the child policy
*/
virtual Affinity filter_session_affinity(Affinity const &affinity)
{
return affinity;
}
/**
* Unregister services that had been provided by the child
*/

View File

@ -0,0 +1,63 @@
#
# \brief Test to affinity subspacing
# \author Norman Feske
#
if {[have_spec platform_pbxa9] || (![have_spec nova] && ![have_spec foc])} {
puts "Platform is unsupported."
exit 0
}
build "core init test/affinity"
create_boot_directory
install_config {
<config>
<parent-provides>
<service name="LOG"/>
<service name="CPU"/>
<service name="RM"/>
<service name="ROM"/>
<service name="RAM"/>
<service name="CAP"/>
<service name="PD"/>
<service name="SIGNAL"/>
</parent-provides>
<affinity-space width="2" />
<default-route>
<any-service> <parent/> </any-service>
</default-route>
<start name="init">
<resource name="RAM" quantum="10M"/>
<!-- assign the right half of the available CPUs -->
<affinity xpos="1" width="1" />
<config>
<parent-provides>
<service name="LOG"/>
<service name="CPU"/>
<service name="RM"/>
</parent-provides>
<default-route>
<any-service> <parent/> </any-service>
</default-route>
<!-- assign the leftmost half of CPUs to test-affinity -->
<affinity-space width="2" />
<start name="test-affinity">
<resource name="RAM" quantum="2M"/>
<affinity xpos="0" width="1" />
</start>
</config>
</start>
</config>
}
append qemu_args " -nographic -m 64 -smp 8,cores=8 "
build_boot_image "core init test-affinity"
run_genode_until {.*Detected 2x1 CPUs.*} 60
puts "Test succeeded"

View File

@ -257,6 +257,9 @@ Session_capability Child::session(Parent::Service_name const &name,
strncpy(_args, args.string(), sizeof(_args));
_policy->filter_session_args(name.string(), _args, sizeof(_args));
/* filter session affinity */
Affinity const filtered_affinity = _policy->filter_session_affinity(affinity);
/* transfer the quota donation from the child's account to ourself */
size_t ram_quota = Arg_string::find_arg(_args, "ram_quota").long_value(0);
@ -274,7 +277,7 @@ Session_capability Child::session(Parent::Service_name const &name,
/* create session */
Session_capability cap;
try { cap = service->session(_args, affinity); }
try { cap = service->session(_args, filtered_affinity); }
catch (Service::Invalid_args) { throw Service_denied(); }
catch (Service::Unavailable) { throw Service_denied(); }
catch (Service::Quota_exceeded) { throw Quota_exceeded(); }

View File

@ -658,6 +658,32 @@ namespace Init {
_pd_args_policy. filter_session_args(service, args, args_len);
}
Genode::Affinity filter_session_affinity(Genode::Affinity const &session_affinity)
{
using namespace Genode;
/* check if no valid affinity space was specified */
if (session_affinity.space().total() == 0)
return session_affinity;
Affinity::Space const &session_space = session_affinity.space();
Affinity::Location const &session_location = session_affinity.location();
Affinity::Space const &child_space = _resources.affinity.space();
Affinity::Location const &child_location = _resources.affinity.location();
/* scale resolution of resulting space */
Affinity::Space space(child_space.multiply(session_space));
/* subordinate session affinity to child affinity subspace */
Affinity::Location location(child_location
.multiply_position(session_space)
.transpose(session_location.xpos(),
session_location.ypos()));
return Affinity(space, location);
}
bool announce_service(const char *service_name,
Genode::Root_capability root,
Genode::Allocator *alloc,