mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 15:02:25 +00:00
app/cli_monitor: API transition
Besides updating CLI monitor to the new API, the patch removes Fiasco.OC-specific extensions that remained unused for a long time. Ref #1987
This commit is contained in:
parent
7f5e2c2eb2
commit
e91170a49c
@ -78,7 +78,7 @@ struct Launcher::Main
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Subsystem_manager _subsystem_manager { _env.ep(), _env.pd(),
|
Subsystem_manager _subsystem_manager { _env,
|
||||||
_ram_preservation(_config.xml()),
|
_ram_preservation(_config.xml()),
|
||||||
_exited_child_handler };
|
_exited_child_handler };
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ namespace Launcher {
|
|||||||
|
|
||||||
class Subsystem_manager;
|
class Subsystem_manager;
|
||||||
using Decorator::string_attribute;
|
using Decorator::string_attribute;
|
||||||
|
using Cli_monitor::Ram;
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,12 +41,11 @@ class Launcher::Subsystem_manager
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Entrypoint &_ep;
|
Env & _env;
|
||||||
Pd_session &_pd;
|
Heap _heap { _env.ram(), _env.rm() };
|
||||||
|
|
||||||
size_t const _ram_preservation;
|
size_t const _ram_preservation;
|
||||||
|
|
||||||
struct Child : Child_base, List<Child>::Element
|
struct Child : Cli_monitor::Child_base, List<Child>::Element
|
||||||
{
|
{
|
||||||
template <typename... ARGS>
|
template <typename... ARGS>
|
||||||
Child(ARGS &&... args) : Child_base(args...) { }
|
Child(ARGS &&... args) : Child_base(args...) { }
|
||||||
@ -60,7 +60,7 @@ class Launcher::Subsystem_manager
|
|||||||
}
|
}
|
||||||
|
|
||||||
Signal_handler<Subsystem_manager> _yield_broadcast_handler =
|
Signal_handler<Subsystem_manager> _yield_broadcast_handler =
|
||||||
{ _ep, *this, &Subsystem_manager::_handle_yield_broadcast };
|
{ _env.ep(), *this, &Subsystem_manager::_handle_yield_broadcast };
|
||||||
|
|
||||||
void _handle_yield_broadcast()
|
void _handle_yield_broadcast()
|
||||||
{
|
{
|
||||||
@ -90,7 +90,7 @@ class Launcher::Subsystem_manager
|
|||||||
}
|
}
|
||||||
|
|
||||||
Signal_handler<Subsystem_manager> _resource_avail_handler =
|
Signal_handler<Subsystem_manager> _resource_avail_handler =
|
||||||
{ _ep, *this, &Subsystem_manager::_handle_resource_avail };
|
{ _env.ep(), *this, &Subsystem_manager::_handle_resource_avail };
|
||||||
|
|
||||||
void _handle_resource_avail()
|
void _handle_resource_avail()
|
||||||
{
|
{
|
||||||
@ -98,7 +98,7 @@ class Launcher::Subsystem_manager
|
|||||||
}
|
}
|
||||||
|
|
||||||
Signal_handler<Subsystem_manager> _yield_response_handler =
|
Signal_handler<Subsystem_manager> _yield_response_handler =
|
||||||
{ _ep, *this, &Subsystem_manager::_handle_yield_response };
|
{ _env.ep(), *this, &Subsystem_manager::_handle_yield_response };
|
||||||
|
|
||||||
void _handle_yield_response()
|
void _handle_yield_response()
|
||||||
{
|
{
|
||||||
@ -107,7 +107,9 @@ class Launcher::Subsystem_manager
|
|||||||
|
|
||||||
Genode::Signal_context_capability _exited_child_sig_cap;
|
Genode::Signal_context_capability _exited_child_sig_cap;
|
||||||
|
|
||||||
Ram _ram { _ram_preservation,
|
Ram _ram { _env.ram(),
|
||||||
|
_env.ram_session_cap(),
|
||||||
|
_ram_preservation,
|
||||||
_yield_broadcast_handler,
|
_yield_broadcast_handler,
|
||||||
_resource_avail_handler };
|
_resource_avail_handler };
|
||||||
|
|
||||||
@ -147,11 +149,11 @@ class Launcher::Subsystem_manager
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Subsystem_manager(Genode::Entrypoint &ep, Pd_session &pd,
|
Subsystem_manager(Genode::Env & env,
|
||||||
size_t ram_preservation,
|
size_t ram_preservation,
|
||||||
Genode::Signal_context_capability exited_child_sig_cap)
|
Genode::Signal_context_capability exited_child_sig_cap)
|
||||||
:
|
:
|
||||||
_ep(ep), _pd(pd), _ram_preservation(ram_preservation),
|
_env(env), _ram_preservation(ram_preservation),
|
||||||
_exited_child_sig_cap(exited_child_sig_cap)
|
_exited_child_sig_cap(exited_child_sig_cap)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -172,12 +174,12 @@ class Launcher::Subsystem_manager
|
|||||||
Genode::log("starting child '", label.string(), "'");
|
Genode::log("starting child '", label.string(), "'");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Child *child = new (env()->heap())
|
Child *child = new (_heap)
|
||||||
Child(_ram, label, binary_name.string(),
|
Child(_ram, label, binary_name.string(),
|
||||||
*Genode::env()->pd_session(),
|
_env.pd(),
|
||||||
*Genode::env()->ram_session(),
|
_env.ram(),
|
||||||
Genode::env()->ram_session_cap(),
|
_env.ram_session_cap(),
|
||||||
*Genode::env()->rm_session(),
|
_env.rm(),
|
||||||
ram_config.quantum, ram_config.limit,
|
ram_config.quantum, ram_config.limit,
|
||||||
_yield_broadcast_handler,
|
_yield_broadcast_handler,
|
||||||
_exited_child_sig_cap);
|
_exited_child_sig_cap);
|
||||||
@ -203,7 +205,7 @@ class Launcher::Subsystem_manager
|
|||||||
for (Child *c = _children.first(); c; c = c->next()) {
|
for (Child *c = _children.first(); c; c = c->next()) {
|
||||||
if (c->label() == Label(label)) {
|
if (c->label() == Label(label)) {
|
||||||
_children.remove(c);
|
_children.remove(c);
|
||||||
destroy(env()->heap(), c);
|
destroy(_heap, c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,10 @@
|
|||||||
/* CLI-monitor includes */
|
/* CLI-monitor includes */
|
||||||
#include <cli_monitor/ram.h>
|
#include <cli_monitor/ram.h>
|
||||||
|
|
||||||
|
namespace Cli_monitor { class Child_base; }
|
||||||
|
|
||||||
class Child_base : public Genode::Child_policy
|
|
||||||
|
class Cli_monitor::Child_base : public Genode::Child_policy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -17,15 +17,19 @@
|
|||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <ram_session/connection.h>
|
#include <ram_session/connection.h>
|
||||||
|
|
||||||
class Ram
|
namespace Cli_monitor { class Ram; }
|
||||||
|
|
||||||
|
|
||||||
|
class Cli_monitor::Ram
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef Genode::size_t size_t;
|
typedef Genode::size_t size_t;
|
||||||
|
|
||||||
|
Genode::Ram_session &_ram;
|
||||||
|
Genode::Ram_session_capability _ram_cap;
|
||||||
|
|
||||||
Genode::Lock mutable _lock;
|
Genode::Lock mutable _lock;
|
||||||
Genode::Ram_session &_ram = *Genode::env()->ram_session();
|
|
||||||
Genode::Ram_session_capability _ram_cap = Genode::env()->ram_session_cap();
|
|
||||||
Genode::Signal_context_capability _yield_sigh;
|
Genode::Signal_context_capability _yield_sigh;
|
||||||
Genode::Signal_context_capability _resource_avail_sigh;
|
Genode::Signal_context_capability _resource_avail_sigh;
|
||||||
|
|
||||||
@ -50,10 +54,13 @@ class Ram
|
|||||||
: quota(quota), used(used), avail(avail), preserve(preserve) { }
|
: quota(quota), used(used), avail(avail), preserve(preserve) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
Ram(size_t preserve,
|
Ram(Genode::Ram_session &ram,
|
||||||
|
Genode::Ram_session_capability ram_cap,
|
||||||
|
size_t preserve,
|
||||||
Genode::Signal_context_capability yield_sigh,
|
Genode::Signal_context_capability yield_sigh,
|
||||||
Genode::Signal_context_capability resource_avail_sigh)
|
Genode::Signal_context_capability resource_avail_sigh)
|
||||||
:
|
:
|
||||||
|
_ram(ram), _ram_cap(ram_cap),
|
||||||
_yield_sigh(yield_sigh),
|
_yield_sigh(yield_sigh),
|
||||||
_resource_avail_sigh(resource_avail_sigh),
|
_resource_avail_sigh(resource_avail_sigh),
|
||||||
_preserve(preserve)
|
_preserve(preserve)
|
||||||
@ -128,10 +135,7 @@ class Ram
|
|||||||
throw Transfer_quota_failed();
|
throw Transfer_quota_failed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
size_t avail() const { return _ram.avail(); }
|
||||||
* Return singleton object
|
|
||||||
*/
|
|
||||||
static Ram &ram();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _INCLUDE__CLI_MONITOR__RAM_H_ */
|
#endif /* _INCLUDE__CLI_MONITOR__RAM_H_ */
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
SRC_CC = no_extension.cc
|
|
||||||
INC_DIR += $(REP_DIR)/src/app/cli_monitor
|
|
||||||
|
|
||||||
vpath no_extension.cc $(REP_DIR)/src/app/cli_monitor
|
|
@ -1,7 +0,0 @@
|
|||||||
SRC_CC = extension.cc
|
|
||||||
REQUIRES = foc
|
|
||||||
INC_DIR += $(REP_DIR)/src/app/cli_monitor \
|
|
||||||
$(REP_DIR)/src/app/cli_monitor/spec/foc
|
|
||||||
LIBS += syscall-foc
|
|
||||||
|
|
||||||
vpath extension.cc $(REP_DIR)/src/app/cli_monitor/spec/foc
|
|
@ -1,7 +0,0 @@
|
|||||||
SRC_CC = extension.cc
|
|
||||||
REQUIRES = foc_arndale
|
|
||||||
INC_DIR += $(REP_DIR)/src/app/cli_monitor \
|
|
||||||
$(REP_DIR)/src/app/cli_monitor/spec/foc
|
|
||||||
LIBS += syscall-foc
|
|
||||||
|
|
||||||
vpath extension.cc $(REP_DIR)/src/app/cli_monitor/spec/foc/arndale
|
|
@ -1 +0,0 @@
|
|||||||
LIBS += foc_cli_monitor
|
|
@ -20,7 +20,10 @@
|
|||||||
/* local includes */
|
/* local includes */
|
||||||
#include <line_editor.h>
|
#include <line_editor.h>
|
||||||
|
|
||||||
struct Child : Child_base, List<Child>::Element
|
namespace Cli_monitor { struct Child; }
|
||||||
|
|
||||||
|
|
||||||
|
struct Cli_monitor::Child : Child_base, List<Child>::Element
|
||||||
{
|
{
|
||||||
Argument argument;
|
Argument argument;
|
||||||
|
|
||||||
|
@ -20,7 +20,10 @@
|
|||||||
/* local includes */
|
/* local includes */
|
||||||
#include <child.h>
|
#include <child.h>
|
||||||
|
|
||||||
class Child_registry : public List<Child>
|
namespace Cli_monitor { class Child_registry; }
|
||||||
|
|
||||||
|
|
||||||
|
class Cli_monitor::Child_registry : public List<Child>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -16,7 +16,10 @@
|
|||||||
|
|
||||||
#include <line_editor.h>
|
#include <line_editor.h>
|
||||||
|
|
||||||
class Command_line
|
namespace Cli_monitor { class Command_line; }
|
||||||
|
|
||||||
|
|
||||||
|
class Cli_monitor::Command_line
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Interface for platform-specific CLI-monitor commands
|
|
||||||
* \author Norman Feske
|
|
||||||
* \date 2013-03-21
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _EXTENSION_H_
|
|
||||||
#define _EXTENSION_H_
|
|
||||||
|
|
||||||
/* local includes */
|
|
||||||
#include <line_editor.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize and register platform-specific commands
|
|
||||||
*/
|
|
||||||
void init_extension(Command_registry &);
|
|
||||||
|
|
||||||
#endif /* _EXTENSION_H_ */
|
|
@ -17,96 +17,98 @@
|
|||||||
/* local includes */
|
/* local includes */
|
||||||
#include <terminal_util.h>
|
#include <terminal_util.h>
|
||||||
|
|
||||||
|
namespace Cli_monitor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print rational number with two fractional decimals
|
* Print rational number with two fractional decimals
|
||||||
*/
|
*/
|
||||||
static inline size_t format_number(char *dst, size_t len, size_t const value,
|
static inline size_t format_number(char *dst, size_t len, size_t const value,
|
||||||
size_t const quotient, char const *unit)
|
size_t const quotient, char const *unit)
|
||||||
{
|
{
|
||||||
size_t const integer = value / quotient;
|
size_t const integer = value / quotient;
|
||||||
size_t const n = snprintf(dst, len, "%ld.", integer);
|
size_t const n = snprintf(dst, len, "%ld.", integer);
|
||||||
size_t const remainder = ((value - (integer * quotient))*100) / quotient;
|
size_t const remainder = ((value - (integer * quotient))*100) / quotient;
|
||||||
|
|
||||||
if (len == n) return n;
|
if (len == n) return n;
|
||||||
|
|
||||||
return n + snprintf(dst + n, len - n, "%s%ld%s",
|
return n + snprintf(dst + n, len - n, "%s%ld%s",
|
||||||
remainder < 10 ? "0" : "", remainder, unit);
|
remainder < 10 ? "0" : "", remainder, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print number of bytes using the best suitable unit
|
* Print number of bytes using the best suitable unit
|
||||||
*/
|
*/
|
||||||
static inline size_t format_bytes(char *dst, size_t len, size_t bytes)
|
static inline size_t format_bytes(char *dst, size_t len, size_t bytes)
|
||||||
{
|
{
|
||||||
enum { KB = 1024, MB = 1024*KB };
|
enum { KB = 1024, MB = 1024*KB };
|
||||||
|
|
||||||
if (bytes > MB)
|
if (bytes > MB)
|
||||||
return format_number(dst, len, bytes, MB, " MiB");
|
return format_number(dst, len, bytes, MB, " MiB");
|
||||||
|
|
||||||
if (bytes > KB)
|
if (bytes > KB)
|
||||||
return format_number(dst, len, bytes, KB, " KiB");
|
return format_number(dst, len, bytes, KB, " KiB");
|
||||||
|
|
||||||
return snprintf(dst, len, "%ld bytes", bytes);
|
return snprintf(dst, len, "%ld bytes", bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print number in MiB, without unit
|
* Print number in MiB, without unit
|
||||||
*/
|
*/
|
||||||
static inline size_t format_mib(char *dst, size_t len, size_t bytes)
|
static inline size_t format_mib(char *dst, size_t len, size_t bytes)
|
||||||
{
|
{
|
||||||
enum { KB = 1024, MB = 1024*KB };
|
enum { KB = 1024, MB = 1024*KB };
|
||||||
|
|
||||||
return format_number(dst, len, bytes, MB , "");
|
return format_number(dst, len, bytes, MB , "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline size_t format_bytes(size_t bytes)
|
static inline size_t format_bytes(size_t bytes)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
return format_bytes(buf, sizeof(buf), bytes);
|
return format_bytes(buf, sizeof(buf), bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline size_t format_mib(size_t bytes)
|
static inline size_t format_mib(size_t bytes)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
return format_mib(buf, sizeof(buf), bytes);
|
return format_mib(buf, sizeof(buf), bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void tprint_bytes(Terminal::Session &terminal, size_t bytes)
|
static inline void tprint_bytes(Terminal::Session &terminal, size_t bytes)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
format_bytes(buf, sizeof(buf), bytes);
|
format_bytes(buf, sizeof(buf), bytes);
|
||||||
Terminal::tprintf(terminal, "%s", buf);
|
Terminal::tprintf(terminal, "%s", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void tprint_mib(Terminal::Session &terminal, size_t bytes)
|
static inline void tprint_mib(Terminal::Session &terminal, size_t bytes)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
format_mib(buf, sizeof(buf), bytes);
|
format_mib(buf, sizeof(buf), bytes);
|
||||||
Terminal::tprintf(terminal, "%s", buf);
|
Terminal::tprintf(terminal, "%s", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void tprint_status_bytes(Terminal::Session &terminal,
|
static inline void tprint_status_bytes(Terminal::Session &terminal,
|
||||||
char const *label, size_t bytes)
|
char const *label, size_t bytes)
|
||||||
{
|
{
|
||||||
Terminal::tprintf(terminal, label);
|
Terminal::tprintf(terminal, label);
|
||||||
tprint_bytes(terminal, bytes);
|
tprint_bytes(terminal, bytes);
|
||||||
Terminal::tprintf(terminal, "\n");
|
Terminal::tprintf(terminal, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void tprint_padding(Terminal::Session &terminal, size_t pad, char c = ' ')
|
static void tprint_padding(Terminal::Session &terminal, size_t pad, char c = ' ')
|
||||||
{
|
{
|
||||||
char const buf[2] = { c, 0 };
|
char const buf[2] = { c, 0 };
|
||||||
for (unsigned i = 0; i < pad; i++)
|
for (unsigned i = 0; i < pad; i++)
|
||||||
Terminal::tprintf(terminal, buf);
|
Terminal::tprintf(terminal, buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _FORMAT_UTIL_H_ */
|
#endif /* _FORMAT_UTIL_H_ */
|
||||||
|
@ -14,7 +14,10 @@
|
|||||||
#ifndef _HELP_COMMAND_H_
|
#ifndef _HELP_COMMAND_H_
|
||||||
#define _HELP_COMMAND_H_
|
#define _HELP_COMMAND_H_
|
||||||
|
|
||||||
struct Help_command : Command
|
namespace Cli_monitor { struct Help_command; }
|
||||||
|
|
||||||
|
|
||||||
|
struct Cli_monitor::Help_command : Command
|
||||||
{
|
{
|
||||||
Help_command() : Command("help", "brief help information") { }
|
Help_command() : Command("help", "brief help information") { }
|
||||||
|
|
||||||
|
@ -17,23 +17,29 @@
|
|||||||
/* local includes */
|
/* local includes */
|
||||||
#include <child_registry.h>
|
#include <child_registry.h>
|
||||||
|
|
||||||
struct Kill_command : Command
|
namespace Cli_monitor { struct Kill_command; }
|
||||||
|
|
||||||
|
|
||||||
|
struct Cli_monitor::Kill_command : Command
|
||||||
{
|
{
|
||||||
Child_registry &_children;
|
Child_registry &_children;
|
||||||
|
|
||||||
|
Genode::Allocator &_alloc;
|
||||||
|
|
||||||
|
Parameter _kill_all_param { "--all", Parameter::VOID, "kill all subsystems" };
|
||||||
|
|
||||||
void _destroy_child(Child *child, Terminal::Session &terminal)
|
void _destroy_child(Child *child, Terminal::Session &terminal)
|
||||||
{
|
{
|
||||||
tprintf(terminal, "destroying subsystem '%s'\n", child->name().string());
|
tprintf(terminal, "destroying subsystem '%s'\n", child->name().string());
|
||||||
_children.remove(child);
|
_children.remove(child);
|
||||||
Genode::destroy(Genode::env()->heap(), child);
|
Genode::destroy(_alloc, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
Kill_command(Child_registry &children)
|
Kill_command(Child_registry &children, Genode::Allocator &alloc)
|
||||||
:
|
:
|
||||||
Command("kill", "destroy subsystem"),
|
Command("kill", "destroy subsystem"), _children(children), _alloc(alloc)
|
||||||
_children(children)
|
|
||||||
{
|
{
|
||||||
add_parameter(new Parameter("--all", Parameter::VOID, "kill all subsystems"));
|
add_parameter(_kill_all_param);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _for_each_argument(Argument_fn const &fn) const override
|
void _for_each_argument(Argument_fn const &fn) const override
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
|
#include <base/registry.h>
|
||||||
#include <terminal_session/connection.h>
|
#include <terminal_session/connection.h>
|
||||||
#include <util/string.h>
|
#include <util/string.h>
|
||||||
#include <util/list.h>
|
#include <util/list.h>
|
||||||
@ -23,17 +24,33 @@
|
|||||||
#include <util/misc_math.h>
|
#include <util/misc_math.h>
|
||||||
#include <base/snprintf.h>
|
#include <base/snprintf.h>
|
||||||
|
|
||||||
using Genode::List;
|
namespace Cli_monitor {
|
||||||
using Genode::max;
|
|
||||||
using Genode::strlen;
|
using Genode::Registry;
|
||||||
using Genode::strncpy;
|
using Genode::List;
|
||||||
using Genode::snprintf;
|
using Genode::max;
|
||||||
using Genode::strcmp;
|
using Genode::strlen;
|
||||||
using Genode::size_t;
|
using Genode::strncpy;
|
||||||
using Genode::off_t;
|
using Genode::snprintf;
|
||||||
|
using Genode::strcmp;
|
||||||
|
using Genode::size_t;
|
||||||
|
using Genode::off_t;
|
||||||
|
|
||||||
|
struct Completable;
|
||||||
|
struct Argument;
|
||||||
|
struct Parameter;
|
||||||
|
struct Command_line;
|
||||||
|
struct Command;
|
||||||
|
struct Command_registry;
|
||||||
|
struct Scanner_policy;
|
||||||
|
struct Argument_tracker;
|
||||||
|
struct Line_editor;
|
||||||
|
|
||||||
|
typedef Genode::Token<Scanner_policy> Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Completable
|
struct Cli_monitor::Completable
|
||||||
{
|
{
|
||||||
typedef Genode::String<64> Name;
|
typedef Genode::String<64> Name;
|
||||||
typedef Genode::String<160> Short_help;
|
typedef Genode::String<160> Short_help;
|
||||||
@ -52,7 +69,7 @@ struct Completable
|
|||||||
/**
|
/**
|
||||||
* Representation of normal command-line argument
|
* Representation of normal command-line argument
|
||||||
*/
|
*/
|
||||||
struct Argument : Completable
|
struct Cli_monitor::Argument : Completable
|
||||||
{
|
{
|
||||||
Argument(char const *name, char const *short_help)
|
Argument(char const *name, char const *short_help)
|
||||||
: Completable(name, short_help) { }
|
: Completable(name, short_help) { }
|
||||||
@ -64,7 +81,7 @@ struct Argument : Completable
|
|||||||
/**
|
/**
|
||||||
* Representation of a parameter of the form '--tag value'
|
* Representation of a parameter of the form '--tag value'
|
||||||
*/
|
*/
|
||||||
struct Parameter : List<Parameter>::Element, Completable
|
struct Cli_monitor::Parameter : List<Parameter>::Element, Completable
|
||||||
{
|
{
|
||||||
enum Type { IDENT, NUMBER, VOID };
|
enum Type { IDENT, NUMBER, VOID };
|
||||||
|
|
||||||
@ -89,13 +106,10 @@ struct Parameter : List<Parameter>::Element, Completable
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Command_line;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of a command that can have arguments and parameters
|
* Representation of a command that can have arguments and parameters
|
||||||
*/
|
*/
|
||||||
struct Command : List<Command>::Element, Completable
|
struct Cli_monitor::Command : List<Command>::Element, Completable
|
||||||
{
|
{
|
||||||
List<Parameter> _parameters;
|
List<Parameter> _parameters;
|
||||||
|
|
||||||
@ -110,7 +124,7 @@ struct Command : List<Command>::Element, Completable
|
|||||||
Command(char const *name, char const *short_help)
|
Command(char const *name, char const *short_help)
|
||||||
: Completable(name, short_help) { }
|
: Completable(name, short_help) { }
|
||||||
|
|
||||||
void add_parameter(Parameter *par) { _parameters.insert(par); }
|
void add_parameter(Parameter &par) { _parameters.insert(&par); }
|
||||||
|
|
||||||
char const *name_suffix() const { return ""; }
|
char const *name_suffix() const { return ""; }
|
||||||
|
|
||||||
@ -141,13 +155,13 @@ struct Command : List<Command>::Element, Completable
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Command_registry : List<Command> { };
|
struct Cli_monitor::Command_registry : List<Command> { };
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scanner policy that accepts '-', '.' and '_' as valid identifier characters
|
* Scanner policy that accepts '-', '.' and '_' as valid identifier characters
|
||||||
*/
|
*/
|
||||||
struct Scanner_policy
|
struct Cli_monitor::Scanner_policy
|
||||||
{
|
{
|
||||||
static bool identifier_char(char c, unsigned i)
|
static bool identifier_char(char c, unsigned i)
|
||||||
{
|
{
|
||||||
@ -157,13 +171,10 @@ struct Scanner_policy
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef Genode::Token<Scanner_policy> Token;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State machine used for sequentially parsing command-line arguments
|
* State machine used for sequentially parsing command-line arguments
|
||||||
*/
|
*/
|
||||||
struct Argument_tracker
|
struct Cli_monitor::Argument_tracker
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -288,7 +299,7 @@ struct Argument_tracker
|
|||||||
/**
|
/**
|
||||||
* Editing and completion logic
|
* Editing and completion logic
|
||||||
*/
|
*/
|
||||||
class Line_editor
|
class Cli_monitor::Line_editor
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -482,7 +493,7 @@ class Line_editor
|
|||||||
&& strlen(curr->name()) == tag.len())
|
&& strlen(curr->name()) == tag.len())
|
||||||
return curr;
|
return curr;
|
||||||
}
|
}
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Command *_lookup_matching_command()
|
Command *_lookup_matching_command()
|
||||||
@ -492,7 +503,7 @@ class Line_editor
|
|||||||
if (strcmp(cmd.start(), curr->name().string(), cmd.len()) == 0
|
if (strcmp(cmd.start(), curr->name().string(), cmd.len()) == 0
|
||||||
&& _cursor_pos > cmd.len())
|
&& _cursor_pos > cmd.len())
|
||||||
return curr;
|
return curr;
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <os/config.h>
|
#include <base/attached_rom_dataspace.h>
|
||||||
#include <cap_session/connection.h>
|
#include <base/registry.h>
|
||||||
#include <vfs/file_system_factory.h>
|
#include <vfs/file_system_factory.h>
|
||||||
#include <vfs/dir_file_system.h>
|
#include <vfs/dir_file_system.h>
|
||||||
#include <base/component.h>
|
#include <base/component.h>
|
||||||
@ -25,7 +25,6 @@
|
|||||||
#include <line_editor.h>
|
#include <line_editor.h>
|
||||||
#include <command_line.h>
|
#include <command_line.h>
|
||||||
#include <format_util.h>
|
#include <format_util.h>
|
||||||
#include <extension.h>
|
|
||||||
#include <status_command.h>
|
#include <status_command.h>
|
||||||
#include <kill_command.h>
|
#include <kill_command.h>
|
||||||
#include <start_command.h>
|
#include <start_command.h>
|
||||||
@ -33,12 +32,10 @@
|
|||||||
#include <yield_command.h>
|
#include <yield_command.h>
|
||||||
#include <ram_command.h>
|
#include <ram_command.h>
|
||||||
|
|
||||||
using Genode::Xml_node;
|
namespace Cli_monitor {
|
||||||
|
|
||||||
|
struct Main;
|
||||||
inline void *operator new (__SIZE_TYPE__ size)
|
using namespace Genode;
|
||||||
{
|
|
||||||
return Genode::env()->heap()->alloc(size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -46,186 +43,187 @@ inline void *operator new (__SIZE_TYPE__ size)
|
|||||||
** Main program **
|
** Main program **
|
||||||
******************/
|
******************/
|
||||||
|
|
||||||
static inline Command *lookup_command(char const *buf, Command_registry ®istry)
|
struct Cli_monitor::Main
|
||||||
{
|
{
|
||||||
Token token(buf);
|
Genode::Env &_env;
|
||||||
for (Command *curr = registry.first(); curr; curr = curr->next())
|
|
||||||
if (strcmp(token.start(), curr->name().string(), token.len()) == 0
|
|
||||||
&& strlen(curr->name().string()) == token.len())
|
|
||||||
return curr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Terminal::Connection _terminal { _env };
|
||||||
|
|
||||||
static size_t ram_preservation_from_config()
|
Command_registry _commands;
|
||||||
{
|
|
||||||
Genode::Number_of_bytes ram_preservation = 0;
|
|
||||||
try {
|
|
||||||
Genode::Xml_node node =
|
|
||||||
Genode::config()->xml_node().sub_node("preservation");
|
|
||||||
|
|
||||||
if (node.attribute("name").has_value("RAM"))
|
Child_registry _children;
|
||||||
node.attribute("quantum").value(&ram_preservation);
|
|
||||||
} catch (...) { }
|
|
||||||
|
|
||||||
return ram_preservation;
|
Command *_lookup_command(char const *buf)
|
||||||
}
|
{
|
||||||
|
Token token(buf);
|
||||||
|
for (Command *curr = _commands.first(); curr; curr = curr->next())
|
||||||
static Genode::Xml_node vfs_config()
|
if (strcmp(token.start(), curr->name().string(), token.len()) == 0
|
||||||
{
|
&& strlen(curr->name().string()) == token.len())
|
||||||
try { return Genode::config()->xml_node().sub_node("vfs"); }
|
return curr;
|
||||||
catch (Genode::Xml_node::Nonexistent_sub_node) {
|
return 0;
|
||||||
Genode::error("missing '<vfs>' configuration");
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Component::construct(Genode::Env &env)
|
|
||||||
{
|
|
||||||
using Genode::Signal_context;
|
|
||||||
using Genode::Signal_context_capability;
|
|
||||||
using Genode::Signal_receiver;
|
|
||||||
|
|
||||||
static Genode::Cap_connection cap;
|
|
||||||
static Terminal::Connection terminal(env);
|
|
||||||
static Command_registry commands;
|
|
||||||
static Child_registry children;
|
|
||||||
|
|
||||||
/* initialize platform-specific commands */
|
|
||||||
init_extension(commands);
|
|
||||||
|
|
||||||
static Signal_receiver sig_rec;
|
|
||||||
static Signal_context read_avail_sig_ctx;
|
|
||||||
terminal.read_avail_sigh(sig_rec.manage(&read_avail_sig_ctx));
|
|
||||||
|
|
||||||
static Signal_context yield_response_sig_ctx;
|
|
||||||
static Signal_context_capability yield_response_sig_cap =
|
|
||||||
sig_rec.manage(&yield_response_sig_ctx);
|
|
||||||
|
|
||||||
static Signal_context yield_broadcast_sig_ctx;
|
|
||||||
static Signal_context resource_avail_sig_ctx;
|
|
||||||
|
|
||||||
static Signal_context exited_child_sig_ctx;
|
|
||||||
static Signal_context_capability exited_child_sig_cap =
|
|
||||||
sig_rec.manage(&exited_child_sig_ctx);
|
|
||||||
|
|
||||||
static Ram ram(ram_preservation_from_config(),
|
|
||||||
sig_rec.manage(&yield_broadcast_sig_ctx),
|
|
||||||
sig_rec.manage(&resource_avail_sig_ctx));
|
|
||||||
|
|
||||||
/* initialize virtual file system */
|
|
||||||
static Vfs::Dir_file_system root_dir(env, *Genode::env()->heap(), vfs_config(),
|
|
||||||
Vfs::global_file_system_factory());
|
|
||||||
|
|
||||||
static Subsystem_config_registry subsystem_config_registry(root_dir);
|
|
||||||
|
|
||||||
/* initialize generic commands */
|
|
||||||
commands.insert(new Help_command);
|
|
||||||
Kill_command kill_command(children);
|
|
||||||
commands.insert(&kill_command);
|
|
||||||
commands.insert(new Start_command(ram, env.pd(),
|
|
||||||
env.ram(), env.ram_session_cap(),
|
|
||||||
env.rm(), children,
|
|
||||||
subsystem_config_registry,
|
|
||||||
yield_response_sig_cap,
|
|
||||||
exited_child_sig_cap));
|
|
||||||
commands.insert(new Status_command(ram, children));
|
|
||||||
commands.insert(new Yield_command(children));
|
|
||||||
commands.insert(new Ram_command(children));
|
|
||||||
|
|
||||||
enum { COMMAND_MAX_LEN = 1000 };
|
enum { COMMAND_MAX_LEN = 1000 };
|
||||||
static char buf[COMMAND_MAX_LEN];
|
char _command_buf[COMMAND_MAX_LEN];
|
||||||
static Line_editor line_editor("genode> ", buf, sizeof(buf), terminal, commands);
|
Line_editor _line_editor {
|
||||||
|
"genode> ", _command_buf, sizeof(_command_buf), _terminal, _commands };
|
||||||
|
|
||||||
for (;;) {
|
void _handle_terminal_read_avail();
|
||||||
|
|
||||||
/* block for event, e.g., the arrival of new user input */
|
Signal_handler<Main> _terminal_read_avail_handler {
|
||||||
Genode::Signal signal = sig_rec.wait_for_signal();
|
_env.ep(), *this, &Main::_handle_terminal_read_avail };
|
||||||
|
|
||||||
if (signal.context() == &read_avail_sig_ctx) {
|
/**
|
||||||
|
* Handler for child yield responses, or RAM resource-avail signals
|
||||||
/* supply pending terminal input to line editor */
|
*/
|
||||||
while (terminal.avail() && !line_editor.completed()) {
|
void _handle_yield_response()
|
||||||
char c;
|
{
|
||||||
terminal.read(&c, 1);
|
for (Child *child = _children.first(); child; child = child->next())
|
||||||
line_editor.submit_input(c);
|
child->try_response_to_resource_request();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signal.context() == &yield_response_sig_ctx
|
|
||||||
|| signal.context() == &resource_avail_sig_ctx) {
|
|
||||||
|
|
||||||
for (Child *child = children.first(); child; child = child->next())
|
|
||||||
child->try_response_to_resource_request();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signal.context() == &yield_broadcast_sig_ctx) {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compute argument of yield request to be broadcasted to all
|
|
||||||
* processes.
|
|
||||||
*/
|
|
||||||
size_t amount = 0;
|
|
||||||
|
|
||||||
/* amount needed to reach preservation limit */
|
|
||||||
Ram::Status ram_status = ram.status();
|
|
||||||
if (ram_status.avail < ram_status.preserve)
|
|
||||||
amount += ram_status.preserve - ram_status.avail;
|
|
||||||
|
|
||||||
/* sum of pending resource requests */
|
|
||||||
for (Child *child = children.first(); child; child = child->next())
|
|
||||||
amount += child->requested_ram_quota();
|
|
||||||
|
|
||||||
for (Child *child = children.first(); child; child = child->next())
|
|
||||||
child->yield(amount, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signal.context() == &exited_child_sig_ctx) {
|
|
||||||
Child *next = nullptr;
|
|
||||||
for (Child *child = children.first(); child; child = next) {
|
|
||||||
next = child->next();
|
|
||||||
if (child->exited()) {
|
|
||||||
children.remove(child);
|
|
||||||
Genode::destroy(Genode::env()->heap(), child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!line_editor.completed())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Command *command = lookup_command(buf, commands);
|
|
||||||
if (!command) {
|
|
||||||
Token cmd_name(buf);
|
|
||||||
tprintf(terminal, "Error: unknown command \"");
|
|
||||||
terminal.write(cmd_name.start(), cmd_name.len());
|
|
||||||
tprintf(terminal, "\"\n");
|
|
||||||
line_editor.reset();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* validate parameters against command meta data */
|
|
||||||
Command_line cmd_line(buf, *command);
|
|
||||||
Token unexpected = cmd_line.unexpected_parameter();
|
|
||||||
if (unexpected) {
|
|
||||||
tprintf(terminal, "Error: unexpected parameter \"");
|
|
||||||
terminal.write(unexpected.start(), unexpected.len());
|
|
||||||
tprintf(terminal, "\"\n");
|
|
||||||
line_editor.reset();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
command->execute(cmd_line, terminal);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The command might result in a change of the RAM usage. Validate
|
|
||||||
* that the preservation is satisfied.
|
|
||||||
*/
|
|
||||||
ram.validate_preservation();
|
|
||||||
line_editor.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
env.parent().exit(0);
|
Signal_handler<Main> _yield_response_handler {
|
||||||
|
_env.ep(), *this, &Main::_handle_yield_response };
|
||||||
|
|
||||||
|
void _handle_child_exit()
|
||||||
|
{
|
||||||
|
Child *next = nullptr;
|
||||||
|
for (Child *child = _children.first(); child; child = next) {
|
||||||
|
next = child->next();
|
||||||
|
if (child->exited()) {
|
||||||
|
_children.remove(child);
|
||||||
|
Genode::destroy(_heap, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Signal_handler<Main> _child_exit_handler {
|
||||||
|
_env.ep(), *this, &Main::_handle_child_exit };
|
||||||
|
|
||||||
|
void _handle_yield_broadcast()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Compute argument of yield request to be broadcasted to all
|
||||||
|
* processes.
|
||||||
|
*/
|
||||||
|
size_t amount = 0;
|
||||||
|
|
||||||
|
/* amount needed to reach preservation limit */
|
||||||
|
Ram::Status ram_status = _ram.status();
|
||||||
|
if (ram_status.avail < ram_status.preserve)
|
||||||
|
amount += ram_status.preserve - ram_status.avail;
|
||||||
|
|
||||||
|
/* sum of pending resource requests */
|
||||||
|
for (Child *child = _children.first(); child; child = child->next())
|
||||||
|
amount += child->requested_ram_quota();
|
||||||
|
|
||||||
|
for (Child *child = _children.first(); child; child = child->next())
|
||||||
|
child->yield(amount, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Signal_handler<Main> _yield_broadcast_handler {
|
||||||
|
_env.ep(), *this, &Main::_handle_yield_broadcast };
|
||||||
|
|
||||||
|
Genode::Attached_rom_dataspace _config { _env, "config" };
|
||||||
|
|
||||||
|
Xml_node _vfs_config() const
|
||||||
|
{
|
||||||
|
try { return _config.xml().sub_node("vfs"); }
|
||||||
|
catch (Genode::Xml_node::Nonexistent_sub_node) {
|
||||||
|
Genode::error("missing '<vfs>' configuration");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t _ram_preservation_from_config() const
|
||||||
|
{
|
||||||
|
if (!_config.xml().has_sub_node("preservation"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return _config.xml().sub_node("preservation")
|
||||||
|
.attribute_value("name", Genode::Number_of_bytes(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ram _ram { _env.ram(), _env.ram_session_cap(), _ram_preservation_from_config(),
|
||||||
|
_yield_broadcast_handler, _yield_response_handler };
|
||||||
|
|
||||||
|
Heap _heap { _env.ram(), _env.rm() };
|
||||||
|
|
||||||
|
/* initialize virtual file system */
|
||||||
|
Vfs::Dir_file_system _root_dir { _env, _heap, _vfs_config(),
|
||||||
|
Vfs::global_file_system_factory() };
|
||||||
|
|
||||||
|
Subsystem_config_registry _subsystem_config_registry { _root_dir, _heap };
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct Registered : T
|
||||||
|
{
|
||||||
|
template <typename... ARGS>
|
||||||
|
Registered(Command_registry &commands, ARGS &&... args)
|
||||||
|
: T(args...) { commands.insert(this); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* initialize generic commands */
|
||||||
|
Registered<Help_command> _help_command { _commands };
|
||||||
|
Registered<Kill_command> _kill_command { _commands, _children, _heap };
|
||||||
|
Registered<Start_command> _start_command { _commands, _ram, _heap, _env.pd(),
|
||||||
|
_env.ram(), _env.ram_session_cap(),
|
||||||
|
_env.rm(), _children,
|
||||||
|
_subsystem_config_registry,
|
||||||
|
_yield_response_handler,
|
||||||
|
_child_exit_handler };
|
||||||
|
Registered<Status_command> _status_command { _commands, _ram, _children };
|
||||||
|
Registered<Yield_command> _yield_command { _commands, _children };
|
||||||
|
Registered<Ram_command> _ram_command { _commands, _children, _ram };
|
||||||
|
|
||||||
|
Main(Env &env) : _env(env)
|
||||||
|
{
|
||||||
|
_terminal.read_avail_sigh(_terminal_read_avail_handler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void Cli_monitor::Main::_handle_terminal_read_avail()
|
||||||
|
{
|
||||||
|
/* supply pending terminal input to line editor */
|
||||||
|
while (_terminal.avail() && !_line_editor.completed()) {
|
||||||
|
char c = 0;
|
||||||
|
_terminal.read(&c, 1);
|
||||||
|
_line_editor.submit_input(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_line_editor.completed())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Command *command = _lookup_command(_command_buf);
|
||||||
|
if (!command) {
|
||||||
|
Token cmd_name(_command_buf);
|
||||||
|
tprintf(_terminal, "Error: unknown command \"");
|
||||||
|
_terminal.write(cmd_name.start(), cmd_name.len());
|
||||||
|
tprintf(_terminal, "\"\n");
|
||||||
|
_line_editor.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* validate parameters against command meta data */
|
||||||
|
Command_line cmd_line(_command_buf, *command);
|
||||||
|
Token unexpected = cmd_line.unexpected_parameter();
|
||||||
|
if (unexpected) {
|
||||||
|
tprintf(_terminal, "Error: unexpected parameter \"");
|
||||||
|
_terminal.write(unexpected.start(), unexpected.len());
|
||||||
|
tprintf(_terminal, "\"\n");
|
||||||
|
_line_editor.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
command->execute(cmd_line, _terminal);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The command might result in a change of the RAM usage. Validate
|
||||||
|
* that the preservation is satisfied.
|
||||||
|
*/
|
||||||
|
_ram.validate_preservation();
|
||||||
|
_line_editor.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Component::construct(Genode::Env &env) { static Cli_monitor::Main main(env); }
|
||||||
|
@ -13,5 +13,5 @@
|
|||||||
|
|
||||||
#include <extension.h>
|
#include <extension.h>
|
||||||
|
|
||||||
void init_extension(Command_registry &) { }
|
void Cli_monitor::init_extension(Command_registry &) { }
|
||||||
|
|
||||||
|
@ -17,17 +17,24 @@
|
|||||||
/* local includes */
|
/* local includes */
|
||||||
#include <child_registry.h>
|
#include <child_registry.h>
|
||||||
|
|
||||||
struct Ram_command : Command
|
namespace Cli_monitor { struct Ram_command; }
|
||||||
{
|
|
||||||
Child_registry &_children;
|
|
||||||
|
|
||||||
Ram_command(Child_registry &children)
|
|
||||||
|
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"),
|
Command("ram", "set RAM quota of subsystem"),
|
||||||
_children(children)
|
_children(children), _ram(ram)
|
||||||
{
|
{
|
||||||
add_parameter(new Parameter("--quota", Parameter::NUMBER, "new RAM quota"));
|
add_parameter(_quota_param);
|
||||||
add_parameter(new Parameter("--limit", Parameter::NUMBER, "on-demand quota limit"));
|
add_parameter(_limit_param);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _set_quota(Terminal::Session &terminal, Child &child, size_t const new_quota)
|
void _set_quota(Terminal::Session &terminal, Child &child, size_t const new_quota)
|
||||||
@ -37,7 +44,7 @@ struct Ram_command : Command
|
|||||||
if (new_quota > old_quota) {
|
if (new_quota > old_quota) {
|
||||||
|
|
||||||
size_t amount = new_quota - old_quota;
|
size_t amount = new_quota - old_quota;
|
||||||
size_t const avail = Genode::env()->ram_session()->avail();
|
size_t const avail = _ram.avail();
|
||||||
if (amount > avail) {
|
if (amount > avail) {
|
||||||
tprintf(terminal, "upgrade of '%s' exceeds available quota of ",
|
tprintf(terminal, "upgrade of '%s' exceeds available quota of ",
|
||||||
child.name().string());
|
child.name().string());
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Prefix of the GDB binary
|
|
||||||
* \author Christian Prochaska
|
|
||||||
* \date 2013-10-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _APP__CLI_MONITOR__SPEC__ARM__GDB_PREFIX_H_
|
|
||||||
#define _APP__CLI_MONITOR__SPEC__ARM__GDB_PREFIX_H_
|
|
||||||
|
|
||||||
static const char *gdb_prefix = "genode-arm-";
|
|
||||||
|
|
||||||
#endif /* _APP__CLI_MONITOR__SPEC__ARM__GDB_PREFIX_H_ */
|
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Fiasco.OC on Arndale specific CLI-monitor extensions
|
|
||||||
* \author Norman Feske
|
|
||||||
* \author Stefan Kalkowski
|
|
||||||
* \date 2013-03-18
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <regulator_session/connection.h>
|
|
||||||
#include <util/string.h>
|
|
||||||
|
|
||||||
/* local includes */
|
|
||||||
#include <common.h>
|
|
||||||
|
|
||||||
struct Cpufreq_command : Command
|
|
||||||
{
|
|
||||||
Regulator::Connection ®ulator;
|
|
||||||
|
|
||||||
Cpufreq_command(Regulator::Connection &r)
|
|
||||||
: Command("cpu_frequency", "set/show CPU frequency"),
|
|
||||||
regulator(r) { }
|
|
||||||
|
|
||||||
void execute(Command_line &cmd, Terminal::Session &terminal)
|
|
||||||
{
|
|
||||||
char freq[128];
|
|
||||||
freq[0] = 0;
|
|
||||||
if (cmd.argument(0, freq, sizeof(freq)) == false) {
|
|
||||||
tprintf(terminal, "Current CPU frequency: %ld Hz\n",
|
|
||||||
regulator.level());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long f = 0;
|
|
||||||
Genode::ascii_to(freq, f);
|
|
||||||
tprintf(terminal, "set frequency to %ld Hz\n", f);
|
|
||||||
regulator.level(f);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void init_extension(Command_registry &commands)
|
|
||||||
{
|
|
||||||
try { /* only inserts commands if route to regulator session exists */
|
|
||||||
static Regulator::Connection reg(Regulator::CLK_CPU);
|
|
||||||
static Cpufreq_command cpufreq_command(reg);
|
|
||||||
commands.insert(&cpufreq_command);
|
|
||||||
} catch (...) { Genode::warning("no regulator session available!"); };
|
|
||||||
|
|
||||||
static Kdebug_command kdebug_command;
|
|
||||||
commands.insert(&kdebug_command);
|
|
||||||
|
|
||||||
static Reboot_command reboot_command;
|
|
||||||
commands.insert(&reboot_command);
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Fiasco.OC-specific CLI-monitor extensions
|
|
||||||
* \author Norman Feske
|
|
||||||
* \date 2013-03-18
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _APP__CLI_MONITOR__SPEC__FOC__COMMON_H_
|
|
||||||
#define _APP__CLI_MONITOR__SPEC__FOC__COMMON_H_
|
|
||||||
|
|
||||||
/* local includes */
|
|
||||||
#include <extension.h>
|
|
||||||
#include <terminal_util.h>
|
|
||||||
#include <command_line.h>
|
|
||||||
|
|
||||||
/* Fiasco includes */
|
|
||||||
namespace Fiasco {
|
|
||||||
#include <l4/sys/kdebug.h>
|
|
||||||
#include <l4/sys/ipc.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void clear_host_terminal()
|
|
||||||
{
|
|
||||||
using namespace Fiasco;
|
|
||||||
|
|
||||||
outstring("\e[99S"); /* scroll up */
|
|
||||||
outstring("\e[99T"); /* scroll down */
|
|
||||||
outstring("\e[199A"); /* move cursor up */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct Kdebug_command : Command
|
|
||||||
{
|
|
||||||
Kdebug_command() : Command("kdebug", "enter kernel debugger (via serial console)") { }
|
|
||||||
|
|
||||||
void execute(Command_line &, Terminal::Session &terminal)
|
|
||||||
{
|
|
||||||
using namespace Fiasco;
|
|
||||||
|
|
||||||
/* let kernel debugger detect the screen size */
|
|
||||||
enter_kdebug("*#JS");
|
|
||||||
|
|
||||||
clear_host_terminal();
|
|
||||||
enter_kdebug("Entering kernel debugger... Press [?] for help");
|
|
||||||
clear_host_terminal();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct Reboot_command : Command
|
|
||||||
{
|
|
||||||
Reboot_command() : Command("reboot", "reboot machine") { }
|
|
||||||
|
|
||||||
void execute(Command_line &, Terminal::Session &terminal)
|
|
||||||
{
|
|
||||||
using namespace Fiasco;
|
|
||||||
|
|
||||||
clear_host_terminal();
|
|
||||||
enter_kdebug("*#^");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _APP__CLI_MONITOR__SPEC__FOC__COMMON_H_ */
|
|
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Fiasco.OC-specific CLI-monitor extensions
|
|
||||||
* \author Norman Feske
|
|
||||||
* \date 2013-03-18
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* local includes */
|
|
||||||
#include <common.h>
|
|
||||||
|
|
||||||
|
|
||||||
void init_extension(Command_registry &commands)
|
|
||||||
{
|
|
||||||
static Kdebug_command kdebug_command;
|
|
||||||
commands.insert(&kdebug_command);
|
|
||||||
|
|
||||||
static Reboot_command reboot_command;
|
|
||||||
commands.insert(&reboot_command);
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Prefix of the GDB binary
|
|
||||||
* \author Sebastian Sumpf
|
|
||||||
* \date 2016-02-16
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 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 _APP__CLI_MONITOR__SPEC__RISCV__GDB_PREFIX_H_
|
|
||||||
#define _APP__CLI_MONITOR__SPEC__RISCV__GDB_PREFIX_H_
|
|
||||||
|
|
||||||
static const char *gdb_prefix = "genode-riscv-";
|
|
||||||
|
|
||||||
#endif /* _APP__CLI_MONITOR__SPEC__RISCV__GDB_PREFIX_H_ */
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Prefix of the GDB binary
|
|
||||||
* \author Christian Prochaska
|
|
||||||
* \date 2013-10-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _APP__CLI_MONITOR__SPEC__X86__GDB_PREFIX_H_
|
|
||||||
#define _APP__CLI_MONITOR__SPEC__X86__GDB_PREFIX_H_
|
|
||||||
|
|
||||||
static const char *gdb_prefix = "genode-x86-";
|
|
||||||
|
|
||||||
#endif /* _APP__CLI_MONITOR__SPEC__X86__GDB_PREFIX_H_ */
|
|
@ -20,7 +20,10 @@
|
|||||||
/* local includes */
|
/* local includes */
|
||||||
#include <subsystem_config_registry.h>
|
#include <subsystem_config_registry.h>
|
||||||
|
|
||||||
class Start_command : public Command
|
namespace Cli_monitor { class Start_command; }
|
||||||
|
|
||||||
|
|
||||||
|
class Cli_monitor::Start_command : public Command
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -29,6 +32,7 @@ class Start_command : public Command
|
|||||||
typedef Genode::Dataspace_capability Dataspace_capability;
|
typedef Genode::Dataspace_capability Dataspace_capability;
|
||||||
|
|
||||||
Ram &_ram;
|
Ram &_ram;
|
||||||
|
Genode::Allocator &_alloc;
|
||||||
Child_registry &_children;
|
Child_registry &_children;
|
||||||
Genode::Pd_session &_pd;
|
Genode::Pd_session &_pd;
|
||||||
Genode::Ram_session &_ref_ram;
|
Genode::Ram_session &_ref_ram;
|
||||||
@ -67,7 +71,7 @@ class Start_command : public Command
|
|||||||
|
|
||||||
/* acount for cli_monitor local metadata */
|
/* acount for cli_monitor local metadata */
|
||||||
size_t preserve_ram = 100*1024;
|
size_t preserve_ram = 100*1024;
|
||||||
if (count * (ram + preserve_ram) > Genode::env()->ram_session()->avail()) {
|
if (count * (ram + preserve_ram) > _ram.avail()) {
|
||||||
tprintf(terminal, "Error: RAM quota exceeds available quota\n");
|
tprintf(terminal, "Error: RAM quota exceeds available quota\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -108,7 +112,7 @@ class Start_command : public Command
|
|||||||
|
|
||||||
Child *child = 0;
|
Child *child = 0;
|
||||||
try {
|
try {
|
||||||
child = new (Genode::env()->heap())
|
child = new (_alloc)
|
||||||
Child(_ram, label, binary_name, _pd, _ref_ram, _ref_ram_cap,
|
Child(_ram, label, binary_name, _pd, _ref_ram, _ref_ram_cap,
|
||||||
_local_rm, ram, ram_limit,
|
_local_rm, ram, ram_limit,
|
||||||
_yield_response_sigh_cap, _exit_sig_cap);
|
_yield_response_sigh_cap, _exit_sig_cap);
|
||||||
@ -122,7 +126,7 @@ class Start_command : public Command
|
|||||||
tprintf(terminal, "Error: insufficient memory, need ");
|
tprintf(terminal, "Error: insufficient memory, need ");
|
||||||
tprint_bytes(terminal, ram + Child::DONATED_RAM_QUOTA);
|
tprint_bytes(terminal, ram + Child::DONATED_RAM_QUOTA);
|
||||||
tprintf(terminal, ", have ");
|
tprintf(terminal, ", have ");
|
||||||
tprint_bytes(terminal, Genode::env()->ram_session()->avail());
|
tprint_bytes(terminal, _ram.avail());
|
||||||
tprintf(terminal, "\n");
|
tprintf(terminal, "\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -147,9 +151,15 @@ class Start_command : public Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Parameter _count_param { "--count", Parameter::NUMBER, "number of instances" };
|
||||||
|
Parameter _ram_param { "--ram", Parameter::NUMBER, "initial RAM quota" };
|
||||||
|
Parameter _ram_limit_param { "--ram-limit", Parameter::NUMBER, "limit for expanding RAM quota" };
|
||||||
|
Parameter _verbose_param { "--verbose", Parameter::VOID, "show diagnostics" };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Start_command(Ram &ram,
|
Start_command(Ram &ram,
|
||||||
|
Genode::Allocator &alloc,
|
||||||
Genode::Pd_session &pd,
|
Genode::Pd_session &pd,
|
||||||
Genode::Ram_session &ref_ram,
|
Genode::Ram_session &ref_ram,
|
||||||
Genode::Ram_session_capability ref_ram_cap,
|
Genode::Ram_session_capability ref_ram_cap,
|
||||||
@ -160,16 +170,16 @@ class Start_command : public Command
|
|||||||
Signal_context_capability exit_sig_cap)
|
Signal_context_capability exit_sig_cap)
|
||||||
:
|
:
|
||||||
Command("start", "create new subsystem"),
|
Command("start", "create new subsystem"),
|
||||||
_ram(ram), _children(children), _pd(pd),
|
_ram(ram), _alloc(alloc), _children(children), _pd(pd),
|
||||||
_ref_ram(ref_ram), _ref_ram_cap(ref_ram_cap), _local_rm(local_rm),
|
_ref_ram(ref_ram), _ref_ram_cap(ref_ram_cap), _local_rm(local_rm),
|
||||||
_subsystem_configs(subsustem_configs),
|
_subsystem_configs(subsustem_configs),
|
||||||
_yield_response_sigh_cap(yield_response_sigh_cap),
|
_yield_response_sigh_cap(yield_response_sigh_cap),
|
||||||
_exit_sig_cap(exit_sig_cap)
|
_exit_sig_cap(exit_sig_cap)
|
||||||
{
|
{
|
||||||
add_parameter(new Parameter("--count", Parameter::NUMBER, "number of instances"));
|
add_parameter(_count_param);
|
||||||
add_parameter(new Parameter("--ram", Parameter::NUMBER, "initial RAM quota"));
|
add_parameter(_ram_param);
|
||||||
add_parameter(new Parameter("--ram-limit", Parameter::NUMBER, "limit for expanding RAM quota"));
|
add_parameter(_ram_limit_param);
|
||||||
add_parameter(new Parameter("--verbose", Parameter::VOID, "show diagnostics"));
|
add_parameter(_verbose_param);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _for_each_argument(Argument_fn const &fn) const override
|
void _for_each_argument(Argument_fn const &fn) const override
|
||||||
|
@ -18,7 +18,10 @@
|
|||||||
#include <table.h>
|
#include <table.h>
|
||||||
#include <child_registry.h>
|
#include <child_registry.h>
|
||||||
|
|
||||||
struct Status_command : Command
|
namespace Cli_monitor { struct Status_command; }
|
||||||
|
|
||||||
|
|
||||||
|
struct Cli_monitor::Status_command : Command
|
||||||
{
|
{
|
||||||
Child_registry &_children;
|
Child_registry &_children;
|
||||||
Ram &_ram;
|
Ram &_ram;
|
||||||
|
@ -18,7 +18,10 @@
|
|||||||
#include <vfs/file_system.h>
|
#include <vfs/file_system.h>
|
||||||
#include <vfs/vfs_handle.h>
|
#include <vfs/vfs_handle.h>
|
||||||
|
|
||||||
class Subsystem_config_registry
|
namespace Cli_monitor { class Subsystem_config_registry; }
|
||||||
|
|
||||||
|
|
||||||
|
class Cli_monitor::Subsystem_config_registry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -29,7 +32,8 @@ class Subsystem_config_registry
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Vfs::File_system &_fs;
|
Vfs::File_system &_fs;
|
||||||
|
Genode::Allocator &_alloc;
|
||||||
|
|
||||||
enum { CONFIG_BUF_SIZE = 32*1024 };
|
enum { CONFIG_BUF_SIZE = 32*1024 };
|
||||||
char _config_buf[CONFIG_BUF_SIZE];
|
char _config_buf[CONFIG_BUF_SIZE];
|
||||||
@ -58,9 +62,9 @@ class Subsystem_config_registry
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Subsystem_config_registry(Vfs::File_system &fs)
|
Subsystem_config_registry(Vfs::File_system &fs, Genode::Allocator &alloc)
|
||||||
:
|
:
|
||||||
_fs(fs)
|
_fs(fs), _alloc(alloc)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +93,7 @@ class Subsystem_config_registry
|
|||||||
Vfs::Directory_service::Open_result const open_result =
|
Vfs::Directory_service::Open_result const open_result =
|
||||||
_fs.open(path.base(),
|
_fs.open(path.base(),
|
||||||
Vfs::Directory_service::OPEN_MODE_RDONLY,
|
Vfs::Directory_service::OPEN_MODE_RDONLY,
|
||||||
&handle, *Genode::env()->heap());
|
&handle, _alloc);
|
||||||
|
|
||||||
Vfs::Vfs_handle::Guard handle_guard(handle);
|
Vfs::Vfs_handle::Guard handle_guard(handle);
|
||||||
|
|
||||||
|
@ -14,8 +14,13 @@
|
|||||||
#ifndef _TABLE_H_
|
#ifndef _TABLE_H_
|
||||||
#define _TABLE_H_
|
#define _TABLE_H_
|
||||||
|
|
||||||
|
#include <terminal_session/terminal_session.h>
|
||||||
|
|
||||||
|
namespace Cli_monitor { template <typename TI> class Table; }
|
||||||
|
|
||||||
|
|
||||||
template <typename TI>
|
template <typename TI>
|
||||||
class Table
|
class Cli_monitor::Table
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -1,16 +1,4 @@
|
|||||||
TARGET = cli_monitor
|
TARGET = cli_monitor
|
||||||
SRC_CC = main.cc
|
SRC_CC = main.cc
|
||||||
LIBS = base cli_monitor config vfs
|
LIBS = base vfs
|
||||||
INC_DIR += $(PRG_DIR)
|
INC_DIR += $(PRG_DIR)
|
||||||
|
|
||||||
ifeq ($(findstring arm, $(SPECS)), arm)
|
|
||||||
INC_DIR += $(PRG_DIR)/spec/arm
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(findstring x86, $(SPECS)), x86)
|
|
||||||
INC_DIR += $(PRG_DIR)/spec/x86
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(findstring riscv, $(SPECS)), riscv)
|
|
||||||
INC_DIR += $(PRG_DIR)/spec/riscv
|
|
||||||
endif
|
|
||||||
|
@ -17,17 +17,23 @@
|
|||||||
/* local includes */
|
/* local includes */
|
||||||
#include <child_registry.h>
|
#include <child_registry.h>
|
||||||
|
|
||||||
struct Yield_command : Command
|
namespace Cli_monitor { struct Yield_command; }
|
||||||
|
|
||||||
|
|
||||||
|
struct Cli_monitor::Yield_command : Command
|
||||||
{
|
{
|
||||||
Child_registry &_children;
|
Child_registry &_children;
|
||||||
|
|
||||||
|
Parameter _ram_param { "--ram", Parameter::NUMBER, "RAM quota to free" };
|
||||||
|
Parameter _greedy_param { "--greedy", Parameter::VOID, "withdraw yielded RAM quota" };
|
||||||
|
|
||||||
Yield_command(Child_registry &children)
|
Yield_command(Child_registry &children)
|
||||||
:
|
:
|
||||||
Command("yield", "instruct subsystem to yield resources"),
|
Command("yield", "instruct subsystem to yield resources"),
|
||||||
_children(children)
|
_children(children)
|
||||||
{
|
{
|
||||||
add_parameter(new Parameter("--ram", Parameter::NUMBER, "RAM quota to free"));
|
add_parameter(_ram_param);
|
||||||
add_parameter(new Parameter("--greedy", Parameter::VOID, "withdraw yielded RAM quota"));
|
add_parameter(_greedy_param);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _for_each_argument(Argument_fn const &fn) const override
|
void _for_each_argument(Argument_fn const &fn) const override
|
||||||
|
Loading…
Reference in New Issue
Block a user