Attach affinity information to session requests

This patch extends the 'Parent::session()' and 'Root::session()'
functions with an additional 'affinity' parameter, which is inteded to
express the preferred affinity of the new session. For CPU sessions
provided by core, the values will be used to select the set of CPUs
assigned to the CPU session. For other services, the session affinity
information can be utilized to optimize the locality of the server
thread with the client. For example, to enable the IRQ session to route
an IRQ to the CPU core on which the corresponding device driver (the IRQ
client) is running.
This commit is contained in:
Norman Feske 2013-08-07 23:10:28 +02:00
parent f1af8e371d
commit 6d837c9e26
35 changed files with 137 additions and 78 deletions

View File

@ -56,7 +56,8 @@ Platform_env_base::Rm_session_mmap::_dataspace_writable(Dataspace_capability ds)
Session_capability
Platform_env::Local_parent::session(Service_name const &service_name,
Session_args const &args)
Session_args const &args,
Affinity const &affinity)
{
if (strcmp(service_name.string(),
Rm_session::service_name()) == 0)
@ -66,7 +67,7 @@ Platform_env::Local_parent::session(Service_name const &service_name,
.ulong_value(~0);
if (size == 0)
return Parent_client::session(service_name, args);
return Parent_client::session(service_name, args, affinity);
Rm_session_mmap *rm = new (env()->heap())
Rm_session_mmap(true, size);
@ -74,7 +75,7 @@ Platform_env::Local_parent::session(Service_name const &service_name,
return Session_capability::local_cap(rm);
}
return Parent_client::session(service_name, args);
return Parent_client::session(service_name, args, affinity);
}

View File

@ -387,7 +387,8 @@ namespace Genode {
**********************/
Session_capability session(Service_name const &,
Session_args const &);
Session_args const &,
Affinity const & = Affinity());
void close(Session_capability);
/**

View File

@ -117,6 +117,8 @@ namespace Genode {
Space _space;
Location _location;
public:
Affinity(Space const &space, Location const &location)
: _space(space), _location(location) { }

View File

@ -269,7 +269,8 @@ namespace Genode {
**********************/
void announce(Service_name const &, Root_capability);
Session_capability session(Service_name const &, Session_args const &);
Session_capability session(Service_name const &, Session_args const &,
Affinity const &);
void upgrade(Session_capability, Upgrade_args const &);
void close(Session_capability);
void exit(int);

View File

@ -126,13 +126,15 @@ namespace Genode {
/**
* Create session
*
* \param args session-construction arguments
* \param args session-construction arguments
* \param affinity preferred CPU affinity of session
*
* \throw Invalid_args
* \throw Unavailable
* \throw Quota_exceeded
*/
virtual Session_capability session(const char *args) = 0;
virtual Session_capability session(char const *args,
Affinity const &affinity) = 0;
/**
* Extend resource donation to an existing session
@ -175,9 +177,9 @@ namespace Genode {
Local_service(const char *name, Root *root)
: Service(name), _root(root) { }
Session_capability session(const char *args)
Session_capability session(const char *args, Affinity const &affinity)
{
try { return _root->session(args); }
try { return _root->session(args, affinity); }
catch (Root::Invalid_args) { throw Invalid_args(); }
catch (Root::Unavailable) { throw Unavailable(); }
catch (Root::Quota_exceeded) { throw Quota_exceeded(); }
@ -200,9 +202,9 @@ namespace Genode {
Parent_service(const char *name) : Service(name) { }
Session_capability session(const char *args)
Session_capability session(const char *args, Affinity const &affinity)
{
try { return env()->parent()->session(name(), args); }
try { return env()->parent()->session(name(), args, affinity); }
catch (Parent::Unavailable) {
PWRN("parent has no service \"%s\"", name());
throw Unavailable();
@ -245,12 +247,12 @@ namespace Genode {
Server *server() const { return _server; }
Session_capability session(const char *args)
Session_capability session(const char *args, Affinity const &affinity)
{
if (!_root_cap.valid())
throw Unavailable();
try { return _root.session(args); }
try { return _root.session(args, affinity); }
catch (Root::Invalid_args) { throw Invalid_args(); }
catch (Root::Unavailable) { throw Unavailable(); }
catch (Root::Quota_exceeded) { throw Quota_exceeded(); }

View File

@ -30,8 +30,9 @@ namespace Genode {
call<Rpc_announce>(service, root); }
Session_capability session(Service_name const &service,
Session_args const &args) {
return call<Rpc_session>(service, args); }
Session_args const &args,
Affinity const &affinity) {
return call<Rpc_session>(service, args, affinity); }
void upgrade(Session_capability to_session, Upgrade_args const &args) {
call<Rpc_upgrade>(to_session, args); }

View File

@ -107,6 +107,7 @@ namespace Genode {
*
* \param service_name name of the requested interface
* \param args session constructor arguments
* \param affinity preferred CPU affinity for the session
*
* \throw Service_denied parent denies session request
* \throw Quota_exceeded our own quota does not suffice for
@ -119,13 +120,15 @@ namespace Genode {
* 'session()' template instead.
*/
virtual Session_capability session(Service_name const &service_name,
Session_args const &args) = 0;
Session_args const &args,
Affinity const &affinity = Affinity()) = 0;
/**
* Create session to a service
*
* \param SESSION_TYPE session interface type
* \param args session constructor arguments
* \param SESSION_TYPE session interface type
* \param args session constructor arguments
* \param affinity preferred CPU affinity for the session
*
* \throw Service_denied parent denies session request
* \throw Quota_exceeded our own quota does not suffice for
@ -135,9 +138,11 @@ namespace Genode {
* \return capability to new session
*/
template <typename SESSION_TYPE>
Capability<SESSION_TYPE> session(Session_args const &args)
Capability<SESSION_TYPE> session(Session_args const &args,
Affinity const &affinity = Affinity())
{
Session_capability cap = session(SESSION_TYPE::service_name(), args);
Session_capability cap = session(SESSION_TYPE::service_name(),
args, affinity);
return reinterpret_cap_cast<SESSION_TYPE>(cap);
}
@ -176,7 +181,7 @@ namespace Genode {
Service_name const &, Root_capability);
GENODE_RPC_THROW(Rpc_session, Session_capability, session,
GENODE_TYPE_LIST(Service_denied, Quota_exceeded, Unavailable),
Service_name const &, Session_args const &);
Service_name const &, Session_args const &, Affinity const &);
GENODE_RPC_THROW(Rpc_upgrade, void, upgrade,
GENODE_TYPE_LIST(Quota_exceeded),
Session_capability, Upgrade_args const &);

View File

@ -24,8 +24,8 @@ namespace Genode {
explicit Root_client(Root_capability root)
: Rpc_client<Root>(root) { }
Session_capability session(Session_args const &args) {
return call<Rpc_session>(args); }
Session_capability session(Session_args const &args, Affinity const &affinity) {
return call<Rpc_session>(args, affinity); }
void upgrade(Session_capability session, Upgrade_args const &args) {
call<Rpc_upgrade>(session, args); }

View File

@ -120,12 +120,25 @@ namespace Genode {
* by 'Root_component' must be used for allocating the session
* object.
*
* If the server implementation does not evaluate the session
* affinity, it suffices to override the overload without the
* affinity argument.
*
* \throw Allocator::Out_of_memory typically caused by the
* meta-data allocator
* \throw Root::Invalid_args typically caused by the
* session-component constructor
*/
virtual SESSION_TYPE *_create_session(const char *args) = 0;
virtual SESSION_TYPE *_create_session(const char *args,
Affinity const &)
{
return _create_session(args);
}
virtual SESSION_TYPE *_create_session(const char *args)
{
throw Root::Invalid_args();
}
/**
* Inform session about a quota upgrade
@ -175,7 +188,8 @@ namespace Genode {
** Root interface **
********************/
Session_capability session(Root::Session_args const &args)
Session_capability session(Root::Session_args const &args,
Affinity const &affinity)
{
if (!args.is_valid_string()) throw Root::Invalid_args();
@ -213,7 +227,7 @@ namespace Genode {
"ram_quota", ram_quota_buf);
SESSION_TYPE *s = 0;
try { s = _create_session(adjusted_args); }
try { s = _create_session(adjusted_args, affinity); }
catch (Allocator::Out_of_memory) { throw Root::Quota_exceeded(); }
return _ep->manage(s);

View File

@ -17,6 +17,7 @@
#include <base/exception.h>
#include <base/rpc.h>
#include <base/rpc_args.h>
#include <base/affinity.h>
#include <session/capability.h>
namespace Genode {
@ -46,7 +47,8 @@ namespace Genode {
*
* \return capability to new session
*/
virtual Session_capability session(Session_args const &args) = 0;
virtual Session_capability session(Session_args const &args,
Affinity const &affinity) = 0;
/**
* Extend resource donation to an existing session
@ -65,7 +67,7 @@ namespace Genode {
GENODE_RPC_THROW(Rpc_session, Session_capability, session,
GENODE_TYPE_LIST(Unavailable, Quota_exceeded, Invalid_args),
Session_args const &);
Session_args const &, Affinity const &);
GENODE_RPC_THROW(Rpc_upgrade, void, upgrade,
GENODE_TYPE_LIST(Invalid_args),
Session_capability, Upgrade_args const &);

View File

@ -242,7 +242,8 @@ void Child::announce(Parent::Service_name const &name, Root_capability root)
Session_capability Child::session(Parent::Service_name const &name,
Parent::Session_args const &args)
Parent::Session_args const &args,
Affinity const &affinity)
{
if (!name.is_valid_string() || !args.is_valid_string()) throw Unavailable();
@ -273,7 +274,7 @@ Session_capability Child::session(Parent::Service_name const &name,
/* create session */
Session_capability cap;
try { cap = service->session(_args); }
try { cap = service->session(_args, affinity); }
catch (Service::Invalid_args) { throw Service_denied(); }
catch (Service::Unavailable) { throw Service_denied(); }
catch (Service::Quota_exceeded) { throw Quota_exceeded(); }

View File

@ -45,7 +45,8 @@ namespace Genode {
PDBG("implement me, please");
}
Session_capability session(Service_name const &, Session_args const &);
Session_capability session(Service_name const &, Session_args const &,
Affinity const &);
void upgrade(Session_capability, Upgrade_args const &)
{

View File

@ -56,7 +56,7 @@ namespace Genode {
** Root interface **
********************/
Session_capability session(Session_args const &args)
Session_capability session(Session_args const &args, Affinity const &affinity)
{
if (!args.is_valid_string()) throw Invalid_args();

View File

@ -56,9 +56,9 @@ namespace Genode {
size == 0 ? _vm_size : size);
}
Session_capability session(Root::Session_args const &args)
Session_capability session(Root::Session_args const &args, Affinity const &affinity)
{
Session_capability cap = Root_component<Rm_session_component>::session(args);
Session_capability cap = Root_component<Rm_session_component>::session(args, affinity);
/* lookup rm_session_component object */
Object_pool<Rm_session_component>::Guard rm_session(ep()->lookup_and_lock(cap));

View File

@ -84,12 +84,13 @@ Platform_generic *Genode::platform() { return platform_specific(); }
*************************/
Session_capability Core_parent::session(Parent::Service_name const &name,
Parent::Session_args const &args)
Parent::Session_args const &args,
Affinity const &affinity)
{
Service *service = local_services.find(name.string());
if (service)
return service->session(args.string());
return service->session(args.string(), affinity);
PWRN("service_name=\"%s\" arg=\"%s\" not handled", name.string(), args.string());
return Session_capability();
@ -235,7 +236,7 @@ int main()
/* create ram session for init and transfer some of our own quota */
Ram_session_capability init_ram_session_cap
= static_cap_cast<Ram_session>(ram_root.session("ram_quota=32K"));
= static_cap_cast<Ram_session>(ram_root.session("ram_quota=32K", Affinity()));
Ram_session_client(init_ram_session_cap).ref_account(env()->ram_session_cap());
Cpu_connection init_cpu("init");

View File

@ -156,7 +156,8 @@ int main(int, char **)
6*4096 + tx_buf_size + rx_buf_size,
tx_buf_size, rx_buf_size))
*/
nic_root.session("ram_quota=155648, tx_buf_size=65536, rx_buf_size=65536");
nic_root.session("ram_quota=155648, tx_buf_size=65536, rx_buf_size=65536",
Affinity());
sleep_forever();
return 0;

View File

@ -51,7 +51,9 @@ class Iso9660_boot_probe
Proxy_service(Genode::Session_capability session)
: Genode::Service("proxy"), _session(session) { }
Genode::Session_capability session(const char *) { return _session; }
Genode::Session_capability session(char const *,
Genode::Affinity const &)
{ return _session; }
void upgrade(Genode::Session_capability session, const char *) { }
@ -127,7 +129,8 @@ class Iso9660_boot_probe
{
char const *args = "ram_quota=140K, tx_buf_size=128K";
Genode::Root_client root(_block_root);
return Genode::static_cap_cast<Block::Session>(root.session(args));
return Genode::static_cap_cast<Block::Session>
(root.session(args, Genode::Affinity()));
}
/**
@ -152,7 +155,7 @@ class Iso9660_boot_probe
char args[Genode::Root::Session_args::MAX_SIZE];
Genode::snprintf(args, sizeof(args), "ram_quota=4K, filename=\"%s\"",
boot_tag_name);
rom_root.session(args);
rom_root.session(args, Genode::Affinity());
}
public:
@ -297,11 +300,12 @@ namespace Block {
Root(Driver_registry &driver_registry)
: _driver_registry(driver_registry) { }
Genode::Session_capability session(Genode::Root::Session_args const &args)
Genode::Session_capability session(Genode::Root::Session_args const &args,
Genode::Affinity const &affinity)
{
PDBG("\nsession requested args=\"%s\"", args.string());
Genode::Root_capability root = _driver_registry.root();
return Genode::Root_client(root).session(args);
return Genode::Root_client(root).session(args, affinity);
}
void upgrade(Genode::Session_capability,

View File

@ -55,7 +55,8 @@ namespace Input {
try {
using namespace Genode;
return static_cap_cast<Session>(Root_client(root).session(args));
return static_cap_cast<Session>
(Root_client(root).session(args, Genode::Affinity()));
} catch (...) {
throw Source_unavailable();
}

View File

@ -40,7 +40,8 @@ namespace Nic {
public:
Genode::Session_capability session(Session_args const &args)
Genode::Session_capability session(Session_args const &args,
Genode::Affinity const &affinity)
{
if (!args.is_valid_string()) throw Invalid_args();
@ -48,7 +49,8 @@ namespace Nic {
throw Unavailable();
try {
return Genode::Root_client(_nic_provider.root()).session(args.string());
return Genode::Root_client(_nic_provider.root())
.session(args.string(), affinity);
} catch (...) {
throw Unavailable();
}

View File

@ -229,7 +229,8 @@ namespace Init {
}
}
Genode::Session_capability session(const char *args)
Genode::Session_capability session(const char *args,
Genode::Affinity const &affinity)
{
/*
* This function is called from the context of the client's
@ -246,7 +247,7 @@ namespace Init {
_applicants_lock.unlock();
Genode::Session_capability cap;
try { cap = Genode::Root_client(_root).session(args); }
try { cap = Genode::Root_client(_root).session(args, affinity); }
catch (Genode::Root::Invalid_args) { throw Invalid_args(); }
catch (Genode::Root::Unavailable) { throw Unavailable(); }
catch (Genode::Root::Quota_exceeded) { throw Quota_exceeded(); }

View File

@ -171,7 +171,8 @@ namespace Init {
Local_rom_service(Genode::Rom_session_capability rom_cap, bool valid)
: Genode::Service("ROM"), _rom_cap(rom_cap), _valid(valid) { }
Genode::Session_capability session(const char * /*args*/)
Genode::Session_capability session(char const * /*args*/,
Genode::Affinity const &)
{
if (!_valid)
throw Invalid_args();

View File

@ -135,7 +135,9 @@ namespace Genode {
** Service interface **
***********************/
Session_capability session(const char *) { return _rom_session_cap; }
Session_capability session(const char *, Affinity const &) {
return _rom_session_cap; }
void upgrade(Session_capability, const char *) { }
void close(Session_capability) { }

View File

@ -51,7 +51,7 @@ class Genode::Static_root : public Genode::Rpc_object<Genode::Typed_root<SESSION
** Root interface **
********************/
Capability<Session> session(Root::Session_args const &args)
Capability<Session> session(Root::Session_args const &args, Affinity const &)
{
return _session;
}

View File

@ -74,7 +74,8 @@ namespace Irq {
/**
* Remap IRQ number and create IRQ session at parent
*/
Genode::Session_capability session(Root::Session_args const &args)
Genode::Session_capability session(Root::Session_args const &args,
Genode::Affinity const &)
{
using namespace Genode;
@ -127,7 +128,8 @@ namespace Pci {
Root(Provider &pci_provider) : _pci_provider(pci_provider) { }
Genode::Session_capability session(Session_args const &args)
Genode::Session_capability session(Session_args const &args,
Genode::Affinity const &affinity)
{
if (!args.is_valid_string()) throw Invalid_args();
@ -135,7 +137,8 @@ namespace Pci {
throw Unavailable();
try {
return Genode::Root_client(_pci_provider.root()).session(args.string());
return Genode::Root_client(_pci_provider.root())
.session(args.string(), affinity);
} catch (...) {
throw Unavailable();
}
@ -179,7 +182,8 @@ class Pci_policy : public Genode::Slave_policy, public Pci::Provider
try {
using namespace Genode;
session = static_cap_cast<Pci::Session>(Root_client(_cap).session(args));
session = static_cap_cast<Pci::Session>(Root_client(_cap)
.session(args, Genode::Affinity()));
} catch (...) { return; }
Acpi::configure_pci_devices(session);

View File

@ -94,7 +94,7 @@ int main(int argc, char **argv)
static Device_pd_policy device_pd_policy(device_pd_ep);
static Genode::Slave device_pd_slave(device_pd_ep, device_pd_policy,
PCI_DEVICE_PD_RAM_QUOTA);
session_dev_pd = Genode::Root_client(device_pd_policy.root()).session("");
session_dev_pd = Genode::Root_client(device_pd_policy.root()).session("", Affinity());
} catch (...) {
PWRN("PCI device protection domain for IOMMU support is not available");
}

View File

@ -95,7 +95,7 @@ namespace Loader {
try {
char args[Session::Name::MAX_SIZE];
snprintf(args, sizeof(args), "ram_quota=4K, filename=\"%s\"", name);
return static_cap_cast<Rom_session>(_local_rom_service.session(args));
return static_cap_cast<Rom_session>(_local_rom_service.session(args, Affinity()));
} catch (Genode::Parent::Service_denied) {
PERR("Lookup for ROM module \"%s\" failed", name);
throw;

View File

@ -73,7 +73,8 @@ namespace Loader {
_close(_rom_sessions.first()); }
}
Genode::Session_capability session(const char *args)
Genode::Session_capability session(char const *args,
Affinity const &affinity)
{
/* try to find ROM module at local ROM service */
try {
@ -97,7 +98,7 @@ namespace Loader {
} catch (...) { }
/* fall back to parent_rom_service */
return _parent_rom_service.session(args);
return _parent_rom_service.session(args, affinity);
}
void close(Session_capability session)
@ -145,9 +146,10 @@ namespace Loader {
{
Local_cpu_service() : Intercepted_parent_service("CPU") { }
Genode::Session_capability session(const char *args)
Genode::Session_capability session(char const *args,
Affinity const &affinity)
{
Capability<Cpu_session> cap = env()->parent()->session<Cpu_session>(args);
Capability<Cpu_session> cap = env()->parent()->session<Cpu_session>(args, affinity);
Cpu_session_client(cap).exception_handler(Thread_capability(), fault_sigh);
return cap;
}
@ -160,9 +162,10 @@ namespace Loader {
{
Local_rm_service() : Intercepted_parent_service("RM") { }
Genode::Session_capability session(const char *args)
Genode::Session_capability session(char const *args,
Affinity const &affinity)
{
Capability<Rm_session> cap = env()->parent()->session<Rm_session>(args);
Capability<Rm_session> cap = env()->parent()->session<Rm_session>(args, affinity);
Rm_session_client(cap).fault_handler(fault_sigh);
return cap;
}
@ -195,7 +198,8 @@ namespace Loader {
destroy(&_md_alloc, open_session);
}
Genode::Session_capability session(const char *args)
Genode::Session_capability session(char const *args,
Affinity const &)
{
if (open_session)
throw Unavailable();

View File

@ -41,7 +41,8 @@ namespace Terminal {
public:
Session_capability session(Root::Session_args const &args)
Session_capability session(Root::Session_args const &args,
Genode::Affinity const &)
{
if (!(_session_state & FIRST_SESSION_OPEN)) {
_session_state |= FIRST_SESSION_OPEN;

View File

@ -85,9 +85,10 @@ namespace Gdb_monitor {
_rm_root(entrypoint, md_alloc, managed_ds_map)
{ }
Genode::Session_capability session(const char *args)
Genode::Session_capability session(const char *args,
Genode::Affinity const &affinity)
{
return _rm_root.session(args);
return _rm_root.session(args, affinity);
}
void upgrade(Genode::Session_capability, const char *) { }
@ -102,7 +103,7 @@ namespace Gdb_monitor {
{
_entrypoint.manage(&_rm_root);
Capability<Rm_session> cap = static_cap_cast<Rm_session>
(_rm_root.session("ram_quota=64K"));
(_rm_root.session("ram_quota=64K", Affinity()));
Rm_session_client rm(cap);
rm.fault_handler(_gdb_stub_thread.exception_signal_receiver()->manage(new (env()->heap()) Signal_context()));
@ -114,7 +115,7 @@ namespace Gdb_monitor {
_entrypoint.manage(&_cpu_root);
char args[64];
Genode::snprintf(args, sizeof(args), "ram_quota=32K, label=\"%s\"", _unique_name);
return static_cap_cast<Cpu_session>(_cpu_root.session(args));
return static_cap_cast<Cpu_session>(_cpu_root.session(args, Affinity()));
}
/**
@ -172,7 +173,8 @@ namespace Gdb_monitor {
** Root interface **
********************/
Session_capability session(Session_args const &args)
Session_capability session(Session_args const &args,
Affinity const &affinity)
{
using namespace Genode;
@ -183,7 +185,7 @@ namespace Gdb_monitor {
/* forward session quota to child */
env()->ram_session()->transfer_quota(_child_ram, ram_quota);
Session_capability cap = _child_root.session(args);
Session_capability cap = _child_root.session(args, affinity);
/*
* Keep information about donated quota in '_sessions'

View File

@ -114,8 +114,8 @@ namespace Gdb_monitor {
: Service("ROM"), _root(entrypoint, md_alloc)
{ }
Capability<Session> session(char const *args) {
return _root.session(args); }
Capability<Session> session(char const *args, Affinity const &affinity) {
return _root.session(args, affinity); }
void upgrade(Capability<Session>, char const *) { }

View File

@ -37,7 +37,7 @@ namespace Noux {
_cap(cap)
{ }
Genode::Session_capability session(const char *args)
Genode::Session_capability session(const char *args, Affinity const &)
{
PDBG("Implement me!");
return Genode::Session_capability();

View File

@ -33,7 +33,11 @@ namespace Noux {
Local_noux_service(Genode::Session_capability cap)
: Service(Session::service_name()), _cap(cap) { }
Genode::Session_capability session(const char *args) { return _cap; }
Genode::Session_capability session(const char *args, Affinity const &)
{
return _cap;
}
void upgrade(Genode::Session_capability, const char *args) { }
void close(Genode::Session_capability) { }
};

View File

@ -35,7 +35,7 @@ namespace Noux {
Service(Ram_session::service_name()), _ep(ep)
{ }
Genode::Session_capability session(const char *args)
Genode::Session_capability session(const char *args, Affinity const &)
{
PDBG("Implement me!");
return Genode::Session_capability();

View File

@ -103,7 +103,7 @@ namespace Noux {
_ds_registry(ds_registry)
{ }
Genode::Session_capability session(const char *args)
Genode::Session_capability session(const char *args, Affinity const &)
{
addr_t start = Arg_string::find_arg(args, "start").ulong_value(~0UL);
size_t size = Arg_string::find_arg(args, "size").ulong_value(0);

View File

@ -42,7 +42,7 @@ namespace Noux {
_ds_registry(ds_registry)
{ }
Genode::Session_capability session(const char *args)
Genode::Session_capability session(const char *args, Affinity const &)
{
enum { NAME_MAX_LEN = 128 };
char name[NAME_MAX_LEN];