168 lines
4.5 KiB
C
168 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;
|
||
|
|
||
|
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_ */
|