136 lines
3.4 KiB
C++
136 lines
3.4 KiB
C++
/*
|
|
* \brief RAM command
|
|
* \author Norman Feske
|
|
* \date 2013-10-05
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2013-2017 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
#ifndef _RAM_COMMAND_H_
|
|
#define _RAM_COMMAND_H_
|
|
|
|
/* local includes */
|
|
#include <child_registry.h>
|
|
|
|
namespace Cli_monitor { struct Ram_command; }
|
|
|
|
|
|
struct Cli_monitor::Ram_command : Command
|
|
{
|
|
Child_registry &_children;
|
|
Ram &_ram;
|
|
|
|
Parameter _quota_param { "--quota", Parameter::NUMBER, "new RAM quota" };
|
|
Parameter _limit_param { "--limit", Parameter::NUMBER, "on-demand quota limit" };
|
|
|
|
Ram_command(Child_registry &children, Ram &ram)
|
|
:
|
|
Command("ram", "set RAM quota of subsystem"),
|
|
_children(children), _ram(ram)
|
|
{
|
|
add_parameter(_quota_param);
|
|
add_parameter(_limit_param);
|
|
}
|
|
|
|
void _set_quota(Terminal::Session &terminal, Child &child, size_t const new_quota)
|
|
{
|
|
size_t const old_quota = child.ram_status().quota;
|
|
|
|
if (new_quota > old_quota) {
|
|
|
|
size_t amount = new_quota - old_quota;
|
|
size_t const avail = _ram.avail();
|
|
if (amount > avail) {
|
|
tprintf(terminal, "upgrade of '%s' exceeds available quota of ",
|
|
child.name().string());
|
|
tprint_bytes(terminal, avail);
|
|
tprintf(terminal, "\n");
|
|
amount = avail;
|
|
}
|
|
|
|
tprintf(terminal, "upgrading quota of '%s' to ", child.name().string());
|
|
tprint_bytes(terminal, old_quota + amount);
|
|
tprintf(terminal, "\n");
|
|
|
|
try {
|
|
child.upgrade_ram_quota(amount); }
|
|
catch (Ram::Transfer_quota_failed) {
|
|
tprintf(terminal, "Error: transfer_quota failed\n"); }
|
|
|
|
} if (new_quota < old_quota) {
|
|
|
|
size_t amount = old_quota - new_quota;
|
|
size_t const avail = child.ram_status().avail;
|
|
|
|
if (amount > avail) {
|
|
tprintf(terminal, "withdrawal of ");
|
|
tprint_bytes(terminal, amount);
|
|
tprintf(terminal, " exceeds available quota of ");
|
|
tprint_bytes(terminal, avail);
|
|
tprintf(terminal, "\n");
|
|
amount = avail;
|
|
}
|
|
|
|
tprintf(terminal, "depleting quota of '%s' to ", child.name().string());
|
|
tprint_bytes(terminal, old_quota - amount);
|
|
tprintf(terminal, "\n");
|
|
|
|
try {
|
|
child.withdraw_ram_quota(amount); }
|
|
catch (Ram::Transfer_quota_failed) {
|
|
tprintf(terminal, "Error: transfer_quota failed\n"); }
|
|
}
|
|
}
|
|
|
|
void _for_each_argument(Argument_fn const &fn) const override
|
|
{
|
|
auto child_name_fn = [&] (Child_base::Name const &child_name) {
|
|
Argument arg(child_name.string(), "");
|
|
fn(arg);
|
|
};
|
|
|
|
_children.for_each_child_name(child_name_fn);
|
|
}
|
|
|
|
void execute(Command_line &cmd, Terminal::Session &terminal) override
|
|
{
|
|
char label[128];
|
|
label[0] = 0;
|
|
if (cmd.argument(0, label, sizeof(label)) == false) {
|
|
tprintf(terminal, "Error: no subsystem name specified\n");
|
|
return;
|
|
}
|
|
|
|
/* lookup child by its unique name */
|
|
Child *child = _children.first();
|
|
for (; child; child = child->next())
|
|
if (child->name() == label)
|
|
break;
|
|
|
|
if (!child) {
|
|
tprintf(terminal, "Error: subsystem '%s' does not exist\n", label);
|
|
return;
|
|
}
|
|
|
|
bool const limit_specified = cmd.parameter_exists("--limit");
|
|
Genode::Number_of_bytes limit = 0;
|
|
if (limit_specified) {
|
|
cmd.parameter("--limit", limit);
|
|
child->ram_limit(limit);
|
|
}
|
|
|
|
if (cmd.parameter_exists("--quota")) {
|
|
Genode::Number_of_bytes quota = 0;
|
|
cmd.parameter("--quota", quota);
|
|
_set_quota(terminal, *child, quota);
|
|
}
|
|
}
|
|
};
|
|
|
|
#endif /* _RAM_COMMAND_H_ */
|