-
Notifications
You must be signed in to change notification settings - Fork 246
/
affinity.h
191 lines (153 loc) · 5.04 KB
/
affinity.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
* \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 { class Affinity; }
/**
* 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 Genode::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; }
Space multiply(Space const &other) const
{
return Space(_width*other.width(), _height*other.height());
}
/**
* Return the location of the Nth CPU within the affinity
* space
*
* This method returns a valid location even if the index
* is larger than the number of CPUs in the space. In this
* case, the x and y coordinates are wrapped by the bounds
* of the space.
*/
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; }
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:
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));
}
};
Genode::Affinity::Location Genode::Affinity::Space::location_of_index(int index)
{
return Location(index % _width, (index / _width) % _height, 1, 1);
}
#endif /* _INCLUDE__BASE__AFFINITY_H_ */