Files
genode/base/include/base/affinity.h
Norman Feske 6d837c9e26 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.
2013-08-13 17:08:25 +02:00

170 lines
4.5 KiB
C++

/*
* \brief Representation of CPU affinities
* \author Norman Feske
* \date 2013-08-07
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__BASE__AFFINITY_H_
#define _INCLUDE__BASE__AFFINITY_H_
namespace Genode {
/**
* Affinity to CPU nodes
*
* The entity of CPU nodes is expected to form a grid where the Euclidean
* distance between nodes roughly correlate to the locality of their
* respective resources. Closely interacting processes are supposed to
* perform best when using nodes close to each other. To allow a relatively
* simple specification of such constraints, the affinity of a subsystem
* (e.g., a process) to CPU nodes is expressed as a rectangle within the
* grid of available CPU nodes. The dimensions of the grid are represented
* by 'Affinity::Space'. The rectangle within the grid is represented by
* 'Affinity::Location'.
*/
class Affinity
{
public:
class Location;
/**
* Bounds of the affinity name space
*
* An 'Affinity::Space' defines the bounds of a Cartesian
* coordinate space that expresses the entity of available CPU
* nodes. The dimension values do not necessarily correspond to
* physical CPU numbers. They solely represent the range the
* 'Affinity::Location' is relative to.
*/
class Space
{
private:
unsigned _width, _height;
public:
Space() : _width(0), _height(0) { }
/**
* Construct a two-dimensional affinity space
*/
Space(unsigned width, unsigned height)
: _width(width), _height(height) { }
/**
* Constuct one-dimensional affinity space
*/
Space(unsigned size) : _width(size), _height(1) { }
unsigned width() const { return _width; }
unsigned height() const { return _height; }
unsigned total() const { return _width*_height; }
/**
* Return location of a single CPU of specified index
*/
inline Location location_of_index(int index);
};
/**
* Location within 'Space'
*/
class Location
{
private:
int _xpos, _ypos;
unsigned _width, _height;
public:
/**
* Default constructor creates invalid location
*/
Location() : _xpos(0), _ypos(0), _width(0), _height(0) { }
/**
* Constructor to express the affinity to a single CPU
*/
Location(int xpos, unsigned ypos)
: _xpos(xpos), _ypos(ypos), _width(1), _height(1) { }
/**
* Constructor to express the affinity to a set of CPUs
*/
Location(int xpos, int ypos, unsigned width, unsigned height)
: _xpos(xpos), _ypos(ypos), _width(width), _height(height) { }
int xpos() const { return _xpos; }
int ypos() const { return _ypos; }
unsigned width() const { return _width; }
unsigned height() const { return _height; }
bool valid() const { return _width*_height > 0; }
};
private:
Space _space;
Location _location;
public:
Affinity(Space const &space, Location const &location)
: _space(space), _location(location) { }
Affinity() { }
Space space() const { return _space; }
Location location() const { return _location; }
/**
* Return location scaled to specified affinity space
*/
Location scale_to(Space const &space) const
{
if (_space.total() == 0)
return Location();
/*
* Calculate coordinates of rectangle corners
*
* P1 is the upper left corner, inside the rectangle.
* P2 is the lower right corner, outside the rectangle.
*/
int const x1 = _location.xpos(),
y1 = _location.ypos(),
x2 = _location.width() + x1,
y2 = _location.height() + y1;
/* scale corner positions */
int const scaled_x1 = (x1*space.width()) / _space.width(),
scaled_y1 = (y1*space.height()) / _space.height(),
scaled_x2 = (x2*space.width()) / _space.width(),
scaled_y2 = (y2*space.height()) / _space.height();
/* make sure to not scale the location size to zero */
return Location(scaled_x1, scaled_y1,
max(scaled_x2 - scaled_x1, 1),
max(scaled_y2 - scaled_y1, 1));
}
};
Affinity::Location Affinity::Space::location_of_index(int index)
{
return Location(index % _width, index / _width, 1, 1);
}
}
#endif /* _INCLUDE__BASE__AFFINITY_H_ */