mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-21 02:01:38 +00:00
CPU load display application
This commit is contained in:
parent
e45e01ee8e
commit
caa809e593
217
repos/gems/run/cpu_load_display.run
Normal file
217
repos/gems/run/cpu_load_display.run
Normal file
@ -0,0 +1,217 @@
|
||||
#
|
||||
# Build
|
||||
#
|
||||
|
||||
if {[have_spec hw_odroid_xu]} {
|
||||
puts "Run script not supported on this platform."; exit 0 }
|
||||
|
||||
set build_components {
|
||||
core init
|
||||
drivers/timer
|
||||
server/nitpicker
|
||||
server/dynamic_rom
|
||||
drivers/framebuffer drivers/input
|
||||
app/trace_subject_reporter
|
||||
app/cpu_load_display
|
||||
app/cpu_burner
|
||||
}
|
||||
|
||||
lappend_if [have_spec usb] build_components drivers/usb
|
||||
lappend_if [have_spec gpio] build_components drivers/gpio
|
||||
|
||||
source ${genode_dir}/repos/base/run/platform_drv.inc
|
||||
append_platform_drv_build_components
|
||||
|
||||
build $build_components
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Generate config
|
||||
#
|
||||
|
||||
append config {
|
||||
<config prio_levels="2">
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="SIGNAL"/>
|
||||
<service name="TRACE"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>}
|
||||
|
||||
append_if [have_spec sdl] config {
|
||||
<start name="fb_sdl">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides>
|
||||
<service name="Input"/>
|
||||
<service name="Framebuffer"/>
|
||||
</provides>
|
||||
</start>}
|
||||
|
||||
append_platform_drv_config
|
||||
|
||||
append_if [have_spec framebuffer] config {
|
||||
<start name="fb_drv">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides><service name="Framebuffer"/></provides>
|
||||
<config buffered="yes"/>
|
||||
</start>}
|
||||
|
||||
append_if [have_spec gpio] config {
|
||||
<start name="gpio_drv">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides><service name="Gpio"/></provides>
|
||||
<config/>
|
||||
</start>}
|
||||
|
||||
append_if [have_spec imx53] config {
|
||||
<start name="input_drv">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Input"/></provides>
|
||||
<config/>
|
||||
</start> }
|
||||
|
||||
append_if [have_spec ps2] config {
|
||||
<start name="ps2_drv">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Input"/></provides>
|
||||
</start>}
|
||||
|
||||
append_if [expr ![have_spec ps2] && [have_spec usb]] config {
|
||||
<start name="usb_drv">
|
||||
<resource name="RAM" quantum="12M"/>
|
||||
<provides><service name="Input"/></provides>
|
||||
<config ehci="yes" uhci="yes" xhci="no"> <hid/> </config>
|
||||
</start> }
|
||||
|
||||
append config {
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
<start name="nitpicker">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Nitpicker"/></provides>
|
||||
<config>
|
||||
<domain name="default" layer="2" />
|
||||
<policy label="" domain="default"/>
|
||||
</config>
|
||||
</start>
|
||||
<start name="report_rom">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides>
|
||||
<service name="Report"/>
|
||||
<service name="ROM"/>
|
||||
</provides>
|
||||
<config>
|
||||
<rom>
|
||||
<policy label="cpu_load_display -> trace_subjects"
|
||||
report="trace_subject_reporter -> trace_subjects"/>
|
||||
</rom>
|
||||
</config>
|
||||
</start>
|
||||
<start name="trace_subject_reporter" >
|
||||
<resource name="RAM" quantum="6M"/>
|
||||
<config period_ms="500">
|
||||
<report activity="yes" affinity="yes"/>
|
||||
</config>
|
||||
<route>
|
||||
<any-service> <child name="report_rom"/> <any-child/> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
<start name="cpu_load_display">
|
||||
<resource name="RAM" quantum="6M"/>
|
||||
<route>
|
||||
<any-service> <child name="report_rom"/> <any-child/> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
<start name="dynamic_rom">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides><service name="ROM"/></provides>
|
||||
<config verbose="yes">
|
||||
<rom name="cpu_burner1.config">
|
||||
<inline description="initial state">
|
||||
<config percent="5"/>
|
||||
</inline>
|
||||
<sleep milliseconds="5000" />
|
||||
<inline description="50%">
|
||||
<config percent="50" />
|
||||
</inline>
|
||||
<sleep milliseconds="5000" />
|
||||
</rom>
|
||||
<rom name="cpu_burner2.config">
|
||||
<inline description="initial state">
|
||||
<config percent="5"/>
|
||||
</inline>
|
||||
<sleep milliseconds="4800" />
|
||||
<inline description="100%">
|
||||
<config percent="70" />
|
||||
</inline>
|
||||
<sleep milliseconds="2700" />
|
||||
</rom>
|
||||
</config>
|
||||
</start>
|
||||
<start name="cpu_burner.1">
|
||||
<binary name="cpu_burner"/>
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<configfile name="cpu_burner1.config"/>
|
||||
<route>
|
||||
<any-service> <child name="dynamic_rom"/> <any-child/> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
<start name="cpu_burner.2">
|
||||
<binary name="cpu_burner"/>
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<configfile name="cpu_burner2.config"/>
|
||||
<route>
|
||||
<any-service> <child name="dynamic_rom"/> <any-child/> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
</config>}
|
||||
|
||||
install_config $config
|
||||
|
||||
# copy backdrop PNG images to bin directory
|
||||
foreach file { genode_logo.png grid.png } {
|
||||
file copy -force [genode_dir]/repos/gems/src/app/backdrop/$file bin/ }
|
||||
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
|
||||
# generic modules
|
||||
set boot_modules {
|
||||
core init
|
||||
timer
|
||||
nitpicker report_rom dynamic_rom
|
||||
cpu_load_display cpu_burner trace_subject_reporter
|
||||
}
|
||||
|
||||
# platform-specific modules
|
||||
append_platform_drv_boot_modules
|
||||
|
||||
lappend_if [have_spec linux] boot_modules fb_sdl
|
||||
lappend_if [have_spec ps2] boot_modules ps2_drv
|
||||
lappend_if [have_spec framebuffer] boot_modules fb_drv
|
||||
lappend_if [have_spec usb] boot_modules usb_drv
|
||||
lappend_if [have_spec gpio] boot_modules gpio_drv
|
||||
lappend_if [have_spec imx53] boot_modules input_drv
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
append qemu_args " -m 256 "
|
||||
append qemu_args " -smp 4,cores=4 "
|
||||
|
||||
run_genode_until forever
|
2
repos/gems/src/app/cpu_load_display/README
Normal file
2
repos/gems/src/app/cpu_load_display/README
Normal file
@ -0,0 +1,2 @@
|
||||
This nitpicker client application generates a graph based on the data supplied
|
||||
by the trace-subject reporter.
|
472
repos/gems/src/app/cpu_load_display/main.cc
Normal file
472
repos/gems/src/app/cpu_load_display/main.cc
Normal file
@ -0,0 +1,472 @@
|
||||
/*
|
||||
* \brief CPU load display
|
||||
* \author Norman Feske
|
||||
* \date 2015-06-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/config.h>
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
#include <polygon_gfx/shaded_polygon_painter.h>
|
||||
#include <polygon_gfx/interpolate_rgb565.h>
|
||||
#include <os/pixel_alpha8.h>
|
||||
#include <nano3d/scene.h>
|
||||
#include <nano3d/sincos_frac16.h>
|
||||
#include <gems/color_hsv.h>
|
||||
|
||||
|
||||
namespace Cpu_load_display {
|
||||
|
||||
class Timeline;
|
||||
class Cpu;
|
||||
class Cpu_registry;
|
||||
template <typename> class Scene;
|
||||
|
||||
typedef Genode::Xml_node Xml_node;
|
||||
typedef Genode::Color Color;
|
||||
|
||||
using Genode::max;
|
||||
};
|
||||
|
||||
|
||||
class Cpu_load_display::Timeline : public Genode::List<Timeline>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
enum { HISTORY_LEN = 32 };
|
||||
|
||||
typedef Genode::String<160> Label;
|
||||
|
||||
private:
|
||||
|
||||
unsigned const _subject_id = 0;
|
||||
|
||||
unsigned _activity[HISTORY_LEN];
|
||||
|
||||
unsigned _sum_activity = 0;
|
||||
|
||||
Label _label;
|
||||
|
||||
/**
|
||||
* Return hue value based on subject ID
|
||||
*/
|
||||
unsigned _hue() const
|
||||
{
|
||||
/*
|
||||
* To get nicely varying hue values, we pass the subject ID
|
||||
* to a hash function.
|
||||
*/
|
||||
unsigned int const a = 1588635695, q = 2, r = 1117695901;
|
||||
return (a*(_subject_id % q) - r*(_subject_id / q)) & 255;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Timeline(unsigned subject_id, Label const &label)
|
||||
:
|
||||
_subject_id(subject_id), _label(label)
|
||||
{
|
||||
Genode::memset(_activity, 0, sizeof(_activity));
|
||||
}
|
||||
|
||||
void activity(unsigned long recent_activity, unsigned now)
|
||||
{
|
||||
unsigned const i = now % HISTORY_LEN;
|
||||
|
||||
_sum_activity -= _activity[i];
|
||||
|
||||
_activity[i] = recent_activity;
|
||||
|
||||
_sum_activity += recent_activity;
|
||||
}
|
||||
|
||||
unsigned long activity(unsigned i) const
|
||||
{
|
||||
return _activity[i % HISTORY_LEN];
|
||||
}
|
||||
|
||||
bool has_subject_id(unsigned subject_id) const
|
||||
{
|
||||
return _subject_id == subject_id;
|
||||
}
|
||||
|
||||
bool idle() const { return _sum_activity == 0; }
|
||||
|
||||
bool is_kernel() const
|
||||
{
|
||||
return _label == Label("kernel");
|
||||
}
|
||||
|
||||
enum Color_type { COLOR_TOP, COLOR_BOTTOM };
|
||||
|
||||
Color color(Color_type type) const
|
||||
{
|
||||
unsigned const brightness = 140;
|
||||
unsigned const saturation = type == COLOR_TOP ? 70 : 140;
|
||||
unsigned const alpha = 230;
|
||||
|
||||
Color const c = color_from_hsv(_hue(), saturation, brightness);
|
||||
return Color(c.r, c.g, c.b, alpha);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Cpu_load_display::Cpu : public Genode::List<Cpu>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Point<> const _pos;
|
||||
Genode::List<Timeline> _timelines;
|
||||
|
||||
Timeline *_lookup_timeline(Xml_node subject)
|
||||
{
|
||||
unsigned long const subject_id = subject.attribute_value("id", 0UL);
|
||||
|
||||
char label[sizeof(Timeline::Label)];
|
||||
subject.attribute("label").value(label, sizeof(label));
|
||||
|
||||
for (Timeline *t = _timelines.first(); t; t = t->next()) {
|
||||
if (t->has_subject_id(subject_id))
|
||||
return t;
|
||||
}
|
||||
|
||||
/* add new timeline */
|
||||
Timeline *t = new (Genode::env()->heap()) Timeline(subject_id, label);
|
||||
_timelines.insert(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
unsigned long _activity(Xml_node subject)
|
||||
{
|
||||
try {
|
||||
Xml_node activity = subject.sub_node("activity");
|
||||
return activity.attribute_value("recent", 0UL);
|
||||
} catch (Xml_node::Nonexistent_sub_node) { }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Cpu(Genode::Point<> pos) : _pos(pos) { }
|
||||
|
||||
bool has_pos(Genode::Point<> pos) const
|
||||
{
|
||||
return pos == _pos;
|
||||
}
|
||||
|
||||
void import_trace_subject(Xml_node subject, unsigned now)
|
||||
{
|
||||
unsigned long const activity = _activity(subject);
|
||||
|
||||
if (activity)
|
||||
_lookup_timeline(subject)->activity(activity, now);
|
||||
}
|
||||
|
||||
void advance(unsigned now)
|
||||
{
|
||||
Timeline *next = nullptr;
|
||||
for (Timeline *t = _timelines.first(); t; t = next) {
|
||||
|
||||
next = t->next();
|
||||
|
||||
t->activity(0, now);
|
||||
|
||||
if (t->idle()) {
|
||||
|
||||
PDBG("discard timeline");
|
||||
_timelines.remove(t);
|
||||
Genode::destroy(Genode::env()->heap(), t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long activity_sum(unsigned i) const
|
||||
{
|
||||
unsigned long sum = 0;
|
||||
|
||||
for (Timeline const *t = _timelines.first(); t; t = t->next())
|
||||
sum += t->activity(i);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
template <typename FN>
|
||||
void for_each_timeline(FN const &fn) const
|
||||
{
|
||||
for (Timeline const *t = _timelines.first(); t; t = t->next())
|
||||
fn(*t);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Cpu_load_display::Cpu_registry
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::List<Cpu> _cpus;
|
||||
|
||||
static Genode::Point<> _cpu_pos(Xml_node subject)
|
||||
{
|
||||
try {
|
||||
Xml_node affinity = subject.sub_node("affinity");
|
||||
return Genode::Point<>(affinity.attribute_value("xpos", 0UL),
|
||||
affinity.attribute_value("ypos", 0UL));
|
||||
} catch (Xml_node::Nonexistent_sub_node) { }
|
||||
|
||||
return Genode::Point<>(0, 0);
|
||||
}
|
||||
|
||||
Cpu *_lookup_cpu(Xml_node subject)
|
||||
{
|
||||
/* find CPU that matches the affinity of the subject */
|
||||
Genode::Point<> cpu_pos = _cpu_pos(subject);
|
||||
for (Cpu *cpu = _cpus.first(); cpu; cpu = cpu->next()) {
|
||||
if (cpu->has_pos(cpu_pos))
|
||||
return cpu;
|
||||
}
|
||||
|
||||
/* add new CPU */
|
||||
Cpu *cpu = new (Genode::env()->heap()) Cpu(cpu_pos);
|
||||
_cpus.insert(cpu);
|
||||
return cpu;
|
||||
}
|
||||
|
||||
void _import_trace_subject(Xml_node subject, unsigned now)
|
||||
{
|
||||
Cpu *cpu = _lookup_cpu(subject);
|
||||
|
||||
cpu->import_trace_subject(subject, now);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void import_trace_subjects(Xml_node node, unsigned now)
|
||||
{
|
||||
node.for_each_sub_node("subject", [&] (Xml_node subject) {
|
||||
_import_trace_subject(subject, now); });
|
||||
}
|
||||
|
||||
template <typename FN>
|
||||
void for_each_cpu(FN const &fn) const
|
||||
{
|
||||
for (Cpu const *cpu = _cpus.first(); cpu; cpu = cpu->next())
|
||||
fn(*cpu);
|
||||
}
|
||||
|
||||
void advance(unsigned now)
|
||||
{
|
||||
for (Cpu *cpu = _cpus.first(); cpu; cpu = cpu->next())
|
||||
cpu->advance(now);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename PT>
|
||||
class Cpu_load_display::Scene : public Nano3d::Scene<PT>
|
||||
{
|
||||
private:
|
||||
|
||||
Nitpicker::Area const _size;
|
||||
|
||||
void _handle_config(unsigned)
|
||||
{
|
||||
Genode::config()->reload();
|
||||
}
|
||||
|
||||
Genode::Signal_dispatcher<Scene> _config_dispatcher;
|
||||
|
||||
Genode::Attached_rom_dataspace _trace_subjects { "trace_subjects" };
|
||||
|
||||
unsigned _now = 0;
|
||||
|
||||
Cpu_registry _cpu_registry;
|
||||
|
||||
void _handle_trace_subjects(unsigned)
|
||||
{
|
||||
_trace_subjects.update();
|
||||
|
||||
if (!_trace_subjects.is_valid())
|
||||
return;
|
||||
|
||||
_cpu_registry.advance(++_now);
|
||||
|
||||
try {
|
||||
Xml_node subjects(_trace_subjects.local_addr<char>());
|
||||
_cpu_registry.import_trace_subjects(subjects, _now);
|
||||
} catch (...) { PWRN("failed to import trace subjects"); }
|
||||
}
|
||||
|
||||
Genode::Signal_dispatcher<Scene> _trace_subjects_dispatcher;
|
||||
|
||||
public:
|
||||
|
||||
Scene(Genode::Signal_receiver &sig_rec, unsigned update_rate_ms,
|
||||
Nitpicker::Point pos, Nitpicker::Area size)
|
||||
:
|
||||
Nano3d::Scene<PT>(sig_rec, update_rate_ms, pos, size), _size(size),
|
||||
_config_dispatcher(sig_rec, *this, &Scene::_handle_config),
|
||||
_trace_subjects_dispatcher(sig_rec, *this, &Scene::_handle_trace_subjects)
|
||||
{
|
||||
Genode::config()->sigh(_config_dispatcher);
|
||||
_handle_config(0);
|
||||
|
||||
_trace_subjects.sigh(_trace_subjects_dispatcher);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Polygon::Shaded_painter _shaded_painter {
|
||||
*Genode::env()->heap(), _size.h() };
|
||||
|
||||
long _activity_sum[Timeline::HISTORY_LEN];
|
||||
long _y_level[Timeline::HISTORY_LEN];
|
||||
long _y_curr[Timeline::HISTORY_LEN];
|
||||
|
||||
void _plot_cpu(Genode::Surface<PT> &pixel,
|
||||
Genode::Surface<Genode::Pixel_alpha8> &alpha,
|
||||
Cpu const &cpu, Nitpicker::Rect rect)
|
||||
{
|
||||
enum { HISTORY_LEN = Timeline::HISTORY_LEN };
|
||||
|
||||
/* calculate activity sum for each point in history */
|
||||
for (unsigned i = 0; i < HISTORY_LEN; i++)
|
||||
_activity_sum[i] = cpu.activity_sum(i);
|
||||
|
||||
for (unsigned i = 0; i < HISTORY_LEN; i++)
|
||||
_y_level[i] = 0;
|
||||
|
||||
int const h = rect.h();
|
||||
int const w = rect.w();
|
||||
|
||||
cpu.for_each_timeline([&] (Timeline const &timeline) {
|
||||
|
||||
if (timeline.is_kernel())
|
||||
return;
|
||||
|
||||
bool first = true;
|
||||
|
||||
/* reset values of the current timeline */
|
||||
for (unsigned i = 0; i < HISTORY_LEN; i++)
|
||||
_y_curr[i] = 0;
|
||||
|
||||
Color const top_color = timeline.color(Timeline::COLOR_TOP);
|
||||
Color const bottom_color = timeline.color(Timeline::COLOR_BOTTOM);
|
||||
|
||||
for (unsigned i = 0; i < HISTORY_LEN; i++) {
|
||||
|
||||
unsigned const t = (_now - i - 0) % HISTORY_LEN;
|
||||
unsigned const prev_t = (_now - i + 1) % HISTORY_LEN;
|
||||
|
||||
unsigned long const activity = timeline.activity(t);
|
||||
|
||||
int const dy = _activity_sum[t] ? (activity*h) / _activity_sum[t] : 0;
|
||||
|
||||
_y_curr[t] = _y_level[t] + dy;
|
||||
|
||||
if (!first) {
|
||||
|
||||
/* draw polygon */
|
||||
int const n = HISTORY_LEN - 1;
|
||||
int const x0 = ((n - i + 0)*w)/n + rect.x1();
|
||||
int const x1 = ((n - i + 1)*w)/n + rect.x1();
|
||||
|
||||
int const y0 = rect.y1() + h - _y_curr[t];
|
||||
int const y1 = rect.y1() + h - _y_curr[prev_t];
|
||||
int const y2 = rect.y1() + h - _y_level[prev_t];
|
||||
int const y3 = rect.y1() + h - _y_level[t];
|
||||
|
||||
typedef Polygon::Shaded_painter::Point Point;
|
||||
Point points[4];
|
||||
points[0] = Point(x0, y0, top_color);
|
||||
points[1] = Point(x1, y1, top_color);
|
||||
points[2] = Point(x1, y2, y1 == y2 ? top_color : bottom_color);
|
||||
points[3] = Point(x0, y3, y3 == y0 ? top_color : bottom_color);
|
||||
_shaded_painter.paint(pixel, alpha, points, 4);
|
||||
|
||||
/* drop shadow */
|
||||
Color const black (0, 0, 0, 100);
|
||||
Color const translucent (0, 0, 0, 0);
|
||||
|
||||
points[0] = Point(x0, y3 - 5, translucent);
|
||||
points[1] = Point(x1, y2 - 5, translucent);
|
||||
points[2] = Point(x1, y2, black);
|
||||
points[3] = Point(x0, y3, black);
|
||||
|
||||
_shaded_painter.paint(pixel, alpha, points, 4);
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
||||
/* raise level by the values of the current timeline */
|
||||
for (unsigned i = 0; i < HISTORY_LEN; i++)
|
||||
_y_level[i] = _y_curr[i];
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Scene interface
|
||||
*/
|
||||
void render(Genode::Surface<PT> &pixel,
|
||||
Genode::Surface<Genode::Pixel_alpha8> &alpha) override
|
||||
{
|
||||
/* background */
|
||||
Color const top_color = Color(10, 10, 10, 20);
|
||||
Color const bottom_color = Color(10, 10, 10, 100);
|
||||
|
||||
unsigned const w = pixel.size().w();
|
||||
unsigned const h = pixel.size().h();
|
||||
|
||||
typedef Polygon::Shaded_painter::Point Point;
|
||||
Point points[4];
|
||||
points[0] = Point(0, 0, top_color);
|
||||
points[1] = Point(w - 1, 0, top_color);
|
||||
points[2] = Point(w - 1, h - 1, bottom_color);
|
||||
points[3] = Point(0, h - 1, bottom_color);
|
||||
_shaded_painter.paint(pixel, alpha, points, 4);
|
||||
|
||||
/* determine number of CPUs */
|
||||
unsigned num_cpus = 0;
|
||||
_cpu_registry.for_each_cpu([&] (Cpu const &cpu) { num_cpus++; });
|
||||
|
||||
if (num_cpus == 0)
|
||||
return;
|
||||
|
||||
/* plot graphs for the CPUs below each other */
|
||||
enum { GAP = 8 };
|
||||
Nitpicker::Point const step(0, _size.h()/num_cpus);
|
||||
Nitpicker::Area const size(_size.w(), step.y() - GAP);
|
||||
Nitpicker::Point point(0, GAP/2);
|
||||
|
||||
_cpu_registry.for_each_cpu([&] (Cpu const &cpu) {
|
||||
_plot_cpu(pixel, alpha, cpu, Nitpicker::Rect(point, size));
|
||||
point = point + step;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
static Genode::Signal_receiver sig_rec;
|
||||
|
||||
enum { UPDATE_RATE_MS = 250 };
|
||||
|
||||
static Cpu_load_display::Scene<Genode::Pixel_rgb565>
|
||||
scene(sig_rec, UPDATE_RATE_MS,
|
||||
Nitpicker::Point(0, 0), Nitpicker::Area(400, 400));
|
||||
|
||||
scene.dispatch_signals_loop(sig_rec);
|
||||
|
||||
return 0;
|
||||
}
|
4
repos/gems/src/app/cpu_load_display/target.mk
Normal file
4
repos/gems/src/app/cpu_load_display/target.mk
Normal file
@ -0,0 +1,4 @@
|
||||
TARGET = cpu_load_display
|
||||
SRC_CC = main.cc
|
||||
LIBS = base config
|
||||
INC_DIR += $(PRG_DIR)
|
Loading…
x
Reference in New Issue
Block a user