diff --git a/repos/base/include/arm/cpu/cpu_state.h b/repos/base/include/arm/cpu/cpu_state.h index 2dee83c8f..e63f05afa 100644 --- a/repos/base/include/arm/cpu/cpu_state.h +++ b/repos/base/include/arm/cpu/cpu_state.h @@ -21,63 +21,68 @@ namespace Genode { - /** - * Basic CPU state - */ - struct Cpu_state - { - /** - * Native exception types - */ - enum Cpu_exception { - RESET = 1, - UNDEFINED_INSTRUCTION = 2, - SUPERVISOR_CALL = 3, - PREFETCH_ABORT = 4, - DATA_ABORT = 5, - INTERRUPT_REQUEST = 6, - FAST_INTERRUPT_REQUEST = 7, - }; - - /** - * Registers - */ - addr_t r0, r1, r2, r3, r4, r5, r6, - r7, r8, r9, r10, r11, r12; /* general purpose register 0..12 */ - addr_t sp; /* stack pointer */ - addr_t lr; /* link register */ - addr_t ip; /* instruction pointer */ - addr_t cpsr; /* current program status register */ - addr_t cpu_exception; /* last hardware exception */ - }; - - /** - * Extend CPU state by banked registers - */ - struct Cpu_state_modes : Cpu_state - { - /** - * Common banked registers for exception modes - */ - struct Mode_state { - - enum Mode { - UND, /* Undefined */ - SVC, /* Supervisor */ - ABORT, /* Abort */ - IRQ, /* Interrupt */ - FIQ, /* Fast Interrupt */ - MAX - }; - - addr_t spsr; /* saved program status register */ - addr_t sp; /* banked stack pointer */ - addr_t lr; /* banked link register */ - }; - - Mode_state mode[Mode_state::MAX]; /* exception mode registers */ - addr_t fiq_r[5]; /* fast-interrupt mode r8-r12 */ - }; + struct Cpu_state; + struct Cpu_state_modes; } + +/** + * Basic CPU state + */ +struct Genode::Cpu_state +{ + /** + * Native exception types + */ + enum Cpu_exception { + RESET = 1, + UNDEFINED_INSTRUCTION = 2, + SUPERVISOR_CALL = 3, + PREFETCH_ABORT = 4, + DATA_ABORT = 5, + INTERRUPT_REQUEST = 6, + FAST_INTERRUPT_REQUEST = 7, + }; + + /** + * Registers + */ + addr_t r0, r1, r2, r3, r4, r5, r6, + r7, r8, r9, r10, r11, r12; /* general purpose register 0..12 */ + addr_t sp; /* stack pointer */ + addr_t lr; /* link register */ + addr_t ip; /* instruction pointer */ + addr_t cpsr; /* current program status register */ + addr_t cpu_exception; /* last hardware exception */ +}; + + +/** + * Extend CPU state by banked registers + */ +struct Genode::Cpu_state_modes : Cpu_state +{ + /** + * Common banked registers for exception modes + */ + struct Mode_state { + + enum Mode { + UND, /* Undefined */ + SVC, /* Supervisor */ + ABORT, /* Abort */ + IRQ, /* Interrupt */ + FIQ, /* Fast Interrupt */ + MAX + }; + + addr_t spsr; /* saved program status register */ + addr_t sp; /* banked stack pointer */ + addr_t lr; /* banked link register */ + }; + + Mode_state mode[Mode_state::MAX]; /* exception mode registers */ + addr_t fiq_r[5]; /* fast-interrupt mode r8-r12 */ +}; + #endif /* _INCLUDE__ARM__CPU__CPU_STATE_H_ */ diff --git a/repos/base/include/arm/cpu/string.h b/repos/base/include/arm/cpu/string.h index a0b9ab7c0..34fa6d336 100644 --- a/repos/base/include/arm/cpu/string.h +++ b/repos/base/include/arm/cpu/string.h @@ -15,8 +15,8 @@ #ifndef _INCLUDE__ARM__CPU__STRING_H_ #define _INCLUDE__ARM__CPU__STRING_H_ -namespace Genode -{ +namespace Genode { + /** * Copy memory block * diff --git a/repos/base/include/arm/vfp/cpu/string.h b/repos/base/include/arm/vfp/cpu/string.h index c4a1b1bdc..9cd98aa00 100644 --- a/repos/base/include/arm/vfp/cpu/string.h +++ b/repos/base/include/arm/vfp/cpu/string.h @@ -16,8 +16,8 @@ #ifndef _INCLUDE__ARM__VFP__STRING_H_ #define _INCLUDE__ARM__VFP__STRING_H_ -namespace Genode -{ +namespace Genode { + /** * Copy memory block * diff --git a/repos/base/include/base/affinity.h b/repos/base/include/base/affinity.h index 2e1794104..d9a6e5c9a 100644 --- a/repos/base/include/base/affinity.h +++ b/repos/base/include/base/affinity.h @@ -14,178 +14,178 @@ #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; } - - 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 function 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); - }; +namespace Genode { class Affinity; } - /** - * Location within 'Space' - */ - class Location - { - private: +/** + * 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: - int _xpos, _ypos; - unsigned _width, _height; + class Location; - public: + /** + * 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: - /** - * Default constructor creates invalid location - */ - Location() : _xpos(0), _ypos(0), _width(0), _height(0) { } + unsigned _width, _height; - /** - * Constructor to express the affinity to a single CPU - */ - Location(int xpos, unsigned ypos) - : _xpos(xpos), _ypos(ypos), _width(1), _height(1) { } + public: - /** - * 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) { } + Space() : _width(0), _height(0) { } - 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. + /** + * Construct a two-dimensional affinity space */ - int const x1 = _location.xpos(), - y1 = _location.ypos(), - x2 = _location.width() + x1, - y2 = _location.height() + y1; + Space(unsigned width, unsigned height) + : _width(width), _height(height) { } - /* 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(); + /** + * Constuct one-dimensional affinity space + */ + Space(unsigned size) : _width(size), _height(1) { } - /* 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)); - } - }; + 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 function 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); + }; - Affinity::Location Affinity::Space::location_of_index(int index) - { - return Location(index % _width, (index / _width) % _height, 1, 1); - } + /** + * 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_ */ diff --git a/repos/base/include/base/allocator.h b/repos/base/include/base/allocator.h index 7bfbdab9d..9d4747ec6 100644 --- a/repos/base/include/base/allocator.h +++ b/repos/base/include/base/allocator.h @@ -19,187 +19,9 @@ namespace Genode { - struct Deallocator - { - /** - * Free block a previously allocated block - */ - virtual void free(void *addr, size_t size) = 0; - - /** - * Return true if the size argument of 'free' is required - * - * The generic 'Allocator' interface requires the caller of 'free' - * to supply a valid size argument but not all implementations make - * use of this argument. If this function returns false, it is safe - * to call 'free' with an invalid size. - * - * Allocators that rely on the size argument must not be used for - * constructing objects whose constructors may throw exceptions. - * See the documentation of 'operator delete(void *, Allocator *)' - * below for more details. - */ - virtual bool need_size_for_free() const = 0; - }; - - - struct Allocator : Deallocator - { - /** - * Exception type - */ - class Out_of_memory : public Exception { }; - - /** - * Destructor - */ - virtual ~Allocator() { } - - /** - * Allocate block - * - * \param size block size to allocate - * \param out_addr resulting pointer to the new block, - * undefined in the error case - * \return true on success - */ - virtual bool alloc(size_t size, void **out_addr) = 0; - - /** - * Allocate typed block - * - * This template allocates a typed block returned as a pointer to - * a non-void type. By providing this function, we prevent the - * compiler from warning us about "dereferencing type-punned - * pointer will break strict-aliasing rules". - */ - template bool alloc(size_t size, T **out_addr) - { - void *addr = 0; - bool ret = alloc(size, &addr); - *out_addr = (T *)addr; - return ret; - } - - /** - * Return total amount of backing store consumed by the allocator - */ - virtual size_t consumed() { return 0; } - - /** - * Return meta-data overhead per block - */ - virtual size_t overhead(size_t size) = 0; - - - /*************************** - ** Convenience functions ** - ***************************/ - - /** - * Allocate block and signal error as an exception - * - * \param size block size to allocate - * \return pointer to the new block - * \throw Out_of_memory - */ - void *alloc(size_t size) - { - void *result = 0; - if (!alloc(size, &result)) - throw Out_of_memory(); - - return result; - } - }; - - - struct Range_allocator : Allocator - { - /** - * Destructor - */ - virtual ~Range_allocator() { } - - /** - * Add free address range to allocator - */ - virtual int add_range(addr_t base, size_t size) = 0; - - /** - * Remove address range from allocator - */ - virtual int remove_range(addr_t base, size_t size) = 0; - - /** - * Return value of allocation functons - * - * 'OK' on success, or - * 'OUT_OF_METADATA' if meta-data allocation failed, or - * 'RANGE_CONFLICT' if no fitting address range is found - */ - struct Alloc_return - { - enum Value { OK = 0, OUT_OF_METADATA = -1, RANGE_CONFLICT = -2 }; - Value const value; - Alloc_return(Value value) : value(value) { } - - bool is_ok() const { return value == OK; } - bool is_error() const { return !is_ok(); } - }; - - /** - * Allocate block - * - * \param size size of new block - * \param out_addr start address of new block, - * undefined in the error case - * \param align alignment of new block specified - * as the power of two - */ - virtual Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0, addr_t from=0, addr_t to = ~0UL) = 0; - - /** - * Allocate block at address - * - * \param size size of new block - * \param addr desired address of block - * - * \return 'ALLOC_OK' on success, or - * 'OUT_OF_METADATA' if meta-data allocation failed, or - * 'RANGE_CONFLICT' if specified range is occupied - */ - virtual Alloc_return alloc_addr(size_t size, addr_t addr) = 0; - - /** - * Free a previously allocated block - * - * NOTE: We have to declare the 'Allocator::free(void *)' function - * here as well to make the compiler happy. Otherwise the C++ - * overload resolution would not find 'Allocator::free(void *)'. - */ - virtual void free(void *addr) = 0; - virtual void free(void *addr, size_t size) = 0; - - /** - * Return the sum of available memory - * - * Note that the returned value is not neccessarily allocatable - * because the memory may be fragmented. - */ - virtual size_t avail() = 0; - - /** - * Check if address is inside an allocated block - * - * \param addr address to check - * - * \return true if address is inside an allocated block, false - * otherwise - */ - virtual bool valid_addr(addr_t addr) = 0; - }; - + struct Deallocator; + struct Allocator; + struct Range_allocator; /** * Destroy object @@ -221,6 +43,189 @@ namespace Genode { template void destroy(DEALLOC && dealloc, T *obj); } + +struct Genode::Deallocator +{ + /** + * Free block a previously allocated block + */ + virtual void free(void *addr, size_t size) = 0; + + /** + * Return true if the size argument of 'free' is required + * + * The generic 'Allocator' interface requires the caller of 'free' + * to supply a valid size argument but not all implementations make + * use of this argument. If this function returns false, it is safe + * to call 'free' with an invalid size. + * + * Allocators that rely on the size argument must not be used for + * constructing objects whose constructors may throw exceptions. + * See the documentation of 'operator delete(void *, Allocator *)' + * below for more details. + */ + virtual bool need_size_for_free() const = 0; +}; + + +struct Genode::Allocator : Deallocator +{ + /** + * Exception type + */ + class Out_of_memory : public Exception { }; + + /** + * Destructor + */ + virtual ~Allocator() { } + + /** + * Allocate block + * + * \param size block size to allocate + * \param out_addr resulting pointer to the new block, + * undefined in the error case + * \return true on success + */ + virtual bool alloc(size_t size, void **out_addr) = 0; + + /** + * Allocate typed block + * + * This template allocates a typed block returned as a pointer to + * a non-void type. By providing this function, we prevent the + * compiler from warning us about "dereferencing type-punned + * pointer will break strict-aliasing rules". + */ + template bool alloc(size_t size, T **out_addr) + { + void *addr = 0; + bool ret = alloc(size, &addr); + *out_addr = (T *)addr; + return ret; + } + + /** + * Return total amount of backing store consumed by the allocator + */ + virtual size_t consumed() { return 0; } + + /** + * Return meta-data overhead per block + */ + virtual size_t overhead(size_t size) = 0; + + + /*************************** + ** Convenience functions ** + ***************************/ + + /** + * Allocate block and signal error as an exception + * + * \param size block size to allocate + * \return pointer to the new block + * \throw Out_of_memory + */ + void *alloc(size_t size) + { + void *result = 0; + if (!alloc(size, &result)) + throw Out_of_memory(); + + return result; + } +}; + + +struct Genode::Range_allocator : Allocator +{ + /** + * Destructor + */ + virtual ~Range_allocator() { } + + /** + * Add free address range to allocator + */ + virtual int add_range(addr_t base, size_t size) = 0; + + /** + * Remove address range from allocator + */ + virtual int remove_range(addr_t base, size_t size) = 0; + + /** + * Return value of allocation functons + * + * 'OK' on success, or + * 'OUT_OF_METADATA' if meta-data allocation failed, or + * 'RANGE_CONFLICT' if no fitting address range is found + */ + struct Alloc_return + { + enum Value { OK = 0, OUT_OF_METADATA = -1, RANGE_CONFLICT = -2 }; + Value const value; + Alloc_return(Value value) : value(value) { } + + bool is_ok() const { return value == OK; } + bool is_error() const { return !is_ok(); } + }; + + /** + * Allocate block + * + * \param size size of new block + * \param out_addr start address of new block, + * undefined in the error case + * \param align alignment of new block specified + * as the power of two + */ + virtual Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0, addr_t from=0, addr_t to = ~0UL) = 0; + + /** + * Allocate block at address + * + * \param size size of new block + * \param addr desired address of block + * + * \return 'ALLOC_OK' on success, or + * 'OUT_OF_METADATA' if meta-data allocation failed, or + * 'RANGE_CONFLICT' if specified range is occupied + */ + virtual Alloc_return alloc_addr(size_t size, addr_t addr) = 0; + + /** + * Free a previously allocated block + * + * NOTE: We have to declare the 'Allocator::free(void *)' function + * here as well to make the compiler happy. Otherwise the C++ + * overload resolution would not find 'Allocator::free(void *)'. + */ + virtual void free(void *addr) = 0; + virtual void free(void *addr, size_t size) = 0; + + /** + * Return the sum of available memory + * + * Note that the returned value is not neccessarily allocatable + * because the memory may be fragmented. + */ + virtual size_t avail() = 0; + + /** + * Check if address is inside an allocated block + * + * \param addr address to check + * + * \return true if address is inside an allocated block, false + * otherwise + */ + virtual bool valid_addr(addr_t addr) = 0; +}; + + void *operator new (Genode::size_t, Genode::Allocator *); void *operator new [] (Genode::size_t, Genode::Allocator *); diff --git a/repos/base/include/base/allocator_avl.h b/repos/base/include/base/allocator_avl.h index a8ff4b410..b32cb84a2 100644 --- a/repos/base/include/base/allocator_avl.h +++ b/repos/base/include/base/allocator_avl.h @@ -25,309 +25,10 @@ namespace Genode { - class Allocator_avl_base : public Range_allocator - { - private: - - static bool _sum_in_range(addr_t addr, addr_t offset) { - return (~0UL - addr > offset); } - - protected: - - class Block : public Avl_node - { - private: - - addr_t _addr; /* base address */ - size_t _size; /* size of block */ - bool _used; /* block is in use */ - short _id; /* for debugging */ - size_t _max_avail; /* biggest free block size of subtree */ - - /** - * Request max_avail value of subtree - */ - inline size_t _child_max_avail(bool side) { - return child(side) ? child(side)->max_avail() : 0; } - - /** - * Query if block can hold a specified subblock - * - * \param n number of bytes - * \param from minimum start address of subblock - * \param to maximum end address of subblock - * \param align alignment (power of two) - * \return true if block fits - */ - inline bool _fits(size_t n, unsigned align, - addr_t from, addr_t to) - { - addr_t a = align_addr(addr() < from ? from : addr(), - align); - return (a >= addr()) && _sum_in_range(a, n) && - (a - addr() + n <= avail()) && (a + n - 1 <= to); - } - - public: - - /** - * Avl_node interface: compare two nodes - */ - bool higher(Block *a) { - return a->_addr >= _addr; } - - /** - * Avl_node interface: update meta data on node rearrangement - */ - void recompute(); - - /** - * Accessor functions - */ - inline int id() { return _id; } - inline addr_t addr() { return _addr; } - inline size_t avail() { return _used ? 0 : _size; } - inline size_t size() { return _size; } - inline bool used() { return _used; } - inline size_t max_avail() { return _max_avail; } - inline void used(bool used) { _used = used; } - - enum { FREE = false, USED = true }; - - /** - * Constructor - * - * This constructor is called from meta-data allocator during - * initialization of new meta-data blocks. - */ - Block() : _addr(0), _size(0), _used(0), _max_avail(0) { } - - /** - * Constructor - */ - Block(addr_t addr, size_t size, bool used) - : _addr(addr), _size(size), _used(used), - _max_avail(used ? 0 : size) - { - static int num_blocks; - _id = ++num_blocks; - } - - /** - * Find best-fitting block - */ - Block *find_best_fit(size_t size, unsigned align = 1, - addr_t from = 0UL, addr_t to = ~0UL); - - /** - * Find block that contains the specified address range - */ - Block *find_by_address(addr_t addr, size_t size = 0, - bool check_overlap = 0); - - /** - * Return sum of available memory in subtree - */ - size_t avail_in_subtree(void); - - /** - * Debug hooks - */ - void dump(); - void dump_dot(int indent = 0); - }; - - private: - - Avl_tree _addr_tree; /* blocks sorted by base address */ - Allocator *_md_alloc; /* meta-data allocator */ - size_t _md_entry_size; /* size of block meta-data entry */ - - /** - * Alloc meta-data block - */ - Block *_alloc_block_metadata(); - - /** - * Alloc two meta-data blocks in a transactional way - */ - bool _alloc_two_blocks_metadata(Block **dst1, Block **dst2); - - /** - * Create new block - */ - int _add_block(Block *block_metadata, - addr_t base, size_t size, bool used); - - /** - * Destroy block - */ - void _destroy_block(Block *b); - - /** - * Cut specified area from block - * - * The original block gets replaced by (up to) two smaller blocks - * with remaining space. - */ - void _cut_from_block(Block *b, addr_t cut_addr, size_t cut_size, - Block *dst1, Block *dst2); - - protected: - - /** - * Find block by specified address - */ - Block *_find_by_address(addr_t addr, size_t size = 0, - bool check_overlap = 0) const - { - Block *b = static_cast(_addr_tree.first()); - - /* if the tree has one or more nodes, start search */ - return b ? b->find_by_address(addr, size, check_overlap) : 0; - } - - /** - * Constructor - * - * This constructor can only be called from a derived class that - * provides an allocator for block meta-data entries. This way, - * we can attach custom information to block meta data. - */ - Allocator_avl_base(Allocator *md_alloc, size_t md_entry_size) : - _md_alloc(md_alloc), _md_entry_size(md_entry_size) { } - - public: - - /** - * Return address of any block of the allocator - * - * \param out_addr result that contains address of block - * \return true if block was found or - * false if there is no block available - * - * If no block was found, out_addr is set to zero. - */ - bool any_block_addr(addr_t *out_addr); - - /** - * Debug hook - */ - void dump_addr_tree(Block *addr_node = 0); - - - /******************************* - ** Range allocator interface ** - *******************************/ - - int add_range(addr_t base, size_t size); - int remove_range(addr_t base, size_t size); - Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0, addr_t from = 0, addr_t to = ~0UL); - Alloc_return alloc_addr(size_t size, addr_t addr); - void free(void *addr); - size_t avail(); - bool valid_addr(addr_t addr); - - - /************************* - ** Allocator interface ** - *************************/ - - bool alloc(size_t size, void **out_addr) { - return (Allocator_avl_base::alloc_aligned(size, out_addr).is_ok()); } - - void free(void *addr, size_t) { free(addr); } - - /** - * Return size of block at specified address - */ - size_t size_at(void const *addr) const; - - /** - * Return the memory overhead per Block - * - * The overhead is a rough estimation. If a block is somewhere - * in the middle of a free area, we could consider the meta data - * for the two free subareas when calculating the overhead. - * - * The 'sizeof(umword_t)' represents the overhead of the meta-data - * slab allocator. - */ - size_t overhead(size_t) { return sizeof(Block) + sizeof(umword_t); } - - bool need_size_for_free() const override { return false; } - }; - - - /** - * AVL-based allocator with custom meta data attached to each block. - * - * \param BMDT block meta-data type - */ - template - class Allocator_avl_tpl : public Allocator_avl_base - { - protected: - - /* - * Pump up the Block class with custom meta-data type - */ - class Block : public Allocator_avl_base::Block, public BMDT { }; - - Tslab _metadata; /* meta-data allocator */ - char _initial_md_block[SLAB_BLOCK_SIZE]; /* first (static) meta-data block */ - - public: - - /** - * Constructor - * - * \param metadata_chunk_alloc pointer to allocator used to allocate - * meta-data blocks. If set to 0, - * use ourself for allocating our - * meta-data blocks. This works only - * if the managed memory is completely - * accessible by the allocator. - */ - explicit Allocator_avl_tpl(Allocator *metadata_chunk_alloc) : - Allocator_avl_base(&_metadata, sizeof(Block)), - _metadata((metadata_chunk_alloc) ? metadata_chunk_alloc : this, - (Slab_block *)&_initial_md_block) { } - - /** - * Assign custom meta data to block at specified address - */ - void metadata(void *addr, BMDT bmd) const - { - Block *b = static_cast(_find_by_address((addr_t)addr)); - if (b) *static_cast(b) = bmd; - } - - /** - * Return meta data that was attached to block at specified address - */ - BMDT* metadata(void *addr) const - { - Block *b = static_cast(_find_by_address((addr_t)addr)); - return b && b->used() ? b : 0; - } - - int add_range(addr_t base, size_t size) - { - /* - * We disable the slab block allocation while - * processing add_range to prevent avalanche - * effects when (slab trying to make an allocation - * at Allocator_avl that is empty). - */ - Allocator *md_bs = _metadata.backing_store(); - _metadata.backing_store(0); - int ret = Allocator_avl_base::add_range(base, size); - _metadata.backing_store(md_bs); - return ret; - } - }; + class Allocator_avl_base; + template + class Allocator_avl_tpl; /** * Define AVL-based allocator without any meta data attached to each block @@ -336,4 +37,308 @@ namespace Genode { typedef Allocator_avl_tpl Allocator_avl; } + +class Genode::Allocator_avl_base : public Range_allocator +{ + private: + + static bool _sum_in_range(addr_t addr, addr_t offset) { + return (~0UL - addr > offset); } + + protected: + + class Block : public Avl_node + { + private: + + addr_t _addr; /* base address */ + size_t _size; /* size of block */ + bool _used; /* block is in use */ + short _id; /* for debugging */ + size_t _max_avail; /* biggest free block size of subtree */ + + /** + * Request max_avail value of subtree + */ + inline size_t _child_max_avail(bool side) { + return child(side) ? child(side)->max_avail() : 0; } + + /** + * Query if block can hold a specified subblock + * + * \param n number of bytes + * \param from minimum start address of subblock + * \param to maximum end address of subblock + * \param align alignment (power of two) + * \return true if block fits + */ + inline bool _fits(size_t n, unsigned align, + addr_t from, addr_t to) + { + addr_t a = align_addr(addr() < from ? from : addr(), + align); + return (a >= addr()) && _sum_in_range(a, n) && + (a - addr() + n <= avail()) && (a + n - 1 <= to); + } + + public: + + /** + * Avl_node interface: compare two nodes + */ + bool higher(Block *a) { + return a->_addr >= _addr; } + + /** + * Avl_node interface: update meta data on node rearrangement + */ + void recompute(); + + /** + * Accessor functions + */ + inline int id() { return _id; } + inline addr_t addr() { return _addr; } + inline size_t avail() { return _used ? 0 : _size; } + inline size_t size() { return _size; } + inline bool used() { return _used; } + inline size_t max_avail() { return _max_avail; } + inline void used(bool used) { _used = used; } + + enum { FREE = false, USED = true }; + + /** + * Constructor + * + * This constructor is called from meta-data allocator during + * initialization of new meta-data blocks. + */ + Block() : _addr(0), _size(0), _used(0), _max_avail(0) { } + + /** + * Constructor + */ + Block(addr_t addr, size_t size, bool used) + : _addr(addr), _size(size), _used(used), + _max_avail(used ? 0 : size) + { + static int num_blocks; + _id = ++num_blocks; + } + + /** + * Find best-fitting block + */ + Block *find_best_fit(size_t size, unsigned align = 1, + addr_t from = 0UL, addr_t to = ~0UL); + + /** + * Find block that contains the specified address range + */ + Block *find_by_address(addr_t addr, size_t size = 0, + bool check_overlap = 0); + + /** + * Return sum of available memory in subtree + */ + size_t avail_in_subtree(void); + + /** + * Debug hooks + */ + void dump(); + void dump_dot(int indent = 0); + }; + + private: + + Avl_tree _addr_tree; /* blocks sorted by base address */ + Allocator *_md_alloc; /* meta-data allocator */ + size_t _md_entry_size; /* size of block meta-data entry */ + + /** + * Alloc meta-data block + */ + Block *_alloc_block_metadata(); + + /** + * Alloc two meta-data blocks in a transactional way + */ + bool _alloc_two_blocks_metadata(Block **dst1, Block **dst2); + + /** + * Create new block + */ + int _add_block(Block *block_metadata, + addr_t base, size_t size, bool used); + + /** + * Destroy block + */ + void _destroy_block(Block *b); + + /** + * Cut specified area from block + * + * The original block gets replaced by (up to) two smaller blocks + * with remaining space. + */ + void _cut_from_block(Block *b, addr_t cut_addr, size_t cut_size, + Block *dst1, Block *dst2); + + protected: + + /** + * Find block by specified address + */ + Block *_find_by_address(addr_t addr, size_t size = 0, + bool check_overlap = 0) const + { + Block *b = static_cast(_addr_tree.first()); + + /* if the tree has one or more nodes, start search */ + return b ? b->find_by_address(addr, size, check_overlap) : 0; + } + + /** + * Constructor + * + * This constructor can only be called from a derived class that + * provides an allocator for block meta-data entries. This way, + * we can attach custom information to block meta data. + */ + Allocator_avl_base(Allocator *md_alloc, size_t md_entry_size) : + _md_alloc(md_alloc), _md_entry_size(md_entry_size) { } + + public: + + /** + * Return address of any block of the allocator + * + * \param out_addr result that contains address of block + * \return true if block was found or + * false if there is no block available + * + * If no block was found, out_addr is set to zero. + */ + bool any_block_addr(addr_t *out_addr); + + /** + * Debug hook + */ + void dump_addr_tree(Block *addr_node = 0); + + + /******************************* + ** Range allocator interface ** + *******************************/ + + int add_range(addr_t base, size_t size); + int remove_range(addr_t base, size_t size); + Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0, addr_t from = 0, addr_t to = ~0UL); + Alloc_return alloc_addr(size_t size, addr_t addr); + void free(void *addr); + size_t avail(); + bool valid_addr(addr_t addr); + + + /************************* + ** Allocator interface ** + *************************/ + + bool alloc(size_t size, void **out_addr) { + return (Allocator_avl_base::alloc_aligned(size, out_addr).is_ok()); } + + void free(void *addr, size_t) { free(addr); } + + /** + * Return size of block at specified address + */ + size_t size_at(void const *addr) const; + + /** + * Return the memory overhead per Block + * + * The overhead is a rough estimation. If a block is somewhere + * in the middle of a free area, we could consider the meta data + * for the two free subareas when calculating the overhead. + * + * The 'sizeof(umword_t)' represents the overhead of the meta-data + * slab allocator. + */ + size_t overhead(size_t) { return sizeof(Block) + sizeof(umword_t); } + + bool need_size_for_free() const override { return false; } +}; + + +/** + * AVL-based allocator with custom meta data attached to each block. + * + * \param BMDT block meta-data type + */ +template +class Genode::Allocator_avl_tpl : public Allocator_avl_base +{ + protected: + + /* + * Pump up the Block class with custom meta-data type + */ + class Block : public Allocator_avl_base::Block, public BMDT { }; + + Tslab _metadata; /* meta-data allocator */ + char _initial_md_block[SLAB_BLOCK_SIZE]; /* first (static) meta-data block */ + + public: + + /** + * Constructor + * + * \param metadata_chunk_alloc pointer to allocator used to allocate + * meta-data blocks. If set to 0, + * use ourself for allocating our + * meta-data blocks. This works only + * if the managed memory is completely + * accessible by the allocator. + */ + explicit Allocator_avl_tpl(Allocator *metadata_chunk_alloc) : + Allocator_avl_base(&_metadata, sizeof(Block)), + _metadata((metadata_chunk_alloc) ? metadata_chunk_alloc : this, + (Slab_block *)&_initial_md_block) { } + + /** + * Assign custom meta data to block at specified address + */ + void metadata(void *addr, BMDT bmd) const + { + Block *b = static_cast(_find_by_address((addr_t)addr)); + if (b) *static_cast(b) = bmd; + } + + /** + * Return meta data that was attached to block at specified address + */ + BMDT* metadata(void *addr) const + { + Block *b = static_cast(_find_by_address((addr_t)addr)); + return b && b->used() ? b : 0; + } + + int add_range(addr_t base, size_t size) + { + /* + * We disable the slab block allocation while + * processing add_range to prevent avalanche + * effects when (slab trying to make an allocation + * at Allocator_avl that is empty). + */ + Allocator *md_bs = _metadata.backing_store(); + _metadata.backing_store(0); + int ret = Allocator_avl_base::add_range(base, size); + _metadata.backing_store(md_bs); + return ret; + } +}; + #endif /* _INCLUDE__BASE__ALLOCATOR_AVL_H_ */ diff --git a/repos/base/include/base/allocator_guard.h b/repos/base/include/base/allocator_guard.h index 1feba9859..fa04368d2 100644 --- a/repos/base/include/base/allocator_guard.h +++ b/repos/base/include/base/allocator_guard.h @@ -18,95 +18,95 @@ #include #include -namespace Genode { +namespace Genode { class Allocator_guard; } - /** - * This class acts as guard for arbitrary allocators to limit - * memory exhaustion - */ - class Allocator_guard : public Allocator - { - private: - Allocator *_allocator; /* allocator to guard */ - size_t _amount; /* total amount */ - size_t _consumed; /* already consumed bytes */ +/** + * This class acts as guard for arbitrary allocators to limit + * memory exhaustion + */ +class Genode::Allocator_guard : public Allocator +{ + private: - public: + Allocator *_allocator; /* allocator to guard */ + size_t _amount; /* total amount */ + size_t _consumed; /* already consumed bytes */ - Allocator_guard(Allocator *allocator, size_t amount) - : _allocator(allocator), _amount(amount), _consumed(0) { } + public: - /** - * Extend allocation limit - */ - void upgrade(size_t additional_amount) { - _amount += additional_amount; } + Allocator_guard(Allocator *allocator, size_t amount) + : _allocator(allocator), _amount(amount), _consumed(0) { } - /** - * Consume bytes without actually allocating them - */ - bool withdraw(size_t size) - { - if ((_amount - _consumed) < size) - return false; + /** + * Extend allocation limit + */ + void upgrade(size_t additional_amount) { + _amount += additional_amount; } - _consumed += size; - return true; + /** + * Consume bytes without actually allocating them + */ + bool withdraw(size_t size) + { + if ((_amount - _consumed) < size) + return false; + + _consumed += size; + return true; + } + + /************************* + ** Allocator interface ** + *************************/ + + /** + * Allocate block + * + * \param size block size to allocate + * \param out_addr resulting pointer to the new block, + * undefined in the error case + * \return true on success + */ + bool alloc(size_t size, void **out_addr) override + { + if ((_amount - _consumed) < (size + _allocator->overhead(size))) { + PWRN("Quota exceeded! amount=%zu, size=%zu, consumed=%zu", + _amount, (size + _allocator->overhead(size)), _consumed); + return false; } + bool b = _allocator->alloc(size, out_addr); + if (b) + _consumed += size + _allocator->overhead(size); + return b; + } - /************************* - ** Allocator interface ** - *************************/ + /** + * Free block a previously allocated block + */ + void free(void *addr, size_t size) override + { + _allocator->free(addr, size); + _consumed -= size + _allocator->overhead(size); + } - /** - * Allocate block - * - * \param size block size to allocate - * \param out_addr resulting pointer to the new block, - * undefined in the error case - * \return true on success - */ - bool alloc(size_t size, void **out_addr) - { - if ((_amount - _consumed) < (size + _allocator->overhead(size))) { - PWRN("Quota exceeded! amount=%zu, size=%zu, consumed=%zu", - _amount, (size + _allocator->overhead(size)), _consumed); - return false; - } - bool b = _allocator->alloc(size, out_addr); - if (b) - _consumed += size + _allocator->overhead(size); - return b; - } + /** + * Return amount of backing store consumed by the allocator + */ + size_t consumed() override { return _consumed; } - /** - * Free block a previously allocated block - */ - void free(void *addr, size_t size) - { - _allocator->free(addr, size); - _consumed -= size + _allocator->overhead(size); - } + /** + * Return allocation limit + */ + size_t quota() const { return _amount; } - /** - * Return amount of backing store consumed by the allocator - */ - size_t consumed() { return _consumed; } + /** + * Return meta-data overhead per block + */ + size_t overhead(size_t size) override { return _allocator->overhead(size); } - /** - * Return allocation limit - */ - size_t quota() const { return _amount; } - - /** - * Return meta-data overhead per block - */ - size_t overhead(size_t size) { return _allocator->overhead(size); } - - bool need_size_for_free() const override { - return _allocator->need_size_for_free(); } - }; -} + bool need_size_for_free() const override { + return _allocator->need_size_for_free(); } +}; #endif /* _ALLOCATOR_GUARD_H_ */ diff --git a/repos/base/include/base/blocking.h b/repos/base/include/base/blocking.h index 2be17a482..c08aa246a 100644 --- a/repos/base/include/base/blocking.h +++ b/repos/base/include/base/blocking.h @@ -23,6 +23,8 @@ #include -namespace Genode { class Blocking_canceled : public Exception { }; } +namespace Genode { class Blocking_canceled; } + +class Genode::Blocking_canceled : public Exception { }; #endif /* _INCLUDE__BASE__BLOCKING_H_ */ diff --git a/repos/base/include/base/cache.h b/repos/base/include/base/cache.h index 9a4b1baeb..a63986390 100644 --- a/repos/base/include/base/cache.h +++ b/repos/base/include/base/cache.h @@ -15,6 +15,8 @@ #define _INCLUDE__BASE__CACHE_H_ namespace Genode { + enum Cache_attribute { UNCACHED, WRITE_COMBINED, CACHED }; } + #endif /* _INCLUDE__BASE__CACHE_H_ */ diff --git a/repos/base/include/base/cancelable_lock.h b/repos/base/include/base/cancelable_lock.h index 725e356ad..d2b591e6f 100644 --- a/repos/base/include/base/cancelable_lock.h +++ b/repos/base/include/base/cancelable_lock.h @@ -20,76 +20,78 @@ namespace Genode { class Thread_base; - - class Cancelable_lock - { - private: - - class Applicant - { - private: - - Thread_base *_thread_base; - Applicant *_to_wake_up; - - public: - - explicit Applicant(Thread_base *thread_base) - : _thread_base(thread_base), _to_wake_up(0) { } - - void applicant_to_wake_up(Applicant *to_wake_up) { - _to_wake_up = to_wake_up; } - - Applicant *applicant_to_wake_up() { return _to_wake_up; } - - Thread_base *thread_base() { return _thread_base; } - - /** - * Called from previous lock owner - */ - void wake_up(); - - bool operator == (Applicant &a) { return _thread_base == a.thread_base(); } - bool operator != (Applicant &a) { return _thread_base != a.thread_base(); } - }; - - /* - * Note that modifications of the applicants queue must be performed - * atomically. Hence, we use the additional spinlock here. - */ - - volatile int _spinlock_state; - volatile int _state; - - Applicant* volatile _last_applicant; - Applicant _owner; - - public: - - enum State { LOCKED, UNLOCKED }; - - /** - * Constructor - */ - explicit Cancelable_lock(State initial = UNLOCKED); - - /** - * Try to aquire lock an block while lock is not free - * - * This function may throw a Genode::Blocking_canceled exception. - */ - void lock(); - - /** - * Release lock - */ - void unlock(); - - /** - * Lock guard - */ - typedef Genode::Lock_guard Guard; - }; + class Cancelable_lock; } + +class Genode::Cancelable_lock +{ + private: + + class Applicant + { + private: + + Thread_base *_thread_base; + Applicant *_to_wake_up; + + public: + + explicit Applicant(Thread_base *thread_base) + : _thread_base(thread_base), _to_wake_up(0) { } + + void applicant_to_wake_up(Applicant *to_wake_up) { + _to_wake_up = to_wake_up; } + + Applicant *applicant_to_wake_up() { return _to_wake_up; } + + Thread_base *thread_base() { return _thread_base; } + + /** + * Called from previous lock owner + */ + void wake_up(); + + bool operator == (Applicant &a) { return _thread_base == a.thread_base(); } + bool operator != (Applicant &a) { return _thread_base != a.thread_base(); } + }; + + /* + * Note that modifications of the applicants queue must be performed + * atomically. Hence, we use the additional spinlock here. + */ + + volatile int _spinlock_state; + volatile int _state; + + Applicant* volatile _last_applicant; + Applicant _owner; + + public: + + enum State { LOCKED, UNLOCKED }; + + /** + * Constructor + */ + explicit Cancelable_lock(State initial = UNLOCKED); + + /** + * Try to aquire lock an block while lock is not free + * + * This function may throw a Genode::Blocking_canceled exception. + */ + void lock(); + + /** + * Release lock + */ + void unlock(); + + /** + * Lock guard + */ + typedef Genode::Lock_guard Guard; +}; + #endif /* _INCLUDE__BASE__CANCELABLE_LOCK_H_ */ diff --git a/repos/base/include/base/capability.h b/repos/base/include/base/capability.h index 86532a471..00e399c85 100644 --- a/repos/base/include/base/capability.h +++ b/repos/base/include/base/capability.h @@ -33,299 +33,307 @@ namespace Genode { */ typedef Native_capability Untyped_capability; + template class Capability; - /** - * Capability referring to a specific RPC interface - * - * \param RPC_INTERFACE class containing the RPC interface declaration - */ template - class Capability : public Untyped_capability - { - private: + Capability reinterpret_cap_cast(Untyped_capability const &); - /** - * Insert RPC arguments into the message buffer - */ - template - void _marshal_args(Ipc_client &ipc_client, ATL &args) const; - - void _marshal_args(Ipc_client &, Meta::Empty &) const { } - - /** - * Unmarshal single RPC argument from the message buffer - */ - template - void _unmarshal_result(Ipc_client &ipc_client, T &arg, - Meta::Overload_selector) const; - - template - void _unmarshal_result(Ipc_client &ipc_client, T &arg, - Meta::Overload_selector) const; - - template - void _unmarshal_result(Ipc_client &, T &, - Meta::Overload_selector) const { } - - /** - * Read RPC results from the message buffer - */ - template - void _unmarshal_results(Ipc_client &ipc_client, ATL &args) const; - - void _unmarshal_results(Ipc_client &, Meta::Empty &) const { } - - /** - * Check RPC return code for the occurrence of exceptions - * - * A server-side exception is indicated by a non-zero exception - * code. Each exception code corresponds to an entry in the - * exception type list specified in the RPC function declaration. - * The '_check_for_exception' function template throws the - * exception type belonging to the received exception code. - */ - template - void _check_for_exceptions(Rpc_exception_code const exc_code, - Meta::Overload_selector) const - { - enum { EXCEPTION_CODE = RPC_EXCEPTION_BASE - Meta::Length::Value }; - - if (exc_code == EXCEPTION_CODE) - throw typename EXC_TL::Head(); - - _check_for_exceptions(exc_code, Meta::Overload_selector()); - } - - void _check_for_exceptions(Rpc_exception_code const, - Meta::Overload_selector) const - { } - - /** - * Perform RPC call, arguments passed a as nested 'Ref_tuple' object - */ - template - void _call(typename IF::Client_args &args, - typename IF::Ret_type &ret) const; - - /** - * Shortcut for querying argument types used in 'call' functions - */ - template - struct Arg - { - typedef typename Meta::Type_at::Type Type; - }; - - template - Untyped_capability - _check_compatibility(Capability const &cap) const - { - FROM_RPC_INTERFACE *from = 0; - RPC_INTERFACE *to = from; - (void)to; - return cap; - } - - /** - * Private constructor, should be used by the local-capability - * factory method only. - * - * \param ptr pointer to the local object this capability represents. - */ - Capability(void *ptr) : Untyped_capability(ptr) {} - - /** - * Wrapper for the return type instantiated by 'call' overloads - * - * Each 'call' overload creates an instance of the return value - * type as local variable. A reference to this variable is passed - * to the '_call' function, which will assign its value. Even - * though the variable does not need to be initialized prior the - * call of '_call', the GCC will still complain "warning: ‘ret’ may - * be used uninitialized in this function". Wrapping the return - * value in a struct silences the compiler. - */ - template - struct Return - { - typedef typename Trait::Call_return::Type - Return_type; - - volatile Return_type _value; - Return_type &value() { return *(Return_type *)(&_value); } - }; - - public: - - typedef RPC_INTERFACE Rpc_interface; - - /** - * Constructor - * - * This implicit constructor checks at compile time for the - * compatibility of the source and target capability types. The - * construction is performed only if the target capability type is - * identical to or a base type of the source capability type. - */ - template - Capability(Capability const &cap) - : Untyped_capability(_check_compatibility(cap)) - { } - - /** - * Default constructor creates invalid capability - */ - Capability() { } - - /** - * Factory method to construct a local-capability. - * - * Local-capabilities can be used protection-domain internally - * only. They simply incorporate a pointer to some process-local - * object. - * - * \param ptr pointer to the corresponding local object. - * \return a capability that represents the local object. - */ - static Capability local_cap(RPC_INTERFACE* ptr) { - return Capability((void*)ptr); } - - /** - * Dereference a local-capability. - * - * \param c the local-capability. - * \return pointer to the corresponding local object. - */ - static RPC_INTERFACE* deref(Capability c) { - return reinterpret_cast(c.local()); } - - template - typename Trait::Call_return::Type - call() const - { - Meta::Empty e; - Return ret; - _call(e, ret.value()); - return ret.value(); - } - - template - typename Trait::Call_return::Type - call(typename Arg::Type v1) const - { - Meta::Empty e; - typename IF::Client_args args(v1, e); - Return ret; - _call(args, ret.value()); - return ret.value(); - } - - template - typename Trait::Call_return::Type - call(typename Arg::Type v1, typename Arg::Type v2) const - { - Meta::Empty e; - typename IF::Client_args args(v1, v2, e); - Return ret; - _call(args, ret.value()); - return ret.value(); - } - - template - typename Trait::Call_return::Type - call(typename Arg::Type v1, typename Arg::Type v2, - typename Arg::Type v3) const - { - Meta::Empty e; - typename IF::Client_args args(v1, v2, v3, e); - Return ret; - _call(args, ret.value()); - return ret.value(); - } - - template - typename Trait::Call_return::Type - call(typename Arg::Type v1, typename Arg::Type v2, - typename Arg::Type v3, typename Arg::Type v4) const - { - Meta::Empty e; - typename IF::Client_args args(v1, v2, v3, v4, e); - Return ret; - _call(args, ret.value()); - return ret.value(); - } - - template - typename Trait::Call_return::Type - call(typename Arg::Type v1, typename Arg::Type v2, - typename Arg::Type v3, typename Arg::Type v4, - typename Arg::Type v5) const - { - Meta::Empty e; - typename IF::Client_args args(v1, v2, v3, v4, v5, e); - Return ret; - _call(args, ret.value()); - return ret.value(); - } - - template - typename Trait::Call_return::Type - call(typename Arg::Type v1, typename Arg::Type v2, - typename Arg::Type v3, typename Arg::Type v4, - typename Arg::Type v5, typename Arg::Type v6) const - { - Meta::Empty e; - typename IF::Client_args args(v1, v2, v3, v4, v5, v6, e); - Return ret; - _call(args, ret.value()); - return ret.value(); - } - - template - typename Trait::Call_return::Type - call(typename Arg::Type v1, typename Arg::Type v2, - typename Arg::Type v3, typename Arg::Type v4, - typename Arg::Type v5, typename Arg::Type v6, - typename Arg::Type v7) const - { - Meta::Empty e; - typename IF::Client_args args(v1, v2, v3, v4, v5, v6, v7, e); - Return ret; - _call(args, ret.value()); - return ret.value(); - } - }; - - - /** - * Convert an untyped capability to a typed capability - */ - template - Capability - reinterpret_cap_cast(Untyped_capability const &untyped_cap) - { - /* - * The object layout of untyped and typed capabilities is identical. - * Hence we can just use it's copy-constructors. - */ - Untyped_capability *ptr = const_cast(&untyped_cap); - return *static_cast*>(ptr); - } - - - /** - * Convert capability type from an interface base type to an inherited - * interface type - */ template - Capability - static_cap_cast(Capability cap) - { - /* check interface compatibility */ - (void)static_cast((FROM_RPC_INTERFACE *)0); + Capability static_cap_cast(Capability); +} - return reinterpret_cap_cast(cap); - } + +/** + * Capability referring to a specific RPC interface + * + * \param RPC_INTERFACE class containing the RPC interface declaration + */ +template +class Genode::Capability : public Untyped_capability +{ + private: + + /** + * Insert RPC arguments into the message buffer + */ + template + void _marshal_args(Ipc_client &ipc_client, ATL &args) const; + + void _marshal_args(Ipc_client &, Meta::Empty &) const { } + + /** + * Unmarshal single RPC argument from the message buffer + */ + template + void _unmarshal_result(Ipc_client &ipc_client, T &arg, + Meta::Overload_selector) const; + + template + void _unmarshal_result(Ipc_client &ipc_client, T &arg, + Meta::Overload_selector) const; + + template + void _unmarshal_result(Ipc_client &, T &, + Meta::Overload_selector) const { } + + /** + * Read RPC results from the message buffer + */ + template + void _unmarshal_results(Ipc_client &ipc_client, ATL &args) const; + + void _unmarshal_results(Ipc_client &, Meta::Empty &) const { } + + /** + * Check RPC return code for the occurrence of exceptions + * + * A server-side exception is indicated by a non-zero exception + * code. Each exception code corresponds to an entry in the + * exception type list specified in the RPC function declaration. + * The '_check_for_exception' function template throws the + * exception type belonging to the received exception code. + */ + template + void _check_for_exceptions(Rpc_exception_code const exc_code, + Meta::Overload_selector) const + { + enum { EXCEPTION_CODE = RPC_EXCEPTION_BASE - Meta::Length::Value }; + + if (exc_code == EXCEPTION_CODE) + throw typename EXC_TL::Head(); + + _check_for_exceptions(exc_code, Meta::Overload_selector()); + } + + void _check_for_exceptions(Rpc_exception_code const, + Meta::Overload_selector) const + { } + + /** + * Perform RPC call, arguments passed a as nested 'Ref_tuple' object + */ + template + void _call(typename IF::Client_args &args, + typename IF::Ret_type &ret) const; + + /** + * Shortcut for querying argument types used in 'call' functions + */ + template + struct Arg + { + typedef typename Meta::Type_at::Type Type; + }; + + template + Untyped_capability + _check_compatibility(Capability const &cap) const + { + FROM_RPC_INTERFACE *from = 0; + RPC_INTERFACE *to = from; + (void)to; + return cap; + } + + /** + * Private constructor, should be used by the local-capability + * factory method only. + * + * \param ptr pointer to the local object this capability represents. + */ + Capability(void *ptr) : Untyped_capability(ptr) {} + + /** + * Wrapper for the return type instantiated by 'call' overloads + * + * Each 'call' overload creates an instance of the return value + * type as local variable. A reference to this variable is passed + * to the '_call' function, which will assign its value. Even + * though the variable does not need to be initialized prior the + * call of '_call', the GCC will still complain "warning: ‘ret’ may + * be used uninitialized in this function". Wrapping the return + * value in a struct silences the compiler. + */ + template + struct Return + { + typedef typename Trait::Call_return::Type + Return_type; + + volatile Return_type _value; + Return_type &value() { return *(Return_type *)(&_value); } + }; + + public: + + typedef RPC_INTERFACE Rpc_interface; + + /** + * Constructor + * + * This implicit constructor checks at compile time for the + * compatibility of the source and target capability types. The + * construction is performed only if the target capability type is + * identical to or a base type of the source capability type. + */ + template + Capability(Capability const &cap) + : Untyped_capability(_check_compatibility(cap)) + { } + + /** + * Default constructor creates invalid capability + */ + Capability() { } + + /** + * Factory method to construct a local-capability. + * + * Local-capabilities can be used protection-domain internally + * only. They simply incorporate a pointer to some process-local + * object. + * + * \param ptr pointer to the corresponding local object. + * \return a capability that represents the local object. + */ + static Capability local_cap(RPC_INTERFACE* ptr) { + return Capability((void*)ptr); } + + /** + * Dereference a local-capability. + * + * \param c the local-capability. + * \return pointer to the corresponding local object. + */ + static RPC_INTERFACE* deref(Capability c) { + return reinterpret_cast(c.local()); } + + template + typename Trait::Call_return::Type + call() const + { + Meta::Empty e; + Return ret; + _call(e, ret.value()); + return ret.value(); + } + + template + typename Trait::Call_return::Type + call(typename Arg::Type v1) const + { + Meta::Empty e; + typename IF::Client_args args(v1, e); + Return ret; + _call(args, ret.value()); + return ret.value(); + } + + template + typename Trait::Call_return::Type + call(typename Arg::Type v1, typename Arg::Type v2) const + { + Meta::Empty e; + typename IF::Client_args args(v1, v2, e); + Return ret; + _call(args, ret.value()); + return ret.value(); + } + + template + typename Trait::Call_return::Type + call(typename Arg::Type v1, typename Arg::Type v2, + typename Arg::Type v3) const + { + Meta::Empty e; + typename IF::Client_args args(v1, v2, v3, e); + Return ret; + _call(args, ret.value()); + return ret.value(); + } + + template + typename Trait::Call_return::Type + call(typename Arg::Type v1, typename Arg::Type v2, + typename Arg::Type v3, typename Arg::Type v4) const + { + Meta::Empty e; + typename IF::Client_args args(v1, v2, v3, v4, e); + Return ret; + _call(args, ret.value()); + return ret.value(); + } + + template + typename Trait::Call_return::Type + call(typename Arg::Type v1, typename Arg::Type v2, + typename Arg::Type v3, typename Arg::Type v4, + typename Arg::Type v5) const + { + Meta::Empty e; + typename IF::Client_args args(v1, v2, v3, v4, v5, e); + Return ret; + _call(args, ret.value()); + return ret.value(); + } + + template + typename Trait::Call_return::Type + call(typename Arg::Type v1, typename Arg::Type v2, + typename Arg::Type v3, typename Arg::Type v4, + typename Arg::Type v5, typename Arg::Type v6) const + { + Meta::Empty e; + typename IF::Client_args args(v1, v2, v3, v4, v5, v6, e); + Return ret; + _call(args, ret.value()); + return ret.value(); + } + + template + typename Trait::Call_return::Type + call(typename Arg::Type v1, typename Arg::Type v2, + typename Arg::Type v3, typename Arg::Type v4, + typename Arg::Type v5, typename Arg::Type v6, + typename Arg::Type v7) const + { + Meta::Empty e; + typename IF::Client_args args(v1, v2, v3, v4, v5, v6, v7, e); + Return ret; + _call(args, ret.value()); + return ret.value(); + } +}; + + +/** + * Convert an untyped capability to a typed capability + */ +template +Genode::Capability +Genode::reinterpret_cap_cast(Untyped_capability const &untyped_cap) +{ + /* + * The object layout of untyped and typed capabilities is identical. + * Hence we can just use it's copy-constructors. + */ + Untyped_capability *ptr = const_cast(&untyped_cap); + return *static_cast*>(ptr); +} + + +/** + * Convert capability type from an interface base type to an inherited + * interface type + */ +template +Genode::Capability +Genode::static_cap_cast(Capability cap) +{ + /* check interface compatibility */ + (void)static_cast((FROM_RPC_INTERFACE *)0); + + return reinterpret_cap_cast(cap); } #endif /* _INCLUDE__BASE__CAPABILITY_H_ */ diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index d0eba447f..70909d1f3 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -24,308 +24,312 @@ namespace Genode { - /** - * Child policy interface - * - * A child-policy object is an argument to a 'Child'. It is responsible for - * taking policy decisions regarding the parent interface. Most importantly, - * it defines how session requests are resolved and how session arguments - * are passed to servers when creating sessions. - */ - struct Child_policy - { - virtual ~Child_policy() { } - - /** - * Return process name of the child - */ - virtual const char *name() const = 0; - - /** - * Determine service to provide a session request - * - * \return Service to be contacted for the new session, or - * 0 if session request could not be resolved - */ - virtual Service *resolve_session_request(const char * /*service_name*/, - const char * /*args*/) - { return 0; } - - /** - * Apply transformations to session arguments - */ - virtual void filter_session_args(const char * /*service*/, - char * /*args*/, size_t /*args_len*/) { } - - /** - * Register a service provided by the child - * - * \param name service name - * \param root interface for creating sessions for the service - * \param alloc allocator to be used for child-specific - * meta-data allocations - * \return true if announcement succeeded, or false if - * child is not permitted to announce service - */ - virtual bool announce_service(const char * /*name*/, - Root_capability /*root*/, - Allocator * /*alloc*/, - Server * /*server*/) - { return false; } - - /** - * Apply session affinity policy - * - * \param affinity affinity passed along with a session request - * \return affinity subordinated to the child policy - */ - virtual Affinity filter_session_affinity(Affinity const &affinity) - { - return affinity; - } - - /** - * Unregister services that had been provided by the child - */ - virtual void unregister_services() { } - - /** - * Exit child - */ - virtual void exit(int exit_value) - { - PDBG("child \"%s\" exited with exit value %d", name(), exit_value); - } - - /** - * Reference RAM session - * - * The RAM session returned by this function is used for session-quota - * transfers. - */ - virtual Ram_session *ref_ram_session() { return env()->ram_session(); } - - /** - * Return platform-specific PD-session arguments - * - * This function is used on Linux to supply additional PD-session - * argument to core, i.e., the chroot path, the UID, and the GID. - */ - virtual Native_pd_args const *pd_args() const { return 0; } - - /** - * Respond to the release of resources by the child - * - * This function is called when the child confirms the release of - * resources in response to a yield request. - */ - virtual void yield_response() { } - - /** - * Take action on additional resource needs by the child - */ - virtual void resource_request(Parent::Resource_args const &) { } - }; - - - /** - * Implementation of the parent interface that supports resource trading - * - * There are three possible cases of how a session can be provided to - * a child: - * - * # The service is implemented locally - * # The session was obtained by asking our parent - * # The session is provided by one of our children - * - * These types must be differentiated for the quota management when a child - * issues the closing of a session or a transfers quota via our parent - * interface. - * - * If we close a session to a local service, we transfer the session quota - * from our own account to the client. - * - * If we close a parent session, we receive the session quota on our own - * account and must transfer this amount to the session-closing child. - * - * If we close a session provided by a server child, we close the session - * at the server, transfer the session quota from the server's ram session - * to our account, and subsequently transfer the same amount from our - * account to the client. - */ - class Child : protected Rpc_object - { - private: - - class Session; - - /* RAM session that contains the quota of the child */ - Ram_session_capability _ram; - Ram_session_client _ram_session_client; - - /* CPU session that contains the quota of the child */ - Cpu_session_capability _cpu; - - /* RM session representing the address space of the child */ - Rm_session_capability _rm; - - /* Services where the RAM, CPU, and RM resources come from */ - Service &_ram_service; - Service &_cpu_service; - Service &_rm_service; - - /* heap for child-specific allocations using the child's quota */ - Heap _heap; - - Rpc_entrypoint *_entrypoint; - Parent_capability _parent_cap; - - /* child policy */ - Child_policy *_policy; - - /* sessions opened by the child */ - Lock _lock; /* protect list manipulation */ - Object_pool _session_pool; - List _session_list; - - /* server role */ - Server _server; - - /* session-argument buffer */ - char _args[Parent::Session_args::MAX_SIZE]; - - /* signal handlers registered by the child */ - Signal_context_capability _resource_avail_sigh; - Signal_context_capability _yield_sigh; - - /* arguments fetched by the child in response to a yield signal */ - Lock _yield_request_lock; - Resource_args _yield_request_args; - - Process _process; - - /** - * Attach session information to a child - * - * \throw Ram_session::Quota_exceeded the child's heap partition cannot - * hold the session meta data - */ - void _add_session(const Session &s); - - /** - * Close session and revert quota donation associated with it - */ - void _remove_session(Session *s); - - /** - * Return service interface targetting the parent - * - * The service returned by this function is used as default - * provider for the RAM, CPU, and RM resources of the child. It is - * solely used for targeting resource donations during - * 'Parent::upgrade_quota()' calls. - */ - static Service *_parent_service(); - - public: - - /** - * Constructor - * - * \param elf_ds dataspace containing the binary - * \param ram RAM session with the child's quota - * \param cpu CPU session with the child's quota - * \param rm RM session representing the address space - * of the child - * \param entrypoint server entrypoint to serve the parent interface - * \param policy child policy - * \param ram_service provider of the 'ram' session - * \param cpu_service provider of the 'cpu' session - * \param rm_service provider of the 'rm' session - * - * If assigning a separate entry point to each child, the host of - * multiple children is able to handle a blocking invocation of - * the parent interface of one child while still maintaining the - * service to other children, each having an independent entry - * point. - * - * The 'ram_service', 'cpu_service', and 'rm_service' arguments are - * needed to direct quota upgrades referring to the resources of - * the child environment. By default, we expect that these - * resources are provided by the parent. - */ - Child(Dataspace_capability elf_ds, - Ram_session_capability ram, - Cpu_session_capability cpu, - Rm_session_capability rm, - Rpc_entrypoint *entrypoint, - Child_policy *policy, - Service &ram_service = *_parent_service(), - Service &cpu_service = *_parent_service(), - Service &rm_service = *_parent_service()); - - /** - * Destructor - * - * On destruction of a child, we close all sessions of the child to - * other services. - */ - virtual ~Child(); - - /** - * Return heap that uses the child's quota - */ - Allocator *heap() { return &_heap; } - - Ram_session_capability ram_session_cap() const { return _ram; } - Cpu_session_capability cpu_session_cap() const { return _cpu; } - Rm_session_capability rm_session_cap() const { return _rm; } - Parent_capability parent_cap() const { return cap(); } - - /** - * Discard all sessions to specified service - * - * When this function is called, we assume the server protection - * domain to be dead and all that all server quota was already - * transferred back to our own 'env()->ram_session()' account. Note - * that the specified server object may not exist anymore. We do - * not de-reference the server argument in here! - */ - void revoke_server(const Server *server); - - /** - * Instruct the child to yield resources - * - * By calling this function, the child will be notified about the - * need to release the specified amount of resources. For more - * details about the protocol between a child and its parent, - * refer to the description given in 'parent/parent.h'. - */ - void yield(Resource_args const &args); - - /** - * Notify the child about newly available resources - */ - void notify_resource_avail() const; - - - /********************** - ** Parent interface ** - **********************/ - - void announce(Service_name const &, Root_capability); - Session_capability session(Service_name const &, Session_args const &, - Affinity const &); - void upgrade(Session_capability, Upgrade_args const &); - void close(Session_capability); - void exit(int); - Thread_capability main_thread_cap() const; - void resource_avail_sigh(Signal_context_capability); - void resource_request(Resource_args const &); - void yield_sigh(Signal_context_capability); - Resource_args yield_request(); - void yield_response(); - }; + struct Child_policy; + struct Child; } + +/** + * Child policy interface + * + * A child-policy object is an argument to a 'Child'. It is responsible for + * taking policy decisions regarding the parent interface. Most importantly, + * it defines how session requests are resolved and how session arguments + * are passed to servers when creating sessions. + */ +struct Genode::Child_policy +{ + virtual ~Child_policy() { } + + /** + * Return process name of the child + */ + virtual const char *name() const = 0; + + /** + * Determine service to provide a session request + * + * \return Service to be contacted for the new session, or + * 0 if session request could not be resolved + */ + virtual Service *resolve_session_request(const char * /*service_name*/, + const char * /*args*/) + { return 0; } + + /** + * Apply transformations to session arguments + */ + virtual void filter_session_args(const char * /*service*/, + char * /*args*/, size_t /*args_len*/) { } + + /** + * Register a service provided by the child + * + * \param name service name + * \param root interface for creating sessions for the service + * \param alloc allocator to be used for child-specific + * meta-data allocations + * \return true if announcement succeeded, or false if + * child is not permitted to announce service + */ + virtual bool announce_service(const char * /*name*/, + Root_capability /*root*/, + Allocator * /*alloc*/, + Server * /*server*/) + { return false; } + + /** + * Apply session affinity policy + * + * \param affinity affinity passed along with a session request + * \return affinity subordinated to the child policy + */ + virtual Affinity filter_session_affinity(Affinity const &affinity) + { + return affinity; + } + + /** + * Unregister services that had been provided by the child + */ + virtual void unregister_services() { } + + /** + * Exit child + */ + virtual void exit(int exit_value) + { + PDBG("child \"%s\" exited with exit value %d", name(), exit_value); + } + + /** + * Reference RAM session + * + * The RAM session returned by this function is used for session-quota + * transfers. + */ + virtual Ram_session *ref_ram_session() { return env()->ram_session(); } + + /** + * Return platform-specific PD-session arguments + * + * This function is used on Linux to supply additional PD-session + * argument to core, i.e., the chroot path, the UID, and the GID. + */ + virtual Native_pd_args const *pd_args() const { return 0; } + + /** + * Respond to the release of resources by the child + * + * This function is called when the child confirms the release of + * resources in response to a yield request. + */ + virtual void yield_response() { } + + /** + * Take action on additional resource needs by the child + */ + virtual void resource_request(Parent::Resource_args const &) { } +}; + + +/** + * Implementation of the parent interface that supports resource trading + * + * There are three possible cases of how a session can be provided to + * a child: + * + * # The service is implemented locally + * # The session was obtained by asking our parent + * # The session is provided by one of our children + * + * These types must be differentiated for the quota management when a child + * issues the closing of a session or a transfers quota via our parent + * interface. + * + * If we close a session to a local service, we transfer the session quota + * from our own account to the client. + * + * If we close a parent session, we receive the session quota on our own + * account and must transfer this amount to the session-closing child. + * + * If we close a session provided by a server child, we close the session + * at the server, transfer the session quota from the server's ram session + * to our account, and subsequently transfer the same amount from our + * account to the client. + */ +class Genode::Child : protected Rpc_object +{ + private: + + class Session; + + /* RAM session that contains the quota of the child */ + Ram_session_capability _ram; + Ram_session_client _ram_session_client; + + /* CPU session that contains the quota of the child */ + Cpu_session_capability _cpu; + + /* RM session representing the address space of the child */ + Rm_session_capability _rm; + + /* Services where the RAM, CPU, and RM resources come from */ + Service &_ram_service; + Service &_cpu_service; + Service &_rm_service; + + /* heap for child-specific allocations using the child's quota */ + Heap _heap; + + Rpc_entrypoint *_entrypoint; + Parent_capability _parent_cap; + + /* child policy */ + Child_policy *_policy; + + /* sessions opened by the child */ + Lock _lock; /* protect list manipulation */ + Object_pool _session_pool; + List _session_list; + + /* server role */ + Server _server; + + /* session-argument buffer */ + char _args[Parent::Session_args::MAX_SIZE]; + + /* signal handlers registered by the child */ + Signal_context_capability _resource_avail_sigh; + Signal_context_capability _yield_sigh; + + /* arguments fetched by the child in response to a yield signal */ + Lock _yield_request_lock; + Resource_args _yield_request_args; + + Process _process; + + /** + * Attach session information to a child + * + * \throw Ram_session::Quota_exceeded the child's heap partition cannot + * hold the session meta data + */ + void _add_session(const Session &s); + + /** + * Close session and revert quota donation associated with it + */ + void _remove_session(Session *s); + + /** + * Return service interface targetting the parent + * + * The service returned by this function is used as default + * provider for the RAM, CPU, and RM resources of the child. It is + * solely used for targeting resource donations during + * 'Parent::upgrade_quota()' calls. + */ + static Service *_parent_service(); + + public: + + /** + * Constructor + * + * \param elf_ds dataspace containing the binary + * \param ram RAM session with the child's quota + * \param cpu CPU session with the child's quota + * \param rm RM session representing the address space + * of the child + * \param entrypoint server entrypoint to serve the parent interface + * \param policy child policy + * \param ram_service provider of the 'ram' session + * \param cpu_service provider of the 'cpu' session + * \param rm_service provider of the 'rm' session + * + * If assigning a separate entry point to each child, the host of + * multiple children is able to handle a blocking invocation of + * the parent interface of one child while still maintaining the + * service to other children, each having an independent entry + * point. + * + * The 'ram_service', 'cpu_service', and 'rm_service' arguments are + * needed to direct quota upgrades referring to the resources of + * the child environment. By default, we expect that these + * resources are provided by the parent. + */ + Child(Dataspace_capability elf_ds, + Ram_session_capability ram, + Cpu_session_capability cpu, + Rm_session_capability rm, + Rpc_entrypoint *entrypoint, + Child_policy *policy, + Service &ram_service = *_parent_service(), + Service &cpu_service = *_parent_service(), + Service &rm_service = *_parent_service()); + + /** + * Destructor + * + * On destruction of a child, we close all sessions of the child to + * other services. + */ + virtual ~Child(); + + /** + * Return heap that uses the child's quota + */ + Allocator *heap() { return &_heap; } + + Ram_session_capability ram_session_cap() const { return _ram; } + Cpu_session_capability cpu_session_cap() const { return _cpu; } + Rm_session_capability rm_session_cap() const { return _rm; } + Parent_capability parent_cap() const { return cap(); } + + /** + * Discard all sessions to specified service + * + * When this function is called, we assume the server protection + * domain to be dead and all that all server quota was already + * transferred back to our own 'env()->ram_session()' account. Note + * that the specified server object may not exist anymore. We do + * not de-reference the server argument in here! + */ + void revoke_server(const Server *server); + + /** + * Instruct the child to yield resources + * + * By calling this function, the child will be notified about the + * need to release the specified amount of resources. For more + * details about the protocol between a child and its parent, + * refer to the description given in 'parent/parent.h'. + */ + void yield(Resource_args const &args); + + /** + * Notify the child about newly available resources + */ + void notify_resource_avail() const; + + + /********************** + ** Parent interface ** + **********************/ + + void announce(Service_name const &, Root_capability) override; + Session_capability session(Service_name const &, Session_args const &, + Affinity const &) override; + void upgrade(Session_capability, Upgrade_args const &) override; + void close(Session_capability) override; + void exit(int) override; + Thread_capability main_thread_cap() const override; + void resource_avail_sigh(Signal_context_capability) override; + void resource_request(Resource_args const &) override; + void yield_sigh(Signal_context_capability) override; + Resource_args yield_request() override; + void yield_response() override; +}; + #endif /* _INCLUDE__BASE__CHILD_H_ */ diff --git a/repos/base/include/base/connection.h b/repos/base/include/base/connection.h index 80c501bb5..cdc720988 100644 --- a/repos/base/include/base/connection.h +++ b/repos/base/include/base/connection.h @@ -17,99 +17,99 @@ #include #include -namespace Genode { +namespace Genode { template class Connection; } - /** - * Representation of an open connection to a service - */ - template - class Connection : public Noncopyable - { - public: - enum On_destruction { CLOSE = false, KEEP_OPEN = true }; +/** + * Representation of an open connection to a service + */ +template +class Genode::Connection : public Noncopyable +{ + public: - private: + enum On_destruction { CLOSE = false, KEEP_OPEN = true }; - /* - * Because the argument string is used with the parent interface, - * the message-buffer size of the parent-interface provides a - * realistic upper bound for dimensioning the format- string - * buffer. - */ - enum { FORMAT_STRING_SIZE = Parent::Session_args::MAX_SIZE }; + private: - Capability _cap; + /* + * Because the argument string is used with the parent interface, + * the message-buffer size of the parent-interface provides a + * realistic upper bound for dimensioning the format- string + * buffer. + */ + enum { FORMAT_STRING_SIZE = Parent::Session_args::MAX_SIZE }; - On_destruction _on_destruction; + Capability _cap; - Capability _session(Affinity const &affinity, - const char *format_args, va_list list) - { - char buf[FORMAT_STRING_SIZE]; + On_destruction _on_destruction; - String_console sc(buf, FORMAT_STRING_SIZE); - sc.vprintf(format_args, list); + Capability _session(Affinity const &affinity, + const char *format_args, va_list list) + { + char buf[FORMAT_STRING_SIZE]; - va_end(list); + String_console sc(buf, FORMAT_STRING_SIZE); + sc.vprintf(format_args, list); - /* call parent interface with the resulting argument buffer */ - return env()->parent()->session(buf, affinity); - } + va_end(list); - public: + /* call parent interface with the resulting argument buffer */ + return env()->parent()->session(buf, affinity); + } - /** - * Constructor - * - * \param cap session capability - * \param od session policy applied when destructing the connection - */ - Connection(Capability cap, On_destruction od = CLOSE): - _cap(cap), _on_destruction(od) { } + public: - /** - * Destructor - */ - ~Connection() - { - if (_on_destruction == CLOSE) - env()->parent()->close(_cap); - } + /** + * Constructor + * + * \param cap session capability + * \param od session policy applied when destructing the connection + */ + Connection(Capability cap, On_destruction od = CLOSE): + _cap(cap), _on_destruction(od) { } - /** - * Return session capability - */ - Capability cap() const { return _cap; } + /** + * Destructor + */ + ~Connection() + { + if (_on_destruction == CLOSE) + env()->parent()->close(_cap); + } - /** - * Define session policy - */ - void on_destruction(On_destruction od) { _on_destruction = od; } + /** + * Return session capability + */ + Capability cap() const { return _cap; } - /** - * Shortcut for env()->parent()->session() - */ - Capability session(const char *format_args, ...) - { - va_list list; - va_start(list, format_args); + /** + * Define session policy + */ + void on_destruction(On_destruction od) { _on_destruction = od; } - return _session(Affinity(), format_args, list); - } + /** + * Shortcut for env()->parent()->session() + */ + Capability session(const char *format_args, ...) + { + va_list list; + va_start(list, format_args); - /** - * Shortcut for env()->parent()->session() - */ - Capability session(Affinity const &affinity, - char const *format_args, ...) - { - va_list list; - va_start(list, format_args); + return _session(Affinity(), format_args, list); + } - return _session(affinity, format_args, list); - } - }; -} + /** + * Shortcut for env()->parent()->session() + */ + Capability session(Affinity const &affinity, + char const *format_args, ...) + { + va_list list; + va_start(list, format_args); + + return _session(affinity, format_args, list); + } +}; #endif /* _INCLUDE__BASE__CONNECTION_H_ */ diff --git a/repos/base/include/base/console.h b/repos/base/include/base/console.h index f916c7d5d..51d0fe7fc 100644 --- a/repos/base/include/base/console.h +++ b/repos/base/include/base/console.h @@ -16,45 +16,45 @@ #include -namespace Genode { +namespace Genode { class Console; } - class Console - { - public: - virtual ~Console() {} +class Genode::Console +{ + public: - /** - * Print format string - */ - void printf(const char *format, ...) __attribute__((format(printf, 2, 3))); - void vprintf(const char *format, va_list) __attribute__((format(printf, 2, 0))); + virtual ~Console() {} - protected: + /** + * Print format string + */ + void printf(const char *format, ...) __attribute__((format(printf, 2, 3))); + void vprintf(const char *format, va_list) __attribute__((format(printf, 2, 0))); - /** - * Backend function for the output of one character - */ - virtual void _out_char(char c) = 0; + protected: - /** - * Backend function for the output of a null-terminated string - * - * The default implementation uses _out_char. This function may - * be overridden by the backend for improving efficiency. - * - * This function is virtual to enable the use an optimized - * string-output functions on some target platforms, e.g. - * a kernel debugger that offers a string-output syscall. The - * default implementation calls '_out_char' for each character. - */ - virtual void _out_string(const char *str); + /** + * Backend function for the output of one character + */ + virtual void _out_char(char c) = 0; - private: + /** + * Backend function for the output of a null-terminated string + * + * The default implementation uses _out_char. This function may + * be overridden by the backend for improving efficiency. + * + * This function is virtual to enable the use an optimized + * string-output functions on some target platforms, e.g. + * a kernel debugger that offers a string-output syscall. The + * default implementation calls '_out_char' for each character. + */ + virtual void _out_string(const char *str); - template void _out_unsigned(T value, unsigned base = 10, int pad = 0); - template void _out_signed(T value, unsigned base = 10); - }; -} + private: + + template void _out_unsigned(T value, unsigned base = 10, int pad = 0); + template void _out_signed(T value, unsigned base = 10); +}; #endif /* _INCLUDE__BASE__CONSOLE_H_ */ diff --git a/repos/base/include/base/elf.h b/repos/base/include/base/elf.h index fa138f421..e7585000e 100644 --- a/repos/base/include/base/elf.h +++ b/repos/base/include/base/elf.h @@ -19,139 +19,141 @@ namespace Genode { class Elf_segment; - - class Elf_binary - { - public: - - /** - * Default constructor creates invalid object - */ - Elf_binary() : _valid(false) { } - - /** - * Constructor - * - * The object is only useful if valid() returns true. - */ - explicit Elf_binary(addr_t start); - - /* special types */ - - struct Flags { - unsigned r:1; - unsigned w:1; - unsigned x:1; - unsigned skip:1; - }; - - /** - * Read information about program segments - * - * \return properties of the specified program segment - */ - Elf_segment get_segment(unsigned num); - - /** - * Check validity - */ - bool valid() { return _valid; } - - /** - * Check for dynamic elf - */ - bool is_dynamically_linked() { return (_dynamic && _interp); } - - - /************************ - ** Accessor functions ** - ************************/ - - addr_t entry() { return valid() ? _entry : 0; } - - private: - - /* validity indicator indicates if the loaded ELF is valid and supported */ - bool _valid; - - /* dynamically linked */ - bool _dynamic; - - /* dynamic linker name matches 'genode' */ - bool _interp; - - /* ELF start pointer in memory */ - addr_t _start; - - /* ELF entry point */ - addr_t _entry; - - /* program segments */ - addr_t _ph_table; - size_t _phentsize; - unsigned _phnum; - - - /************ - ** Helper ** - ************/ - - /** - * Check ELF header compatibility - */ - int _ehdr_check_compat(); - - /** - * Check program header compatibility - */ - int _ph_table_check_compat(); - - /** - * Check for dynamic program segments - */ - bool _dynamic_check_compat(unsigned type); - }; - - - class Elf_segment - { - public: - - /** - * Standard constructor creates invalid object - */ - Elf_segment() : _valid(false) { } - - Elf_segment(const Elf_binary *elf, void *start, size_t file_offset, - size_t file_size, size_t mem_size, Elf_binary::Flags flags) - : _elf(elf), _start((unsigned char *)start), _file_offset(file_offset), - _file_size(file_size), _mem_size(mem_size), _flags(flags) - { - _valid = elf ? true : false; - } - - const Elf_binary * elf() { return _elf; } - void * start() { return (void *)_start; } - size_t file_offset() { return _file_offset; } - size_t file_size() { return _file_size; } - size_t mem_size() { return _mem_size; } - Elf_binary::Flags flags() { return _flags; } - - /** - * Check validity - */ - bool valid() { return _valid; } - - private: - - const Elf_binary *_elf; - bool _valid; /* validity indicator */ - unsigned char *_start; - size_t _file_offset; - size_t _file_size; - size_t _mem_size; - Elf_binary::Flags _flags; - }; + class Elf_binary; } + +class Genode::Elf_binary +{ + public: + + /** + * Default constructor creates invalid object + */ + Elf_binary() : _valid(false) { } + + /** + * Constructor + * + * The object is only useful if valid() returns true. + */ + explicit Elf_binary(addr_t start); + + /* special types */ + + struct Flags { + unsigned r:1; + unsigned w:1; + unsigned x:1; + unsigned skip:1; + }; + + /** + * Read information about program segments + * + * \return properties of the specified program segment + */ + Elf_segment get_segment(unsigned num); + + /** + * Check validity + */ + bool valid() { return _valid; } + + /** + * Check for dynamic elf + */ + bool is_dynamically_linked() { return (_dynamic && _interp); } + + + /************************ + ** Accessor functions ** + ************************/ + + addr_t entry() { return valid() ? _entry : 0; } + + private: + + /* validity indicator indicates if the loaded ELF is valid and supported */ + bool _valid; + + /* dynamically linked */ + bool _dynamic; + + /* dynamic linker name matches 'genode' */ + bool _interp; + + /* ELF start pointer in memory */ + addr_t _start; + + /* ELF entry point */ + addr_t _entry; + + /* program segments */ + addr_t _ph_table; + size_t _phentsize; + unsigned _phnum; + + + /************ + ** Helper ** + ************/ + + /** + * Check ELF header compatibility + */ + int _ehdr_check_compat(); + + /** + * Check program header compatibility + */ + int _ph_table_check_compat(); + + /** + * Check for dynamic program segments + */ + bool _dynamic_check_compat(unsigned type); +}; + + +class Genode::Elf_segment +{ + public: + + /** + * Standard constructor creates invalid object + */ + Elf_segment() : _valid(false) { } + + Elf_segment(const Elf_binary *elf, void *start, size_t file_offset, + size_t file_size, size_t mem_size, Elf_binary::Flags flags) + : _elf(elf), _start((unsigned char *)start), _file_offset(file_offset), + _file_size(file_size), _mem_size(mem_size), _flags(flags) + { + _valid = elf ? true : false; + } + + const Elf_binary * elf() { return _elf; } + void * start() { return (void *)_start; } + size_t file_offset() { return _file_offset; } + size_t file_size() { return _file_size; } + size_t mem_size() { return _mem_size; } + Elf_binary::Flags flags() { return _flags; } + + /** + * Check validity + */ + bool valid() { return _valid; } + + private: + + const Elf_binary *_elf; + bool _valid; /* validity indicator */ + unsigned char *_start; + size_t _file_offset; + size_t _file_size; + size_t _mem_size; + Elf_binary::Flags _flags; +}; + #endif /* _INCLUDE__BASE__ELF_H_ */ diff --git a/repos/base/include/base/env.h b/repos/base/include/base/env.h index 733550ade..7ef86abd5 100644 --- a/repos/base/include/base/env.h +++ b/repos/base/include/base/env.h @@ -30,53 +30,10 @@ namespace Genode { - class Env - { - public: - - virtual ~Env() { } - - /** - * Communication channel to our parent - */ - virtual Parent *parent() = 0; - - /** - * RAM session for the program - * - * The RAM Session represents a quota of memory that is - * available to the program. Quota can be used to allocate - * RAM-Dataspaces. - */ - virtual Ram_session *ram_session() = 0; - virtual Ram_session_capability ram_session_cap() = 0; - - /** - * CPU session for the program - * - * This session is used to create threads. - */ - virtual Cpu_session *cpu_session() = 0; - virtual Cpu_session_capability cpu_session_cap() = 0; - - /** - * Region manager session of the program - */ - virtual Rm_session *rm_session() = 0; - - /** - * Pd session of the program - */ - virtual Pd_session *pd_session() = 0; - - /** - * Heap backed by the ram_session of the environment. - */ - virtual Allocator *heap() = 0; - }; + struct Env; extern Env *env(); - + /** * Return parent capability * @@ -86,4 +43,50 @@ namespace Genode { Parent_capability parent_cap(); } + +struct Genode::Env +{ + virtual ~Env() { } + + /** + * Communication channel to our parent + */ + virtual Parent *parent() = 0; + + /** + * RAM session for the program + * + * The RAM Session represents a quota of memory that is + * available to the program. Quota can be used to allocate + * RAM-Dataspaces. + */ + virtual Ram_session *ram_session() = 0; + virtual Ram_session_capability ram_session_cap() = 0; + + /** + * CPU session for the program + * + * This session is used to create threads. + */ + virtual Cpu_session *cpu_session() = 0; + virtual Cpu_session_capability cpu_session_cap() = 0; + + /** + * Region manager session of the program + */ + virtual Rm_session *rm_session() = 0; + + /** + * Pd session of the program + */ + virtual Pd_session *pd_session() = 0; + + /** + * Heap backed by the ram_session of the environment. + */ + virtual Allocator *heap() = 0; +}; + + + #endif /* _INCLUDE__BASE__ENV_H_ */ diff --git a/repos/base/include/base/exception.h b/repos/base/include/base/exception.h index f2897fa46..a946efaea 100644 --- a/repos/base/include/base/exception.h +++ b/repos/base/include/base/exception.h @@ -14,6 +14,8 @@ #ifndef _INCLUDE__BASE__EXCEPTION_H_ #define _INCLUDE__BASE__EXCEPTION_H_ -namespace Genode { class Exception { }; } +namespace Genode { class Exception; } + +class Genode::Exception { }; #endif /* _INCLUDE__BASE__EXCEPTION_H_ */ diff --git a/repos/base/include/base/flex_iterator.h b/repos/base/include/base/flex_iterator.h index 339e16390..1db114eb6 100644 --- a/repos/base/include/base/flex_iterator.h +++ b/repos/base/include/base/flex_iterator.h @@ -19,95 +19,98 @@ namespace Genode { - class Flexpage - { - public: - - addr_t addr; - addr_t hotspot; - size_t log2_order; - - Flexpage() : addr(~0UL), hotspot(0), log2_order(0) { } - - Flexpage(addr_t a, addr_t h, size_t o) - : addr(a), hotspot(h), log2_order(o) { } - - bool valid() { return addr != ~0UL; } - }; - - - class Flexpage_iterator { - - private: - - addr_t _src_start, _src_size; - addr_t _dst_start, _dst_size; - addr_t _hotspot, _offset; - - /** - * Find least significant set bit in value - */ - inline addr_t - lsb_bit(addr_t const scan) - { - if (scan == 0) - return ~0UL; - return __builtin_ctzl(scan); - } - - public: - - Flexpage_iterator() { } - - Flexpage_iterator(addr_t src_start, size_t src_size, - addr_t dst_start, size_t dst_size, - addr_t hotspot) : - _src_start(src_start), _src_size(src_size), - _dst_start(dst_start), _dst_size(dst_size), - _hotspot(hotspot), _offset(0) - { } - - Flexpage page() - { - size_t const size = min (_src_size, _dst_size); - - addr_t const from_end = _src_start + size; - addr_t const to_end = _dst_start + size; - - if (_offset >= size) - return Flexpage(); - - addr_t const from_curr = _src_start + _offset; - addr_t const to_curr = _dst_start + _offset; - - /* - * The common alignment corresponds to the number of least - * significant zero bits in both addresses. - */ - addr_t const common_bits = from_curr | to_curr; - - /* find least set bit in common bits */ - size_t order = lsb_bit(common_bits); - size_t max = (order == ~0UL) ? ~0UL : (1UL << order); - - /* look if it still fits into both 'src' and 'dst' ranges */ - if ((from_end - from_curr) < max) { - order = log2(from_end - from_curr); - order = (order == ~0UL) ? 12 : order; - max = 1UL << order; - } - - if ((to_end - to_curr) < max) { - order = log2(to_end - to_curr); - order = (order == ~0UL) ? 12 : order; - } - - /* advance offset by current flexpage size */ - _offset += (1UL << order); - - return Flexpage(from_curr, _hotspot + _offset - (1UL << order), order); - } - }; - + struct Flexpage; + class Flexpage_iterator; } + + +struct Genode::Flexpage +{ + addr_t addr; + addr_t hotspot; + size_t log2_order; + + Flexpage() : addr(~0UL), hotspot(0), log2_order(0) { } + + Flexpage(addr_t a, addr_t h, size_t o) + : addr(a), hotspot(h), log2_order(o) { } + + bool valid() { return addr != ~0UL; } +}; + + +class Genode::Flexpage_iterator +{ + private: + + addr_t _src_start, _src_size; + addr_t _dst_start, _dst_size; + addr_t _hotspot, _offset; + + /** + * Find least significant set bit in value + */ + inline addr_t + lsb_bit(addr_t const scan) + { + if (scan == 0) + return ~0UL; + return __builtin_ctzl(scan); + } + + public: + + Flexpage_iterator() { } + + Flexpage_iterator(addr_t src_start, size_t src_size, + addr_t dst_start, size_t dst_size, + addr_t hotspot) + : + _src_start(src_start), _src_size(src_size), + _dst_start(dst_start), _dst_size(dst_size), + _hotspot(hotspot), _offset(0) + { } + + Flexpage page() + { + size_t const size = min (_src_size, _dst_size); + + addr_t const from_end = _src_start + size; + addr_t const to_end = _dst_start + size; + + if (_offset >= size) + return Flexpage(); + + addr_t const from_curr = _src_start + _offset; + addr_t const to_curr = _dst_start + _offset; + + /* + * The common alignment corresponds to the number of least + * significant zero bits in both addresses. + */ + addr_t const common_bits = from_curr | to_curr; + + /* find least set bit in common bits */ + size_t order = lsb_bit(common_bits); + size_t max = (order == ~0UL) ? ~0UL : (1UL << order); + + /* look if it still fits into both 'src' and 'dst' ranges */ + if ((from_end - from_curr) < max) { + order = log2(from_end - from_curr); + order = (order == ~0UL) ? 12 : order; + max = 1UL << order; + } + + if ((to_end - to_curr) < max) { + order = log2(to_end - to_curr); + order = (order == ~0UL) ? 12 : order; + } + + /* advance offset by current flexpage size */ + _offset += (1UL << order); + + return Flexpage(from_curr, _hotspot + _offset - (1UL << order), order); + } +}; + #endif /* _INCLUDE__BASE__FLEX_ITERATOR_H */ diff --git a/repos/base/include/base/heap.h b/repos/base/include/base/heap.h index 875fbe65b..9ec53262a 100644 --- a/repos/base/include/base/heap.h +++ b/repos/base/include/base/heap.h @@ -21,194 +21,198 @@ #include namespace Genode { + + class Heap; + class Sliced_heap; +} - /** - * Heap that uses dataspaces as backing store - * - * The heap class provides an allocator that uses a list of dataspaces of a ram - * session as backing store. One dataspace may be used for holding multiple blocks. - */ - class Heap : public Allocator - { - private: - enum { - MIN_CHUNK_SIZE = 4*1024, /* in machine words */ - MAX_CHUNK_SIZE = 256*1024, - /* - * Meta data includes the Dataspace structure and meta data of - * the AVL allocator. - */ - META_DATA_SIZE = 1024, /* in bytes */ - /* - * Allocation sizes >= this value are considered as big - * allocations, which get their own dataspace. In contrast - * to smaller allocations, this memory is released to - * the RAM session when 'free()' is called. - */ - BIG_ALLOCATION_THRESHOLD = 64*1024 /* in bytes */ - }; - - class Dataspace : public List::Element - { - public: - - Ram_dataspace_capability cap; - void *local_addr; - size_t size; - - Dataspace(Ram_dataspace_capability c, void *local_addr, size_t size) - : cap(c), local_addr(local_addr), size(size) { } - - inline void * operator new(Genode::size_t, void* addr) { - return addr; } - inline void operator delete(void*) { } - }; +/** + * Heap that uses dataspaces as backing store + * + * The heap class provides an allocator that uses a list of dataspaces of a ram + * session as backing store. One dataspace may be used for holding multiple blocks. + */ +class Genode::Heap : public Allocator +{ + private: + enum { + MIN_CHUNK_SIZE = 4*1024, /* in machine words */ + MAX_CHUNK_SIZE = 256*1024, /* - * This structure exists only to make sure that the dataspaces are - * destroyed after the AVL allocator. + * Meta data includes the Dataspace structure and meta data of + * the AVL allocator. */ - struct Dataspace_pool : public List - { - Ram_session *ram_session; /* ram session for backing store */ - Rm_session *rm_session; /* region manager */ - - Dataspace_pool(Ram_session *ram_session, Rm_session *rm_session) - : ram_session(ram_session), rm_session(rm_session) { } - - /** - * Destructor - */ - ~Dataspace_pool(); - - void reassign_resources(Ram_session *ram, Rm_session *rm) { - ram_session = ram, rm_session = rm; } - }; - + META_DATA_SIZE = 1024, /* in bytes */ /* - * NOTE: The order of the member variables is important for - * the calling order of the destructors! + * Allocation sizes >= this value are considered as big + * allocations, which get their own dataspace. In contrast + * to smaller allocations, this memory is released to + * the RAM session when 'free()' is called. */ + BIG_ALLOCATION_THRESHOLD = 64*1024 /* in bytes */ + }; - Lock _lock; - Dataspace_pool _ds_pool; /* list of dataspaces */ - Allocator_avl _alloc; /* local allocator */ - size_t _quota_limit; - size_t _quota_used; - size_t _chunk_size; + class Dataspace : public List::Element + { + public: - /** - * Allocate a new dataspace of the specified size - * - * \param size number of bytes to allocate - * \param enforce_separate_metadata if true, the new dataspace - * will not contain any meta data - * \throw Rm_session::Invalid_dataspace, - * Rm_session::Region_conflict - * \return 0 on success or negative error code - */ - Heap::Dataspace *_allocate_dataspace(size_t size, bool enforce_separate_metadata); + Ram_dataspace_capability cap; + void *local_addr; + size_t size; - /** - * Try to allocate block at our local allocator - * - * \return true on success - * - * This function is a utility used by '_unsynchronized_alloc' to - * avoid code duplication. - */ - bool _try_local_alloc(size_t size, void **out_addr); + Dataspace(Ram_dataspace_capability c, void *local_addr, size_t size) + : cap(c), local_addr(local_addr), size(size) { } - /** - * Unsynchronized implementation of 'alloc' - */ - bool _unsynchronized_alloc(size_t size, void **out_addr); + inline void * operator new(Genode::size_t, void* addr) { + return addr; } + inline void operator delete(void*) { } + }; - public: + /* + * This structure exists only to make sure that the dataspaces are + * destroyed after the AVL allocator. + */ + struct Dataspace_pool : public List + { + Ram_session *ram_session; /* ram session for backing store */ + Rm_session *rm_session; /* region manager */ - enum { UNLIMITED = ~0 }; - - Heap(Ram_session *ram_session, - Rm_session *rm_session, - size_t quota_limit = UNLIMITED, - void *static_addr = 0, - size_t static_size = 0) - : - _ds_pool(ram_session, rm_session), - _alloc(0), - _quota_limit(quota_limit), _quota_used(0), - _chunk_size(MIN_CHUNK_SIZE) - { - if (static_addr) - _alloc.add_range((addr_t)static_addr, static_size); - } - - /** - * Reconfigure quota limit - * - * \return negative error code if new quota limit is higher than - * currently used quota. - */ - int quota_limit(size_t new_quota_limit); - - /** - * Re-assign RAM and RM sessions - */ - void reassign_resources(Ram_session *ram, Rm_session *rm) { - _ds_pool.reassign_resources(ram, rm); } - - - /************************* - ** Allocator interface ** - *************************/ - - bool alloc(size_t, void **); - void free(void *, size_t); - size_t consumed() { return _quota_used; } - size_t overhead(size_t size) { return _alloc.overhead(size); } - bool need_size_for_free() const override { return false; } - }; - - - /** - * Heap that allocates each block at a separate dataspace - */ - class Sliced_heap : public Allocator - { - private: - - class Block; - - Ram_session *_ram_session; /* ram session for backing store */ - Rm_session *_rm_session; /* region manager */ - size_t _consumed; /* number of allocated bytes */ - List _block_list; /* list of allocated blocks */ - Lock _lock; /* serialize allocations */ - - public: - - /** - * Constructor - */ - Sliced_heap(Ram_session *ram_session, Rm_session *rm_session); + Dataspace_pool(Ram_session *ram_session, Rm_session *rm_session) + : ram_session(ram_session), rm_session(rm_session) { } /** * Destructor */ - ~Sliced_heap(); + ~Dataspace_pool(); + + void reassign_resources(Ram_session *ram, Rm_session *rm) { + ram_session = ram, rm_session = rm; } + }; + + /* + * NOTE: The order of the member variables is important for + * the calling order of the destructors! + */ + + Lock _lock; + Dataspace_pool _ds_pool; /* list of dataspaces */ + Allocator_avl _alloc; /* local allocator */ + size_t _quota_limit; + size_t _quota_used; + size_t _chunk_size; + + /** + * Allocate a new dataspace of the specified size + * + * \param size number of bytes to allocate + * \param enforce_separate_metadata if true, the new dataspace + * will not contain any meta data + * \throw Rm_session::Invalid_dataspace, + * Rm_session::Region_conflict + * \return 0 on success or negative error code + */ + Heap::Dataspace *_allocate_dataspace(size_t size, bool enforce_separate_metadata); + + /** + * Try to allocate block at our local allocator + * + * \return true on success + * + * This function is a utility used by '_unsynchronized_alloc' to + * avoid code duplication. + */ + bool _try_local_alloc(size_t size, void **out_addr); + + /** + * Unsynchronized implementation of 'alloc' + */ + bool _unsynchronized_alloc(size_t size, void **out_addr); + + public: + + enum { UNLIMITED = ~0 }; + + Heap(Ram_session *ram_session, + Rm_session *rm_session, + size_t quota_limit = UNLIMITED, + void *static_addr = 0, + size_t static_size = 0) + : + _ds_pool(ram_session, rm_session), + _alloc(0), + _quota_limit(quota_limit), _quota_used(0), + _chunk_size(MIN_CHUNK_SIZE) + { + if (static_addr) + _alloc.add_range((addr_t)static_addr, static_size); + } + + /** + * Reconfigure quota limit + * + * \return negative error code if new quota limit is higher than + * currently used quota. + */ + int quota_limit(size_t new_quota_limit); + + /** + * Re-assign RAM and RM sessions + */ + void reassign_resources(Ram_session *ram, Rm_session *rm) { + _ds_pool.reassign_resources(ram, rm); } - /************************* - ** Allocator interface ** - *************************/ + /************************* + ** Allocator interface ** + *************************/ - bool alloc(size_t, void **); - void free(void *, size_t); - size_t consumed() { return _consumed; } - size_t overhead(size_t size); - bool need_size_for_free() const override { return false; } - }; -} + bool alloc(size_t, void **) override; + void free(void *, size_t) override; + size_t consumed() override { return _quota_used; } + size_t overhead(size_t size) override { return _alloc.overhead(size); } + bool need_size_for_free() const override { return false; } +}; + + +/** + * Heap that allocates each block at a separate dataspace + */ +class Genode::Sliced_heap : public Allocator +{ + private: + + class Block; + + Ram_session *_ram_session; /* ram session for backing store */ + Rm_session *_rm_session; /* region manager */ + size_t _consumed; /* number of allocated bytes */ + List _block_list; /* list of allocated blocks */ + Lock _lock; /* serialize allocations */ + + public: + + /** + * Constructor + */ + Sliced_heap(Ram_session *ram_session, Rm_session *rm_session); + + /** + * Destructor + */ + ~Sliced_heap(); + + + /************************* + ** Allocator interface ** + *************************/ + + bool alloc(size_t, void **); + void free(void *, size_t); + size_t consumed() { return _consumed; } + size_t overhead(size_t size); + bool need_size_for_free() const override { return false; } +}; #endif /* _INCLUDE__BASE__HEAP_H_ */ diff --git a/repos/base/include/base/ipc.h b/repos/base/include/base/ipc.h index 463551d4d..f7a5379c4 100644 --- a/repos/base/include/base/ipc.h +++ b/repos/base/include/base/ipc.h @@ -38,593 +38,600 @@ namespace Genode { enum Ipc_server_reply { IPC_REPLY }; enum Ipc_server_reply_wait { IPC_REPLY_WAIT }; - - /********************* - ** Exception types ** - *********************/ - - class Ipc_error : public Exception { }; - - - /** - * Marshal arguments into send message buffer - */ - class Ipc_marshaller - { - protected: - - char *_sndbuf; - size_t _sndbuf_size; - unsigned _write_offset; - - protected: - - /** - * Write value to send buffer - */ - template - void _write_to_buf(T const &value) - { - /* check buffer range */ - if (_write_offset + sizeof(T) >= _sndbuf_size) return; - - /* write integer to buffer */ - *reinterpret_cast(&_sndbuf[_write_offset]) = value; - - /* increment write pointer to next dword-aligned value */ - _write_offset += align_natural(sizeof(T)); - } - - /** - * Write bytes to send buffer - */ - void _write_to_buf(char const *src_addr, unsigned num_bytes) - { - /* check buffer range */ - if (_write_offset + num_bytes >= _sndbuf_size) return; - - /* copy buffer */ - memcpy(&_sndbuf[_write_offset], src_addr, num_bytes); - - /* increment write pointer to next dword-aligned value */ - _write_offset += align_natural(num_bytes); - } - - /** - * Write 'Rpc_in_buffer' to send buffer - */ - void _write_buffer_to_buf(Rpc_in_buffer_base const &b) - { - size_t size = b.size(); - _write_to_buf(size); - _write_to_buf(b.base(), size); - } - - /** - * Write array to send buffer - */ - template - void _write_to_buf(T const (&array)[N]) - { - /* check buffer range */ - if (_write_offset + sizeof(array) >= _sndbuf_size) - PERR("send buffer overrun"); - - memcpy(&_sndbuf[_write_offset], array, sizeof(array)); - _write_offset += align_natural(sizeof(array)); - } - - public: - - Ipc_marshaller(char *sndbuf, size_t sndbuf_size) - : _sndbuf(sndbuf), _sndbuf_size(sndbuf_size), _write_offset(0) { } - }; - - - /** - * Unmarshal arguments from receive buffer - */ - class Ipc_unmarshaller - { - protected: - - char *_rcvbuf; - size_t _rcvbuf_size; - unsigned _read_offset; - - protected: - - /** - * Read value of type T from buffer - */ - template - void _read_from_buf(T &value) - { - /* check receive buffer range */ - if (_read_offset + sizeof(T) >= _rcvbuf_size) return; - - /* return value from receive buffer */ - value = *reinterpret_cast(&_rcvbuf[_read_offset]); - - /* increment read pointer to next dword-aligned value */ - _read_offset += align_natural(sizeof(T)); - } - - /** - * Read 'Rpc_in_buffer' from receive buffer - */ - void _read_bytebuf_from_buf(Rpc_in_buffer_base &b) - { - size_t size = 0; - _read_from_buf(size); - b = Rpc_in_buffer_base(0, 0); - - /* - * Check receive buffer range - * - * Note: The addr of the Rpc_in_buffer_base is a null pointer when this - * condition triggers. - */ - if (_read_offset + size >= _rcvbuf_size) { - PERR("message buffer overrun"); - return; - } - - b = Rpc_in_buffer_base(&_rcvbuf[_read_offset], size); - _read_offset += align_natural(size); - } - - /** - * Read array from receive buffer - */ - template - void _read_from_buf(T (&array)[N]) - { - if (_read_offset + sizeof(array) >= _rcvbuf_size) { - PERR("receive buffer overrun"); - return; - } - - memcpy(array, &_rcvbuf[_read_offset], sizeof(array)); - _read_offset += align_natural(sizeof(array)); - } - - /** - * Read long value at specified byte index of receive buffer - */ - long _long_at_idx(int idx) { return *(long *)(&_rcvbuf[idx]); } - - public: - - Ipc_unmarshaller(char *rcvbuf, size_t rcvbuf_size) - : _rcvbuf(rcvbuf), _rcvbuf_size(rcvbuf_size), _read_offset(0) { } - }; - - - /** - * Stream for sending information via a capability to an endpoint - */ - class Ipc_ostream : public Ipc_marshaller - { - protected: - - Msgbuf_base *_snd_msg; /* send message buffer */ - Native_capability _dst; - - /** - * Reset marshaller and write badge at the beginning of the message - */ - void _prepare_next_send(); - - /** - * Send message in _snd_msg to _dst - */ - void _send(); - - /** - * Insert capability to message buffer - */ - void _marshal_capability(Native_capability const &cap); - - public: - - /** - * Constructor - */ - Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg); - - /** - * Return true if Ipc_ostream is ready for send - */ - bool ready_for_send() const { return _dst.valid(); } - - /** - * Insert value into send buffer - */ - template - Ipc_ostream &operator << (T const &value) - { - _write_to_buf(value); - return *this; - } - - /** - * Insert byte buffer to send buffer - */ - Ipc_ostream &operator << (Rpc_in_buffer_base const &b) - { - _write_buffer_to_buf(b); - return *this; - } - - /** - * Insert capability to send buffer - */ - Ipc_ostream &operator << (Native_capability const &cap) - { - _marshal_capability(cap); - return *this; - } - - /** - * Insert typed capability to send buffer - */ - template - Ipc_ostream &operator << (Capability const &typed_cap) - { - _marshal_capability(typed_cap); - return *this; - } - - /** - * Issue the sending of the message buffer - */ - Ipc_ostream &operator << (Ipc_ostream_send) - { - _send(); - return *this; - } - - /** - * Return current 'IPC_SEND' destination - * - * This function is typically needed by a server than sends replies - * in a different order as the incoming calls. - */ - Native_capability dst() const { return _dst; } - - /** - * Set destination for the next 'IPC_SEND' - */ - void dst(Native_capability const &dst) { _dst = dst; } - }; - - - /** - * Stream for receiving information - */ - class Ipc_istream : public Ipc_unmarshaller, public Native_capability - { - private: - - /** - * Prevent 'Ipc_istream' objects from being copied - * - * Copying an 'Ipc_istream' object would result in a duplicated - * (and possibly inconsistent) connection state both the original - * and the copied object. - */ - Ipc_istream(const Ipc_istream &); - - protected: - - Msgbuf_base *_rcv_msg; - Native_connection_state _rcv_cs; - - /** - * Obtain capability from message buffer - */ - void _unmarshal_capability(Native_capability &cap); - - protected: - - /** - * Reset unmarshaller - */ - void _prepare_next_receive(); - - /** - * Wait for incoming message to be received in _rcv_msg - */ - void _wait(); - - public: - - explicit Ipc_istream(Msgbuf_base *rcv_msg); - - ~Ipc_istream(); - - /** - * Read badge that was supplied with the message - */ - long badge() { return _long_at_idx(0); } - - /** - * Block for an incoming message filling the receive buffer - */ - Ipc_istream &operator >> (Ipc_istream_wait) - { - _wait(); - return *this; - } - - /** - * Read values from receive buffer - */ - template - Ipc_istream &operator >> (T &value) - { - _read_from_buf(value); - return *this; - } - - /** - * Read byte buffer from receive buffer - */ - Ipc_istream &operator >> (Rpc_in_buffer_base &b) - { - _read_bytebuf_from_buf(b); - return *this; - } - - /** - * Read byte buffer from receive buffer - */ - template - Ipc_istream &operator >> (Rpc_in_buffer &b) - { - _read_bytebuf_from_buf(b); - return *this; - } - - /** - * Read capability from receive buffer - */ - Ipc_istream &operator >> (Native_capability &cap) - { - _unmarshal_capability(cap); - return *this; - } - - /** - * Read typed capability from receive buffer - */ - template - Ipc_istream &operator >> (Capability &typed_cap) - { - _unmarshal_capability(typed_cap); - return *this; - } - }; - - - class Ipc_client: public Ipc_istream, public Ipc_ostream - { - protected: - - int _result; /* result of most recent call */ - - void _prepare_next_call(); - - /** - * Send RPC message and wait for result - */ - void _call(); - - /** - * Set return value if call to server failed - */ - void ret(int retval) - { - *reinterpret_cast(&_rcvbuf[sizeof(umword_t)]) = retval; - } - - public: - - /** - * Constructor - */ - Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg, - Msgbuf_base *rcv_msg, unsigned short rcv_caps = ~0); - - /** - * Operator that issues an IPC call - * - * \throw Ipc_error - * \throw Blocking_canceled - */ - Ipc_client &operator << (Ipc_client_call) - { - _call(); - _read_from_buf(_result); - if (_result == ERR_INVALID_OBJECT) - throw Ipc_error(); - return *this; - } - - template - Ipc_client &operator << (T const &value) - { - _write_to_buf(value); - return *this; - } - - Ipc_client &operator << (Rpc_in_buffer_base const &b) - { - _write_buffer_to_buf(b); - return *this; - } - - template - Ipc_client &operator << (Rpc_in_buffer const &b) - { - _write_buffer_to_buf(b); - return *this; - } - - Ipc_client &operator << (Native_capability const &cap) - { - _marshal_capability(cap); - return *this; - } - - template - Ipc_client &operator << (Capability const &typed_cap) - { - _marshal_capability(typed_cap); - return *this; - } - - Ipc_client &operator >> (Native_capability &cap) - { - _unmarshal_capability(cap); - return *this; - } - - template - Ipc_client &operator >> (Capability &typed_cap) - { - _unmarshal_capability(typed_cap); - return *this; - } - - template - Ipc_client &operator >> (T &value) - { - _read_from_buf(value); - return *this; - } - - Ipc_client &operator >> (Rpc_in_buffer_base &b) - { - _read_bytebuf_from_buf(b); - return *this; - } - - int result() const { return _result; } - }; - - - class Ipc_server : public Ipc_istream, public Ipc_ostream - { - protected: - - bool _reply_needed; /* false for the first reply_wait */ - - void _prepare_next_reply_wait(); - - /** - * Wait for incoming call - * - * In constrast to 'Ipc_istream::_wait()', this function stores the - * next reply destination from into 'dst' of the 'Ipc_ostream'. - */ - void _wait(); - - /** - * Send reply to destination - * - * In contrast to 'Ipc_ostream::_send()', this function prepares - * the 'Ipc_server' to send another subsequent reply without the - * calling '_wait()' in between. This is needed when a server - * answers calls out of order. - */ - void _reply(); - - /** - * Send result of previous RPC request and wait for new one - */ - void _reply_wait(); - - public: - - /** - * Constructor - */ - Ipc_server(Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg); - - /** - * Set return value of server call - */ - void ret(int retval) - { - *reinterpret_cast(&_sndbuf[sizeof(umword_t)]) = retval; - } - - /** - * Set reply destination - */ - void dst(Native_capability const &reply_dst) - { - Ipc_ostream::dst(reply_dst); - _reply_needed = reply_dst.valid(); - } - - using Ipc_ostream::dst; - - /** - * Block for an incoming message filling the receive buffer - */ - Ipc_server &operator >> (Ipc_istream_wait) - { - _wait(); - return *this; - } - - /** - * Issue the sending of the message buffer - */ - Ipc_server &operator << (Ipc_server_reply) - { - _reply(); - return *this; - } - - /** - * Reply current request and wait for a new one - */ - Ipc_server &operator >> (Ipc_server_reply_wait) - { - _reply_wait(); - return *this; - } - - /** - * Write value to send buffer - * - * This operator is only used by test programs - */ - template - Ipc_server &operator << (T const &value) - { - _write_to_buf(value); - return *this; - } - - /** - * Read value from receive buffer - * - * This operator should only be used by the server framework for - * reading the function offset. The server-side processing of the - * payload is done using 'Ipc_istream' and 'Ipc_ostream'. - */ - template - Ipc_server &operator >> (T &value) - { - _read_from_buf(value); - return *this; - } - }; + class Ipc_error; + class Ipc_marshaller; + class Ipc_unmarshaller; + class Ipc_ostream; + class Ipc_istream; + class Ipc_client; + class Ipc_server; } + +/** + * Exception type + */ +class Genode::Ipc_error : public Exception { }; + + +/** + * Marshal arguments into send message buffer + */ +class Genode::Ipc_marshaller +{ + protected: + + char *_sndbuf; + size_t _sndbuf_size; + unsigned _write_offset; + + protected: + + /** + * Write value to send buffer + */ + template + void _write_to_buf(T const &value) + { + /* check buffer range */ + if (_write_offset + sizeof(T) >= _sndbuf_size) return; + + /* write integer to buffer */ + *reinterpret_cast(&_sndbuf[_write_offset]) = value; + + /* increment write pointer to next dword-aligned value */ + _write_offset += align_natural(sizeof(T)); + } + + /** + * Write bytes to send buffer + */ + void _write_to_buf(char const *src_addr, unsigned num_bytes) + { + /* check buffer range */ + if (_write_offset + num_bytes >= _sndbuf_size) return; + + /* copy buffer */ + memcpy(&_sndbuf[_write_offset], src_addr, num_bytes); + + /* increment write pointer to next dword-aligned value */ + _write_offset += align_natural(num_bytes); + } + + /** + * Write 'Rpc_in_buffer' to send buffer + */ + void _write_buffer_to_buf(Rpc_in_buffer_base const &b) + { + size_t size = b.size(); + _write_to_buf(size); + _write_to_buf(b.base(), size); + } + + /** + * Write array to send buffer + */ + template + void _write_to_buf(T const (&array)[N]) + { + /* check buffer range */ + if (_write_offset + sizeof(array) >= _sndbuf_size) + PERR("send buffer overrun"); + + memcpy(&_sndbuf[_write_offset], array, sizeof(array)); + _write_offset += align_natural(sizeof(array)); + } + + public: + + Ipc_marshaller(char *sndbuf, size_t sndbuf_size) + : _sndbuf(sndbuf), _sndbuf_size(sndbuf_size), _write_offset(0) { } +}; + + +/** + * Unmarshal arguments from receive buffer + */ +class Genode::Ipc_unmarshaller +{ + protected: + + char *_rcvbuf; + size_t _rcvbuf_size; + unsigned _read_offset; + + protected: + + /** + * Read value of type T from buffer + */ + template + void _read_from_buf(T &value) + { + /* check receive buffer range */ + if (_read_offset + sizeof(T) >= _rcvbuf_size) return; + + /* return value from receive buffer */ + value = *reinterpret_cast(&_rcvbuf[_read_offset]); + + /* increment read pointer to next dword-aligned value */ + _read_offset += align_natural(sizeof(T)); + } + + /** + * Read 'Rpc_in_buffer' from receive buffer + */ + void _read_bytebuf_from_buf(Rpc_in_buffer_base &b) + { + size_t size = 0; + _read_from_buf(size); + b = Rpc_in_buffer_base(0, 0); + + /* + * Check receive buffer range + * + * Note: The addr of the Rpc_in_buffer_base is a null pointer when this + * condition triggers. + */ + if (_read_offset + size >= _rcvbuf_size) { + PERR("message buffer overrun"); + return; + } + + b = Rpc_in_buffer_base(&_rcvbuf[_read_offset], size); + _read_offset += align_natural(size); + } + + /** + * Read array from receive buffer + */ + template + void _read_from_buf(T (&array)[N]) + { + if (_read_offset + sizeof(array) >= _rcvbuf_size) { + PERR("receive buffer overrun"); + return; + } + + memcpy(array, &_rcvbuf[_read_offset], sizeof(array)); + _read_offset += align_natural(sizeof(array)); + } + + /** + * Read long value at specified byte index of receive buffer + */ + long _long_at_idx(int idx) { return *(long *)(&_rcvbuf[idx]); } + + public: + + Ipc_unmarshaller(char *rcvbuf, size_t rcvbuf_size) + : _rcvbuf(rcvbuf), _rcvbuf_size(rcvbuf_size), _read_offset(0) { } +}; + + +/** + * Stream for sending information via a capability to an endpoint + */ +class Genode::Ipc_ostream : public Ipc_marshaller +{ + protected: + + Msgbuf_base *_snd_msg; /* send message buffer */ + Native_capability _dst; + + /** + * Reset marshaller and write badge at the beginning of the message + */ + void _prepare_next_send(); + + /** + * Send message in _snd_msg to _dst + */ + void _send(); + + /** + * Insert capability to message buffer + */ + void _marshal_capability(Native_capability const &cap); + + public: + + /** + * Constructor + */ + Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg); + + /** + * Return true if Ipc_ostream is ready for send + */ + bool ready_for_send() const { return _dst.valid(); } + + /** + * Insert value into send buffer + */ + template + Ipc_ostream &operator << (T const &value) + { + _write_to_buf(value); + return *this; + } + + /** + * Insert byte buffer to send buffer + */ + Ipc_ostream &operator << (Rpc_in_buffer_base const &b) + { + _write_buffer_to_buf(b); + return *this; + } + + /** + * Insert capability to send buffer + */ + Ipc_ostream &operator << (Native_capability const &cap) + { + _marshal_capability(cap); + return *this; + } + + /** + * Insert typed capability to send buffer + */ + template + Ipc_ostream &operator << (Capability const &typed_cap) + { + _marshal_capability(typed_cap); + return *this; + } + + /** + * Issue the sending of the message buffer + */ + Ipc_ostream &operator << (Ipc_ostream_send) + { + _send(); + return *this; + } + + /** + * Return current 'IPC_SEND' destination + * + * This function is typically needed by a server than sends replies + * in a different order as the incoming calls. + */ + Native_capability dst() const { return _dst; } + + /** + * Set destination for the next 'IPC_SEND' + */ + void dst(Native_capability const &dst) { _dst = dst; } +}; + + +/** + * Stream for receiving information + */ +class Genode::Ipc_istream : public Ipc_unmarshaller, public Native_capability +{ + private: + + /** + * Prevent 'Ipc_istream' objects from being copied + * + * Copying an 'Ipc_istream' object would result in a duplicated + * (and possibly inconsistent) connection state both the original + * and the copied object. + */ + Ipc_istream(const Ipc_istream &); + + protected: + + Msgbuf_base *_rcv_msg; + Native_connection_state _rcv_cs; + + /** + * Obtain capability from message buffer + */ + void _unmarshal_capability(Native_capability &cap); + + protected: + + /** + * Reset unmarshaller + */ + void _prepare_next_receive(); + + /** + * Wait for incoming message to be received in _rcv_msg + */ + void _wait(); + + public: + + explicit Ipc_istream(Msgbuf_base *rcv_msg); + + ~Ipc_istream(); + + /** + * Read badge that was supplied with the message + */ + long badge() { return _long_at_idx(0); } + + /** + * Block for an incoming message filling the receive buffer + */ + Ipc_istream &operator >> (Ipc_istream_wait) + { + _wait(); + return *this; + } + + /** + * Read values from receive buffer + */ + template + Ipc_istream &operator >> (T &value) + { + _read_from_buf(value); + return *this; + } + + /** + * Read byte buffer from receive buffer + */ + Ipc_istream &operator >> (Rpc_in_buffer_base &b) + { + _read_bytebuf_from_buf(b); + return *this; + } + + /** + * Read byte buffer from receive buffer + */ + template + Ipc_istream &operator >> (Rpc_in_buffer &b) + { + _read_bytebuf_from_buf(b); + return *this; + } + + /** + * Read capability from receive buffer + */ + Ipc_istream &operator >> (Native_capability &cap) + { + _unmarshal_capability(cap); + return *this; + } + + /** + * Read typed capability from receive buffer + */ + template + Ipc_istream &operator >> (Capability &typed_cap) + { + _unmarshal_capability(typed_cap); + return *this; + } +}; + + +class Genode::Ipc_client: public Ipc_istream, public Ipc_ostream +{ + protected: + + int _result; /* result of most recent call */ + + void _prepare_next_call(); + + /** + * Send RPC message and wait for result + */ + void _call(); + + /** + * Set return value if call to server failed + */ + void ret(int retval) + { + *reinterpret_cast(&_rcvbuf[sizeof(umword_t)]) = retval; + } + + public: + + /** + * Constructor + */ + Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg, + Msgbuf_base *rcv_msg, unsigned short rcv_caps = ~0); + + /** + * Operator that issues an IPC call + * + * \throw Ipc_error + * \throw Blocking_canceled + */ + Ipc_client &operator << (Ipc_client_call) + { + _call(); + _read_from_buf(_result); + if (_result == ERR_INVALID_OBJECT) + throw Ipc_error(); + return *this; + } + + template + Ipc_client &operator << (T const &value) + { + _write_to_buf(value); + return *this; + } + + Ipc_client &operator << (Rpc_in_buffer_base const &b) + { + _write_buffer_to_buf(b); + return *this; + } + + template + Ipc_client &operator << (Rpc_in_buffer const &b) + { + _write_buffer_to_buf(b); + return *this; + } + + Ipc_client &operator << (Native_capability const &cap) + { + _marshal_capability(cap); + return *this; + } + + template + Ipc_client &operator << (Capability const &typed_cap) + { + _marshal_capability(typed_cap); + return *this; + } + + Ipc_client &operator >> (Native_capability &cap) + { + _unmarshal_capability(cap); + return *this; + } + + template + Ipc_client &operator >> (Capability &typed_cap) + { + _unmarshal_capability(typed_cap); + return *this; + } + + template + Ipc_client &operator >> (T &value) + { + _read_from_buf(value); + return *this; + } + + Ipc_client &operator >> (Rpc_in_buffer_base &b) + { + _read_bytebuf_from_buf(b); + return *this; + } + + int result() const { return _result; } +}; + + +class Genode::Ipc_server : public Ipc_istream, public Ipc_ostream +{ + protected: + + bool _reply_needed; /* false for the first reply_wait */ + + void _prepare_next_reply_wait(); + + /** + * Wait for incoming call + * + * In constrast to 'Ipc_istream::_wait()', this function stores the + * next reply destination from into 'dst' of the 'Ipc_ostream'. + */ + void _wait(); + + /** + * Send reply to destination + * + * In contrast to 'Ipc_ostream::_send()', this function prepares + * the 'Ipc_server' to send another subsequent reply without the + * calling '_wait()' in between. This is needed when a server + * answers calls out of order. + */ + void _reply(); + + /** + * Send result of previous RPC request and wait for new one + */ + void _reply_wait(); + + public: + + /** + * Constructor + */ + Ipc_server(Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg); + + /** + * Set return value of server call + */ + void ret(int retval) + { + *reinterpret_cast(&_sndbuf[sizeof(umword_t)]) = retval; + } + + /** + * Set reply destination + */ + void dst(Native_capability const &reply_dst) + { + Ipc_ostream::dst(reply_dst); + _reply_needed = reply_dst.valid(); + } + + using Ipc_ostream::dst; + + /** + * Block for an incoming message filling the receive buffer + */ + Ipc_server &operator >> (Ipc_istream_wait) + { + _wait(); + return *this; + } + + /** + * Issue the sending of the message buffer + */ + Ipc_server &operator << (Ipc_server_reply) + { + _reply(); + return *this; + } + + /** + * Reply current request and wait for a new one + */ + Ipc_server &operator >> (Ipc_server_reply_wait) + { + _reply_wait(); + return *this; + } + + /** + * Write value to send buffer + * + * This operator is only used by test programs + */ + template + Ipc_server &operator << (T const &value) + { + _write_to_buf(value); + return *this; + } + + /** + * Read value from receive buffer + * + * This operator should only be used by the server framework for + * reading the function offset. The server-side processing of the + * payload is done using 'Ipc_istream' and 'Ipc_ostream'. + */ + template + Ipc_server &operator >> (T &value) + { + _read_from_buf(value); + return *this; + } +}; + #endif /* _INCLUDE__BASE__IPC_GENERIC_H_ */ diff --git a/repos/base/include/base/lock.h b/repos/base/include/base/lock.h index caf24c8be..5d59141fe 100644 --- a/repos/base/include/base/lock.h +++ b/repos/base/include/base/lock.h @@ -16,32 +16,32 @@ #include -namespace Genode { +namespace Genode { class Lock; } - class Lock : public Cancelable_lock - { - public: - /** - * Constructor - */ - explicit Lock(State initial = UNLOCKED) - : Cancelable_lock(initial) { } +class Genode::Lock : public Cancelable_lock +{ + public: - void lock() - { - while (1) - try { - Cancelable_lock::lock(); - return; - } catch (Blocking_canceled) { } - } + /** + * Constructor + */ + explicit Lock(State initial = UNLOCKED) + : Cancelable_lock(initial) { } - /** - * Lock guard - */ - typedef Lock_guard Guard; - }; -} + void lock() + { + while (1) + try { + Cancelable_lock::lock(); + return; + } catch (Blocking_canceled) { } + } + + /** + * Lock guard + */ + typedef Lock_guard Guard; +}; #endif /* _INCLUDE__BASE__LOCK_H_ */ diff --git a/repos/base/include/base/lock_guard.h b/repos/base/include/base/lock_guard.h index 569cdc9fd..261a95c6f 100644 --- a/repos/base/include/base/lock_guard.h +++ b/repos/base/include/base/lock_guard.h @@ -21,26 +21,26 @@ #ifndef _INCLUDE__BASE__LOCK_GUARD_H_ #define _INCLUDE__BASE__LOCK_GUARD_H_ -namespace Genode { +namespace Genode { template class Lock_guard; } - /** - * Lock guard template - * - * \param LT lock type - */ - template - class Lock_guard - { - private: - LT &_lock; +/** + * Lock guard template + * + * \param LT lock type + */ +template +class Genode::Lock_guard +{ + private: - public: + LT &_lock; - explicit Lock_guard(LT &lock) : _lock(lock) { _lock.lock(); } + public: - ~Lock_guard() { _lock.unlock(); } - }; -} + explicit Lock_guard(LT &lock) : _lock(lock) { _lock.lock(); } + + ~Lock_guard() { _lock.unlock(); } +}; #endif /* _INCLUDE__BASE__LOCK_GUARD_H_ */ diff --git a/repos/base/include/base/native_capability.h b/repos/base/include/base/native_capability.h index 2444504be..2c7e29112 100644 --- a/repos/base/include/base/native_capability.h +++ b/repos/base/include/base/native_capability.h @@ -18,102 +18,102 @@ #ifndef _INCLUDE__BASE__NATIVE_CAPABILITY_H_ #define _INCLUDE__BASE__NATIVE_CAPABILITY_H_ -namespace Genode { +namespace Genode { template class Native_capability_tpl; } - /** - * Generic parts of the platform-specific 'Native_capability' - * - * \param POLICY policy class that provides the type used as capability - * destination and functions for checking the validity of - * the platform-specific destination type and for - * invalid destinations. - * - * The struct passed as 'POLICY' argument must have the following - * interface: - * - * ! typedef Dst; - * ! static bool valid(Dst dst); - * ! static Dst invalid(); - * - * The 'Dst' type is the platform-specific destination type (e.g., the ID - * of the destination thread targeted by the capability). The 'valid' - * function returns true if the specified destination is valid. The - * 'invalid' function produces an invalid destination. - */ - template - class Native_capability_tpl - { - public: - typedef typename POLICY::Dst Dst; +/** + * Generic parts of the platform-specific 'Native_capability' + * + * \param POLICY policy class that provides the type used as capability + * destination and functions for checking the validity of + * the platform-specific destination type and for + * invalid destinations. + * + * The struct passed as 'POLICY' argument must have the following + * interface: + * + * ! typedef Dst; + * ! static bool valid(Dst dst); + * ! static Dst invalid(); + * + * The 'Dst' type is the platform-specific destination type (e.g., the ID + * of the destination thread targeted by the capability). The 'valid' + * function returns true if the specified destination is valid. The + * 'invalid' function produces an invalid destination. + */ +template +class Genode::Native_capability_tpl +{ + public: - /** - * Compound object used to copy raw capability members - * - * This type is a utility solely used to communicate the - * information about the parent capability from the parent to the - * new process. - */ - struct Raw { Dst dst; long local_name; }; + typedef typename POLICY::Dst Dst; - private: + /** + * Compound object used to copy raw capability members + * + * This type is a utility solely used to communicate the + * information about the parent capability from the parent to the + * new process. + */ + struct Raw { Dst dst; long local_name; }; - Dst _dst; - long _local_name; + private: - protected: + Dst _dst; + long _local_name; - /** - * Constructor for a local capability - * - * A local capability just encapsulates a pointer to some - * local object. This constructor is only used by a factory - * method for local-capabilities in the generic Capability - * class. - * - * \param ptr address of the local object - */ - Native_capability_tpl(void* ptr) - : _dst(POLICY::invalid()), _local_name((long)ptr) { } + protected: - public: + /** + * Constructor for a local capability + * + * A local capability just encapsulates a pointer to some + * local object. This constructor is only used by a factory + * method for local-capabilities in the generic Capability + * class. + * + * \param ptr address of the local object + */ + Native_capability_tpl(void* ptr) + : _dst(POLICY::invalid()), _local_name((long)ptr) { } - /** - * Constructor for an invalid capability - */ - Native_capability_tpl() : _dst(POLICY::invalid()), _local_name(0) { } + public: - /** - * Publicly available constructor - * - * \param tid kernel-specific thread id - * \param local_name ID used as key to lookup the 'Rpc_object' - * that corresponds to the capability. - */ - Native_capability_tpl(Dst tid, long local_name) - : _dst(tid), _local_name(local_name) { } + /** + * Constructor for an invalid capability + */ + Native_capability_tpl() : _dst(POLICY::invalid()), _local_name(0) { } - /** - * Return true when the capability is valid - */ - bool valid() const { return POLICY::valid(_dst); } + /** + * Publicly available constructor + * + * \param tid kernel-specific thread id + * \param local_name ID used as key to lookup the 'Rpc_object' + * that corresponds to the capability. + */ + Native_capability_tpl(Dst tid, long local_name) + : _dst(tid), _local_name(local_name) { } - /** - * Return ID used to lookup the 'Rpc_object' by its capability - */ - long local_name() const { return _local_name; } + /** + * Return true when the capability is valid + */ + bool valid() const { return POLICY::valid(_dst); } - /** - * Return pointer to object referenced by a local-capability - */ - void* local() const { return (void*)_local_name; } + /** + * Return ID used to lookup the 'Rpc_object' by its capability + */ + long local_name() const { return _local_name; } - /** - * Return capability destination - */ - Dst dst() const { return _dst; } - }; -} + /** + * Return pointer to object referenced by a local-capability + */ + void* local() const { return (void*)_local_name; } + + /** + * Return capability destination + */ + Dst dst() const { return _dst; } +}; #endif /* _INCLUDE__BASE__NATIVE_CAPABILITY_H_ */ diff --git a/repos/base/include/base/object_pool.h b/repos/base/include/base/object_pool.h index 17f00600f..93db32b02 100644 --- a/repos/base/include/base/object_pool.h +++ b/repos/base/include/base/object_pool.h @@ -19,198 +19,198 @@ #include #include -namespace Genode { +namespace Genode { template class Object_pool; } - /** - * Map object ids to local objects - * - * \param OBJ_TYPE object type (must be inherited from Object_pool::Entry) - * - * The local names of a capabilities are used to differentiate multiple server - * objects managed by one and the same object pool. - */ - template - class Object_pool - { - public: - class Guard - { - private: +/** + * Map object ids to local objects + * + * \param OBJ_TYPE object type (must be inherited from Object_pool::Entry) + * + * The local names of a capabilities are used to differentiate multiple server + * objects managed by one and the same object pool. + */ +template +class Genode::Object_pool +{ + public: - OBJ_TYPE * _object; + class Guard + { + private: - public: - operator OBJ_TYPE*() const { return _object; } - OBJ_TYPE * operator->() const { return _object; } - OBJ_TYPE * object() const { return _object; } + OBJ_TYPE * _object; - template - explicit Guard(X * object) { - _object = dynamic_cast(object); } + public: + operator OBJ_TYPE*() const { return _object; } + OBJ_TYPE * operator->() const { return _object; } + OBJ_TYPE * object() const { return _object; } - ~Guard() - { - if (!_object) return; + template + explicit Guard(X * object) { + _object = dynamic_cast(object); } - _object->release(); - } - }; + ~Guard() + { + if (!_object) return; - class Entry : public Avl_node - { - private: - - Untyped_capability _cap; - short int _ref; - bool _dead; - - Lock _entry_lock; - - inline unsigned long _obj_id() { return _cap.local_name(); } - - friend class Object_pool; - friend class Avl_tree; - - /** - * Support functions for atomic lookup and lock - * functionality of class Object_pool. - */ - void lock() { _entry_lock.lock(); }; - void unlock() { _entry_lock.unlock(); }; - - void add_ref() { _ref += 1; } - void del_ref() { _ref -= 1; } - - bool is_dead(bool set_dead = false) { - return (set_dead ? (_dead = true) : _dead); } - bool is_ref_zero() { return _ref <= 0; } - - public: - - enum { OBJ_ID_INVALID = 0 }; - - /** - * Constructors - */ - Entry() : _ref(0), _dead(false) { } - Entry(Untyped_capability cap) : _cap(cap), _ref(0), _dead(false) { } - - /** - * Avl_node interface - */ - bool higher(Entry *e) { return e->_obj_id() > _obj_id(); } - void recompute() { } /* for gcc-3.4 compatibility */ - - /** - * Support for object pool - */ - Entry *find_by_obj_id(unsigned long obj_id) - { - if (obj_id == _obj_id()) return this; - - Entry *obj = this->child(obj_id > _obj_id()); - - return obj ? obj->find_by_obj_id(obj_id) : 0; - } - - /** - * Assign capability to object pool entry - */ - void cap(Untyped_capability c) { _cap = c; } - - Untyped_capability const cap() const { return _cap; } - - /** - * Function used - ideally - solely by the Guard. - */ - void release() { del_ref(); unlock(); } - void acquire() { lock(); add_ref(); } - }; - - private: - - Avl_tree _tree; - Lock _lock; - - public: - - void insert(OBJ_TYPE *obj) - { - Lock::Guard lock_guard(_lock); - _tree.insert(obj); - } - - void remove_locked(OBJ_TYPE *obj) - { - obj->is_dead(true); - obj->del_ref(); - - while (true) { - obj->unlock(); - { - Lock::Guard lock_guard(_lock); - if (obj->is_ref_zero()) { - _tree.remove(obj); - return; - } - } - obj->lock(); + _object->release(); } - } + }; - /** - * Lookup object - */ - OBJ_TYPE *lookup_and_lock(addr_t obj_id) - { - OBJ_TYPE * obj_typed; + class Entry : public Avl_node + { + private: + + Untyped_capability _cap; + short int _ref; + bool _dead; + + Lock _entry_lock; + + inline unsigned long _obj_id() { return _cap.local_name(); } + + friend class Object_pool; + friend class Avl_tree; + + /** + * Support functions for atomic lookup and lock + * functionality of class Object_pool. + */ + void lock() { _entry_lock.lock(); }; + void unlock() { _entry_lock.unlock(); }; + + void add_ref() { _ref += 1; } + void del_ref() { _ref -= 1; } + + bool is_dead(bool set_dead = false) { + return (set_dead ? (_dead = true) : _dead); } + bool is_ref_zero() { return _ref <= 0; } + + public: + + enum { OBJ_ID_INVALID = 0 }; + + /** + * Constructors + */ + Entry() : _ref(0), _dead(false) { } + Entry(Untyped_capability cap) : _cap(cap), _ref(0), _dead(false) { } + + /** + * Avl_node interface + */ + bool higher(Entry *e) { return e->_obj_id() > _obj_id(); } + void recompute() { } /* for gcc-3.4 compatibility */ + + /** + * Support for object pool + */ + Entry *find_by_obj_id(unsigned long obj_id) + { + if (obj_id == _obj_id()) return this; + + Entry *obj = this->child(obj_id > _obj_id()); + + return obj ? obj->find_by_obj_id(obj_id) : 0; + } + + /** + * Assign capability to object pool entry + */ + void cap(Untyped_capability c) { _cap = c; } + + Untyped_capability const cap() const { return _cap; } + + /** + * Function used - ideally - solely by the Guard. + */ + void release() { del_ref(); unlock(); } + void acquire() { lock(); add_ref(); } + }; + + private: + + Avl_tree _tree; + Lock _lock; + + public: + + void insert(OBJ_TYPE *obj) + { + Lock::Guard lock_guard(_lock); + _tree.insert(obj); + } + + void remove_locked(OBJ_TYPE *obj) + { + obj->is_dead(true); + obj->del_ref(); + + while (true) { + obj->unlock(); { Lock::Guard lock_guard(_lock); - Entry *obj = _tree.first(); - if (!obj) return 0; - - obj_typed = (OBJ_TYPE *)obj->find_by_obj_id(obj_id); - if (!obj_typed || obj_typed->is_dead()) - return 0; - - obj_typed->add_ref(); + if (obj->is_ref_zero()) { + _tree.remove(obj); + return; + } } - - obj_typed->lock(); - return obj_typed; + obj->lock(); } + } - OBJ_TYPE *lookup_and_lock(Untyped_capability cap) - { - return lookup_and_lock(cap.local_name()); - } - - /** - * Return first element of tree - * - * This function is used for removing tree elements step by step. - */ - OBJ_TYPE *first() + /** + * Lookup object + */ + OBJ_TYPE *lookup_and_lock(addr_t obj_id) + { + OBJ_TYPE * obj_typed; { Lock::Guard lock_guard(_lock); - return (OBJ_TYPE *)_tree.first(); + Entry *obj = _tree.first(); + if (!obj) return 0; + + obj_typed = (OBJ_TYPE *)obj->find_by_obj_id(obj_id); + if (!obj_typed || obj_typed->is_dead()) + return 0; + + obj_typed->add_ref(); } - /** - * Return first element of tree locked - * - * This function is used for removing tree elements step by step. - */ - OBJ_TYPE *first_locked() - { - Lock::Guard lock_guard(_lock); - OBJ_TYPE * const obj_typed = (OBJ_TYPE *)_tree.first(); - if (!obj_typed) { return 0; } - obj_typed->lock(); - return obj_typed; - } - }; -} + obj_typed->lock(); + return obj_typed; + } + + OBJ_TYPE *lookup_and_lock(Untyped_capability cap) + { + return lookup_and_lock(cap.local_name()); + } + + /** + * Return first element of tree + * + * This function is used for removing tree elements step by step. + */ + OBJ_TYPE *first() + { + Lock::Guard lock_guard(_lock); + return (OBJ_TYPE *)_tree.first(); + } + + /** + * Return first element of tree locked + * + * This function is used for removing tree elements step by step. + */ + OBJ_TYPE *first_locked() + { + Lock::Guard lock_guard(_lock); + OBJ_TYPE * const obj_typed = (OBJ_TYPE *)_tree.first(); + if (!obj_typed) { return 0; } + obj_typed->lock(); + return obj_typed; + } +}; #endif /* _INCLUDE__BASE__OBJECT_POOL_H_ */ diff --git a/repos/base/include/base/pager.h b/repos/base/include/base/pager.h index 7e987e895..2bba834b7 100644 --- a/repos/base/include/base/pager.h +++ b/repos/base/include/base/pager.h @@ -27,191 +27,198 @@ namespace Genode { - /** - * Special server object for paging - * - * A 'Pager_object' is very similar to a 'Rpc_object'. It is just a - * special implementation for page-fault handling, which does not allow to - * define a "badge" for pager capabilities. - */ - class Pager_object : public Object_pool::Entry - { - protected: - - /** - * Local name for this pager object - */ - unsigned long _badge; - - Thread_capability _thread_cap; - - /** - * User-level signal handler registered for this pager object via - * 'Cpu_session::exception_handler()'. - */ - Signal_context_capability _exception_sigh; - - public: - - /** - * Contains information about exception state of corresponding thread. - */ - Thread_state state; - - /** - * Constructor - * - * \param location affinity of paged thread to physical CPU - */ - Pager_object(unsigned long badge, Affinity::Location location) - : _badge(badge) { } - - virtual ~Pager_object() { } - - unsigned long badge() const { return _badge; } - - /** - * Interface to be implemented by a derived class - * - * \param ps 'Ipc_pager' stream - * - * Returns !0 on error and pagefault will not be answered. - */ - virtual int pager(Ipc_pager &ps) = 0; - - /** - * Wake up the faulter - */ - void wake_up(); - - /** - * Assign user-level exception handler for the pager object - */ - void exception_handler(Signal_context_capability sigh) - { - _exception_sigh = sigh; - } - - /** - * Notify exception handler about the occurrence of an exception - */ - void submit_exception_signal() - { - if (!_exception_sigh.valid()) return; - - Signal_transmitter transmitter(_exception_sigh); - transmitter.submit(); - } - - /** - * Remember thread cap so that rm_session can tell thread that - * rm_client is gone. - */ - Thread_capability thread_cap() { return _thread_cap; } const - void thread_cap(Thread_capability cap) { _thread_cap = cap; } - - /* - * Note in the thread state that an unresolved page - * fault occurred. - */ - void unresolved_page_fault_occurred(); - }; - - /** - * A 'Pager_activation' processes one page fault of a 'Pager_object' at a time. - */ + class Pager_object; class Pager_entrypoint; - class Pager_activation_base: public Thread_base - { - private: - - Native_capability _cap; - Pager_entrypoint *_ep; /* entry point to which the - activation belongs */ - /** - * Lock used for blocking until '_cap' is initialized - */ - Lock _cap_valid; - - public: - - Pager_activation_base(const char *name, size_t stack_size) : - Thread_base(0, name, stack_size), - _cap(Native_capability()), _ep(0), _cap_valid(Lock::LOCKED) { } - - /** - * Set entry point, which the activation serves - * - * This function is only called by the 'Pager_entrypoint' - * constructor. - */ - void ep(Pager_entrypoint *ep) { _ep = ep; } - - /** - * Thread interface - */ - void entry(); - - /** - * Return capability to this activation - * - * This function should only be called from 'Pager_entrypoint' - */ - Native_capability cap() - { - /* ensure that the initialization of our 'Ipc_pager' is done */ - if (!_cap.valid()) - _cap_valid.lock(); - return _cap; - } - }; - - - /** - * Paging entry point - * - * For a paging entry point can hold only one activation. So, paging is - * strictly serialized for one entry point. - */ - class Pager_entrypoint : public Object_pool - { - private: - - Pager_activation_base *_activation; - Cap_session *_cap_session; - - public: - - /** - * Constructor - * - * \param cap_session Cap_session for creating capabilities - * for the pager objects managed by this - * entry point - * \param a initial activation - */ - Pager_entrypoint(Cap_session *cap_session, Pager_activation_base *a = 0); - - /** - * Associate Pager_object with the entry point - */ - Pager_capability manage(Pager_object *obj); - - /** - * Dissolve Pager_object from entry point - */ - void dissolve(Pager_object *obj); - }; - - - template - class Pager_activation : public Pager_activation_base - { - public: - - Pager_activation() : Pager_activation_base("pager", STACK_SIZE) - { start(); } - }; + class Pager_activation_base; + template class Pager_activation; } + + +/** + * Special server object for paging + * + * A 'Pager_object' is very similar to a 'Rpc_object'. It is just a + * special implementation for page-fault handling, which does not allow to + * define a "badge" for pager capabilities. + */ +class Genode::Pager_object : public Object_pool::Entry +{ + protected: + + /** + * Local name for this pager object + */ + unsigned long _badge; + + Thread_capability _thread_cap; + + /** + * User-level signal handler registered for this pager object via + * 'Cpu_session::exception_handler()'. + */ + Signal_context_capability _exception_sigh; + + public: + + /** + * Contains information about exception state of corresponding thread. + */ + Thread_state state; + + /** + * Constructor + * + * \param location affinity of paged thread to physical CPU + */ + Pager_object(unsigned long badge, Affinity::Location location) + : _badge(badge) { } + + virtual ~Pager_object() { } + + unsigned long badge() const { return _badge; } + + /** + * Interface to be implemented by a derived class + * + * \param ps 'Ipc_pager' stream + * + * Returns !0 on error and pagefault will not be answered. + */ + virtual int pager(Ipc_pager &ps) = 0; + + /** + * Wake up the faulter + */ + void wake_up(); + + /** + * Assign user-level exception handler for the pager object + */ + void exception_handler(Signal_context_capability sigh) + { + _exception_sigh = sigh; + } + + /** + * Notify exception handler about the occurrence of an exception + */ + void submit_exception_signal() + { + if (!_exception_sigh.valid()) return; + + Signal_transmitter transmitter(_exception_sigh); + transmitter.submit(); + } + + /** + * Remember thread cap so that rm_session can tell thread that + * rm_client is gone. + */ + Thread_capability thread_cap() { return _thread_cap; } const + void thread_cap(Thread_capability cap) { _thread_cap = cap; } + + /* + * Note in the thread state that an unresolved page + * fault occurred. + */ + void unresolved_page_fault_occurred(); +}; + + +/** + * A 'Pager_activation' processes one page fault of a 'Pager_object' at a time. + */ +class Genode::Pager_activation_base: public Thread_base +{ + private: + + Native_capability _cap; + Pager_entrypoint *_ep; /* entry point to which the + activation belongs */ + /** + * Lock used for blocking until '_cap' is initialized + */ + Lock _cap_valid; + + public: + + Pager_activation_base(const char *name, size_t stack_size) : + Thread_base(0, name, stack_size), + _cap(Native_capability()), _ep(0), _cap_valid(Lock::LOCKED) { } + + /** + * Set entry point, which the activation serves + * + * This function is only called by the 'Pager_entrypoint' + * constructor. + */ + void ep(Pager_entrypoint *ep) { _ep = ep; } + + /** + * Thread interface + */ + void entry(); + + /** + * Return capability to this activation + * + * This function should only be called from 'Pager_entrypoint' + */ + Native_capability cap() + { + /* ensure that the initialization of our 'Ipc_pager' is done */ + if (!_cap.valid()) + _cap_valid.lock(); + return _cap; + } +}; + + +/** + * Paging entry point + * + * For a paging entry point can hold only one activation. So, paging is + * strictly serialized for one entry point. + */ +class Genode::Pager_entrypoint : public Object_pool +{ + private: + + Pager_activation_base *_activation; + Cap_session *_cap_session; + + public: + + /** + * Constructor + * + * \param cap_session Cap_session for creating capabilities + * for the pager objects managed by this + * entry point + * \param a initial activation + */ + Pager_entrypoint(Cap_session *cap_session, Pager_activation_base *a = 0); + + /** + * Associate Pager_object with the entry point + */ + Pager_capability manage(Pager_object *obj); + + /** + * Dissolve Pager_object from entry point + */ + void dissolve(Pager_object *obj); +}; + + +template +class Genode::Pager_activation : public Pager_activation_base +{ + public: + + Pager_activation() : Pager_activation_base("pager", STACK_SIZE) + { start(); } +}; + #endif /* _INCLUDE__BASE__PAGER_H_ */ diff --git a/repos/base/include/base/process.h b/repos/base/include/base/process.h index 22be44f34..e95303d7c 100644 --- a/repos/base/include/base/process.h +++ b/repos/base/include/base/process.h @@ -20,76 +20,76 @@ #include #include -namespace Genode { +namespace Genode { class Process; } - class Process - { - private: - Pd_connection _pd; - Thread_capability _thread0_cap; - Cpu_session_client _cpu_session_client; - Rm_session_client _rm_session_client; +class Genode::Process +{ + private: - static Dataspace_capability _dynamic_linker_cap; + Pd_connection _pd; + Thread_capability _thread0_cap; + Cpu_session_client _cpu_session_client; + Rm_session_client _rm_session_client; - /* - * Hook for passing additional platform-specific session - * arguments to the PD session. For example, on Linux a new - * process is created locally via 'fork' and the new PID gets - * then communicated to core via a PD-session argument. - */ - enum { PRIV_ARGBUF_LEN = 32 }; - char _priv_pd_argbuf[PRIV_ARGBUF_LEN]; - const char *_priv_pd_args(Parent_capability parent_cap, - Dataspace_capability elf_data_ds, - const char *name, char *const argv[]); + static Dataspace_capability _dynamic_linker_cap; - public: + /* + * Hook for passing additional platform-specific session + * arguments to the PD session. For example, on Linux a new + * process is created locally via 'fork' and the new PID gets + * then communicated to core via a PD-session argument. + */ + enum { PRIV_ARGBUF_LEN = 32 }; + char _priv_pd_argbuf[PRIV_ARGBUF_LEN]; + const char *_priv_pd_args(Parent_capability parent_cap, + Dataspace_capability elf_data_ds, + const char *name, char *const argv[]); - /** - * Constructor - * - * \param elf_data_ds dataspace that contains the elf binary - * \param ram_session RAM session providing the BSS for the - * new protection domain - * \param cpu_session CPU session for the new protection domain - * \param rm_session RM session for the new protection domain - * \param parent parent of the new protection domain - * \param name name of protection domain (can be used - * for debugging) - * \param pd_args platform-specific arguments supplied to - * the PD session of the process - * - * The dataspace 'elf_data_ds' can be read-only. - * - * On construction of a protection domain, execution of the initial - * thread is started immediately. - */ - Process(Dataspace_capability elf_data_ds, - Ram_session_capability ram_session, - Cpu_session_capability cpu_session, - Rm_session_capability rm_session, - Parent_capability parent, - char const *name, - Native_pd_args const *args = 0); + public: - /** - * Destructor - * - * When called, the protection domain gets killed. - */ - ~Process(); + /** + * Constructor + * + * \param elf_data_ds dataspace that contains the elf binary + * \param ram_session RAM session providing the BSS for the + * new protection domain + * \param cpu_session CPU session for the new protection domain + * \param rm_session RM session for the new protection domain + * \param parent parent of the new protection domain + * \param name name of protection domain (can be used + * for debugging) + * \param pd_args platform-specific arguments supplied to + * the PD session of the process + * + * The dataspace 'elf_data_ds' can be read-only. + * + * On construction of a protection domain, execution of the initial + * thread is started immediately. + */ + Process(Dataspace_capability elf_data_ds, + Ram_session_capability ram_session, + Cpu_session_capability cpu_session, + Rm_session_capability rm_session, + Parent_capability parent, + char const *name, + Native_pd_args const *args = 0); - static void dynamic_linker(Dataspace_capability dynamic_linker_cap) - { - _dynamic_linker_cap = dynamic_linker_cap; - } + /** + * Destructor + * + * When called, the protection domain gets killed. + */ + ~Process(); - Pd_session_capability pd_session_cap() const { return _pd.cap(); } + static void dynamic_linker(Dataspace_capability dynamic_linker_cap) + { + _dynamic_linker_cap = dynamic_linker_cap; + } - Thread_capability main_thread_cap() const { return _thread0_cap; } - }; -} + Pd_session_capability pd_session_cap() const { return _pd.cap(); } + + Thread_capability main_thread_cap() const { return _thread0_cap; } +}; #endif /* _INCLUDE__BASE__PROCESS_H_ */ diff --git a/repos/base/include/base/rpc_args.h b/repos/base/include/base/rpc_args.h index fe442d159..e232951fc 100644 --- a/repos/base/include/base/rpc_args.h +++ b/repos/base/include/base/rpc_args.h @@ -19,103 +19,107 @@ namespace Genode { - /** - * Base class of 'Rpc_in_buffer' - */ - class Rpc_in_buffer_base - { - protected: - - const char *_base; - size_t _size; - - /** - * Construct buffer from null-terminated string - */ - explicit Rpc_in_buffer_base(const char *str) - : _base(str), _size(strlen(str) + 1) { } - - /** - * Construct an empty buffer by default - */ - Rpc_in_buffer_base(): _base(0), _size(0) { } - - public: - - /** - * Construct buffer - */ - Rpc_in_buffer_base(const char *base, size_t size) - : _base(base), _size(size) { } - - const char *base() const { return _base; } - size_t size() const { return _size; } - }; - - - /** - * Buffer with size constrain - */ - template - class Rpc_in_buffer : public Rpc_in_buffer_base - { - private: - - /* - * This member is only there to pump up the size of the object such - * that 'sizeof()' returns the maximum buffer size when queried by - * the RPC framework. - */ - char _balloon[MAX]; - - public: - - enum { MAX_SIZE = MAX }; - - /** - * Construct buffer - */ - Rpc_in_buffer(const char *base, size_t size) - : Rpc_in_buffer_base(base, min(size, (size_t)MAX_SIZE)) { } - - /** - * Construct buffer from null-terminated string - */ - Rpc_in_buffer(const char *str) : Rpc_in_buffer_base(str) - { - if (_size >= MAX_SIZE - 1) - _size = MAX_SIZE - 1; - } - - /** - * Default constructor creates invalid buffer - */ - Rpc_in_buffer() { } - - void operator = (Rpc_in_buffer const &from) - { - _base = from.base(); - _size = from.size(); - } - - /** - * Return true if buffer contains a valid null-terminated string - */ - bool is_valid_string() const { - return (_size < MAX_SIZE) && (_size > 0) && (_base[_size - 1] == '\0'); } - - /** - * Return buffer content as null-terminated string - * - * \return pointer to null-terminated string - * - * The function returns an empty string if the buffer does not hold - * a valid null-terminated string. To distinguish a buffer holding - * an invalid string from a buffer holding a valid empty string, - * the function 'is_valid_string' can be used. - */ - char const *string() const { return is_valid_string() ? base() : ""; } - }; + class Rpc_in_buffer_base; + template class Rpc_in_buffer; } + +/** + * Base class of 'Rpc_in_buffer' + */ +class Genode::Rpc_in_buffer_base +{ + protected: + + const char *_base; + size_t _size; + + /** + * Construct buffer from null-terminated string + */ + explicit Rpc_in_buffer_base(const char *str) + : _base(str), _size(strlen(str) + 1) { } + + /** + * Construct an empty buffer by default + */ + Rpc_in_buffer_base(): _base(0), _size(0) { } + + public: + + /** + * Construct buffer + */ + Rpc_in_buffer_base(const char *base, size_t size) + : _base(base), _size(size) { } + + const char *base() const { return _base; } + size_t size() const { return _size; } +}; + + +/** + * Buffer with size constrain + */ +template +class Genode::Rpc_in_buffer : public Rpc_in_buffer_base +{ + private: + + /* + * This member is only there to pump up the size of the object such + * that 'sizeof()' returns the maximum buffer size when queried by + * the RPC framework. + */ + char _balloon[MAX]; + + public: + + enum { MAX_SIZE = MAX }; + + /** + * Construct buffer + */ + Rpc_in_buffer(const char *base, size_t size) + : Rpc_in_buffer_base(base, min(size, (size_t)MAX_SIZE)) { } + + /** + * Construct buffer from null-terminated string + */ + Rpc_in_buffer(const char *str) : Rpc_in_buffer_base(str) + { + if (_size >= MAX_SIZE - 1) + _size = MAX_SIZE - 1; + } + + /** + * Default constructor creates invalid buffer + */ + Rpc_in_buffer() { } + + void operator = (Rpc_in_buffer const &from) + { + _base = from.base(); + _size = from.size(); + } + + /** + * Return true if buffer contains a valid null-terminated string + */ + bool is_valid_string() const { + return (_size < MAX_SIZE) && (_size > 0) && (_base[_size - 1] == '\0'); } + + /** + * Return buffer content as null-terminated string + * + * \return pointer to null-terminated string + * + * The function returns an empty string if the buffer does not hold + * a valid null-terminated string. To distinguish a buffer holding + * an invalid string from a buffer holding a valid empty string, + * the function 'is_valid_string' can be used. + */ + char const *string() const { return is_valid_string() ? base() : ""; } +}; + #endif /* _INCLUDE__BASE__RPC_ARGS_H_ */ diff --git a/repos/base/include/base/rpc_server.h b/repos/base/include/base/rpc_server.h index 85ca9f935..528b4cb2c 100644 --- a/repos/base/include/base/rpc_server.h +++ b/repos/base/include/base/rpc_server.h @@ -24,370 +24,375 @@ #include namespace Genode { + template class Rpc_dispatcher; + class Rpc_object_base; + template struct Rpc_object; + class Rpc_entrypoint; +} + +/** + * RPC dispatcher implementing the specified RPC interface + * + * \param RPC_INTERFACE class providing the RPC interface description + * \param SERVER class to invoke for the server-side RPC functions + * + * This class is the base class of each server-side RPC implementation. It + * contains the logic for dispatching incoming RPC requests and calls the + * server functions according to the RPC declarations in 'RPC_INTERFACE'. + * + * If using the default argument for 'SERVER', the 'RPC_INTERFACE' is expected + * to contain the abstract interface for all RPC functions. So virtual functions + * must be declared in 'RPC_INTERFACE'. In contrast, by explicitly specifying + * the 'SERVER' argument, the server-side dispatching performs direct function + * calls to the respective member functions of the 'SERVER' class and thereby + * omits virtual functions calls. + */ +template +class Genode::Rpc_dispatcher : public RPC_INTERFACE +{ /** - * RPC dispatcher implementing the specified RPC interface - * - * \param RPC_INTERFACE class providing the RPC interface description - * \param SERVER class to invoke for the server-side RPC functions - * - * This class is the base class of each server-side RPC implementation. It - * contains the logic for dispatching incoming RPC requests and calls the - * server functions according to the RPC declarations in 'RPC_INTERFACE'. - * - * If using the default argument for 'SERVER', the 'RPC_INTERFACE' is expected - * to contain the abstract interface for all RPC functions. So virtual functions - * must be declared in 'RPC_INTERFACE'. In contrast, by explicitly specifying - * the 'SERVER' argument, the server-side dispatching performs direct function - * calls to the respective member functions of the 'SERVER' class and thereby - * omits virtual functions calls. + * Shortcut for the type list of RPC functions provided by this server + * component */ - template - class Rpc_dispatcher : public RPC_INTERFACE - { - /** - * Shortcut for the type list of RPC functions provided by this server - * component - */ - typedef typename RPC_INTERFACE::Rpc_functions Rpc_functions; + typedef typename RPC_INTERFACE::Rpc_functions Rpc_functions; - protected: + protected: - template - void _read_args(Ipc_istream &is, ARG_LIST &args) - { - if (Trait::Rpc_direction::Type::IN) - is >> args._1; + template + void _read_args(Ipc_istream &is, ARG_LIST &args) + { + if (Trait::Rpc_direction::Type::IN) + is >> args._1; - _read_args(is, args._2); - } + _read_args(is, args._2); + } - void _read_args(Ipc_istream &, Meta::Empty) { } + void _read_args(Ipc_istream &, Meta::Empty) { } - template - void _write_results(Ipc_ostream &os, ARG_LIST &args) - { - if (Trait::Rpc_direction::Type::OUT) - os << args._1; + template + void _write_results(Ipc_ostream &os, ARG_LIST &args) + { + if (Trait::Rpc_direction::Type::OUT) + os << args._1; - _write_results(os, args._2); - } + _write_results(os, args._2); + } - void _write_results(Ipc_ostream &, Meta::Empty) { } + void _write_results(Ipc_ostream &, Meta::Empty) { } - template - Rpc_exception_code _do_serve(typename RPC_FUNCTION::Server_args &args, - typename RPC_FUNCTION::Ret_type &ret, - Meta::Overload_selector) - { - enum { EXCEPTION_CODE = RPC_EXCEPTION_BASE - Meta::Length::Value }; - try { - typedef typename EXC_TL::Tail Exc_tail; - return _do_serve(args, ret, - Meta::Overload_selector()); - } catch (typename EXC_TL::Head) { return EXCEPTION_CODE; } - } + template + Rpc_exception_code _do_serve(typename RPC_FUNCTION::Server_args &args, + typename RPC_FUNCTION::Ret_type &ret, + Meta::Overload_selector) + { + enum { EXCEPTION_CODE = RPC_EXCEPTION_BASE - Meta::Length::Value }; + try { + typedef typename EXC_TL::Tail Exc_tail; + return _do_serve(args, ret, + Meta::Overload_selector()); + } catch (typename EXC_TL::Head) { return EXCEPTION_CODE; } + } - template - Rpc_exception_code _do_serve(typename RPC_FUNCTION::Server_args &args, - typename RPC_FUNCTION::Ret_type &ret, - Meta::Overload_selector) - { - RPC_FUNCTION::serve(*static_cast(this), args, ret); - return 0; - } + template + Rpc_exception_code _do_serve(typename RPC_FUNCTION::Server_args &args, + typename RPC_FUNCTION::Ret_type &ret, + Meta::Overload_selector) + { + RPC_FUNCTION::serve(*static_cast(this), args, ret); + return 0; + } - template - Rpc_exception_code _do_dispatch(Rpc_opcode opcode, Ipc_istream &is, Ipc_ostream &os, - Meta::Overload_selector) - { - using namespace Meta; + template + Rpc_exception_code _do_dispatch(Rpc_opcode opcode, Ipc_istream &is, Ipc_ostream &os, + Meta::Overload_selector) + { + using namespace Meta; - typedef typename RPC_FUNCTIONS_TO_CHECK::Head This_rpc_function; + typedef typename RPC_FUNCTIONS_TO_CHECK::Head This_rpc_function; - if (opcode == Index_of::Value) { + if (opcode == Index_of::Value) { - typename This_rpc_function::Server_args args{}; + typename This_rpc_function::Server_args args{}; - /* read arguments from istream */ - _read_args(is, args); + /* read arguments from istream */ + _read_args(is, args); - { - Trace::Rpc_dispatch trace_event(This_rpc_function::name()); - } - - /* - * Dispatch call to matching RPC base class, using - * 'This_rpc_function' and the list of its exceptions to - * select the overload. - */ - typedef typename This_rpc_function::Exceptions Exceptions; - - typename This_rpc_function::Ret_type ret; - Rpc_exception_code exc; - exc = _do_serve(args, ret, Overload_selector()); - os << ret; - - { - Trace::Rpc_reply trace_event(This_rpc_function::name()); - } - - /* write results to ostream 'os' */ - _write_results(os, args); - - return exc; + { + Trace::Rpc_dispatch trace_event(This_rpc_function::name()); } - typedef typename RPC_FUNCTIONS_TO_CHECK::Tail Tail; - return _do_dispatch(opcode, is, os, Overload_selector()); + /* + * Dispatch call to matching RPC base class, using + * 'This_rpc_function' and the list of its exceptions to + * select the overload. + */ + typedef typename This_rpc_function::Exceptions Exceptions; + + typename This_rpc_function::Ret_type ret; + Rpc_exception_code exc; + exc = _do_serve(args, ret, Overload_selector()); + os << ret; + + { + Trace::Rpc_reply trace_event(This_rpc_function::name()); + } + + /* write results to ostream 'os' */ + _write_results(os, args); + + return exc; } - int _do_dispatch(int opcode, Ipc_istream &, Ipc_ostream &, - Meta::Overload_selector) - { - PERR("invalid opcode %d\n", opcode); - return RPC_INVALID_OPCODE; - } + typedef typename RPC_FUNCTIONS_TO_CHECK::Tail Tail; + return _do_dispatch(opcode, is, os, Overload_selector()); + } - /** - * Handle corner case of having an RPC interface with no RPC functions - */ - Rpc_exception_code _do_dispatch(int opcode, Ipc_istream &, Ipc_ostream &, - Meta::Overload_selector >) - { - return 0; - } + int _do_dispatch(int opcode, Ipc_istream &, Ipc_ostream &, + Meta::Overload_selector) + { + PERR("invalid opcode %d\n", opcode); + return RPC_INVALID_OPCODE; + } - /** - * Protected constructor - * - * This class is only usable as base class. - */ - Rpc_dispatcher() { } + /** + * Handle corner case of having an RPC interface with no RPC functions + */ + Rpc_exception_code _do_dispatch(int opcode, Ipc_istream &, Ipc_ostream &, + Meta::Overload_selector >) + { + return 0; + } - public: + /** + * Protected constructor + * + * This class is only usable as base class. + */ + Rpc_dispatcher() { } - Rpc_exception_code dispatch(int opcode, Ipc_istream &is, Ipc_ostream &os) - { - return _do_dispatch(opcode, is, os, - Meta::Overload_selector()); - } - }; - - - class Rpc_object_base : public Object_pool::Entry - { - public: - - virtual ~Rpc_object_base() { } - - /** - * Interface to be implemented by a derived class - * - * \param op opcode of invoked method - * \param is Ipc_input stream with method arguments - * \param os Ipc_output stream for storing method results - */ - virtual int dispatch(int op, Ipc_istream &is, Ipc_ostream &os) = 0; - }; - - - /** - * Object that is accessible from remote protection domains - * - * A 'Rpc_object' is a locally implemented object that can be referenced - * from the outer world using a capability. The capability gets created - * when attaching a 'Rpc_object' to a 'Rpc_entrypoint'. - */ - template - struct Rpc_object : Rpc_object_base, Rpc_dispatcher - { - /***************************** - ** Server-object interface ** - *****************************/ + public: Rpc_exception_code dispatch(int opcode, Ipc_istream &is, Ipc_ostream &os) { - return Rpc_dispatcher::dispatch(opcode, is, os); + return _do_dispatch(opcode, is, os, + Meta::Overload_selector()); } - - Capability const cap() const - { - return reinterpret_cap_cast(Rpc_object_base::cap()); - } - }; +}; - /** - * RPC entrypoint serving RPC objects - * - * The entrypoint's thread will initialize its capability but will not - * immediately enable the processing of requests. This way, the - * activation-using server can ensure that it gets initialized completely - * before the first capability invocations come in. Once the server is - * ready, it must enable the entrypoint explicitly by calling the - * 'activate()' function. The 'start_on_construction' argument is a - * shortcut for the common case where the server's capability is handed - * over to other parties _after_ the server is completely initialized. - */ - class Rpc_entrypoint : Thread_base, public Object_pool +class Genode::Rpc_object_base : public Object_pool::Entry +{ + public: + + virtual ~Rpc_object_base() { } + + /** + * Interface to be implemented by a derived class + * + * \param op opcode of invoked method + * \param is Ipc_input stream with method arguments + * \param os Ipc_output stream for storing method results + */ + virtual int dispatch(int op, Ipc_istream &is, Ipc_ostream &os) = 0; +}; + + +/** + * Object that is accessible from remote protection domains + * + * A 'Rpc_object' is a locally implemented object that can be referenced + * from the outer world using a capability. The capability gets created + * when attaching a 'Rpc_object' to a 'Rpc_entrypoint'. + */ +template +struct Genode::Rpc_object : Rpc_object_base, Rpc_dispatcher +{ + /***************************** + ** Server-object interface ** + *****************************/ + + Rpc_exception_code dispatch(int opcode, Ipc_istream &is, Ipc_ostream &os) { - private: + return Rpc_dispatcher::dispatch(opcode, is, os); + } - /** - * Prototype capability to derive capabilities for RPC objects - * from. - */ - Untyped_capability _cap; + Capability const cap() const + { + return reinterpret_cap_cast(Rpc_object_base::cap()); + } +}; - enum { SND_BUF_SIZE = 1024, RCV_BUF_SIZE = 1024 }; - Msgbuf _snd_buf; - Msgbuf _rcv_buf; - /** - * Hook to let low-level thread init code access private members - * - * This function is only used on NOVA. - */ - static void _activation_entry(); +/** + * RPC entrypoint serving RPC objects + * + * The entrypoint's thread will initialize its capability but will not + * immediately enable the processing of requests. This way, the + * activation-using server can ensure that it gets initialized completely + * before the first capability invocations come in. Once the server is + * ready, it must enable the entrypoint explicitly by calling the + * 'activate()' function. The 'start_on_construction' argument is a + * shortcut for the common case where the server's capability is handed + * over to other parties _after_ the server is completely initialized. + */ +class Genode::Rpc_entrypoint : Thread_base, public Object_pool +{ + private: - struct Exit - { - GENODE_RPC(Rpc_exit, void, _exit); - GENODE_RPC_INTERFACE(Rpc_exit); - }; + /** + * Prototype capability to derive capabilities for RPC objects + * from. + */ + Untyped_capability _cap; - struct Exit_handler : Rpc_object - { - int exit; + enum { SND_BUF_SIZE = 1024, RCV_BUF_SIZE = 1024 }; + Msgbuf _snd_buf; + Msgbuf _rcv_buf; - Exit_handler() : exit(false) { } + /** + * Hook to let low-level thread init code access private members + * + * This function is only used on NOVA. + */ + static void _activation_entry(); - void _exit() { exit = true; } - }; + struct Exit + { + GENODE_RPC(Rpc_exit, void, _exit); + GENODE_RPC_INTERFACE(Rpc_exit); + }; - protected: + struct Exit_handler : Rpc_object + { + int exit; - Ipc_server *_ipc_server; - Rpc_object_base *_curr_obj; /* currently dispatched RPC object */ - Lock _curr_obj_lock; /* for the protection of '_curr_obj' */ - Lock _cap_valid; /* thread startup synchronization */ - Lock _delay_start; /* delay start of request dispatching */ - Lock _delay_exit; /* delay destructor until server settled */ - Cap_session *_cap_session; /* for creating capabilities */ - Exit_handler _exit_handler; - Capability _exit_cap; + Exit_handler() : exit(false) { } - /** - * Back-end function to associate RPC object with the entry point - */ - Untyped_capability _manage(Rpc_object_base *obj); + void _exit() { exit = true; } + }; - /** - * Back-end function to Dissolve RPC object from entry point - */ - void _dissolve(Rpc_object_base *obj); + protected: - /** - * Force activation to cancel dispatching the specified server object - */ - void _leave_server_object(Rpc_object_base *obj); + Ipc_server *_ipc_server; + Rpc_object_base *_curr_obj; /* currently dispatched RPC object */ + Lock _curr_obj_lock; /* for the protection of '_curr_obj' */ + Lock _cap_valid; /* thread startup synchronization */ + Lock _delay_start; /* delay start of request dispatching */ + Lock _delay_exit; /* delay destructor until server settled */ + Cap_session *_cap_session; /* for creating capabilities */ + Exit_handler _exit_handler; + Capability _exit_cap; - /** - * Wait until the entrypoint activation is initialized - */ - void _block_until_cap_valid(); + /** + * Back-end function to associate RPC object with the entry point + */ + Untyped_capability _manage(Rpc_object_base *obj); - /** - * Thread interface - */ - void entry(); + /** + * Back-end function to Dissolve RPC object from entry point + */ + void _dissolve(Rpc_object_base *obj); - public: + /** + * Force activation to cancel dispatching the specified server object + */ + void _leave_server_object(Rpc_object_base *obj); - /** - * Constructor - * - * \param cap_session 'Cap_session' for creating capabilities - * for the RPC objects managed by this entry - * point - * \param stack_size stack size of entrypoint thread - * \param name name of entrypoint thread - * \param location CPU affinity - */ - Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, - char const *name, bool start_on_construction = true, - Affinity::Location location = Affinity::Location()); + /** + * Wait until the entrypoint activation is initialized + */ + void _block_until_cap_valid(); - ~Rpc_entrypoint(); + /** + * Thread interface + */ + void entry(); - /** - * Associate RPC object with the entry point - */ - template - Capability - manage(Rpc_object *obj) - { - return reinterpret_cap_cast(_manage(obj)); - } + public: - /** - * Dissolve RPC object from entry point - */ - template - void dissolve(Rpc_object *obj) - { - _dissolve(obj); - } + /** + * Constructor + * + * \param cap_session 'Cap_session' for creating capabilities + * for the RPC objects managed by this entry + * point + * \param stack_size stack size of entrypoint thread + * \param name name of entrypoint thread + * \param location CPU affinity + */ + Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, + char const *name, bool start_on_construction = true, + Affinity::Location location = Affinity::Location()); - /** - * Activate entrypoint, start processing RPC requests - */ - void activate(); + ~Rpc_entrypoint(); - /** - * Request reply capability for current call - * - * Note: This is a temporary API function, which is going to be - * removed. Please do not use this function. - * - * Typically, a capability obtained via this function is used as - * argument of 'intermediate_reply'. - */ - Untyped_capability reply_dst(); + /** + * Associate RPC object with the entry point + */ + template + Capability + manage(Rpc_object *obj) + { + return reinterpret_cap_cast(_manage(obj)); + } - /** - * Prevent reply of current request - * - * Note: This is a temporary API function, which is going to be - * removed. Please do not use this function. - * - * This function can be used to keep the calling client blocked - * after the server has finished the processing of the client's - * request. At a later time, the server may chose to unblock the - * client via the 'intermedate_reply' function. - */ - void omit_reply(); + /** + * Dissolve RPC object from entry point + */ + template + void dissolve(Rpc_object *obj) + { + _dissolve(obj); + } - /** - * Send a reply out of the normal call-reply order - * - * Note: This is a temporary API function, which is going to be - * removed. Please do not use this function. - * - * In combination with the 'reply_dst' accessor functions, this - * function can be used to implement services that dispatch client - * requests out of order. In such cases, the server activation may - * send reply messages to multiple blocking clients before - * answering the original call. - */ - void explicit_reply(Untyped_capability reply_cap, int return_value); + /** + * Activate entrypoint, start processing RPC requests + */ + void activate(); - /** - * Return true if the caller corresponds to the entrypoint called - */ - bool is_myself() const; - }; -} + /** + * Request reply capability for current call + * + * Note: This is a temporary API function, which is going to be + * removed. Please do not use this function. + * + * Typically, a capability obtained via this function is used as + * argument of 'intermediate_reply'. + */ + Untyped_capability reply_dst(); + + /** + * Prevent reply of current request + * + * Note: This is a temporary API function, which is going to be + * removed. Please do not use this function. + * + * This function can be used to keep the calling client blocked + * after the server has finished the processing of the client's + * request. At a later time, the server may chose to unblock the + * client via the 'intermedate_reply' function. + */ + void omit_reply(); + + /** + * Send a reply out of the normal call-reply order + * + * Note: This is a temporary API function, which is going to be + * removed. Please do not use this function. + * + * In combination with the 'reply_dst' accessor functions, this + * function can be used to implement services that dispatch client + * requests out of order. In such cases, the server activation may + * send reply messages to multiple blocking clients before + * answering the original call. + */ + void explicit_reply(Untyped_capability reply_cap, int return_value); + + /** + * Return true if the caller corresponds to the entrypoint called + */ + bool is_myself() const; +}; #endif /* _INCLUDE__BASE__RPC_SERVER_H_ */ diff --git a/repos/base/include/base/semaphore.h b/repos/base/include/base/semaphore.h index d5f979a27..7adeb0943 100644 --- a/repos/base/include/base/semaphore.h +++ b/repos/base/include/base/semaphore.h @@ -21,150 +21,157 @@ namespace Genode { + struct Semaphore_queue; + class Fifo_semaphore_queue; + + template class Semaphore_template; +} + + +/** + * Semaphore queue interface + */ +struct Genode::Semaphore_queue +{ /** - * Semaphore queue interface - */ - class Semaphore_queue - { - public: - - /** - * Semaphore-queue elements - * - * A queue element represents a thread blocking on the - * semaphore. - */ - class Element : Lock - { - public: - - /** - * Constructor - */ - Element() : Lock(LOCKED) { } - - void block() { lock(); } - void wake_up() { unlock(); } - }; - - /** - * Add new queue member that is going to block - */ - void enqueue(Element *e); - - /** - * Dequeue queue member to wake up next - */ - Element *dequeue(); - }; - - - /** - * First-in-first-out variant of the semaphore-queue interface - */ - class Fifo_semaphore_queue : public Semaphore_queue - { - public: - - class Element : public Semaphore_queue::Element, - public Fifo::Element { }; - - private: - - Fifo _fifo; - - public: - - void enqueue(Element *e) { _fifo.enqueue(e); } - - Element *dequeue() { return _fifo.dequeue(); } - }; - - - /** - * Semaphore base template + * Semaphore-queue elements * - * \param QT semaphore wait queue type implementing the - * 'Semaphore_queue' interface - * \param QTE wait-queue element type implementing the - * 'Semaphore_queue::Element' interface - * - * The queuing policy is defined via the QT and QTE types. - * This way, the platform-specific semaphore-queueing policies - * such as priority-sorted queueing can be easily supported. + * A queue element represents a thread blocking on the + * semaphore. */ - template - class Semaphore_template + class Element : Lock { - protected: - - int _cnt; - Lock _meta_lock; - QT _queue; - public: /** * Constructor - * - * \param n initial counter value of the semphore */ - Semaphore_template(int n = 0) : _cnt(n) { } + Element() : Lock(LOCKED) { } - ~Semaphore_template() - { - /* synchronize destruction with unfinished 'up()' */ - try { _meta_lock.lock(); } catch (...) { } - } - - void up() - { - Lock::Guard lock_guard(_meta_lock); - - if (++_cnt > 0) - return; - - /* - * Remove element from queue and wake up the corresponding - * blocking thread - */ - Semaphore_queue::Element * element = _queue.dequeue(); - if (element) - element->wake_up(); - } - - void down() - { - _meta_lock.lock(); - - if (--_cnt < 0) { - - /* - * Create semaphore queue element representing the thread - * in the wait queue. - */ - QTE queue_element; - _queue.enqueue(&queue_element); - _meta_lock.unlock(); - - /* - * The thread is going to block on a local lock now, - * waiting for getting waked from another thread - * calling 'up()' - * */ - queue_element.block(); - - } else { - _meta_lock.unlock(); - } - } - - /** - * Return current semaphore counter - */ - int cnt() { return _cnt; } + void block() { lock(); } + void wake_up() { unlock(); } }; + /** + * Add new queue member that is going to block + */ + void enqueue(Element *e); + + /** + * Dequeue queue member to wake up next + */ + Element *dequeue(); +}; + + +/** + * First-in-first-out variant of the semaphore-queue interface + */ +class Genode::Fifo_semaphore_queue : public Semaphore_queue +{ + public: + + class Element : public Semaphore_queue::Element, + public Fifo::Element { }; + + private: + + Fifo _fifo; + + public: + + void enqueue(Element *e) { _fifo.enqueue(e); } + + Element *dequeue() { return _fifo.dequeue(); } +}; + + +/** + * Semaphore base template + * + * \param QT semaphore wait queue type implementing the + * 'Semaphore_queue' interface + * \param QTE wait-queue element type implementing the + * 'Semaphore_queue::Element' interface + * + * The queuing policy is defined via the QT and QTE types. + * This way, the platform-specific semaphore-queueing policies + * such as priority-sorted queueing can be easily supported. + */ +template +class Genode::Semaphore_template +{ + protected: + + int _cnt; + Lock _meta_lock; + QT _queue; + + public: + + /** + * Constructor + * + * \param n initial counter value of the semphore + */ + Semaphore_template(int n = 0) : _cnt(n) { } + + ~Semaphore_template() + { + /* synchronize destruction with unfinished 'up()' */ + try { _meta_lock.lock(); } catch (...) { } + } + + void up() + { + Lock::Guard lock_guard(_meta_lock); + + if (++_cnt > 0) + return; + + /* + * Remove element from queue and wake up the corresponding + * blocking thread + */ + Semaphore_queue::Element * element = _queue.dequeue(); + if (element) + element->wake_up(); + } + + void down() + { + _meta_lock.lock(); + + if (--_cnt < 0) { + + /* + * Create semaphore queue element representing the thread + * in the wait queue. + */ + QTE queue_element; + _queue.enqueue(&queue_element); + _meta_lock.unlock(); + + /* + * The thread is going to block on a local lock now, + * waiting for getting waked from another thread + * calling 'up()' + * */ + queue_element.block(); + + } else { + _meta_lock.unlock(); + } + } + + /** + * Return current semaphore counter + */ + int cnt() { return _cnt; } +}; + + +namespace Genode { /** * Semaphore with default behaviour diff --git a/repos/base/include/base/service.h b/repos/base/include/base/service.h index e9400c17b..1940efd64 100644 --- a/repos/base/include/base/service.h +++ b/repos/base/include/base/service.h @@ -22,424 +22,433 @@ namespace Genode { - /** - * Client role - * - * A client is someone who applies for a service. If the service is not - * available yet, we enqueue the client into a wait queue and wake him up - * as soon as the requested service gets available. - */ - class Client : public List::Element - { - private: - - Cancelable_lock _service_apply_lock; - const char *_apply_for; - - public: - - /** - * Constructor - */ - Client(): _service_apply_lock(Lock::LOCKED), _apply_for(0) { } - - virtual ~Client() { } - - /** - * Set/Request service name that we are currently applying for - */ - void apply_for(const char *apply_for) { _apply_for = apply_for; } - const char *apply_for() { return _apply_for; } - - /** - * Service wait queue support - */ - void sleep() { _service_apply_lock.lock(); } - void wakeup() { _service_apply_lock.unlock(); } - }; - - - /** - * Server role - * - * A server is a process that provides one or multiple services. For the - * most part, this class is used as an opaque key to represent the server - * role. - */ - class Server - { - private: - - Ram_session_capability _ram; - - public: - - /** - * Constructor - * - * \param ram RAM session capability of the server process used, - * for quota transfers from/to the server - */ - Server(Ram_session_capability ram): _ram(ram) { } - - /** - * Return RAM session capability of the server process - */ - Ram_session_capability ram_session_cap() const { return _ram; } - }; - - - class Service : public List::Element - { - public: - - enum { MAX_NAME_LEN = 32 }; - - private: - - char _name[MAX_NAME_LEN]; - - public: - - /********************* - ** Exception types ** - *********************/ - - class Invalid_args { }; - class Unavailable { }; - class Quota_exceeded { }; - - /** - * Constructor - * - * \param name service name - */ - Service(const char *name) { strncpy(_name, name, sizeof(_name)); } - - virtual ~Service() { } - - /** - * Return service name - */ - const char *name() const { return _name; } - - /** - * Create session - * - * \param args session-construction arguments - * \param affinity preferred CPU affinity of session - * - * \throw Invalid_args - * \throw Unavailable - * \throw Quota_exceeded - */ - virtual Session_capability session(char const *args, - Affinity const &affinity) = 0; - - /** - * Extend resource donation to an existing session - */ - virtual void upgrade(Session_capability session, const char *args) = 0; - - /** - * Close session - */ - virtual void close(Session_capability /*session*/) { } - - /** - * Return server providing the service - */ - virtual Server *server() const { return 0; } - - /** - * Return the RAM session to be used for trading resources - */ - Ram_session_capability ram_session_cap() - { - if (server()) - return server()->ram_session_cap(); - return Ram_session_capability(); - } - }; - - - /** - * Representation of a locally implemented service - */ - class Local_service : public Service - { - private: - - Root *_root; - - public: - - Local_service(const char *name, Root *root) - : Service(name), _root(root) { } - - Session_capability session(const char *args, Affinity const &affinity) - { - try { return _root->session(args, affinity); } - catch (Root::Invalid_args) { throw Invalid_args(); } - catch (Root::Unavailable) { throw Unavailable(); } - catch (Root::Quota_exceeded) { throw Quota_exceeded(); } - catch (Genode::Ipc_error) { throw Unavailable(); } - } - - void upgrade(Session_capability session, const char *args) - { - try { _root->upgrade(session, args); } - catch (Genode::Ipc_error) { throw Unavailable(); } - } - - void close(Session_capability session) - { - try { _root->close(session); } - catch (Genode::Ipc_error) { throw Blocking_canceled(); } - } - }; - - - /** - * Representation of a service provided by our parent - */ - class Parent_service : public Service - { - public: - - Parent_service(const char *name) : Service(name) { } - - Session_capability session(const char *args, Affinity const &affinity) - { - try { return env()->parent()->session(name(), args, affinity); } - catch (Parent::Unavailable) { - PWRN("parent has no service \"%s\"", name()); - throw Unavailable(); - } - catch (Parent::Quota_exceeded) { throw Quota_exceeded(); } - catch (Genode::Ipc_error) { throw Unavailable(); } - } - - void upgrade(Session_capability session, const char *args) - { - try { env()->parent()->upgrade(session, args); } - catch (Genode::Ipc_error) { throw Unavailable(); } - } - - void close(Session_capability session) - { - try { env()->parent()->close(session); } - catch (Genode::Ipc_error) { throw Blocking_canceled(); } - } - }; - - - /** - * Representation of a service that is implemented in a child - */ - class Child_service : public Service - { - private: - - Root_capability _root_cap; - Root_client _root; - Server *_server; - - public: - - /** - * Constructor - * - * \param name name of service - * \param root capability to root interface - * \param server server process providing the service - */ - Child_service(const char *name, - Root_capability root, - Server *server) - : Service(name), _root_cap(root), _root(root), _server(server) { } - - Server *server() const { return _server; } - - Session_capability session(const char *args, Affinity const &affinity) - { - if (!_root_cap.valid()) - throw Unavailable(); - - try { return _root.session(args, affinity); } - catch (Root::Invalid_args) { throw Invalid_args(); } - catch (Root::Unavailable) { throw Unavailable(); } - catch (Root::Quota_exceeded) { throw Quota_exceeded(); } - catch (Genode::Ipc_error) { throw Unavailable(); } - } - - void upgrade(Session_capability sc, const char *args) - { - if (!_root_cap.valid()) - throw Unavailable(); - - try { _root.upgrade(sc, args); } - catch (Root::Invalid_args) { throw Invalid_args(); } - catch (Root::Unavailable) { throw Unavailable(); } - catch (Root::Quota_exceeded) { throw Quota_exceeded(); } - catch (Genode::Ipc_error) { throw Unavailable(); } - } - - void close(Session_capability sc) - { - try { _root.close(sc); } - catch (Genode::Ipc_error) { throw Blocking_canceled(); } - } - }; - - - /** - * Container for holding service representations - */ - class Service_registry - { - protected: - - Lock _service_wait_queue_lock; - List _service_wait_queue; - List _services; - - public: - - /** - * Probe for service with specified name - * - * \param name service name - * \param server server providing the service, - * default (0) for any server - */ - Service *find(const char *name, Server *server = 0) - { - if (!name) return 0; - - Lock::Guard lock_guard(_service_wait_queue_lock); - - for (Service *s = _services.first(); s; s = s->next()) - if (strcmp(s->name(), name) == 0 - && (!server || s->server() == server)) return s; - - return 0; - } - - /** - * Check if service name is ambiguous - * - * \return true if the same service is provided multiple - * times - */ - bool is_ambiguous(const char *name) - { - Lock::Guard lock_guard(_service_wait_queue_lock); - - /* count number of services with the specified name */ - unsigned cnt = 0; - for (Service *s = _services.first(); s; s = s->next()) - cnt += (strcmp(s->name(), name) == 0); - return cnt > 1; - } - - /** - * Return first service provided by specified server - */ - Service *find_by_server(Server *server) - { - Lock::Guard lock_guard(_service_wait_queue_lock); - - for (Service *s = _services.first(); s; s = s->next()) - if (s->server() == server) - return s; - - return 0; - } - - /** - * Wait for service - * - * This function is called by the clients's thread - * when requesting a session creation. It blocks - * if the requested service is not available. - * - * \return service structure that matches the request or - * 0 if the waiting was canceled. - */ - Service *wait_for_service(const char *name, Client *client, const char *client_name) - { - Service *service; - - client->apply_for(name); - - _service_wait_queue_lock.lock(); - _service_wait_queue.insert(client); - _service_wait_queue_lock.unlock(); - - do { - service = find(name); - - /* - * The service that we are seeking is not available today. - * Lets sleep a night over it. - */ - if (!service) { - printf("%s: service %s not yet available - sleeping\n", - client_name, name); - - try { - client->sleep(); - printf("%s: service %s got available\n", client_name, name); - } catch (Blocking_canceled) { - printf("%s: cancel waiting for service\n", client_name); - break; - } - } - - } while (!service); - - /* we got what we needed, stop applying */ - _service_wait_queue_lock.lock(); - _service_wait_queue.remove(client); - _service_wait_queue_lock.unlock(); - - client->apply_for(0); - - return service; - } - - /** - * Register service - * - * This function is called by the server's thread. - */ - void insert(Service *service) - { - /* make new service known */ - _services.insert(service); - - /* wake up applicants waiting for the service */ - Lock::Guard lock_guard(_service_wait_queue_lock); - for (Client *c = _service_wait_queue.first(); c; c = c->next()) - if (strcmp(service->name(), c->apply_for()) == 0) - c->wakeup(); - } - - /** - * Unregister service - */ - void remove(Service *service) { _services.remove(service); } - - /** - * Unregister all services - */ - void remove_all() - { - while (_services.first()) - remove(_services.first()); - } - }; + class Client; + class Server; + class Service; + class Local_service; + class Parent_service; + class Child_service; + class Service_registry; } + +/** + * Client role + * + * A client is someone who applies for a service. If the service is not + * available yet, we enqueue the client into a wait queue and wake him up + * as soon as the requested service gets available. + */ +class Genode::Client : public List::Element +{ + private: + + Cancelable_lock _service_apply_lock; + const char *_apply_for; + + public: + + /** + * Constructor + */ + Client(): _service_apply_lock(Lock::LOCKED), _apply_for(0) { } + + virtual ~Client() { } + + /** + * Set/Request service name that we are currently applying for + */ + void apply_for(const char *apply_for) { _apply_for = apply_for; } + const char *apply_for() { return _apply_for; } + + /** + * Service wait queue support + */ + void sleep() { _service_apply_lock.lock(); } + void wakeup() { _service_apply_lock.unlock(); } +}; + + +/** + * Server role + * + * A server is a process that provides one or multiple services. For the + * most part, this class is used as an opaque key to represent the server + * role. + */ +class Genode::Server +{ + private: + + Ram_session_capability _ram; + + public: + + /** + * Constructor + * + * \param ram RAM session capability of the server process used, + * for quota transfers from/to the server + */ + Server(Ram_session_capability ram): _ram(ram) { } + + /** + * Return RAM session capability of the server process + */ + Ram_session_capability ram_session_cap() const { return _ram; } +}; + + +class Genode::Service : public List::Element +{ + public: + + enum { MAX_NAME_LEN = 32 }; + + private: + + char _name[MAX_NAME_LEN]; + + public: + + /********************* + ** Exception types ** + *********************/ + + class Invalid_args { }; + class Unavailable { }; + class Quota_exceeded { }; + + /** + * Constructor + * + * \param name service name + */ + Service(const char *name) { strncpy(_name, name, sizeof(_name)); } + + virtual ~Service() { } + + /** + * Return service name + */ + const char *name() const { return _name; } + + /** + * Create session + * + * \param args session-construction arguments + * \param affinity preferred CPU affinity of session + * + * \throw Invalid_args + * \throw Unavailable + * \throw Quota_exceeded + */ + virtual Session_capability session(char const *args, + Affinity const &affinity) = 0; + + /** + * Extend resource donation to an existing session + */ + virtual void upgrade(Session_capability session, const char *args) = 0; + + /** + * Close session + */ + virtual void close(Session_capability /*session*/) { } + + /** + * Return server providing the service + */ + virtual Server *server() const { return 0; } + + /** + * Return the RAM session to be used for trading resources + */ + Ram_session_capability ram_session_cap() + { + if (server()) + return server()->ram_session_cap(); + return Ram_session_capability(); + } +}; + + +/** + * Representation of a locally implemented service + */ +class Genode::Local_service : public Service +{ + private: + + Root *_root; + + public: + + Local_service(const char *name, Root *root) + : Service(name), _root(root) { } + + Session_capability session(const char *args, Affinity const &affinity) override + { + try { return _root->session(args, affinity); } + catch (Root::Invalid_args) { throw Invalid_args(); } + catch (Root::Unavailable) { throw Unavailable(); } + catch (Root::Quota_exceeded) { throw Quota_exceeded(); } + catch (Genode::Ipc_error) { throw Unavailable(); } + } + + void upgrade(Session_capability session, const char *args) override + { + try { _root->upgrade(session, args); } + catch (Genode::Ipc_error) { throw Unavailable(); } + } + + void close(Session_capability session) override + { + try { _root->close(session); } + catch (Genode::Ipc_error) { throw Blocking_canceled(); } + } +}; + + +/** + * Representation of a service provided by our parent + */ +class Genode::Parent_service : public Service +{ + public: + + Parent_service(const char *name) : Service(name) { } + + Session_capability session(const char *args, Affinity const &affinity) override + { + try { return env()->parent()->session(name(), args, affinity); } + catch (Parent::Unavailable) { + PWRN("parent has no service \"%s\"", name()); + throw Unavailable(); + } + catch (Parent::Quota_exceeded) { throw Quota_exceeded(); } + catch (Genode::Ipc_error) { throw Unavailable(); } + } + + void upgrade(Session_capability session, const char *args) override + { + try { env()->parent()->upgrade(session, args); } + catch (Genode::Ipc_error) { throw Unavailable(); } + } + + void close(Session_capability session) override + { + try { env()->parent()->close(session); } + catch (Genode::Ipc_error) { throw Blocking_canceled(); } + } +}; + + +/** + * Representation of a service that is implemented in a child + */ +class Genode::Child_service : public Service +{ + private: + + Root_capability _root_cap; + Root_client _root; + Server *_server; + + public: + + /** + * Constructor + * + * \param name name of service + * \param root capability to root interface + * \param server server process providing the service + */ + Child_service(const char *name, + Root_capability root, + Server *server) + : Service(name), _root_cap(root), _root(root), _server(server) { } + + Server *server() const override { return _server; } + + Session_capability session(const char *args, Affinity const &affinity) override + { + if (!_root_cap.valid()) + throw Unavailable(); + + try { return _root.session(args, affinity); } + catch (Root::Invalid_args) { throw Invalid_args(); } + catch (Root::Unavailable) { throw Unavailable(); } + catch (Root::Quota_exceeded) { throw Quota_exceeded(); } + catch (Genode::Ipc_error) { throw Unavailable(); } + } + + void upgrade(Session_capability sc, const char *args) override + { + if (!_root_cap.valid()) + throw Unavailable(); + + try { _root.upgrade(sc, args); } + catch (Root::Invalid_args) { throw Invalid_args(); } + catch (Root::Unavailable) { throw Unavailable(); } + catch (Root::Quota_exceeded) { throw Quota_exceeded(); } + catch (Genode::Ipc_error) { throw Unavailable(); } + } + + void close(Session_capability sc) override + { + try { _root.close(sc); } + catch (Genode::Ipc_error) { throw Blocking_canceled(); } + } +}; + + +/** + * Container for holding service representations + */ +class Genode::Service_registry +{ + protected: + + Lock _service_wait_queue_lock; + List _service_wait_queue; + List _services; + + public: + + /** + * Probe for service with specified name + * + * \param name service name + * \param server server providing the service, + * default (0) for any server + */ + Service *find(const char *name, Server *server = 0) + { + if (!name) return 0; + + Lock::Guard lock_guard(_service_wait_queue_lock); + + for (Service *s = _services.first(); s; s = s->next()) + if (strcmp(s->name(), name) == 0 + && (!server || s->server() == server)) return s; + + return 0; + } + + /** + * Check if service name is ambiguous + * + * \return true if the same service is provided multiple + * times + */ + bool is_ambiguous(const char *name) + { + Lock::Guard lock_guard(_service_wait_queue_lock); + + /* count number of services with the specified name */ + unsigned cnt = 0; + for (Service *s = _services.first(); s; s = s->next()) + cnt += (strcmp(s->name(), name) == 0); + return cnt > 1; + } + + /** + * Return first service provided by specified server + */ + Service *find_by_server(Server *server) + { + Lock::Guard lock_guard(_service_wait_queue_lock); + + for (Service *s = _services.first(); s; s = s->next()) + if (s->server() == server) + return s; + + return 0; + } + + /** + * Wait for service + * + * This function is called by the clients's thread + * when requesting a session creation. It blocks + * if the requested service is not available. + * + * \return service structure that matches the request or + * 0 if the waiting was canceled. + */ + Service *wait_for_service(const char *name, Client *client, const char *client_name) + { + Service *service; + + client->apply_for(name); + + _service_wait_queue_lock.lock(); + _service_wait_queue.insert(client); + _service_wait_queue_lock.unlock(); + + do { + service = find(name); + + /* + * The service that we are seeking is not available today. + * Lets sleep a night over it. + */ + if (!service) { + printf("%s: service %s not yet available - sleeping\n", + client_name, name); + + try { + client->sleep(); + printf("%s: service %s got available\n", client_name, name); + } catch (Blocking_canceled) { + printf("%s: cancel waiting for service\n", client_name); + break; + } + } + + } while (!service); + + /* we got what we needed, stop applying */ + _service_wait_queue_lock.lock(); + _service_wait_queue.remove(client); + _service_wait_queue_lock.unlock(); + + client->apply_for(0); + + return service; + } + + /** + * Register service + * + * This function is called by the server's thread. + */ + void insert(Service *service) + { + /* make new service known */ + _services.insert(service); + + /* wake up applicants waiting for the service */ + Lock::Guard lock_guard(_service_wait_queue_lock); + for (Client *c = _service_wait_queue.first(); c; c = c->next()) + if (strcmp(service->name(), c->apply_for()) == 0) + c->wakeup(); + } + + /** + * Unregister service + */ + void remove(Service *service) { _services.remove(service); } + + /** + * Unregister all services + */ + void remove_all() + { + while (_services.first()) + remove(_services.first()); + } +}; + #endif /* _INCLUDE__BASE__SERVICE_H_ */ diff --git a/repos/base/include/base/shared_object.h b/repos/base/include/base/shared_object.h index d5ebeb176..cc7544e0d 100644 --- a/repos/base/include/base/shared_object.h +++ b/repos/base/include/base/shared_object.h @@ -11,10 +11,12 @@ #include namespace Genode { + class Shared_object; struct Address_info; }; + class Genode::Shared_object { private: diff --git a/repos/base/include/base/signal.h b/repos/base/include/base/signal.h index acd3e1cd9..bb52d3c14 100644 --- a/repos/base/include/base/signal.h +++ b/repos/base/include/base/signal.h @@ -30,368 +30,370 @@ namespace Genode { class Signal_receiver; class Signal_context; class Signal_context_registry; - - - /** - * Signal - * - * A signal represents a number of asynchronous notifications produced by - * one transmitter. If notifications are generated at a higher rate than as - * they can be processed at the receiver, the transmitter counts the - * notifications and delivers the total amount with the next signal - * transmission. This way, the total number of notifications gets properly - * communicated to the receiver even if the receiver is not highly - * responsive. - * - * Asynchronous notifications do not carry any payload because this payload - * would need to be queued at the transmitter. However, each transmitter - * imprints a signal-context reference into each signal. This context - * can be used by the receiver to distinguish signals coming from different - * transmitters. - */ - class Signal - { - private: - - struct Data - { - Signal_context *context; - unsigned num; - - /** - * Constructor - * - * \param context signal context specific for the - * signal-receiver capability used for signal - * transmission - * \param num number of signals received from the same - * transmitter - */ - Data(Signal_context *context, unsigned num) - : context(context), num(num) { } - - /** - * Default constructor, representing an invalid signal - */ - Data() : context(0), num(0) { } - - } _data; - - /** - * Constructor - * - * Signal objects are constructed by signal receivers only. - */ - Signal(Data data); - - friend class Kernel::Signal_receiver; - friend class Signal_receiver; - friend class Signal_context; - - void _dec_ref_and_unlock(); - void _inc_ref(); - - public: - - Signal(Signal const &other); - Signal &operator=(Signal const &other); - ~Signal(); - - Signal_context *context() { return _data.context; } - unsigned num() const { return _data.num; } - }; - - - - /** - * Signal transmitter - * - * Each signal-transmitter instance acts on behalf the context specified - * as constructor argument. Therefore, the resources needed for the - * transmitter such as the consumed memory 'sizeof(Signal_transmitter)' - * should be accounted to the owner of the context. - */ - class Signal_transmitter - { - private: - - Signal_context_capability _context; /* destination */ - - public: - - /** - * Constructor - * - * \param context capability to signal context that is going to - * receive signals produced by the transmitter - */ - Signal_transmitter(Signal_context_capability context = Signal_context_capability()); - - /** - * Set signal context - */ - void context(Signal_context_capability context); - - - /** - * Return signal context - */ - Signal_context_capability context(); - - - /** - * Trigger signal submission to context - * - * \param cnt number of signals to submit at once - */ - void submit(unsigned cnt = 1); - }; - - - /** - * Signal receiver - */ - class Signal_receiver : Noncopyable - { - private: - - /** - * Semaphore used to indicate that signal(s) are ready to be picked - * up. This is needed for platforms other than 'base-hw' only. - */ - Semaphore _signal_available; - - /** - * Provides the kernel-object name via the 'dst' method. This is - * needed for 'base-hw' only. - */ - Signal_receiver_capability _cap; - - /** - * List of associated contexts - */ - Lock _contexts_lock; - List > _contexts; - - /** - * Helper to dissolve given context - * - * This function prevents duplicated code in '~Signal_receiver' - * and 'dissolve'. Note that '_contexts_lock' must be held when - * calling this function. - */ - void _unsynchronized_dissolve(Signal_context *context); - - /** - * Hook to platform specific destructor parts - */ - void _platform_destructor(); - - public: - - /** - * Exception class - */ - class Context_already_in_use { }; - class Context_not_associated { }; - - /** - * Constructor - */ - Signal_receiver(); - - /** - * Destructor - */ - ~Signal_receiver(); - - /** - * Manage signal context and return new signal-context capability - * - * \param context context associated with signals delivered to the - * receiver - * \throw 'Context_already_in_use' - * \return new signal-context capability that can be - * passed to a signal transmitter - */ - Signal_context_capability manage(Signal_context *context); - - /** - * Dissolve signal context from receiver - * - * \param context context to remove from receiver - * \throw 'Context_not_associated' - */ - void dissolve(Signal_context *context); - - /** - * Return true if signal was received - */ - bool pending(); - - /** - * Block until a signal is received - * - * \return received signal - */ - Signal wait_for_signal(); - - /** - * Locally submit signal to the receiver - */ - void local_submit(Signal::Data signal); - - /** - * Framework-internal signal-dispatcher - * - * This function is called from the thread that monitors the signal - * source associated with the process. It must not be used for other - * purposes. - */ - static void dispatch_signals(Signal_source *signal_source); - }; - - - /** - * Signal context - * - * A signal context is a destination for signals. One receiver can listen - * to multple contexts. If a signal arrives, the context is provided with the - * signel. This enables the receiver to distinguish different signal sources - * and dispatch incoming signals context-specific. - */ - class Signal_context - { - private: - - /** - * List element in 'Signal_receiver' - */ - List_element _receiver_le; - - /** - * List element in process-global registry - */ - List_element _registry_le; - - /** - * Receiver to which the context is associated with - * - * This member is initialized by the receiver when associating - * the context with the receiver via the 'cap' function. - */ - Signal_receiver *_receiver; - - Lock _lock; /* protect '_curr_signal' */ - Signal::Data _curr_signal; /* most-currently received signal */ - bool _pending; /* current signal is valid */ - unsigned int _ref_cnt; /* number of references to this context */ - Lock _destroy_lock; /* prevent destruction while the - context is in use */ - - - /** - * Capability assigned to this context after being assocated with - * a 'Signal_receiver' via the 'manage' function. We store this - * capability in the 'Signal_context' for the mere reason to - * properly destruct the context (see '_unsynchronized_dissolve'). - */ - Signal_context_capability _cap; - - friend class Signal; - friend class Signal_receiver; - friend class Signal_context_registry; - - public: - - /** - * Constructor - */ - Signal_context() - : _receiver_le(this), _registry_le(this), - _receiver(0), _pending(0), _ref_cnt(0) { } - - /** - * Destructor - * - * The virtual destructor is just there to generate a vtable for - * signal-context objects such that signal contexts can be dynamically - * casted. - */ - virtual ~Signal_context(); - - /** - * Local signal submission (DEPRECATED) - * - * Trigger local signal submission (within the same address space), the - * context has to be bound to a sginal receiver beforehand. - * - * \param num number of pending signals - */ - void submit(unsigned num); - - /* - * Signal contexts are never invoked but only used as arguments for - * 'Signal_session' functions. Hence, there exists a capability - * type for it but no real RPC interface. - */ - GENODE_RPC_INTERFACE(); - }; - - - /** - * Abstract interface to be implemented by signal dispatchers - */ - struct Signal_dispatcher_base : Signal_context - { - virtual void dispatch(unsigned num) = 0; - }; - - - /** - * Adapter for directing signals to member functions - * - * This utility associates member functions with signals. It is intended to - * be used as a member variable of the class that handles incoming signals - * of a certain type. The constructor takes a pointer-to-member to the - * signal handling function as argument. If a signal is received at the - * common signal reception code, this function will be invoked by calling - * 'Signal_dispatcher_base::dispatch'. - * - * \param T type of signal-handling class - */ - template - class Signal_dispatcher : public Signal_dispatcher_base, - public Signal_context_capability - { - private: - - T &obj; - void (T::*member) (unsigned); - Signal_receiver &sig_rec; - - public: - - /** - * Constructor - * - * \param sig_rec signal receiver to associate the signal - * handler with - * \param obj,member object and member function to call when - * the signal occurs - */ - Signal_dispatcher(Signal_receiver &sig_rec, - T &obj, void (T::*member)(unsigned)) - : - Signal_context_capability(sig_rec.manage(this)), - obj(obj), member(member), - sig_rec(sig_rec) - { } - - ~Signal_dispatcher() { sig_rec.dissolve(this); } - - void dispatch(unsigned num) { (obj.*member)(num); } - }; + class Signal_transmitter; + class Signal; + class Signal_dispatcher_base; + template class Signal_dispatcher; } + +/** + * Signal + * + * A signal represents a number of asynchronous notifications produced by + * one transmitter. If notifications are generated at a higher rate than as + * they can be processed at the receiver, the transmitter counts the + * notifications and delivers the total amount with the next signal + * transmission. This way, the total number of notifications gets properly + * communicated to the receiver even if the receiver is not highly + * responsive. + * + * Asynchronous notifications do not carry any payload because this payload + * would need to be queued at the transmitter. However, each transmitter + * imprints a signal-context reference into each signal. This context + * can be used by the receiver to distinguish signals coming from different + * transmitters. + */ +class Genode::Signal +{ + private: + + struct Data + { + Signal_context *context; + unsigned num; + + /** + * Constructor + * + * \param context signal context specific for the + * signal-receiver capability used for signal + * transmission + * \param num number of signals received from the same + * transmitter + */ + Data(Signal_context *context, unsigned num) + : context(context), num(num) { } + + /** + * Default constructor, representing an invalid signal + */ + Data() : context(0), num(0) { } + + } _data; + + /** + * Constructor + * + * Signal objects are constructed by signal receivers only. + */ + Signal(Data data); + + friend class Kernel::Signal_receiver; + friend class Signal_receiver; + friend class Signal_context; + + void _dec_ref_and_unlock(); + void _inc_ref(); + + public: + + Signal(Signal const &other); + Signal &operator=(Signal const &other); + ~Signal(); + + Signal_context *context() { return _data.context; } + unsigned num() const { return _data.num; } +}; + + +/** + * Signal transmitter + * + * Each signal-transmitter instance acts on behalf the context specified + * as constructor argument. Therefore, the resources needed for the + * transmitter such as the consumed memory 'sizeof(Signal_transmitter)' + * should be accounted to the owner of the context. + */ +class Genode::Signal_transmitter +{ + private: + + Signal_context_capability _context; /* destination */ + + public: + + /** + * Constructor + * + * \param context capability to signal context that is going to + * receive signals produced by the transmitter + */ + Signal_transmitter(Signal_context_capability context = Signal_context_capability()); + + /** + * Set signal context + */ + void context(Signal_context_capability context); + + + /** + * Return signal context + */ + Signal_context_capability context(); + + + /** + * Trigger signal submission to context + * + * \param cnt number of signals to submit at once + */ + void submit(unsigned cnt = 1); +}; + + +/** + * Signal receiver + */ +class Genode::Signal_receiver : Noncopyable +{ + private: + + /** + * Semaphore used to indicate that signal(s) are ready to be picked + * up. This is needed for platforms other than 'base-hw' only. + */ + Semaphore _signal_available; + + /** + * Provides the kernel-object name via the 'dst' method. This is + * needed for 'base-hw' only. + */ + Signal_receiver_capability _cap; + + /** + * List of associated contexts + */ + Lock _contexts_lock; + List > _contexts; + + /** + * Helper to dissolve given context + * + * This function prevents duplicated code in '~Signal_receiver' + * and 'dissolve'. Note that '_contexts_lock' must be held when + * calling this function. + */ + void _unsynchronized_dissolve(Signal_context *context); + + /** + * Hook to platform specific destructor parts + */ + void _platform_destructor(); + + public: + + /** + * Exception class + */ + class Context_already_in_use { }; + class Context_not_associated { }; + + /** + * Constructor + */ + Signal_receiver(); + + /** + * Destructor + */ + ~Signal_receiver(); + + /** + * Manage signal context and return new signal-context capability + * + * \param context context associated with signals delivered to the + * receiver + * \throw 'Context_already_in_use' + * \return new signal-context capability that can be + * passed to a signal transmitter + */ + Signal_context_capability manage(Signal_context *context); + + /** + * Dissolve signal context from receiver + * + * \param context context to remove from receiver + * \throw 'Context_not_associated' + */ + void dissolve(Signal_context *context); + + /** + * Return true if signal was received + */ + bool pending(); + + /** + * Block until a signal is received + * + * \return received signal + */ + Signal wait_for_signal(); + + /** + * Locally submit signal to the receiver + */ + void local_submit(Signal::Data signal); + + /** + * Framework-internal signal-dispatcher + * + * This function is called from the thread that monitors the signal + * source associated with the process. It must not be used for other + * purposes. + */ + static void dispatch_signals(Signal_source *signal_source); +}; + + +/** + * Signal context + * + * A signal context is a destination for signals. One receiver can listen + * to multple contexts. If a signal arrives, the context is provided with the + * signel. This enables the receiver to distinguish different signal sources + * and dispatch incoming signals context-specific. + */ +class Genode::Signal_context +{ + private: + + /** + * List element in 'Signal_receiver' + */ + List_element _receiver_le; + + /** + * List element in process-global registry + */ + List_element _registry_le; + + /** + * Receiver to which the context is associated with + * + * This member is initialized by the receiver when associating + * the context with the receiver via the 'cap' function. + */ + Signal_receiver *_receiver; + + Lock _lock; /* protect '_curr_signal' */ + Signal::Data _curr_signal; /* most-currently received signal */ + bool _pending; /* current signal is valid */ + unsigned int _ref_cnt; /* number of references to this context */ + Lock _destroy_lock; /* prevent destruction while the + context is in use */ + + /** + * Capability assigned to this context after being assocated with + * a 'Signal_receiver' via the 'manage' function. We store this + * capability in the 'Signal_context' for the mere reason to + * properly destruct the context (see '_unsynchronized_dissolve'). + */ + Signal_context_capability _cap; + + friend class Signal; + friend class Signal_receiver; + friend class Signal_context_registry; + + public: + + /** + * Constructor + */ + Signal_context() + : _receiver_le(this), _registry_le(this), + _receiver(0), _pending(0), _ref_cnt(0) { } + + /** + * Destructor + * + * The virtual destructor is just there to generate a vtable for + * signal-context objects such that signal contexts can be dynamically + * casted. + */ + virtual ~Signal_context(); + + /** + * Local signal submission (DEPRECATED) + * + * Trigger local signal submission (within the same address space), the + * context has to be bound to a sginal receiver beforehand. + * + * \param num number of pending signals + */ + void submit(unsigned num); + + /* + * Signal contexts are never invoked but only used as arguments for + * 'Signal_session' functions. Hence, there exists a capability + * type for it but no real RPC interface. + */ + GENODE_RPC_INTERFACE(); +}; + + +/** + * Abstract interface to be implemented by signal dispatchers + */ +struct Genode::Signal_dispatcher_base : Signal_context +{ + virtual void dispatch(unsigned num) = 0; +}; + + +/** + * Adapter for directing signals to member functions + * + * This utility associates member functions with signals. It is intended to + * be used as a member variable of the class that handles incoming signals + * of a certain type. The constructor takes a pointer-to-member to the + * signal handling function as argument. If a signal is received at the + * common signal reception code, this function will be invoked by calling + * 'Signal_dispatcher_base::dispatch'. + * + * \param T type of signal-handling class + */ +template +class Genode::Signal_dispatcher : public Signal_dispatcher_base, + public Signal_context_capability +{ + private: + + T &obj; + void (T::*member) (unsigned); + Signal_receiver &sig_rec; + + public: + + /** + * Constructor + * + * \param sig_rec signal receiver to associate the signal + * handler with + * \param obj,member object and member function to call when + * the signal occurs + */ + Signal_dispatcher(Signal_receiver &sig_rec, + T &obj, void (T::*member)(unsigned)) + : + Signal_context_capability(sig_rec.manage(this)), + obj(obj), member(member), + sig_rec(sig_rec) + { } + + ~Signal_dispatcher() { sig_rec.dissolve(this); } + + void dispatch(unsigned num) { (obj.*member)(num); } +}; + #endif /* _INCLUDE__BASE__SIGNAL_H__ */ diff --git a/repos/base/include/base/slab.h b/repos/base/include/base/slab.h index 56e2b6bd2..b00a35d26 100644 --- a/repos/base/include/base/slab.h +++ b/repos/base/include/base/slab.h @@ -20,239 +20,240 @@ namespace Genode { class Slab; + class Slab_block; class Slab_entry; - class Allocator; - - /** - * A slab block holds an array of slab entries. - */ - class Slab_block - { - public: - - Slab_block *next; /* next block */ - Slab_block *prev; /* previous block */ - - private: - - enum { FREE, USED }; - - Slab *_slab; /* back reference to slab allocator */ - unsigned _avail; /* free entries of this block */ - - /* - * Each slab block consists of three areas, a fixed-size header - * that contains the member variables declared above, a byte array - * called state table that holds the allocation state for each slab - * entry, and an area holding the actual slab entries. The number - * of state-table elements corresponds to the maximum number of slab - * entries per slab block (the '_num_elem' member variable of the - * Slab allocator). - */ - - char _data[]; /* dynamic data (state table and slab entries) */ - - /* - * Caution! no member variables allowed below this line! - */ - - /** - * Accessor functions to allocation state - * - * \param idx index of slab entry - */ - inline bool state(int idx) { return _data[idx]; } - inline void state(int idx, bool state) { _data[idx] = state; } - - /** - * Request address of slab entry by its index - */ - Slab_entry *slab_entry(int idx); - - /** - * Determine block index of specified slab entry - */ - int slab_entry_idx(Slab_entry *e); - - public: - - /** - * Constructor - * - * Normally, Slab_blocks are constructed by a Slab allocator - * that specifies itself as constructor argument. - */ - explicit Slab_block(Slab *s = 0) { if (s) slab(s); } - - /** - * Configure block to be managed by the specified slab allocator - */ - void slab(Slab *slab); - - /** - * Request number of available entries in block - */ - unsigned avail() { return _avail; } - - /** - * Allocate slab entry from block - */ - void *alloc(); - - /** - * Return a used slab block entry - */ - Slab_entry *first_used_entry(); - - /** - * These functions are called by Slab_entry. - */ - void inc_avail(Slab_entry *e); - void dec_avail(); - - /** - * Debug and test hooks - */ - void dump(); - int check_bounds(); - }; - - - class Slab_entry - { - private: - - Slab_block *_sb; - char _data[]; - - /* - * Caution! no member variables allowed below this line! - */ - - public: - - void init() { _sb = 0; } - - void occupy(Slab_block *sb) - { - _sb = sb; - _sb->dec_avail(); - } - - void free() - { - _sb->inc_avail(this); - _sb = 0; - } - - void *addr() { return _data; } - - /** - * Lookup Slab_entry by given address - * - * The specified address is supposed to point to _data[0]. - */ - static Slab_entry *slab_entry(void *addr) { - return (Slab_entry *)((addr_t)addr - sizeof(Slab_entry)); } - }; - - - /** - * Slab allocator - */ - class Slab : public Allocator - { - private: - - size_t _slab_size; /* size of one slab entry */ - size_t _block_size; /* size of slab block */ - size_t _num_elem; /* number of slab entries per block */ - Slab_block *_first_sb; /* first slab block */ - Slab_block *_initial_sb; /* initial (static) slab block */ - bool _alloc_state; /* indicator for 'currently in service' */ - - Allocator *_backing_store; - - /** - * Allocate and initialize new slab block - */ - Slab_block *_new_slab_block(); - - public: - - inline size_t slab_size() { return _slab_size; } - inline size_t block_size() { return _block_size; } - inline size_t num_elem() { return _num_elem; } - inline size_t entry_size() { return sizeof(Slab_entry) + _slab_size; } - - /** - * Constructor - * - * At construction time, there exists one initial slab - * block that is used for the first couple of allocations, - * especially for the allocation of the second slab - * block. - */ - Slab(size_t slab_size, size_t block_size, Slab_block *initial_sb, - Allocator *backing_store = 0); - - /** - * Destructor - */ - ~Slab(); - - /** - * Debug function for dumping the current slab block list - */ - void dump_sb_list(); - - /** - * Remove block from slab block list - */ - void remove_sb(Slab_block *sb); - - /** - * Insert block into slab block list - */ - void insert_sb(Slab_block *sb, Slab_block *at = 0); - - /** - * Free slab entry - */ - static void free(void *addr); - - /** - * Return a used slab element - */ - void *first_used_elem(); - - /** - * Return true if number of free slab entries is higher than n - */ - bool num_free_entries_higher_than(int n); - - /** - * Define/request backing-store allocator - */ - void backing_store(Allocator *bs) { _backing_store = bs; } - Allocator *backing_store() { return _backing_store; } - - /************************* - ** Allocator interface ** - *************************/ - - /** - * Allocate slab entry - * - * The 'size' parameter is ignored as only slab entries with - * preconfigured slab-entry size are allocated. - */ - bool alloc(size_t size, void **addr); - void free(void *addr, size_t) { free(addr); } - size_t consumed(); - size_t overhead(size_t) { return _block_size/_num_elem; } - bool need_size_for_free() const override { return false; } - }; } + +/** + * A slab block holds an array of slab entries. + */ +class Genode::Slab_block +{ + public: + + Slab_block *next; /* next block */ + Slab_block *prev; /* previous block */ + + private: + + enum { FREE, USED }; + + Slab *_slab; /* back reference to slab allocator */ + unsigned _avail; /* free entries of this block */ + + /* + * Each slab block consists of three areas, a fixed-size header + * that contains the member variables declared above, a byte array + * called state table that holds the allocation state for each slab + * entry, and an area holding the actual slab entries. The number + * of state-table elements corresponds to the maximum number of slab + * entries per slab block (the '_num_elem' member variable of the + * Slab allocator). + */ + + char _data[]; /* dynamic data (state table and slab entries) */ + + /* + * Caution! no member variables allowed below this line! + */ + + /** + * Accessor functions to allocation state + * + * \param idx index of slab entry + */ + inline bool state(int idx) { return _data[idx]; } + inline void state(int idx, bool state) { _data[idx] = state; } + + /** + * Request address of slab entry by its index + */ + Slab_entry *slab_entry(int idx); + + /** + * Determine block index of specified slab entry + */ + int slab_entry_idx(Slab_entry *e); + + public: + + /** + * Constructor + * + * Normally, Slab_blocks are constructed by a Slab allocator + * that specifies itself as constructor argument. + */ + explicit Slab_block(Slab *s = 0) { if (s) slab(s); } + + /** + * Configure block to be managed by the specified slab allocator + */ + void slab(Slab *slab); + + /** + * Request number of available entries in block + */ + unsigned avail() { return _avail; } + + /** + * Allocate slab entry from block + */ + void *alloc(); + + /** + * Return a used slab block entry + */ + Slab_entry *first_used_entry(); + + /** + * These functions are called by Slab_entry. + */ + void inc_avail(Slab_entry *e); + void dec_avail(); + + /** + * Debug and test hooks + */ + void dump(); + int check_bounds(); +}; + + +class Genode::Slab_entry +{ + private: + + Slab_block *_sb; + char _data[]; + + /* + * Caution! no member variables allowed below this line! + */ + + public: + + void init() { _sb = 0; } + + void occupy(Slab_block *sb) + { + _sb = sb; + _sb->dec_avail(); + } + + void free() + { + _sb->inc_avail(this); + _sb = 0; + } + + void *addr() { return _data; } + + /** + * Lookup Slab_entry by given address + * + * The specified address is supposed to point to _data[0]. + */ + static Slab_entry *slab_entry(void *addr) { + return (Slab_entry *)((addr_t)addr - sizeof(Slab_entry)); } +}; + + +/** + * Slab allocator + */ +class Genode::Slab : public Allocator +{ + private: + + size_t _slab_size; /* size of one slab entry */ + size_t _block_size; /* size of slab block */ + size_t _num_elem; /* number of slab entries per block */ + Slab_block *_first_sb; /* first slab block */ + Slab_block *_initial_sb; /* initial (static) slab block */ + bool _alloc_state; /* indicator for 'currently in service' */ + + Allocator *_backing_store; + + /** + * Allocate and initialize new slab block + */ + Slab_block *_new_slab_block(); + + public: + + inline size_t slab_size() { return _slab_size; } + inline size_t block_size() { return _block_size; } + inline size_t num_elem() { return _num_elem; } + inline size_t entry_size() { return sizeof(Slab_entry) + _slab_size; } + + /** + * Constructor + * + * At construction time, there exists one initial slab + * block that is used for the first couple of allocations, + * especially for the allocation of the second slab + * block. + */ + Slab(size_t slab_size, size_t block_size, Slab_block *initial_sb, + Allocator *backing_store = 0); + + /** + * Destructor + */ + ~Slab(); + + /** + * Debug function for dumping the current slab block list + */ + void dump_sb_list(); + + /** + * Remove block from slab block list + */ + void remove_sb(Slab_block *sb); + + /** + * Insert block into slab block list + */ + void insert_sb(Slab_block *sb, Slab_block *at = 0); + + /** + * Free slab entry + */ + static void free(void *addr); + + /** + * Return a used slab element + */ + void *first_used_elem(); + + /** + * Return true if number of free slab entries is higher than n + */ + bool num_free_entries_higher_than(int n); + + /** + * Define/request backing-store allocator + */ + void backing_store(Allocator *bs) { _backing_store = bs; } + Allocator *backing_store() { return _backing_store; } + + /************************* + ** Allocator interface ** + *************************/ + + /** + * Allocate slab entry + * + * The 'size' parameter is ignored as only slab entries with + * preconfigured slab-entry size are allocated. + */ + bool alloc(size_t size, void **addr); + void free(void *addr, size_t) { free(addr); } + size_t consumed(); + size_t overhead(size_t) { return _block_size/_num_elem; } + bool need_size_for_free() const override { return false; } +}; + #endif /* _INCLUDE__BASE__SLAB_H_ */ diff --git a/repos/base/include/base/snprintf.h b/repos/base/include/base/snprintf.h index ec565c3a7..1735ac39d 100644 --- a/repos/base/include/base/snprintf.h +++ b/repos/base/include/base/snprintf.h @@ -18,65 +18,71 @@ #include namespace Genode { - - class String_console : public Console - { - private: - - char *_dst; - size_t _dst_len; - size_t _w_offset; - - public: - - /** - * Constructor - * - * \param dst destination character buffer - * \param dst_len size of dst - */ - String_console(char *dst, size_t dst_len) - : _dst(dst), _dst_len(dst_len), _w_offset(0) - { _dst[0] = 0; } - - /** - * Return number of characters in destination buffer - */ - size_t len() { return _w_offset; } - - - /*********************** - ** Console interface ** - ***********************/ - - void _out_char(char c) - { - /* ensure to leave space for null-termination */ - if (_w_offset + 2 > _dst_len) - return; - - _dst[_w_offset++] = c; - _dst[_w_offset] = 0; - } - }; + + class String_console; /** * Print format string into character buffer * * \return number of characters written to destination buffer */ - inline int snprintf(char *, size_t, const char *, ...) __attribute__((format(printf, 3, 4))); - inline int snprintf(char *dst, size_t dst_len, const char *format, ...) - { - va_list list; - va_start(list, format); + inline int snprintf(char *, size_t, const char *, ...) + __attribute__((format(printf, 3, 4))); +} - String_console sc(dst, dst_len); - sc.vprintf(format, list); - va_end(list); - return sc.len(); - } +class Genode::String_console : public Console +{ + private: + + char *_dst; + size_t _dst_len; + size_t _w_offset; + + public: + + /** + * Constructor + * + * \param dst destination character buffer + * \param dst_len size of dst + */ + String_console(char *dst, size_t dst_len) + : _dst(dst), _dst_len(dst_len), _w_offset(0) + { _dst[0] = 0; } + + /** + * Return number of characters in destination buffer + */ + size_t len() { return _w_offset; } + + + /*********************** + ** Console interface ** + ***********************/ + + void _out_char(char c) override + { + /* ensure to leave space for null-termination */ + if (_w_offset + 2 > _dst_len) + return; + + _dst[_w_offset++] = c; + _dst[_w_offset] = 0; + } +}; + + +inline int Genode::snprintf(char *dst, size_t dst_len, const char *format, ...) +{ + va_list list; + va_start(list, format); + + String_console sc(dst, dst_len); + sc.vprintf(format, list); + + va_end(list); + return sc.len(); } #endif /* _INCLUDE__BASE__SNPRINTF_H_ */ diff --git a/repos/base/include/base/sync_allocator.h b/repos/base/include/base/sync_allocator.h index 640bb441c..c84fc038e 100644 --- a/repos/base/include/base/sync_allocator.h +++ b/repos/base/include/base/sync_allocator.h @@ -18,238 +18,244 @@ #include namespace Genode { - - /** - * Lock-guarded allocator - * - * This class wraps the complete 'Allocator' interface while - * preventing concurrent calls to the wrapped allocator implementation. - * - * \param ALLOCATOR_IMPL class implementing the 'Allocator' - * interface - */ - template - class Synchronized_allocator : public Allocator - { - private: - - Lock _default_lock; - Lock *_lock; - ALLOCATOR_IMPL _alloc; - - public: - - /** - * Constructor - * - * This constructor uses an embedded lock for synchronizing the - * access to the allocator. - */ - Synchronized_allocator() - : _lock(&_default_lock) { } - - /** - * Constructor - * - * This constructor uses an embedded lock for synchronizing the - * access to the allocator. - */ - explicit Synchronized_allocator(Allocator *metadata_alloc) - : _lock(&_default_lock), _alloc(metadata_alloc) { } - - /** - * Return reference to wrapped (non-thread-safe) allocator - * - * This is needed, for example, if the wrapped allocator implements - * methods in addition to the Range_allocator interface. - */ - ALLOCATOR_IMPL *raw() { return &_alloc; } - - /************************* - ** Allocator interface ** - *************************/ - - bool alloc(size_t size, void **out_addr) - { - Lock::Guard lock_guard(*_lock); - return _alloc.alloc(size, out_addr); - } - - void free(void *addr, size_t size) - { - Lock::Guard lock_guard(*_lock); - _alloc.free(addr, size); - } - - size_t consumed() - { - Lock::Guard lock_guard(*_lock); - return _alloc.consumed(); - } - - size_t overhead(size_t size) - { - Lock::Guard lock_guard(*_lock); - return _alloc.overhead(size); - } - - bool need_size_for_free() const override - { - Lock::Guard lock_guard(*_lock); - return _alloc.need_size_for_free(); - } - }; - - /** - * Lock-guarded range allocator - * - * This class wraps the complete 'Range_allocator' interface while - * preventing concurrent calls to the wrapped allocator implementation. - * - * \param ALLOCATOR_IMPL class implementing the 'Range_allocator' - * interface - */ - template - class Synchronized_range_allocator : public Range_allocator - { - private: - - Lock _default_lock; - Lock *_lock; - ALLOCATOR_IMPL _alloc; - - public: - - /** - * Constructor - * - * This constructor uses an embedded lock for synchronizing the - * access to the allocator. - */ - Synchronized_range_allocator() - : _lock(&_default_lock) { } - - /** - * Constructor - * - * This constructor uses an embedded lock for synchronizing the - * access to the allocator. - */ - explicit Synchronized_range_allocator(Allocator *metadata_alloc) - : _lock(&_default_lock), _alloc(metadata_alloc) { } - - /** - * Constructor - * - * \param lock use specified lock rather then an embedded lock for - * synchronization - * - * This constructor is useful if multiple allocators must be - * synchronized with each other. In such as case, the shared - * lock can be passed to each 'Synchronized_range_allocator' - * instance. - */ - Synchronized_range_allocator(Lock *lock, Allocator *metadata_alloc) - : _lock(lock), _alloc(metadata_alloc) { } - - /** - * Return reference to wrapped (non-thread-safe) allocator - * - * This is needed, for example, if the wrapped allocator implements - * methods in addition to the Range_allocator interface. - * - * NOTE: Synchronize accesses to the raw allocator by facilitating - * the lock() member function. - */ - ALLOCATOR_IMPL *raw() { return &_alloc; } - - /** - * Return reference to synchronization lock - */ - Lock *lock() { return _lock; } - - - /************************* - ** Allocator interface ** - *************************/ - - bool alloc(size_t size, void **out_addr) - { - Lock::Guard lock_guard(*_lock); - return _alloc.alloc(size, out_addr); - } - - void free(void *addr, size_t size) - { - Lock::Guard lock_guard(*_lock); - _alloc.free(addr, size); - } - - size_t consumed() - { - Lock::Guard lock_guard(*_lock); - return _alloc.consumed(); - } - - size_t overhead(size_t size) - { - Lock::Guard lock_guard(*_lock); - return _alloc.overhead(size); - } - - bool need_size_for_free() const override - { - Lock::Guard lock_guard(*_lock); - return _alloc.need_size_for_free(); - } - - - /******************************* - ** Range-allocator interface ** - *******************************/ - - int add_range(addr_t base, size_t size) - { - Lock::Guard lock_guard(*_lock); - return _alloc.add_range(base, size); - } - - int remove_range(addr_t base, size_t size) - { - Lock::Guard lock_guard(*_lock); - return _alloc.remove_range(base, size); - } - - Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0, addr_t from = 0, addr_t to = ~0UL) - { - Lock::Guard lock_guard(*_lock); - return _alloc.alloc_aligned(size, out_addr, align, from, to); - } - - Alloc_return alloc_addr(size_t size, addr_t addr) - { - Lock::Guard lock_guard(*_lock); - return _alloc.alloc_addr(size, addr); - } - - void free(void *addr) - { - Lock::Guard lock_guard(*_lock); - _alloc.free(addr); - } - - size_t avail() - { - Lock::Guard lock_guard(*_lock); - return _alloc.avail(); - } - - bool valid_addr(addr_t addr) - { - Lock::Guard lock_guard(*_lock); - return _alloc.valid_addr(addr); - } - }; + + template class Synchronized_allocator; + template class Synchronized_range_allocator; } + +/** + * Lock-guarded allocator + * + * This class wraps the complete 'Allocator' interface while + * preventing concurrent calls to the wrapped allocator implementation. + * + * \param ALLOCATOR_IMPL class implementing the 'Allocator' + * interface + */ +template +class Genode::Synchronized_allocator : public Allocator +{ + private: + + Lock _default_lock; + Lock *_lock; + ALLOCATOR_IMPL _alloc; + + public: + + /** + * Constructor + * + * This constructor uses an embedded lock for synchronizing the + * access to the allocator. + */ + Synchronized_allocator() + : _lock(&_default_lock) { } + + /** + * Constructor + * + * This constructor uses an embedded lock for synchronizing the + * access to the allocator. + */ + explicit Synchronized_allocator(Allocator *metadata_alloc) + : _lock(&_default_lock), _alloc(metadata_alloc) { } + + /** + * Return reference to wrapped (non-thread-safe) allocator + * + * This is needed, for example, if the wrapped allocator implements + * methods in addition to the Range_allocator interface. + */ + ALLOCATOR_IMPL *raw() { return &_alloc; } + + /************************* + ** Allocator interface ** + *************************/ + + bool alloc(size_t size, void **out_addr) override + { + Lock::Guard lock_guard(*_lock); + return _alloc.alloc(size, out_addr); + } + + void free(void *addr, size_t size) override + { + Lock::Guard lock_guard(*_lock); + _alloc.free(addr, size); + } + + size_t consumed() override + { + Lock::Guard lock_guard(*_lock); + return _alloc.consumed(); + } + + size_t overhead(size_t size) override + { + Lock::Guard lock_guard(*_lock); + return _alloc.overhead(size); + } + + bool need_size_for_free() const override + { + Lock::Guard lock_guard(*_lock); + return _alloc.need_size_for_free(); + } +}; + + +/** + * Lock-guarded range allocator + * + * This class wraps the complete 'Range_allocator' interface while + * preventing concurrent calls to the wrapped allocator implementation. + * + * \param ALLOCATOR_IMPL class implementing the 'Range_allocator' + * interface + */ +template +class Genode::Synchronized_range_allocator : public Range_allocator +{ + private: + + Lock _default_lock; + Lock *_lock; + ALLOCATOR_IMPL _alloc; + + public: + + /** + * Constructor + * + * This constructor uses an embedded lock for synchronizing the + * access to the allocator. + */ + Synchronized_range_allocator() + : _lock(&_default_lock) { } + + /** + * Constructor + * + * This constructor uses an embedded lock for synchronizing the + * access to the allocator. + */ + explicit Synchronized_range_allocator(Allocator *metadata_alloc) + : _lock(&_default_lock), _alloc(metadata_alloc) { } + + /** + * Constructor + * + * \param lock use specified lock rather then an embedded lock for + * synchronization + * + * This constructor is useful if multiple allocators must be + * synchronized with each other. In such as case, the shared + * lock can be passed to each 'Synchronized_range_allocator' + * instance. + */ + Synchronized_range_allocator(Lock *lock, Allocator *metadata_alloc) + : _lock(lock), _alloc(metadata_alloc) { } + + /** + * Return reference to wrapped (non-thread-safe) allocator + * + * This is needed, for example, if the wrapped allocator implements + * methods in addition to the Range_allocator interface. + * + * NOTE: Synchronize accesses to the raw allocator by facilitating + * the lock() member function. + */ + ALLOCATOR_IMPL *raw() { return &_alloc; } + + /** + * Return reference to synchronization lock + */ + Lock *lock() { return _lock; } + + + /************************* + ** Allocator interface ** + *************************/ + + bool alloc(size_t size, void **out_addr) override + { + Lock::Guard lock_guard(*_lock); + return _alloc.alloc(size, out_addr); + } + + void free(void *addr, size_t size) override + { + Lock::Guard lock_guard(*_lock); + _alloc.free(addr, size); + } + + size_t consumed() override + { + Lock::Guard lock_guard(*_lock); + return _alloc.consumed(); + } + + size_t overhead(size_t size) override + { + Lock::Guard lock_guard(*_lock); + return _alloc.overhead(size); + } + + bool need_size_for_free() const override + { + Lock::Guard lock_guard(*_lock); + return _alloc.need_size_for_free(); + } + + + /******************************* + ** Range-allocator interface ** + *******************************/ + + int add_range(addr_t base, size_t size) override + { + Lock::Guard lock_guard(*_lock); + return _alloc.add_range(base, size); + } + + int remove_range(addr_t base, size_t size) override + { + Lock::Guard lock_guard(*_lock); + return _alloc.remove_range(base, size); + } + + Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0, + addr_t from = 0, addr_t to = ~0UL) override + { + Lock::Guard lock_guard(*_lock); + return _alloc.alloc_aligned(size, out_addr, align, from, to); + } + + Alloc_return alloc_addr(size_t size, addr_t addr) override + { + Lock::Guard lock_guard(*_lock); + return _alloc.alloc_addr(size, addr); + } + + void free(void *addr) override + { + Lock::Guard lock_guard(*_lock); + _alloc.free(addr); + } + + size_t avail() override + { + Lock::Guard lock_guard(*_lock); + return _alloc.avail(); + } + + bool valid_addr(addr_t addr) override + { + Lock::Guard lock_guard(*_lock); + return _alloc.valid_addr(addr); + } +}; + #endif /* _INCLUDE__BASE__SYNC_ALLOCATOR_H_ */ diff --git a/repos/base/include/base/thread.h b/repos/base/include/base/thread.h index b299d951e..8d37efbfe 100644 --- a/repos/base/include/base/thread.h +++ b/repos/base/include/base/thread.h @@ -9,23 +9,23 @@ * area, each thread has a fixed-sized slot, a thread context. The layout of * each thread context looks as follows * - * ! lower address - * ! ... - * ! ============================ <- aligned at the virtual context size - * ! - * ! empty - * ! - * ! ---------------------------- - * ! - * ! stack - * ! (top) <- initial stack pointer - * ! ---------------------------- <- address of 'Context' object - * ! additional context members - * ! ---------------------------- - * ! UTCB - * ! ============================ <- aligned at the virtual context size - * ! ... - * ! higher address + * ; lower address + * ; ... + * ; ============================ <- aligned at the virtual context size + * ; + * ; empty + * ; + * ; ---------------------------- + * ; + * ; stack + * ; (top) <- initial stack pointer + * ; ---------------------------- <- address of 'Context' object + * ; additional context members + * ; ---------------------------- + * ; UTCB + * ; ============================ <- aligned at the virtual context size + * ; ... + * ; higher address * * On some platforms, a user-level thread-control block (UTCB) area contains * data shared between the user-level thread and the kernel. It is typically @@ -69,484 +69,487 @@ namespace Genode { class Rm_session; + class Thread_base; + template class Thread; +} - /** - * Concurrent control flow - * - * A 'Thread_base' object corresponds to a physical thread. The execution - * starts at the 'entry()' function as soon as 'start()' is called. - */ - class Thread_base - { - public: - class Context_alloc_failed : public Exception { }; - class Stack_too_large : public Exception { }; - class Stack_alloc_failed : public Exception { }; +/** + * Concurrent control flow + * + * A 'Thread_base' object corresponds to a physical thread. The execution + * starts at the 'entry()' function as soon as 'start()' is called. + */ +class Genode::Thread_base +{ + public: + + class Context_alloc_failed : public Exception { }; + class Stack_too_large : public Exception { }; + class Stack_alloc_failed : public Exception { }; + + /** + * Thread context located within the thread-context area + * + * The end of a thread context is placed virtual size aligned. + */ + struct Context + { + private: + + /** + * Top of the stack is accessible via stack_top() + */ + long _stack[]; + + public: /** - * Thread context located within the thread-context area + * Top of stack * - * The end of a thread context is placed virtual size aligned. + * The alignment matches an initial stack frame, which is + * sufficient for the AMD64 ABI (stack top + adjustment is 16-byte + * aligned). */ - struct Context + addr_t stack_top() const { - private: - - /** - * Top of the stack is accessible via stack_top() - */ - long _stack[]; - - public: - - /** - * Top of stack - * - * The alignment matches an initial stack frame, which is - * sufficient for the AMD64 ABI (stack top + adjustment is 16-byte - * aligned). - */ - addr_t stack_top() const - { - return ((addr_t)_stack & ~0xf) - Abi::stack_adjustment(); - } - - /** - * Ensure that the stack has a given size at the minimum - * - * \param size minimum stack size - * - * \throw Stack_too_large - * \throw Stack_alloc_failed - */ - void stack_size(size_t const size); - - /** - * Virtual address of the start of the stack - * - * This address is pointing to the begin of the dataspace used - * for backing the thread context except for the UTCB (which is - * managed by the kernel). - */ - addr_t stack_base; - - /** - * Pointer to corresponding 'Thread_base' object - */ - Thread_base *thread_base; - - /** - * Dataspace containing the backing store for the thread context - * - * We keep the dataspace capability to be able to release the - * backing store on thread destruction. - */ - Ram_dataspace_capability ds_cap; - - /** - * Maximum length of thread name, including null-termination - */ - enum { NAME_LEN = 64 }; - - /** - * Thread name, used for debugging - */ - char name[NAME_LEN]; - - /* - * <- end of regular memory area - * - * The following part of the thread context is backed by - * kernel-managed memory. No member variables are allowed - * beyond this point. - */ - - /** - * Kernel-specific user-level thread control block - */ - Native_utcb utcb; - }; - - private: - - /** - * Manage the allocation of thread contexts - * - * There exists only one instance of this class per process. - */ - class Context_allocator - { - private: - - static constexpr size_t MAX_THREADS = - Native_config::context_area_virtual_size() / - Native_config::context_virtual_size(); - - struct Context_bit_allocator : Bit_allocator - { - Context_bit_allocator() - { - /* the first index is used by main thread */ - _reserve(0, 1); - } - } _alloc; - - Lock _threads_lock; - - public: - - /** - * Allocate thread context for specified thread - * - * \param thread thread for which to allocate the new context - * \param main_thread wether to alloc for the main thread - * - * \return virtual address of new thread context, or - * 0 if the allocation failed - */ - Context *alloc(Thread_base *thread, bool main_thread); - - /** - * Release thread context - */ - void free(Context *thread); - - /** - * Return 'Context' object for a given base address - */ - static Context *base_to_context(addr_t base); - - /** - * Return base address of context containing the specified address - */ - static addr_t addr_to_base(void *addr); - - /** - * Return index in context area for a given base address - */ - static size_t base_to_idx(addr_t base); - - /** - * Return base address of context given index in context area - */ - static addr_t idx_to_base(size_t idx); - }; - - /** - * Return thread-context allocator - */ - static Context_allocator *_context_allocator(); - - /** - * Allocate and locally attach a new thread context - * - * \param stack_size size of this threads stack - * \param main_thread wether this is the main thread - */ - Context *_alloc_context(size_t stack_size, bool main_thread); - - /** - * Detach and release thread context of the thread - */ - void _free_context(Context *context); - - /** - * Platform-specific thread-startup code - * - * On some platforms, each new thread has to perform a startup - * protocol, e.g., waiting for a message from the kernel. This hook - * function allows for the implementation of such protocols. - */ - void _thread_bootstrap(); - - /** - * Helper for thread startup - */ - static void _thread_start(); - - /** - * Hook for platform-specific destructor supplements - */ - void _deinit_platform_thread(); - - protected: - - /** - * Capability for this thread (set by _start()) - * - * Used if thread creation involves core's CPU service. - */ - Genode::Thread_capability _thread_cap; - - /** - * Capability to pager paging this thread (created by _start()) - */ - Genode::Pager_capability _pager_cap; - - /** - * Pointer to cpu session used for this thread - */ - Genode::Cpu_session *_cpu_session; - - /** - * Pointer to primary thread context - */ - Context *_context; - - /** - * Physical thread ID - */ - Native_thread _tid; - - /** - * Lock used for synchronizing the finalization of the thread - */ - Genode::Lock _join_lock; - - /** - * Thread type - * - * Some threads need special treatment at construction. This enum - * is solely used to distinguish them at construction. - */ - enum Type { NORMAL, MAIN, REINITIALIZED_MAIN }; - - private: - - Trace::Logger _trace_logger; - - /** - * Return 'Trace::Logger' instance of calling thread - * - * This function is used by the tracing framework internally. - */ - static Trace::Logger *_logger(); - - /** - * Hook for platform-specific constructor supplements - * - * \param quota CPU quota that shall be granted to the thread - * \param type enables selection of special initialization - */ - void _init_platform_thread(size_t quota, Type type); - - public: - - /** - * Constructor - * - * \param quota CPU quota that shall be granted to the thread - * \param name thread name for debugging - * \param stack_size stack size - * \param type enables selection of special construction - * - * \throw Stack_too_large - * \throw Stack_alloc_failed - * \throw Context_alloc_failed - * - * The stack for the new thread will be allocated from the RAM - * session of the process environment. A small portion of the - * stack size is internally used by the framework for storing - * thread-context information such as the thread's name (see - * 'struct Context'). - * - * FIXME: With type = Forked_main_thread the whole - * Context::_alloc_context call gets skipped but we should - * at least set Context::ds_cap in a way that it references - * the dataspace of the already attached stack. - */ - Thread_base(size_t quota, const char *name, size_t stack_size, - Type type = NORMAL); - - /** - * Constructor - * - * \param quota CPU quota that shall be granted to the thread - * \param name thread name for debugging - * \param stack_size stack size - * \param type enables selection of special construction - * \param cpu_session capability to cpu session used for construction - * - * \throw Stack_too_large - * \throw Stack_alloc_failed - * \throw Context_alloc_failed - */ - Thread_base(size_t quota, const char *name, size_t stack_size, - Type type, Cpu_session *); - - /** - * Destructor - */ - virtual ~Thread_base(); - - /** - * Entry function of the thread - */ - virtual void entry() = 0; - - /** - * Start execution of the thread - * - * This function is virtual to enable the customization of threads - * used as server activation. - */ - virtual void start(); - - /** - * Request name of thread - */ - void name(char *dst, size_t dst_len); - - /** - * Add an additional stack to the thread - * - * \throw Stack_too_large - * \throw Stack_alloc_failed - * \throw Context_alloc_failed - * - * The stack for the new thread will be allocated from the RAM - * session of the process environment. A small portion of the - * stack size is internally used by the framework for storing - * thread-context information such as the thread's name (see - * 'struct Context'). - * - * \return pointer to the new stack's top - */ - void* alloc_secondary_stack(char const *name, size_t stack_size); - - /** - * Remove a secondary stack from the thread - */ - void free_secondary_stack(void* stack_addr); - - /** - * Request capability of thread - */ - Genode::Thread_capability cap() const { return _thread_cap; } - - /** - * Cancel currently blocking operation - */ - void cancel_blocking(); - - /** - * Only to be called from platform-specific code - */ - Native_thread & tid() { return _tid; } - - /** - * Return top of stack - * - * \return pointer just after first stack element - */ - void *stack_top() const { return (void *)_context->stack_top(); } - - /** - * Return base of stack - * - * \return pointer to last stack element - */ - void *stack_base() { return (void*)_context->stack_base; } - - /** - * Return 'Thread_base' object corresponding to the calling thread - * - * \return pointer to 'Thread_base' object, or - * 0 if the calling thread is the main thread - */ - static Thread_base *myself(); + return ((addr_t)_stack & ~0xf) - Abi::stack_adjustment(); + } /** * Ensure that the stack has a given size at the minimum * * \param size minimum stack size * - * \throw Context::Stack_too_large - * \throw Context::Stack_alloc_failed + * \throw Stack_too_large + * \throw Stack_alloc_failed */ - void stack_size(size_t const size) { _context->stack_size(size); } + void stack_size(size_t const size); /** - * Return user-level thread control block + * Virtual address of the start of the stack * - * Note that it is safe to call this function on the result of the - * 'myself' function. It handles the special case of 'myself' being - * 0 when called by the main thread. + * This address is pointing to the begin of the dataspace used + * for backing the thread context except for the UTCB (which is + * managed by the kernel). */ - Native_utcb *utcb(); + addr_t stack_base; /** - * Block until the thread leaves the 'entry' function + * Pointer to corresponding 'Thread_base' object + */ + Thread_base *thread_base; + + /** + * Dataspace containing the backing store for the thread context * - * Join must not be called more than once. Subsequent calls have - * undefined behaviour. + * We keep the dataspace capability to be able to release the + * backing store on thread destruction. */ - void join(); + Ram_dataspace_capability ds_cap; /** - * Log null-terminated string as trace event + * Maximum length of thread name, including null-termination */ - static void trace(char const *cstring) - { - _logger()->log(cstring, strlen(cstring)); - } + enum { NAME_LEN = 64 }; /** - * Log binary data as trace event + * Thread name, used for debugging */ - static void trace(char const *data, size_t len) - { - _logger()->log(data, len); - } + char name[NAME_LEN]; - /** - * Log trace event as defined in base/trace.h - */ - template - static void trace(EVENT const *event) { _logger()->log(event); } - }; - - - template - class Thread : public Thread_base - { - public: - - /** - * Constructor + /* + * <- end of regular memory area * - * \param quota CPU quota that shall be granted to the thread - * \param name thread name (for debugging) - * \param type enables selection of special construction + * The following part of the thread context is backed by + * kernel-managed memory. No member variables are allowed + * beyond this point. */ - explicit Thread(size_t quota, const char *name, Type type = NORMAL) - : Thread_base(quota, name, STACK_SIZE, type) { } /** - * Constructor - * - * \param quota CPU quota that shall be granted to the thread - * \param name thread name (for debugging) - * \param cpu_session thread created via specific cpu session + * Kernel-specific user-level thread control block */ - explicit Thread(size_t quota, const char *name, Cpu_session * cpu_session) - : Thread_base(quota, name, STACK_SIZE, Type::NORMAL, cpu_session) - { } + Native_utcb utcb; + }; - /** - * Shortcut for 'Thread(0, name, type)' - */ - explicit Thread(const char *name, Type type = NORMAL) - : Thread_base(0, name, STACK_SIZE, type) { } + private: - /** - * Shortcut for 'Thread(0, name, cpu_session)' - */ - explicit Thread(const char *name, Cpu_session * cpu_session) - : Thread_base(0, name, STACK_SIZE, Type::NORMAL, cpu_session) - { } - }; -} + /** + * Manage the allocation of thread contexts + * + * There exists only one instance of this class per process. + */ + class Context_allocator + { + private: + + static constexpr size_t MAX_THREADS = + Native_config::context_area_virtual_size() / + Native_config::context_virtual_size(); + + struct Context_bit_allocator : Bit_allocator + { + Context_bit_allocator() + { + /* the first index is used by main thread */ + _reserve(0, 1); + } + } _alloc; + + Lock _threads_lock; + + public: + + /** + * Allocate thread context for specified thread + * + * \param thread thread for which to allocate the new context + * \param main_thread wether to alloc for the main thread + * + * \return virtual address of new thread context, or + * 0 if the allocation failed + */ + Context *alloc(Thread_base *thread, bool main_thread); + + /** + * Release thread context + */ + void free(Context *thread); + + /** + * Return 'Context' object for a given base address + */ + static Context *base_to_context(addr_t base); + + /** + * Return base address of context containing the specified address + */ + static addr_t addr_to_base(void *addr); + + /** + * Return index in context area for a given base address + */ + static size_t base_to_idx(addr_t base); + + /** + * Return base address of context given index in context area + */ + static addr_t idx_to_base(size_t idx); + }; + + /** + * Return thread-context allocator + */ + static Context_allocator *_context_allocator(); + + /** + * Allocate and locally attach a new thread context + * + * \param stack_size size of this threads stack + * \param main_thread wether this is the main thread + */ + Context *_alloc_context(size_t stack_size, bool main_thread); + + /** + * Detach and release thread context of the thread + */ + void _free_context(Context *context); + + /** + * Platform-specific thread-startup code + * + * On some platforms, each new thread has to perform a startup + * protocol, e.g., waiting for a message from the kernel. This hook + * function allows for the implementation of such protocols. + */ + void _thread_bootstrap(); + + /** + * Helper for thread startup + */ + static void _thread_start(); + + /** + * Hook for platform-specific destructor supplements + */ + void _deinit_platform_thread(); + + protected: + + /** + * Capability for this thread (set by _start()) + * + * Used if thread creation involves core's CPU service. + */ + Genode::Thread_capability _thread_cap; + + /** + * Capability to pager paging this thread (created by _start()) + */ + Genode::Pager_capability _pager_cap; + + /** + * Pointer to cpu session used for this thread + */ + Genode::Cpu_session *_cpu_session; + + /** + * Pointer to primary thread context + */ + Context *_context; + + /** + * Physical thread ID + */ + Native_thread _tid; + + /** + * Lock used for synchronizing the finalization of the thread + */ + Genode::Lock _join_lock; + + /** + * Thread type + * + * Some threads need special treatment at construction. This enum + * is solely used to distinguish them at construction. + */ + enum Type { NORMAL, MAIN, REINITIALIZED_MAIN }; + + private: + + Trace::Logger _trace_logger; + + /** + * Return 'Trace::Logger' instance of calling thread + * + * This function is used by the tracing framework internally. + */ + static Trace::Logger *_logger(); + + /** + * Hook for platform-specific constructor supplements + * + * \param quota CPU quota that shall be granted to the thread + * \param type enables selection of special initialization + */ + void _init_platform_thread(size_t quota, Type type); + + public: + + /** + * Constructor + * + * \param quota CPU quota that shall be granted to the thread + * \param name thread name for debugging + * \param stack_size stack size + * \param type enables selection of special construction + * + * \throw Stack_too_large + * \throw Stack_alloc_failed + * \throw Context_alloc_failed + * + * The stack for the new thread will be allocated from the RAM + * session of the process environment. A small portion of the + * stack size is internally used by the framework for storing + * thread-context information such as the thread's name (see + * 'struct Context'). + * + * FIXME: With type = Forked_main_thread the whole + * Context::_alloc_context call gets skipped but we should + * at least set Context::ds_cap in a way that it references + * the dataspace of the already attached stack. + */ + Thread_base(size_t quota, const char *name, size_t stack_size, + Type type = NORMAL); + + /** + * Constructor + * + * \param quota CPU quota that shall be granted to the thread + * \param name thread name for debugging + * \param stack_size stack size + * \param type enables selection of special construction + * \param cpu_session capability to cpu session used for construction + * + * \throw Stack_too_large + * \throw Stack_alloc_failed + * \throw Context_alloc_failed + */ + Thread_base(size_t quota, const char *name, size_t stack_size, + Type type, Cpu_session *); + + /** + * Destructor + */ + virtual ~Thread_base(); + + /** + * Entry function of the thread + */ + virtual void entry() = 0; + + /** + * Start execution of the thread + * + * This function is virtual to enable the customization of threads + * used as server activation. + */ + virtual void start(); + + /** + * Request name of thread + */ + void name(char *dst, size_t dst_len); + + /** + * Add an additional stack to the thread + * + * \throw Stack_too_large + * \throw Stack_alloc_failed + * \throw Context_alloc_failed + * + * The stack for the new thread will be allocated from the RAM + * session of the process environment. A small portion of the + * stack size is internally used by the framework for storing + * thread-context information such as the thread's name (see + * 'struct Context'). + * + * \return pointer to the new stack's top + */ + void* alloc_secondary_stack(char const *name, size_t stack_size); + + /** + * Remove a secondary stack from the thread + */ + void free_secondary_stack(void* stack_addr); + + /** + * Request capability of thread + */ + Genode::Thread_capability cap() const { return _thread_cap; } + + /** + * Cancel currently blocking operation + */ + void cancel_blocking(); + + /** + * Only to be called from platform-specific code + */ + Native_thread & tid() { return _tid; } + + /** + * Return top of stack + * + * \return pointer just after first stack element + */ + void *stack_top() const { return (void *)_context->stack_top(); } + + /** + * Return base of stack + * + * \return pointer to last stack element + */ + void *stack_base() { return (void*)_context->stack_base; } + + /** + * Return 'Thread_base' object corresponding to the calling thread + * + * \return pointer to 'Thread_base' object, or + * 0 if the calling thread is the main thread + */ + static Thread_base *myself(); + + /** + * Ensure that the stack has a given size at the minimum + * + * \param size minimum stack size + * + * \throw Context::Stack_too_large + * \throw Context::Stack_alloc_failed + */ + void stack_size(size_t const size) { _context->stack_size(size); } + + /** + * Return user-level thread control block + * + * Note that it is safe to call this function on the result of the + * 'myself' function. It handles the special case of 'myself' being + * 0 when called by the main thread. + */ + Native_utcb *utcb(); + + /** + * Block until the thread leaves the 'entry' function + * + * Join must not be called more than once. Subsequent calls have + * undefined behaviour. + */ + void join(); + + /** + * Log null-terminated string as trace event + */ + static void trace(char const *cstring) + { + _logger()->log(cstring, strlen(cstring)); + } + + /** + * Log binary data as trace event + */ + static void trace(char const *data, size_t len) + { + _logger()->log(data, len); + } + + /** + * Log trace event as defined in base/trace.h + */ + template + static void trace(EVENT const *event) { _logger()->log(event); } +}; + + +template +class Genode::Thread : public Thread_base +{ + public: + + /** + * Constructor + * + * \param quota CPU quota that shall be granted to the thread + * \param name thread name (for debugging) + * \param type enables selection of special construction + */ + explicit Thread(size_t quota, const char *name, Type type = NORMAL) + : Thread_base(quota, name, STACK_SIZE, type) { } + + /** + * Constructor + * + * \param quota CPU quota that shall be granted to the thread + * \param name thread name (for debugging) + * \param cpu_session thread created via specific cpu session + */ + explicit Thread(size_t quota, const char *name, Cpu_session * cpu_session) + : Thread_base(quota, name, STACK_SIZE, Type::NORMAL, cpu_session) + { } + + /** + * Shortcut for 'Thread(0, name, type)' + */ + explicit Thread(const char *name, Type type = NORMAL) + : Thread_base(0, name, STACK_SIZE, type) { } + + /** + * Shortcut for 'Thread(0, name, cpu_session)' + */ + explicit Thread(const char *name, Cpu_session * cpu_session) + : Thread_base(0, name, STACK_SIZE, Type::NORMAL, cpu_session) + { } +}; #endif /* _INCLUDE__BASE__THREAD_H_ */ diff --git a/repos/base/include/base/thread_state.h b/repos/base/include/base/thread_state.h index 37a02a9e6..05322381e 100644 --- a/repos/base/include/base/thread_state.h +++ b/repos/base/include/base/thread_state.h @@ -19,9 +19,8 @@ #include -namespace Genode { +namespace Genode { struct Thread_state; } - struct Thread_state : Thread_state_base { }; -} +struct Genode::Thread_state : Thread_state_base { }; #endif /* _INCLUDE__BASE__THREAD_STATE_H_ */ diff --git a/repos/base/include/base/thread_state_base.h b/repos/base/include/base/thread_state_base.h index b72b1f338..49d222349 100644 --- a/repos/base/include/base/thread_state_base.h +++ b/repos/base/include/base/thread_state_base.h @@ -18,14 +18,13 @@ #include -namespace Genode { +namespace Genode { struct Thread_state_base; } - struct Thread_state_base : Cpu_state - { - bool unresolved_page_fault; +struct Genode::Thread_state_base : Cpu_state +{ + bool unresolved_page_fault; - Thread_state_base() : unresolved_page_fault(false) { }; - }; -} + Thread_state_base() : unresolved_page_fault(false) { }; +}; #endif /* _INCLUDE__BASE__THREAD_STATE_BASE_H_ */ diff --git a/repos/base/include/base/trace/events.h b/repos/base/include/base/trace/events.h index c73e8a9a1..b7e4b7453 100644 --- a/repos/base/include/base/trace/events.h +++ b/repos/base/include/base/trace/events.h @@ -18,6 +18,7 @@ #include namespace Genode { namespace Trace { + struct Rpc_call; struct Rpc_returned; struct Rpc_dispatch; diff --git a/repos/base/include/base/tslab.h b/repos/base/include/base/tslab.h index 565cc92c2..3c5dc4330 100644 --- a/repos/base/include/base/tslab.h +++ b/repos/base/include/base/tslab.h @@ -16,20 +16,18 @@ #include -namespace Genode { +namespace Genode { template struct Tslab; } - template - class Tslab : public Slab - { - public: - Tslab(Allocator *backing_store, - Slab_block *initial_sb = 0) - : Slab(sizeof(T), BLOCK_SIZE, initial_sb, backing_store) - { } +template +struct Genode::Tslab : Slab +{ + Tslab(Allocator *backing_store, + Slab_block *initial_sb = 0) + : Slab(sizeof(T), BLOCK_SIZE, initial_sb, backing_store) + { } - T *first_object() { return (T *)Slab::first_used_elem(); } - }; -} + T *first_object() { return (T *)Slab::first_used_elem(); } +}; #endif /* _INCLUDE__BASE__TSLAB_H_ */ diff --git a/repos/base/include/cap_session/cap_session.h b/repos/base/include/cap_session/cap_session.h index ad750a952..1c9f3238b 100644 --- a/repos/base/include/cap_session/cap_session.h +++ b/repos/base/include/cap_session/cap_session.h @@ -21,39 +21,39 @@ #include #include -namespace Genode { - - struct Cap_session : Session - { - static const char *service_name() { return "CAP"; } - - virtual ~Cap_session() { } - - /** - * Allocate new unique userland capability - * - * \param ep entry point that will use this capability - * - * \return new userland capability - */ - virtual Native_capability alloc(Native_capability ep) = 0; - - /** - * Free userland capability - * - * \param cap userland capability to free - */ - virtual void free(Native_capability cap) = 0; +namespace Genode { struct Cap_session; } - /********************* - ** RPC declaration ** - *********************/ +struct Genode::Cap_session : Session +{ + static const char *service_name() { return "CAP"; } - GENODE_RPC(Rpc_alloc, Native_capability, alloc, Native_capability); - GENODE_RPC(Rpc_free, void, free, Native_capability); - GENODE_RPC_INTERFACE(Rpc_alloc, Rpc_free); - }; -} + virtual ~Cap_session() { } + + /** + * Allocate new unique userland capability + * + * \param ep entry point that will use this capability + * + * \return new userland capability + */ + virtual Native_capability alloc(Native_capability ep) = 0; + + /** + * Free userland capability + * + * \param cap userland capability to free + */ + virtual void free(Native_capability cap) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_alloc, Native_capability, alloc, Native_capability); + GENODE_RPC(Rpc_free, void, free, Native_capability); + GENODE_RPC_INTERFACE(Rpc_alloc, Rpc_free); +}; #endif /* _INCLUDE__CAP_SESSION__CAP_SESSION_H_ */ diff --git a/repos/base/include/cap_session/client.h b/repos/base/include/cap_session/client.h index 06636ffb3..5d4e466ee 100644 --- a/repos/base/include/cap_session/client.h +++ b/repos/base/include/cap_session/client.h @@ -18,18 +18,18 @@ #include #include -namespace Genode { +namespace Genode { struct Cap_session_client; } - struct Cap_session_client : Rpc_client - { - explicit Cap_session_client(Cap_session_capability session) - : Rpc_client(session) { } - Native_capability alloc(Native_capability ep) { - return call(ep); } +struct Genode::Cap_session_client : Rpc_client +{ + explicit Cap_session_client(Cap_session_capability session) + : Rpc_client(session) { } - void free(Native_capability cap) { call(cap); } - }; -} + Native_capability alloc(Native_capability ep) override { + return call(ep); } + + void free(Native_capability cap) override { call(cap); } +}; #endif /* _INCLUDE__CAP_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/cap_session/connection.h b/repos/base/include/cap_session/connection.h index 12eb56784..b4304a60b 100644 --- a/repos/base/include/cap_session/connection.h +++ b/repos/base/include/cap_session/connection.h @@ -17,16 +17,16 @@ #include #include -namespace Genode { +namespace Genode { struct Cap_connection; } - struct Cap_connection : Connection, Cap_session_client - { - Cap_connection() - : - Connection(session("ram_quota=4K")), - Cap_session_client(cap()) - { } - }; -} + +struct Genode::Cap_connection : Connection, Cap_session_client +{ + Cap_connection() + : + Connection(session("ram_quota=4K")), + Cap_session_client(cap()) + { } +}; #endif /* _INCLUDE__CAP_SESSION__CONNECTION_H_ */ diff --git a/repos/base/include/cpu/cache.h b/repos/base/include/cpu/cache.h index fdf24cb3d..3797fd1ce 100644 --- a/repos/base/include/cpu/cache.h +++ b/repos/base/include/cpu/cache.h @@ -22,7 +22,6 @@ namespace Genode { * Make D-Cache and I-Cache coherent */ void cache_coherent(Genode::addr_t addr, Genode::size_t size); - } #endif /* _INCLUDE__CPU__CACHE_H_ */ diff --git a/repos/base/include/cpu_session/client.h b/repos/base/include/cpu_session/client.h index 11260f4d5..781e38bd4 100644 --- a/repos/base/include/cpu_session/client.h +++ b/repos/base/include/cpu_session/client.h @@ -17,78 +17,78 @@ #include #include -namespace Genode { +namespace Genode { struct Cpu_session_client; } - struct Cpu_session_client : Rpc_client - { - explicit Cpu_session_client(Cpu_session_capability session) - : Rpc_client(session) { } - Thread_capability - create_thread(size_t quota, Name const &name, addr_t utcb = 0) { - return call(quota, name, utcb); } +struct Genode::Cpu_session_client : Rpc_client +{ + explicit Cpu_session_client(Cpu_session_capability session) + : Rpc_client(session) { } - Ram_dataspace_capability utcb(Thread_capability thread) { - return call(thread); } + Thread_capability + create_thread(size_t quota, Name const &name, addr_t utcb = 0) override { + return call(quota, name, utcb); } - void kill_thread(Thread_capability thread) { - call(thread); } + Ram_dataspace_capability utcb(Thread_capability thread) override { + return call(thread); } - int set_pager(Thread_capability thread, Pager_capability pager) { - return call(thread, pager); } + void kill_thread(Thread_capability thread) override { + call(thread); } - int start(Thread_capability thread, addr_t ip, addr_t sp) { - return call(thread, ip, sp); } + int set_pager(Thread_capability thread, Pager_capability pager) override { + return call(thread, pager); } - void pause(Thread_capability thread) { - call(thread); } + int start(Thread_capability thread, addr_t ip, addr_t sp) override { + return call(thread, ip, sp); } - void resume(Thread_capability thread) { - call(thread); } + void pause(Thread_capability thread) override { + call(thread); } - void cancel_blocking(Thread_capability thread) { - call(thread); } + void resume(Thread_capability thread) override { + call(thread); } - Thread_state state(Thread_capability thread) { - return call(thread); } + void cancel_blocking(Thread_capability thread) override { + call(thread); } - void state(Thread_capability thread, Thread_state const &state) { - call(thread, state); } + Thread_state state(Thread_capability thread) override { + return call(thread); } - void exception_handler(Thread_capability thread, Signal_context_capability handler) { - call(thread, handler); } + void state(Thread_capability thread, Thread_state const &state) override { + call(thread, state); } - void single_step(Thread_capability thread, bool enable) { - call(thread, enable); } + void exception_handler(Thread_capability thread, Signal_context_capability handler) override { + call(thread, handler); } - Affinity::Space affinity_space() const { - return call(); } + void single_step(Thread_capability thread, bool enable) override { + call(thread, enable); } - void affinity(Thread_capability thread, Affinity::Location location) { - call(thread, location); } + Affinity::Space affinity_space() const override { + return call(); } - Dataspace_capability trace_control() { - return call(); } + void affinity(Thread_capability thread, Affinity::Location location) override { + call(thread, location); } - unsigned trace_control_index(Thread_capability thread) { - return call(thread); } + Dataspace_capability trace_control() override { + return call(); } - Dataspace_capability trace_buffer(Thread_capability thread) { - return call(thread); } + unsigned trace_control_index(Thread_capability thread) override { + return call(thread); } - Dataspace_capability trace_policy(Thread_capability thread) { - return call(thread); } + Dataspace_capability trace_buffer(Thread_capability thread) override { + return call(thread); } - int ref_account(Cpu_session_capability session) { - return call(session); } + Dataspace_capability trace_policy(Thread_capability thread) override { + return call(thread); } - int transfer_quota(Cpu_session_capability session, size_t amount) { - return call(session, amount); } + int ref_account(Cpu_session_capability session) override { + return call(session); } - size_t quota() { return call(); } + int transfer_quota(Cpu_session_capability session, size_t amount) override { + return call(session, amount); } - size_t used() { return call(); } - }; -} + size_t quota() override { return call(); } + + size_t used() override { return call(); } +}; #endif /* _INCLUDE__CPU_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/cpu_session/connection.h b/repos/base/include/cpu_session/connection.h index 320a33e54..8c5a9e813 100644 --- a/repos/base/include/cpu_session/connection.h +++ b/repos/base/include/cpu_session/connection.h @@ -17,28 +17,28 @@ #include #include -namespace Genode { +namespace Genode { struct Cpu_connection; } - struct Cpu_connection : Connection, Cpu_session_client - { - enum { RAM_QUOTA = 32*1024 }; - /** - * Constructor - * - * \param label initial session label - * \param priority designated priority of all threads created - * with this CPU session - */ - Cpu_connection(char const *label = "", - long priority = DEFAULT_PRIORITY, - Affinity const &affinity = Affinity()) - : - Connection( - session(affinity, "priority=0x%lx, ram_quota=36K, label=\"%s\"", - priority, label)), - Cpu_session_client(cap()) { } - }; -} +struct Genode::Cpu_connection : Connection, Cpu_session_client +{ + enum { RAM_QUOTA = 32*1024 }; + + /** + * Constructor + * + * \param label initial session label + * \param priority designated priority of all threads created + * with this CPU session + */ + Cpu_connection(char const *label = "", + long priority = DEFAULT_PRIORITY, + Affinity const &affinity = Affinity()) + : + Connection( + session(affinity, "priority=0x%lx, ram_quota=36K, label=\"%s\"", + priority, label)), + Cpu_session_client(cap()) { } +}; #endif /* _INCLUDE__CPU_SESSION__CONNECTION_H_ */ diff --git a/repos/base/include/cpu_session/cpu_session.h b/repos/base/include/cpu_session/cpu_session.h index e452594e8..16bed0548 100644 --- a/repos/base/include/cpu_session/cpu_session.h +++ b/repos/base/include/cpu_session/cpu_session.h @@ -2,21 +2,6 @@ * \brief CPU (processing time) manager session interface * \author Christian Helmuth * \date 2006-06-27 - * - * :Question: - * - * Why are thread operations not methods of the thread but - * methods of the CPU session? - * - * :Answer: - * - * This enables the CPU session to impose policies on thread - * operations. These policies are based on the session - * construction arguments. If thread operations would be - * provided as thread methods, Thread would need to consult - * its container object (its CPU session) about the authorization - * of each operation and, thereby, would introduce a circular - * dependency between CPU session and Thread. */ /* @@ -41,344 +26,344 @@ #include #include -namespace Genode { +namespace Genode { struct Cpu_session; } - struct Cpu_session : Session + +struct Genode::Cpu_session : Session +{ + /********************* + ** Exception types ** + *********************/ + + class Thread_creation_failed : public Exception { }; + class State_access_failed : public Exception { }; + class Quota_exceeded : public Thread_creation_failed { }; + class Out_of_metadata : public Exception { }; + + static const char *service_name() { return "CPU"; } + + enum { THREAD_NAME_LEN = 48 }; + enum { PRIORITY_LIMIT = 1 << 16 }; + enum { QUOTA_LIMIT_LOG2 = 15 }; + enum { QUOTA_LIMIT = 1 << QUOTA_LIMIT_LOG2 }; + enum { DEFAULT_PRIORITY = 0 }; + + typedef Rpc_in_buffer Name; + + virtual ~Cpu_session() { } + + /** + * Create a new thread + * + * \param quota CPU quota that shall be granted to the thread + * \param name name for the thread + * \param utcb Base of the UTCB that will be used by the thread + * \return capability representing the new thread + * \throw Thread_creation_failed + * \throw Out_of_metadata + * \throw Quota_exceeded + */ + virtual Thread_capability create_thread(size_t quota, + Name const &name, + addr_t utcb = 0) = 0; + + /** + * Get dataspace of the UTCB that is used by the specified thread + */ + virtual Ram_dataspace_capability utcb(Thread_capability thread) = 0; + + /** + * Kill an existing thread + * + * \param thread capability of the thread to kill + */ + virtual void kill_thread(Thread_capability thread) = 0; + + /** + * Set paging capabilities for thread + * + * \param thread thread to configure + * \param pager capability used to propagate page faults + */ + virtual int set_pager(Thread_capability thread, + Pager_capability pager) = 0; + + /** + * Modify instruction and stack pointer of thread - start the + * thread + * + * \param thread thread to start + * \param ip initial instruction pointer + * \param sp initial stack pointer + * + * \return 0 on success + */ + virtual int start(Thread_capability thread, addr_t ip, addr_t sp) = 0; + + /** + * Pause the specified thread + * + * After calling this function, the execution of the thread can be + * continued by calling 'resume'. + */ + virtual void pause(Thread_capability thread) = 0; + + /** + * Resume the specified thread + */ + virtual void resume(Thread_capability thread) = 0; + + /** + * Cancel a currently blocking operation + * + * \param thread thread to unblock + */ + virtual void cancel_blocking(Thread_capability thread) = 0; + + /** + * Get the current state of a specific thread + * + * \param thread targeted thread + * \return state of the targeted thread + * \throw State_access_failed + */ + virtual Thread_state state(Thread_capability thread) = 0; + + /** + * Override the current state of a specific thread + * + * \param thread targeted thread + * \param state state that shall be applied + * \throw State_access_failed + */ + virtual void state(Thread_capability thread, + Thread_state const &state) = 0; + + /** + * Register signal handler for exceptions of the specified thread + * + * If 'thread' is an invalid capability, the default exception + * handler for the CPU session is set. This handler is used for + * all threads that have no explicitly installed exception handler. + * The new default signal handler will take effect for threads + * created after the call. + * + * On Linux, this exception is delivered when the process triggers + * a SIGCHLD. On other platforms, this exception is delivered on + * the occurrence of CPU exceptions such as division by zero. + */ + virtual void exception_handler(Thread_capability thread, + Signal_context_capability handler) = 0; + + /** + * Enable/disable single stepping for specified thread. + * + * Since this functions is currently supported by a small number of + * platforms, we provide a default implementation + * + * \param thread thread to set into single step mode + * \param enable true = enable single-step mode; false = disable + */ + virtual void single_step(Thread_capability, bool) {} + + /** + * Return affinity space of CPU nodes available to the CPU session + * + * The dimension of the affinity space as returned by this function + * represent the physical CPUs that are available. + */ + virtual Affinity::Space affinity_space() const = 0; + + /** + * Define affinity of thread to one or multiple CPU nodes + * + * In the normal case, a thread is assigned to a single CPU. + * Specifying more than one CPU node is supposed to principally + * allow a CPU service to balance the load of threads among + * multiple CPUs. + */ + virtual void affinity(Thread_capability thread, + Affinity::Location affinity) = 0; + + /** + * Translate generic priority value to kernel-specific priority levels + * + * \param pf_prio_limit maximum priority used for the kernel, must + * be power of 2 + * \param prio generic priority value as used by the CPU + * session interface + * \param inverse order of platform priorities, if true + * 'pf_prio_limit' corresponds to the highest + * priority, otherwise it refers to the + * lowest priority. + * \return platform-specific priority value + */ + static unsigned scale_priority(unsigned pf_prio_limit, unsigned prio, + bool inverse = true) { - /********************* - ** Exception types ** - *********************/ + /* + * Generic priority values are (0 is highest, 'PRIORITY_LIMIT' + * is lowest. On platforms where priority levels are defined + * the other way round, we have to invert the priority value. + */ + prio = inverse ? Cpu_session::PRIORITY_LIMIT - prio : prio; - class Thread_creation_failed : public Exception { }; - class State_access_failed : public Exception { }; - class Quota_exceeded : public Thread_creation_failed { }; - class Out_of_metadata : public Exception { }; + /* scale value to platform priority range 0..pf_prio_limit */ + return (prio*pf_prio_limit)/Cpu_session::PRIORITY_LIMIT; + } - static const char *service_name() { return "CPU"; } + /** + * Request trace control dataspace + * + * The trace-control dataspace is used to propagate tracing + * control information from core to the threads of a CPU session. + * + * The trace-control dataspace is accounted to the CPU session. + */ + virtual Dataspace_capability trace_control() = 0; - enum { THREAD_NAME_LEN = 48 }; - enum { PRIORITY_LIMIT = 1 << 16 }; - enum { QUOTA_LIMIT_LOG2 = 15 }; - enum { QUOTA_LIMIT = 1 << QUOTA_LIMIT_LOG2 }; - enum { DEFAULT_PRIORITY = 0 }; + /** + * Request index of a trace control block for given thread + * + * The trace control dataspace contains the control blocks for + * all threads of the CPU session. Each thread gets assigned a + * different index by the CPU service. + */ + virtual unsigned trace_control_index(Thread_capability thread) = 0; - typedef Rpc_in_buffer Name; + /** + * Request trace buffer for the specified thread + * + * The trace buffer is not accounted to the CPU session. It is + * owned by a TRACE session. + */ + virtual Dataspace_capability trace_buffer(Thread_capability thread) = 0; - virtual ~Cpu_session() { } + /** + * Request trace policy + * + * The trace policy buffer is not accounted to the CPU session. It + * is owned by a TRACE session. + */ + virtual Dataspace_capability trace_policy(Thread_capability thread) = 0; - /** - * Create a new thread - * - * \param quota CPU quota that shall be granted to the thread - * \param name name for the thread - * \param utcb Base of the UTCB that will be used by the thread - * \return capability representing the new thread - * \throw Thread_creation_failed - * \throw Out_of_metadata - * \throw Quota_exceeded - */ - virtual Thread_capability create_thread(size_t quota, - Name const &name, - addr_t utcb = 0) = 0; + /** + * Define reference account for the CPU session + * + * \param cpu_session reference account + * + * \return 0 on success + * + * Each CPU session requires another CPU session as reference + * account to transfer quota to and from. The reference account can + * be defined only once. + */ + virtual int ref_account(Cpu_session_capability cpu_session) = 0; - /** - * Get dataspace of the UTCB that is used by the specified thread - */ - virtual Ram_dataspace_capability utcb(Thread_capability thread) = 0; + /** + * Transfer quota to another CPU session + * + * \param cpu_session receiver of quota donation + * \param amount amount of quota to donate + * \return 0 on success + * + * Quota can only be transfered if the specified CPU session is + * either the reference account for this session or vice versa. + */ + virtual int transfer_quota(Cpu_session_capability cpu_session, + size_t amount) = 0; - /** - * Kill an existing thread - * - * \param thread capability of the thread to kill - */ - virtual void kill_thread(Thread_capability thread) = 0; + /** + * Return current quota limit + */ + virtual size_t quota() = 0; - /** - * Set paging capabilities for thread - * - * \param thread thread to configure - * \param pager capability used to propagate page faults - */ - virtual int set_pager(Thread_capability thread, - Pager_capability pager) = 0; + /** + * Return amount of used quota + */ + virtual size_t used() = 0; - /** - * Modify instruction and stack pointer of thread - start the - * thread - * - * \param thread thread to start - * \param ip initial instruction pointer - * \param sp initial stack pointer - * - * \return 0 on success - */ - virtual int start(Thread_capability thread, addr_t ip, addr_t sp) = 0; + /** + * Return amount of available quota + */ + size_t avail() + { + size_t q = quota(), u = used(); + return q > u ? q - u : 0; + } - /** - * Pause the specified thread - * - * After calling this function, the execution of the thread can be - * continued by calling 'resume'. - */ - virtual void pause(Thread_capability thread) = 0; + /** + * Transform percentage of CPU utilization into CPU quota + */ + static size_t pc_to_quota(size_t const pc) { + return (pc << QUOTA_LIMIT_LOG2) / 100; } - /** - * Resume the specified thread - */ - virtual void resume(Thread_capability thread) = 0; + /********************* + ** RPC declaration ** + *********************/ - /** - * Cancel a currently blocking operation - * - * \param thread thread to unblock - */ - virtual void cancel_blocking(Thread_capability thread) = 0; + GENODE_RPC_THROW(Rpc_create_thread, Thread_capability, create_thread, + GENODE_TYPE_LIST(Thread_creation_failed, Out_of_metadata), + size_t, Name const &, addr_t); + GENODE_RPC(Rpc_utcb, Ram_dataspace_capability, utcb, Thread_capability); + GENODE_RPC(Rpc_kill_thread, void, kill_thread, Thread_capability); + GENODE_RPC(Rpc_set_pager, int, set_pager, Thread_capability, Pager_capability); + GENODE_RPC(Rpc_start, int, start, Thread_capability, addr_t, addr_t); + GENODE_RPC(Rpc_pause, void, pause, Thread_capability); + GENODE_RPC(Rpc_resume, void, resume, Thread_capability); + GENODE_RPC(Rpc_cancel_blocking, void, cancel_blocking, Thread_capability); + GENODE_RPC_THROW(Rpc_get_state, Thread_state, state, + GENODE_TYPE_LIST(State_access_failed), + Thread_capability); + GENODE_RPC_THROW(Rpc_set_state, void, state, + GENODE_TYPE_LIST(State_access_failed), + Thread_capability, Thread_state const &); + GENODE_RPC(Rpc_exception_handler, void, exception_handler, + Thread_capability, Signal_context_capability); + GENODE_RPC(Rpc_single_step, void, single_step, Thread_capability, bool); + GENODE_RPC(Rpc_affinity_space, Affinity::Space, affinity_space); + GENODE_RPC(Rpc_affinity, void, affinity, Thread_capability, Affinity::Location); + GENODE_RPC(Rpc_trace_control, Dataspace_capability, trace_control); + GENODE_RPC(Rpc_trace_control_index, unsigned, trace_control_index, Thread_capability); + GENODE_RPC(Rpc_trace_buffer, Dataspace_capability, trace_buffer, Thread_capability); + GENODE_RPC(Rpc_trace_policy, Dataspace_capability, trace_policy, Thread_capability); + GENODE_RPC(Rpc_ref_account, int, ref_account, Cpu_session_capability); + GENODE_RPC(Rpc_transfer_quota, int, transfer_quota, Cpu_session_capability, size_t); + GENODE_RPC(Rpc_quota, size_t, quota); + GENODE_RPC(Rpc_used, size_t, used); - /** - * Get the current state of a specific thread - * - * \param thread targeted thread - * \return state of the targeted thread - * \throw State_access_failed - */ - virtual Thread_state state(Thread_capability thread) = 0; - - /** - * Override the current state of a specific thread - * - * \param thread targeted thread - * \param state state that shall be applied - * \throw State_access_failed - */ - virtual void state(Thread_capability thread, - Thread_state const &state) = 0; - - /** - * Register signal handler for exceptions of the specified thread - * - * If 'thread' is an invalid capability, the default exception - * handler for the CPU session is set. This handler is used for - * all threads that have no explicitly installed exception handler. - * The new default signal handler will take effect for threads - * created after the call. - * - * On Linux, this exception is delivered when the process triggers - * a SIGCHLD. On other platforms, this exception is delivered on - * the occurrence of CPU exceptions such as division by zero. - */ - virtual void exception_handler(Thread_capability thread, - Signal_context_capability handler) = 0; - - /** - * Enable/disable single stepping for specified thread. - * - * Since this functions is currently supported by a small number of - * platforms, we provide a default implementation - * - * \param thread thread to set into single step mode - * \param enable true = enable single-step mode; false = disable - */ - virtual void single_step(Thread_capability, bool) {} - - /** - * Return affinity space of CPU nodes available to the CPU session - * - * The dimension of the affinity space as returned by this function - * represent the physical CPUs that are available. - */ - virtual Affinity::Space affinity_space() const = 0; - - /** - * Define affinity of thread to one or multiple CPU nodes - * - * In the normal case, a thread is assigned to a single CPU. - * Specifying more than one CPU node is supposed to principally - * allow a CPU service to balance the load of threads among - * multiple CPUs. - */ - virtual void affinity(Thread_capability thread, - Affinity::Location affinity) = 0; - - /** - * Translate generic priority value to kernel-specific priority levels - * - * \param pf_prio_limit maximum priority used for the kernel, must - * be power of 2 - * \param prio generic priority value as used by the CPU - * session interface - * \param inverse order of platform priorities, if true - * 'pf_prio_limit' corresponds to the highest - * priority, otherwise it refers to the - * lowest priority. - * \return platform-specific priority value - */ - static unsigned scale_priority(unsigned pf_prio_limit, unsigned prio, - bool inverse = true) - { - /* - * Generic priority values are (0 is highest, 'PRIORITY_LIMIT' - * is lowest. On platforms where priority levels are defined - * the other way round, we have to invert the priority value. - */ - prio = inverse ? Cpu_session::PRIORITY_LIMIT - prio : prio; - - /* scale value to platform priority range 0..pf_prio_limit */ - return (prio*pf_prio_limit)/Cpu_session::PRIORITY_LIMIT; - } - - /** - * Request trace control dataspace - * - * The trace-control dataspace is used to propagate tracing - * control information from core to the threads of a CPU session. - * - * The trace-control dataspace is accounted to the CPU session. - */ - virtual Dataspace_capability trace_control() = 0; - - /** - * Request index of a trace control block for given thread - * - * The trace control dataspace contains the control blocks for - * all threads of the CPU session. Each thread gets assigned a - * different index by the CPU service. - */ - virtual unsigned trace_control_index(Thread_capability thread) = 0; - - /** - * Request trace buffer for the specified thread - * - * The trace buffer is not accounted to the CPU session. It is - * owned by a TRACE session. - */ - virtual Dataspace_capability trace_buffer(Thread_capability thread) = 0; - - /** - * Request trace policy - * - * The trace policy buffer is not accounted to the CPU session. It - * is owned by a TRACE session. - */ - virtual Dataspace_capability trace_policy(Thread_capability thread) = 0; - - /** - * Define reference account for the CPU session - * - * \param cpu_session reference account - * - * \return 0 on success - * - * Each CPU session requires another CPU session as reference - * account to transfer quota to and from. The reference account can - * be defined only once. - */ - virtual int ref_account(Cpu_session_capability cpu_session) = 0; - - /** - * Transfer quota to another CPU session - * - * \param cpu_session receiver of quota donation - * \param amount amount of quota to donate - * \return 0 on success - * - * Quota can only be transfered if the specified CPU session is - * either the reference account for this session or vice versa. - */ - virtual int transfer_quota(Cpu_session_capability cpu_session, - size_t amount) = 0; - - /** - * Return current quota limit - */ - virtual size_t quota() = 0; - - /** - * Return amount of used quota - */ - virtual size_t used() = 0; - - /** - * Return amount of available quota - */ - size_t avail() - { - size_t q = quota(), u = used(); - return q > u ? q - u : 0; - } - - /** - * Transform percentage of CPU utilization into CPU quota - */ - static size_t pc_to_quota(size_t const pc) { - return (pc << QUOTA_LIMIT_LOG2) / 100; } - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC_THROW(Rpc_create_thread, Thread_capability, create_thread, - GENODE_TYPE_LIST(Thread_creation_failed, Out_of_metadata), - size_t, Name const &, addr_t); - GENODE_RPC(Rpc_utcb, Ram_dataspace_capability, utcb, Thread_capability); - GENODE_RPC(Rpc_kill_thread, void, kill_thread, Thread_capability); - GENODE_RPC(Rpc_set_pager, int, set_pager, Thread_capability, Pager_capability); - GENODE_RPC(Rpc_start, int, start, Thread_capability, addr_t, addr_t); - GENODE_RPC(Rpc_pause, void, pause, Thread_capability); - GENODE_RPC(Rpc_resume, void, resume, Thread_capability); - GENODE_RPC(Rpc_cancel_blocking, void, cancel_blocking, Thread_capability); - GENODE_RPC_THROW(Rpc_get_state, Thread_state, state, - GENODE_TYPE_LIST(State_access_failed), - Thread_capability); - GENODE_RPC_THROW(Rpc_set_state, void, state, - GENODE_TYPE_LIST(State_access_failed), - Thread_capability, Thread_state const &); - GENODE_RPC(Rpc_exception_handler, void, exception_handler, - Thread_capability, Signal_context_capability); - GENODE_RPC(Rpc_single_step, void, single_step, Thread_capability, bool); - GENODE_RPC(Rpc_affinity_space, Affinity::Space, affinity_space); - GENODE_RPC(Rpc_affinity, void, affinity, Thread_capability, Affinity::Location); - GENODE_RPC(Rpc_trace_control, Dataspace_capability, trace_control); - GENODE_RPC(Rpc_trace_control_index, unsigned, trace_control_index, Thread_capability); - GENODE_RPC(Rpc_trace_buffer, Dataspace_capability, trace_buffer, Thread_capability); - GENODE_RPC(Rpc_trace_policy, Dataspace_capability, trace_policy, Thread_capability); - GENODE_RPC(Rpc_ref_account, int, ref_account, Cpu_session_capability); - GENODE_RPC(Rpc_transfer_quota, int, transfer_quota, Cpu_session_capability, size_t); - GENODE_RPC(Rpc_quota, size_t, quota); - GENODE_RPC(Rpc_used, size_t, used); - - /* - * 'GENODE_RPC_INTERFACE' declaration done manually - * - * The number of RPC function of this interface exceeds the maximum - * number of elements supported by 'Meta::Type_list'. Therefore, we - * construct the type list by hand using nested type tuples instead - * of employing the convenience macro 'GENODE_RPC_INTERFACE'. - */ - typedef Meta::Type_tuple - > > > > > > > > > > > > > > > > > > > > > Rpc_functions; - }; -} + /* + * 'GENODE_RPC_INTERFACE' declaration done manually + * + * The number of RPC function of this interface exceeds the maximum + * number of elements supported by 'Meta::Type_list'. Therefore, we + * construct the type list by hand using nested type tuples instead + * of employing the convenience macro 'GENODE_RPC_INTERFACE'. + */ + typedef Meta::Type_tuple + > > > > > > > > > > > > > > > > > > > > > Rpc_functions; +}; #endif /* _INCLUDE__CPU_SESSION__CPU_SESSION_H_ */ diff --git a/repos/base/include/dataspace/client.h b/repos/base/include/dataspace/client.h index fb5a6344a..4d96f4026 100644 --- a/repos/base/include/dataspace/client.h +++ b/repos/base/include/dataspace/client.h @@ -17,17 +17,17 @@ #include #include -namespace Genode { +namespace Genode { struct Dataspace_client; } - struct Dataspace_client : Rpc_client - { - explicit Dataspace_client(Dataspace_capability ds) - : Rpc_client(ds) { } - size_t size() { return call(); } - addr_t phys_addr() { return call(); } - bool writable() { return call(); } - }; -} +struct Genode::Dataspace_client : Rpc_client +{ + explicit Dataspace_client(Dataspace_capability ds) + : Rpc_client(ds) { } + + size_t size() override { return call(); } + addr_t phys_addr() override { return call(); } + bool writable() override { return call(); } +}; #endif /* _INCLUDE__DATASPACE__CLIENT_H_ */ diff --git a/repos/base/include/dataspace/dataspace.h b/repos/base/include/dataspace/dataspace.h index a7aac6050..eb678e4fd 100644 --- a/repos/base/include/dataspace/dataspace.h +++ b/repos/base/include/dataspace/dataspace.h @@ -17,38 +17,38 @@ #include #include -namespace Genode { - - struct Dataspace - { - virtual ~Dataspace() { } - - /** - * Request size of dataspace - */ - virtual size_t size() = 0; - - /** - * Request base address in physical address space - */ - virtual addr_t phys_addr() = 0; - - /** - * Return true if dataspace is writable - */ - virtual bool writable() = 0; +namespace Genode { struct Dataspace; } - /********************* - ** RPC declaration ** - *********************/ +struct Genode::Dataspace +{ + virtual ~Dataspace() { } - GENODE_RPC(Rpc_size, size_t, size); - GENODE_RPC(Rpc_phys_addr, addr_t, phys_addr); - GENODE_RPC(Rpc_writable, bool, writable); + /** + * Request size of dataspace + */ + virtual size_t size() = 0; - GENODE_RPC_INTERFACE(Rpc_size, Rpc_phys_addr, Rpc_writable); - }; -} + /** + * Request base address in physical address space + */ + virtual addr_t phys_addr() = 0; + + /** + * Return true if dataspace is writable + */ + virtual bool writable() = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_size, size_t, size); + GENODE_RPC(Rpc_phys_addr, addr_t, phys_addr); + GENODE_RPC(Rpc_writable, bool, writable); + + GENODE_RPC_INTERFACE(Rpc_size, Rpc_phys_addr, Rpc_writable); +}; #endif /* _INCLUDE__DATASPACE__DATASPACE_H_ */ diff --git a/repos/base/include/drivers/timer/epit_base.h b/repos/base/include/drivers/timer/epit_base.h index a3e73664f..d479642dd 100644 --- a/repos/base/include/drivers/timer/epit_base.h +++ b/repos/base/include/drivers/timer/epit_base.h @@ -19,173 +19,173 @@ /* Genode includes */ #include -namespace Genode +namespace Genode { class Epit_base; } + + +/** + * Core timer + */ +class Genode::Epit_base : public Mmio { - /** - * Core timer - */ - class Epit_base : public Mmio - { - protected: + protected: - enum { TICS_PER_MS = 32 }; + enum { TICS_PER_MS = 32 }; - /** - * Control register - */ - struct Cr : Register<0x0, 32> + /** + * Control register + */ + struct Cr : Register<0x0, 32> + { + struct En : Bitfield<0, 1> { }; /* enable timer */ + + struct En_mod : Bitfield<1, 1> /* reload on enable */ { - struct En : Bitfield<0, 1> { }; /* enable timer */ + enum { RELOAD = 1 }; + }; - struct En_mod : Bitfield<1, 1> /* reload on enable */ - { - enum { RELOAD = 1 }; - }; + struct Oci_en : Bitfield<2, 1> { }; /* interrupt on compare */ - struct Oci_en : Bitfield<2, 1> { }; /* interrupt on compare */ + struct Rld : Bitfield<3, 1> /* reload or roll-over */ + { + enum { RELOAD_FROM_LR = 1 }; + }; - struct Rld : Bitfield<3, 1> /* reload or roll-over */ - { - enum { RELOAD_FROM_LR = 1 }; - }; + struct Prescaler : Bitfield<4, 12> /* clock input divisor */ + { + enum { DIVIDE_BY_1 = 0 }; + }; - struct Prescaler : Bitfield<4, 12> /* clock input divisor */ - { - enum { DIVIDE_BY_1 = 0 }; - }; + struct Swr : Bitfield<16, 1> { }; /* software reset bit */ + struct Iovw : Bitfield<17, 1> { }; /* enable overwrite */ + struct Dbg_en : Bitfield<18, 1> { }; /* enable in debug mode */ + struct Wait_en : Bitfield<19, 1> { }; /* enable in wait mode */ + struct Doz_en : Bitfield<20, 1> { }; /* enable in doze mode */ + struct Stop_en : Bitfield<21, 1> { }; /* enable in stop mode */ - struct Swr : Bitfield<16, 1> { }; /* software reset bit */ - struct Iovw : Bitfield<17, 1> { }; /* enable overwrite */ - struct Dbg_en : Bitfield<18, 1> { }; /* enable in debug mode */ - struct Wait_en : Bitfield<19, 1> { }; /* enable in wait mode */ - struct Doz_en : Bitfield<20, 1> { }; /* enable in doze mode */ - struct Stop_en : Bitfield<21, 1> { }; /* enable in stop mode */ + struct Om : Bitfield<22, 2> /* mode of the output pin */ + { + enum { DISCONNECTED = 0 }; + }; - struct Om : Bitfield<22, 2> /* mode of the output pin */ - { - enum { DISCONNECTED = 0 }; - }; - - struct Clk_src : Bitfield<24, 2> /* select clock input */ - { - enum { IPG_CLK_32K = 3 }; - }; - - /** - * Register value that configures the timer for a one-shot run - */ - static access_t prepare_one_shot() - { - return En::bits(0) | - En_mod::bits(En_mod::RELOAD) | - Oci_en::bits(1) | - Rld::bits(Rld::RELOAD_FROM_LR) | - Prescaler::bits(Prescaler::DIVIDE_BY_1) | - Swr::bits(0) | - Iovw::bits(0) | - Dbg_en::bits(0) | - Wait_en::bits(0) | - Doz_en::bits(0) | - Stop_en::bits(0) | - Om::bits(Om::DISCONNECTED) | - Clk_src::bits(Clk_src::IPG_CLK_32K); - } + struct Clk_src : Bitfield<24, 2> /* select clock input */ + { + enum { IPG_CLK_32K = 3 }; }; /** - * Status register + * Register value that configures the timer for a one-shot run */ - struct Sr : Register<0x4, 32> + static access_t prepare_one_shot() { - struct Ocif : Bitfield<0, 1> { }; /* IRQ status, write 1 clears */ - }; - - struct Lr : Register<0x8, 32> { }; /* load value register */ - struct Cmpr : Register<0xc, 32> { }; /* compare value register */ - struct Cnt : Register<0x10, 32> { }; /* counter register */ - - /** - * Disable timer and clear its interrupt output - */ - void _reset() - { - /* wait until ongoing reset operations are finished */ - while (read()) ; - - /* disable timer */ - write(0); - - /* clear interrupt */ - write(1); + return En::bits(0) | + En_mod::bits(En_mod::RELOAD) | + Oci_en::bits(1) | + Rld::bits(Rld::RELOAD_FROM_LR) | + Prescaler::bits(Prescaler::DIVIDE_BY_1) | + Swr::bits(0) | + Iovw::bits(0) | + Dbg_en::bits(0) | + Wait_en::bits(0) | + Doz_en::bits(0) | + Stop_en::bits(0) | + Om::bits(Om::DISCONNECTED) | + Clk_src::bits(Clk_src::IPG_CLK_32K); } + }; - void _start_one_shot(unsigned const tics) - { - /* stop timer */ - _reset(); + /** + * Status register + */ + struct Sr : Register<0x4, 32> + { + struct Ocif : Bitfield<0, 1> { }; /* IRQ status, write 1 clears */ + }; - /* configure timer for a one-shot */ - write(Cr::prepare_one_shot()); - write(tics); - write(0); + struct Lr : Register<0x8, 32> { }; /* load value register */ + struct Cmpr : Register<0xc, 32> { }; /* compare value register */ + struct Cnt : Register<0x10, 32> { }; /* counter register */ - /* start timer */ - write(1); - } + /** + * Disable timer and clear its interrupt output + */ + void _reset() + { + /* wait until ongoing reset operations are finished */ + while (read()) ; - public: + /* disable timer */ + write(0); - /** - * Constructor - */ - Epit_base(addr_t base) : Mmio(base) { _reset(); } + /* clear interrupt */ + write(1); + } - /** - * Start single timeout run - * - * \param tics delay of timer interrupt - */ - void start_one_shot(unsigned const tics, unsigned) - { - _start_one_shot(tics); - } + void _start_one_shot(unsigned const tics) + { + /* stop timer */ + _reset(); - /** - * Stop the timer from a one-shot run - * - * \return last native timer value of the one-shot run - */ - unsigned long stop_one_shot() - { - /* disable timer */ - write(0); - return value(0); - } + /* configure timer for a one-shot */ + write(Cr::prepare_one_shot()); + write(tics); + write(0); - /** - * Translate milliseconds to a native timer value - */ - unsigned ms_to_tics(unsigned const ms) - { - return TICS_PER_MS * ms; - } + /* start timer */ + write(1); + } - /** - * Translate native timer value to milliseconds - */ - unsigned tics_to_ms(unsigned const tics) - { - return tics / TICS_PER_MS; - } + public: - /** - * Return current native timer value - */ - unsigned value(unsigned const) - { - return read() ? 0 : read(); - } - }; -} + /** + * Constructor + */ + Epit_base(addr_t base) : Mmio(base) { _reset(); } + + /** + * Start single timeout run + * + * \param tics delay of timer interrupt + */ + void start_one_shot(unsigned const tics, unsigned) + { + _start_one_shot(tics); + } + + /** + * Stop the timer from a one-shot run + * + * \return last native timer value of the one-shot run + */ + unsigned long stop_one_shot() + { + /* disable timer */ + write(0); + return value(0); + } + + /** + * Translate milliseconds to a native timer value + */ + unsigned ms_to_tics(unsigned const ms) + { + return TICS_PER_MS * ms; + } + + /** + * Translate native timer value to milliseconds + */ + unsigned tics_to_ms(unsigned const tics) + { + return tics / TICS_PER_MS; + } + + /** + * Return current native timer value + */ + unsigned value(unsigned const) + { + return read() ? 0 : read(); + } +}; #endif /* _INCLUDE__DRIVERS__TIMER__EPIT_BASE_H_ */ diff --git a/repos/base/include/drivers/uart/exynos_uart_base.h b/repos/base/include/drivers/uart/exynos_uart_base.h index 40723e9b2..e81f02873 100644 --- a/repos/base/include/drivers/uart/exynos_uart_base.h +++ b/repos/base/include/drivers/uart/exynos_uart_base.h @@ -17,230 +17,230 @@ /* Genode includes */ #include -namespace Genode +namespace Genode { class Exynos_uart_base; } + + +/** + * Exynos UART driver base + */ +class Genode::Exynos_uart_base : Mmio { - /** - * Exynos UART driver base - */ - class Exynos_uart_base : Mmio - { - protected: + protected: + + /** + * Line control + */ + struct Ulcon : Register<0x0, 32> + { + struct Word_length : Bitfield<0, 2> { enum { _8_BIT = 3 }; }; + struct Stop_bits : Bitfield<2, 1> { enum { _1_BIT = 0 }; }; + struct Parity_mode : Bitfield<3, 3> { enum { NONE = 0 }; }; + struct Infrared_mode : Bitfield<6, 1> { }; /** - * Line control + * Initialization value */ - struct Ulcon : Register<0x0, 32> + static access_t init_value() { - struct Word_length : Bitfield<0, 2> { enum { _8_BIT = 3 }; }; - struct Stop_bits : Bitfield<2, 1> { enum { _1_BIT = 0 }; }; - struct Parity_mode : Bitfield<3, 3> { enum { NONE = 0 }; }; - struct Infrared_mode : Bitfield<6, 1> { }; - - /** - * Initialization value - */ - static access_t init_value() - { - return Word_length::bits(Word_length::_8_BIT) | - Stop_bits::bits(Stop_bits::_1_BIT) | - Parity_mode::bits(Parity_mode::NONE) | - Infrared_mode::bits(0); - } - }; - - /** - * Control - */ - struct Ucon : Register<0x4, 32> - { - struct Receive_mode : Bitfield<0, 2> { enum { IRQ_POLL = 1 }; }; - struct Transmit_mode : Bitfield<2, 2> { enum { IRQ_POLL = 1 }; }; - struct Send_brk_signal : Bitfield<4, 1> { }; - struct Loop_back_mode : Bitfield<5, 1> { }; - struct Rx_err_irq : Bitfield<6, 1> { }; - struct Rx_timeout : Bitfield<7, 1> { }; - struct Rx_irq_type : Bitfield<8, 1> { enum { LEVEL = 1 }; }; - struct Tx_irq_type : Bitfield<9, 1> { enum { LEVEL = 1 }; }; - struct Rx_to_dma_susp : Bitfield<10, 1> { }; - struct Rx_to_empty_rx : Bitfield<11, 1> { }; - struct Rx_to_interval : Bitfield<12, 4> { }; - struct Rx_dma_bst_size : Bitfield<16, 3> { }; - struct Tx_dma_bst_size : Bitfield<20, 3> { }; - - /** - * Initialization value - */ - static access_t init_value() - { - return Receive_mode::bits(Receive_mode::IRQ_POLL) | - Transmit_mode::bits(Transmit_mode::IRQ_POLL) | - Rx_timeout::bits(1); - } - }; - - /** - * FIFO control - */ - struct Ufcon : Register<0x8, 32> - { - struct Fifo_en : Bitfield<0, 1> { }; - struct Rx_fifo_rst : Bitfield<1, 1> { }; - struct Tx_fifo_rst : Bitfield<2, 1> { }; - }; - - /** - * Modem control - */ - struct Umcon : Register<0xc, 32> - { - struct Send_request : Bitfield<0, 1> { }; - struct Modem_irq : Bitfield<3, 1> { }; - struct Auto_flow_ctl : Bitfield<4, 1> { }; - struct Rts_trigger : Bitfield<5, 3> { }; - - /** - * Initialization value - */ - static access_t init_value() - { - return Send_request::bits(0) | - Modem_irq::bits(0) | - Auto_flow_ctl::bits(0) | - Rts_trigger::bits(0); - } - }; - - /** - * FIFO status - */ - struct Ufstat : Register<0x18, 32> - { - struct Rx_fifo_count : Bitfield<0, 8> { }; - struct Rx_fifo_full : Bitfield<8, 1> { }; - struct Tx_fifo_full : Bitfield<24, 1> { }; - }; - - /** - * Transmit buffer - */ - struct Utxh : Register<0x20, 32> - { - struct Transmit_data : Bitfield<0, 8> { }; - }; - - /** - * Receive buffer - */ - struct Urxh : Register<0x24, 32> - { - struct Receive_data : Bitfield<0, 8> { }; - }; - - /** - * Baud Rate Divisor - */ - struct Ubrdiv : Register<0x28, 32> - { - struct Baud_rate_div : Bitfield<0, 16> { }; - }; - - /** - * Fractional part of Baud Rate Divisor - */ - struct Ufracval : Register<0x2c, 32> - { - struct Baud_rate_frac : Bitfield<0, 4> { }; - }; - - /** - * Interrupt mask register - */ - template - struct Uintx : Register - { - struct Rxd : Register::template Bitfield<0, 1> { }; - struct Error : Register::template Bitfield<1, 1> { }; - struct Txd : Register::template Bitfield<2, 1> { }; - struct Modem : Register::template Bitfield<3, 1> { }; - }; - - using Uintp = Uintx<0x30>; - using Uintm = Uintx<0x38>; - - void _rx_enable() - { - write(1); - - /* mask all IRQs except receive IRQ */ - write(Uintm::Error::bits(1) | - Uintm::Txd::bits(1) | - Uintm::Modem::bits(1)); - - /* clear pending IRQs */ - write(Uintp::Rxd::bits(1) | - Uintp::Error::bits(1) | - Uintp::Txd::bits(1) | - Uintp::Modem::bits(1)); + return Word_length::bits(Word_length::_8_BIT) | + Stop_bits::bits(Stop_bits::_1_BIT) | + Parity_mode::bits(Parity_mode::NONE) | + Infrared_mode::bits(0); } + }; - bool _rx_avail() { - return (read() & (Ufstat::Rx_fifo_count::bits(0xff) - | Ufstat::Rx_fifo_full::bits(1))); } + /** + * Control + */ + struct Ucon : Register<0x4, 32> + { + struct Receive_mode : Bitfield<0, 2> { enum { IRQ_POLL = 1 }; }; + struct Transmit_mode : Bitfield<2, 2> { enum { IRQ_POLL = 1 }; }; + struct Send_brk_signal : Bitfield<4, 1> { }; + struct Loop_back_mode : Bitfield<5, 1> { }; + struct Rx_err_irq : Bitfield<6, 1> { }; + struct Rx_timeout : Bitfield<7, 1> { }; + struct Rx_irq_type : Bitfield<8, 1> { enum { LEVEL = 1 }; }; + struct Tx_irq_type : Bitfield<9, 1> { enum { LEVEL = 1 }; }; + struct Rx_to_dma_susp : Bitfield<10, 1> { }; + struct Rx_to_empty_rx : Bitfield<11, 1> { }; + struct Rx_to_interval : Bitfield<12, 4> { }; + struct Rx_dma_bst_size : Bitfield<16, 3> { }; + struct Tx_dma_bst_size : Bitfield<20, 3> { }; /** - * Return character received via UART + * Initialization value */ - char _rx_char() + static access_t init_value() { - read(); - char c = read(); - - /* clear pending RX IRQ */ - write(Uintp::Rxd::bits(1)); - return c; + return Receive_mode::bits(Receive_mode::IRQ_POLL) | + Transmit_mode::bits(Transmit_mode::IRQ_POLL) | + Rx_timeout::bits(1); } + }; - public: + /** + * FIFO control + */ + struct Ufcon : Register<0x8, 32> + { + struct Fifo_en : Bitfield<0, 1> { }; + struct Rx_fifo_rst : Bitfield<1, 1> { }; + struct Tx_fifo_rst : Bitfield<2, 1> { }; + }; + + /** + * Modem control + */ + struct Umcon : Register<0xc, 32> + { + struct Send_request : Bitfield<0, 1> { }; + struct Modem_irq : Bitfield<3, 1> { }; + struct Auto_flow_ctl : Bitfield<4, 1> { }; + struct Rts_trigger : Bitfield<5, 3> { }; /** - * Constructor - * - * \param base MMIO base address - * \param clock reference clock - * \param baud_rate targeted baud rate + * Initialization value */ - Exynos_uart_base(addr_t const base, unsigned const clock, - unsigned const baud_rate) : Mmio(base) + static access_t init_value() { - /* RX and TX FIFO reset */ - write(1); - write(1); - while (read() || read()) ; - - /* init control registers */ - write(Ulcon::init_value()); - write(Ucon::init_value()); - write(Umcon::init_value()); - - /* apply baud rate */ - float const div_val = ((float)clock / (baud_rate * 16)) - 1; - Ubrdiv::access_t const ubrdiv = div_val; - Ufracval::access_t const ufracval = - ((float)div_val - ubrdiv) * 16; - write(ubrdiv); - write(ufracval); + return Send_request::bits(0) | + Modem_irq::bits(0) | + Auto_flow_ctl::bits(0) | + Rts_trigger::bits(0); } + }; - /** - * Print character 'c' through the UART - */ - void put_char(char const c) - { - while (read()) ; - write(c); - } - }; -} + /** + * FIFO status + */ + struct Ufstat : Register<0x18, 32> + { + struct Rx_fifo_count : Bitfield<0, 8> { }; + struct Rx_fifo_full : Bitfield<8, 1> { }; + struct Tx_fifo_full : Bitfield<24, 1> { }; + }; + + /** + * Transmit buffer + */ + struct Utxh : Register<0x20, 32> + { + struct Transmit_data : Bitfield<0, 8> { }; + }; + + /** + * Receive buffer + */ + struct Urxh : Register<0x24, 32> + { + struct Receive_data : Bitfield<0, 8> { }; + }; + + /** + * Baud Rate Divisor + */ + struct Ubrdiv : Register<0x28, 32> + { + struct Baud_rate_div : Bitfield<0, 16> { }; + }; + + /** + * Fractional part of Baud Rate Divisor + */ + struct Ufracval : Register<0x2c, 32> + { + struct Baud_rate_frac : Bitfield<0, 4> { }; + }; + + /** + * Interrupt mask register + */ + template + struct Uintx : Register + { + struct Rxd : Register::template Bitfield<0, 1> { }; + struct Error : Register::template Bitfield<1, 1> { }; + struct Txd : Register::template Bitfield<2, 1> { }; + struct Modem : Register::template Bitfield<3, 1> { }; + }; + + using Uintp = Uintx<0x30>; + using Uintm = Uintx<0x38>; + + void _rx_enable() + { + write(1); + + /* mask all IRQs except receive IRQ */ + write(Uintm::Error::bits(1) | + Uintm::Txd::bits(1) | + Uintm::Modem::bits(1)); + + /* clear pending IRQs */ + write(Uintp::Rxd::bits(1) | + Uintp::Error::bits(1) | + Uintp::Txd::bits(1) | + Uintp::Modem::bits(1)); + } + + bool _rx_avail() { + return (read() & (Ufstat::Rx_fifo_count::bits(0xff) + | Ufstat::Rx_fifo_full::bits(1))); } + + /** + * Return character received via UART + */ + char _rx_char() + { + read(); + char c = read(); + + /* clear pending RX IRQ */ + write(Uintp::Rxd::bits(1)); + return c; + } + + public: + + /** + * Constructor + * + * \param base MMIO base address + * \param clock reference clock + * \param baud_rate targeted baud rate + */ + Exynos_uart_base(addr_t const base, unsigned const clock, + unsigned const baud_rate) : Mmio(base) + { + /* RX and TX FIFO reset */ + write(1); + write(1); + while (read() || read()) ; + + /* init control registers */ + write(Ulcon::init_value()); + write(Ucon::init_value()); + write(Umcon::init_value()); + + /* apply baud rate */ + float const div_val = ((float)clock / (baud_rate * 16)) - 1; + Ubrdiv::access_t const ubrdiv = div_val; + Ufracval::access_t const ufracval = + ((float)div_val - ubrdiv) * 16; + write(ubrdiv); + write(ufracval); + } + + /** + * Print character 'c' through the UART + */ + void put_char(char const c) + { + while (read()) ; + write(c); + } +}; #endif /* _INCLUDE__DRIVERS__UART__EXYNOS_UART_BASE_H_ */ diff --git a/repos/base/include/drivers/uart/imx_uart_base.h b/repos/base/include/drivers/uart/imx_uart_base.h index 3439991f6..b7fb94968 100644 --- a/repos/base/include/drivers/uart/imx_uart_base.h +++ b/repos/base/include/drivers/uart/imx_uart_base.h @@ -18,257 +18,257 @@ /* Genode includes */ #include -namespace Genode +namespace Genode { class Imx_uart_base; } + + +/** + * Driver base for i.MX UART-module + */ +class Genode::Imx_uart_base : Mmio { /** - * Driver base for i.MX UART-module + * Control register 1 */ - class Imx_uart_base : Mmio + struct Cr1 : Register<0x80, 32> { - /** - * Control register 1 - */ - struct Cr1 : Register<0x80, 32> + struct Uart_en : Bitfield<0, 1> { }; /* enable UART */ + struct Doze : Bitfield<1, 1> { }; /* disable on doze */ + struct At_dma_en : Bitfield<2, 1> { }; /* aging DMA + * timer on */ + struct Tx_dma_en : Bitfield<3, 1> { }; /* TX ready DMA on */ + struct Snd_brk : Bitfield<4, 1> { }; /* send breaks */ + struct Rtsd_en : Bitfield<5, 1> { }; /* RTS delta IRQ on */ + struct Tx_mpty_en : Bitfield<6, 1> { }; /* TX empty IRQ on */ + struct Ir_en : Bitfield<7, 1> { }; /* enable infrared */ + struct Rx_dma_en : Bitfield<8, 1> { }; /* RX ready DMA on */ + struct R_rdy_en : Bitfield<9, 1> { }; /* RX ready IRQ on */ + + struct Icd : Bitfield<10, 2> /* idle IRQ condition */ { - struct Uart_en : Bitfield<0, 1> { }; /* enable UART */ - struct Doze : Bitfield<1, 1> { }; /* disable on doze */ - struct At_dma_en : Bitfield<2, 1> { }; /* aging DMA - * timer on */ - struct Tx_dma_en : Bitfield<3, 1> { }; /* TX ready DMA on */ - struct Snd_brk : Bitfield<4, 1> { }; /* send breaks */ - struct Rtsd_en : Bitfield<5, 1> { }; /* RTS delta IRQ on */ - struct Tx_mpty_en : Bitfield<6, 1> { }; /* TX empty IRQ on */ - struct Ir_en : Bitfield<7, 1> { }; /* enable infrared */ - struct Rx_dma_en : Bitfield<8, 1> { }; /* RX ready DMA on */ - struct R_rdy_en : Bitfield<9, 1> { }; /* RX ready IRQ on */ - - struct Icd : Bitfield<10, 2> /* idle IRQ condition */ - { - enum { IDLE_4_FRAMES = 0 }; - }; - - struct Id_en : Bitfield<12, 1> { }; /* enable idle IRQ */ - struct T_rdy_en : Bitfield<13, 1> { }; /* TX ready IRQ on */ - struct Adbr : Bitfield<14, 1> { }; /* enable baud-rate - * auto detect */ - struct Ad_en : Bitfield<15, 1> { }; /* enable ADBR IRQ */ - - /** - * Initialization value - */ - static access_t init_value() - { - return Uart_en::bits(1) | - Doze::bits(0) | - At_dma_en::bits(0) | - Tx_dma_en::bits(0) | - Snd_brk::bits(0) | - Rtsd_en::bits(0) | - Tx_mpty_en::bits(0) | - Ir_en::bits(0) | - Rx_dma_en::bits(0) | - R_rdy_en::bits(0) | - Id_en::bits(0) | - T_rdy_en::bits(0) | - Adbr::bits(0) | - Ad_en::bits(0); - } - + enum { IDLE_4_FRAMES = 0 }; }; - /** - * Control register 2 - */ - struct Cr2 : Register<0x84, 32> - { - struct S_rst : Bitfield<0, 1> /* SW reset bit */ - { - enum { NO_RESET = 1 }; - }; - - struct Rx_en : Bitfield<1, 1> { }; /* enable receiver */ - struct Tx_en : Bitfield<2, 1> { }; /* enable transmitter */ - struct At_en : Bitfield<3, 1> { }; /* enable aging timer */ - struct Rts_en : Bitfield<4, 1> { }; /* send request IRQ on */ - - struct Ws : Bitfield<5, 1> /* select word size */ - { - enum { _8_BITS = 1 }; - }; - - struct Stpb : Bitfield<6, 1> /* number of stop bits */ - { - enum { _1_BIT = 0 }; - }; - - struct Pr_en : Bitfield<8, 1> { }; /* enable parity */ - struct Esc_en : Bitfield<11, 1> { }; /* escape detection on */ - - struct Ctsc : Bitfield<13, 1> /* select CTS control */ - { - enum { BY_RECEIVER = 1 }; - }; - - struct Irts : Bitfield<14, 1> { }; /* ignore RTS pin */ - struct Esci : Bitfield<15, 1> { }; /* enable escape IRQ */ - - /** - * Initialization value - */ - static access_t init_value() - { - return S_rst::bits(S_rst::NO_RESET) | - Rx_en::bits(0) | - Tx_en::bits(1) | - At_en::bits(0) | - Rts_en::bits(0) | - Ws::bits(Ws::_8_BITS) | - Stpb::bits(Stpb::_1_BIT) | - Pr_en::bits(0) | - Esc_en::bits(0) | - Ctsc::bits(Ctsc::BY_RECEIVER) | - Irts::bits(1) | - Esci::bits(0); - } - }; + struct Id_en : Bitfield<12, 1> { }; /* enable idle IRQ */ + struct T_rdy_en : Bitfield<13, 1> { }; /* TX ready IRQ on */ + struct Adbr : Bitfield<14, 1> { }; /* enable baud-rate + * auto detect */ + struct Ad_en : Bitfield<15, 1> { }; /* enable ADBR IRQ */ /** - * Control register 3 + * Initialization value */ - struct Cr3 : Register<0x88, 32> + static access_t init_value() { - struct Rxdmux_sel : Bitfield<2, 1> { }; /* use muxed RXD */ - struct Aci_en : Bitfield<0, 1> { }; /* autobaud count IRQ on */ - struct Dtrd_en : Bitfield<3, 1> { }; /* data terminal ready - * delta IRQ on */ - struct Awak_en : Bitfield<4, 1> { }; /* wake IRQ on */ - struct Air_int_en : Bitfield<5, 1> { }; /* IR wake IRQ on */ - struct Rx_ds_en : Bitfield<6, 1> { }; /* RX status IRQ on */ - struct Ad_nimp : Bitfield<7, 1> { }; /* autobaud detect off */ - struct Ri_en : Bitfield<8, 1> { }; /* ring indicator IRQ on */ - struct Dcd_en : Bitfield<9, 1> { }; /* data carrier detect - * IRQ on */ - struct Dsr : Bitfield<10,1> { }; /* DSR/DTR output */ - struct Frame_en : Bitfield<11,1> { }; /* frame error IRQ on */ - struct Parity_en : Bitfield<12,1> { }; /* parity error IRQ on */ - struct Dtr_en : Bitfield<13,1> { }; /* data terminal ready - * IRQ on */ - struct Dpec_ctrl : Bitfield<14,2> { }; /* DTR/DSR IRQ edge - * control */ - - /** - * Initialization value - */ - static access_t init_value() - { - return Aci_en::bits(0) | - Rxdmux_sel::bits(0) | - Dtrd_en::bits(0) | - Awak_en::bits(0) | - Air_int_en::bits(0) | - Rx_ds_en::bits(0) | - Ad_nimp::bits(1) | - Ri_en::bits(0) | - Dcd_en::bits(0) | - Dsr::bits(0) | - Frame_en::bits(0) | - Parity_en::bits(0) | - Dtr_en::bits(0) | - Dpec_ctrl::bits(0); - } - }; - - /** - * Control register 4 - */ - struct Cr4 : Register<0x8c, 32> - { - struct Dr_en : Bitfield<0, 1> { }; /* RX data ready IRQ on */ - struct Or_en : Bitfield<1, 1> { }; /* RX overrun IRQ on */ - struct Bk_en : Bitfield<2, 1> { }; /* BREAK IRQ on */ - struct Tc_en : Bitfield<3, 1> { }; /* TX complete IRQ on */ - struct Lp_dis : Bitfield<4, 1> { }; /* low power off */ - struct IR_sc : Bitfield<5, 1> { }; /* use UART ref clock - * for vote logic */ - struct Id_dma_en : Bitfield<6, 1> { }; /* idle DMA IRQ on */ - struct Wake_en : Bitfield<7, 1> { }; /* WAKE IRQ on */ - struct IR_en : Bitfield<8, 1> { }; /* serial IR IRQ on */ - struct Cts_level : Bitfield<10,6> { }; /* CTS trigger level*/ - - /** - * Initialization value - */ - static access_t init_value() - { - return Dr_en::bits(0) | - Or_en::bits(0) | - Bk_en::bits(0) | - Tc_en::bits(0) | - Lp_dis::bits(0) | - IR_sc::bits(0) | - Id_dma_en::bits(0) | - Wake_en::bits(0) | - IR_en::bits(0) | - Cts_level::bits(0); - } - }; - - /** - * Status register 2 - */ - struct Sr2 : Register<0x98, 32> - { - struct Txdc : Bitfield<3, 1> { }; /* transmission complete */ - }; - - /** - * Transmitter register - */ - struct Txd : Register<0x40, 32> - { - struct Tx_data : Bitfield<0, 8> { }; /* transmit data */ - }; - - /** - * Transmit character 'c' without care about its type - */ - inline void _put_char(char const c) - { - while (!read()) ; - write(c); + return Uart_en::bits(1) | + Doze::bits(0) | + At_dma_en::bits(0) | + Tx_dma_en::bits(0) | + Snd_brk::bits(0) | + Rtsd_en::bits(0) | + Tx_mpty_en::bits(0) | + Ir_en::bits(0) | + Rx_dma_en::bits(0) | + R_rdy_en::bits(0) | + Id_en::bits(0) | + T_rdy_en::bits(0) | + Adbr::bits(0) | + Ad_en::bits(0); } - public: - - /** - * Constructor - * - * \param base device MMIO base - */ - explicit Imx_uart_base(addr_t const base) : Mmio(base) - { - write(Cr1::init_value()); - write(Cr2::init_value()); - write(Cr3::init_value()); - write(Cr4::init_value()); - } - - /** - * Print character 'c' through the UART - */ - inline void put_char(char const c) - { - enum { ASCII_LINE_FEED = 10, - ASCII_CARRIAGE_RETURN = 13 }; - - /* prepend line feed with carriage return */ - if (c == ASCII_LINE_FEED) _put_char(ASCII_CARRIAGE_RETURN); - - /* transmit character */ - _put_char(c); - } }; -} + + /** + * Control register 2 + */ + struct Cr2 : Register<0x84, 32> + { + struct S_rst : Bitfield<0, 1> /* SW reset bit */ + { + enum { NO_RESET = 1 }; + }; + + struct Rx_en : Bitfield<1, 1> { }; /* enable receiver */ + struct Tx_en : Bitfield<2, 1> { }; /* enable transmitter */ + struct At_en : Bitfield<3, 1> { }; /* enable aging timer */ + struct Rts_en : Bitfield<4, 1> { }; /* send request IRQ on */ + + struct Ws : Bitfield<5, 1> /* select word size */ + { + enum { _8_BITS = 1 }; + }; + + struct Stpb : Bitfield<6, 1> /* number of stop bits */ + { + enum { _1_BIT = 0 }; + }; + + struct Pr_en : Bitfield<8, 1> { }; /* enable parity */ + struct Esc_en : Bitfield<11, 1> { }; /* escape detection on */ + + struct Ctsc : Bitfield<13, 1> /* select CTS control */ + { + enum { BY_RECEIVER = 1 }; + }; + + struct Irts : Bitfield<14, 1> { }; /* ignore RTS pin */ + struct Esci : Bitfield<15, 1> { }; /* enable escape IRQ */ + + /** + * Initialization value + */ + static access_t init_value() + { + return S_rst::bits(S_rst::NO_RESET) | + Rx_en::bits(0) | + Tx_en::bits(1) | + At_en::bits(0) | + Rts_en::bits(0) | + Ws::bits(Ws::_8_BITS) | + Stpb::bits(Stpb::_1_BIT) | + Pr_en::bits(0) | + Esc_en::bits(0) | + Ctsc::bits(Ctsc::BY_RECEIVER) | + Irts::bits(1) | + Esci::bits(0); + } + }; + + /** + * Control register 3 + */ + struct Cr3 : Register<0x88, 32> + { + struct Rxdmux_sel : Bitfield<2, 1> { }; /* use muxed RXD */ + struct Aci_en : Bitfield<0, 1> { }; /* autobaud count IRQ on */ + struct Dtrd_en : Bitfield<3, 1> { }; /* data terminal ready + * delta IRQ on */ + struct Awak_en : Bitfield<4, 1> { }; /* wake IRQ on */ + struct Air_int_en : Bitfield<5, 1> { }; /* IR wake IRQ on */ + struct Rx_ds_en : Bitfield<6, 1> { }; /* RX status IRQ on */ + struct Ad_nimp : Bitfield<7, 1> { }; /* autobaud detect off */ + struct Ri_en : Bitfield<8, 1> { }; /* ring indicator IRQ on */ + struct Dcd_en : Bitfield<9, 1> { }; /* data carrier detect + * IRQ on */ + struct Dsr : Bitfield<10,1> { }; /* DSR/DTR output */ + struct Frame_en : Bitfield<11,1> { }; /* frame error IRQ on */ + struct Parity_en : Bitfield<12,1> { }; /* parity error IRQ on */ + struct Dtr_en : Bitfield<13,1> { }; /* data terminal ready + * IRQ on */ + struct Dpec_ctrl : Bitfield<14,2> { }; /* DTR/DSR IRQ edge + * control */ + + /** + * Initialization value + */ + static access_t init_value() + { + return Aci_en::bits(0) | + Rxdmux_sel::bits(0) | + Dtrd_en::bits(0) | + Awak_en::bits(0) | + Air_int_en::bits(0) | + Rx_ds_en::bits(0) | + Ad_nimp::bits(1) | + Ri_en::bits(0) | + Dcd_en::bits(0) | + Dsr::bits(0) | + Frame_en::bits(0) | + Parity_en::bits(0) | + Dtr_en::bits(0) | + Dpec_ctrl::bits(0); + } + }; + + /** + * Control register 4 + */ + struct Cr4 : Register<0x8c, 32> + { + struct Dr_en : Bitfield<0, 1> { }; /* RX data ready IRQ on */ + struct Or_en : Bitfield<1, 1> { }; /* RX overrun IRQ on */ + struct Bk_en : Bitfield<2, 1> { }; /* BREAK IRQ on */ + struct Tc_en : Bitfield<3, 1> { }; /* TX complete IRQ on */ + struct Lp_dis : Bitfield<4, 1> { }; /* low power off */ + struct IR_sc : Bitfield<5, 1> { }; /* use UART ref clock + * for vote logic */ + struct Id_dma_en : Bitfield<6, 1> { }; /* idle DMA IRQ on */ + struct Wake_en : Bitfield<7, 1> { }; /* WAKE IRQ on */ + struct IR_en : Bitfield<8, 1> { }; /* serial IR IRQ on */ + struct Cts_level : Bitfield<10,6> { }; /* CTS trigger level*/ + + /** + * Initialization value + */ + static access_t init_value() + { + return Dr_en::bits(0) | + Or_en::bits(0) | + Bk_en::bits(0) | + Tc_en::bits(0) | + Lp_dis::bits(0) | + IR_sc::bits(0) | + Id_dma_en::bits(0) | + Wake_en::bits(0) | + IR_en::bits(0) | + Cts_level::bits(0); + } + }; + + /** + * Status register 2 + */ + struct Sr2 : Register<0x98, 32> + { + struct Txdc : Bitfield<3, 1> { }; /* transmission complete */ + }; + + /** + * Transmitter register + */ + struct Txd : Register<0x40, 32> + { + struct Tx_data : Bitfield<0, 8> { }; /* transmit data */ + }; + + /** + * Transmit character 'c' without care about its type + */ + inline void _put_char(char const c) + { + while (!read()) ; + write(c); + } + + public: + + /** + * Constructor + * + * \param base device MMIO base + */ + explicit Imx_uart_base(addr_t const base) : Mmio(base) + { + write(Cr1::init_value()); + write(Cr2::init_value()); + write(Cr3::init_value()); + write(Cr4::init_value()); + } + + /** + * Print character 'c' through the UART + */ + inline void put_char(char const c) + { + enum { ASCII_LINE_FEED = 10, + ASCII_CARRIAGE_RETURN = 13 }; + + /* prepend line feed with carriage return */ + if (c == ASCII_LINE_FEED) _put_char(ASCII_CARRIAGE_RETURN); + + /* transmit character */ + _put_char(c); + } +}; #endif /* _INCLUDE__DRIVERS__UART__IMX_UART_BASE_H_ */ diff --git a/repos/base/include/drivers/uart/pl011_base.h b/repos/base/include/drivers/uart/pl011_base.h index 3c329fff4..b7fad9eba 100644 --- a/repos/base/include/drivers/uart/pl011_base.h +++ b/repos/base/include/drivers/uart/pl011_base.h @@ -17,116 +17,116 @@ /* Genode includes */ #include -namespace Genode +namespace Genode { class Pl011_base; } + + +/** + * Driver base for the PrimeCell UART PL011 Revision r1p3 + */ +class Genode::Pl011_base : Mmio { - /** - * Driver base for the PrimeCell UART PL011 Revision r1p3 - */ - class Pl011_base : Mmio - { - protected: + protected: - enum { MAX_BAUD_RATE = 0xfffffff }; + enum { MAX_BAUD_RATE = 0xfffffff }; - /** - * Data register - */ - struct Uartdr : public Register<0x00, 16> - { - struct Data : Bitfield<0,8> { }; - struct Fe : Bitfield<8,1> { }; - struct Pe : Bitfield<9,1> { }; - struct Be : Bitfield<10,1> { }; - struct Oe : Bitfield<11,1> { }; - }; + /** + * Data register + */ + struct Uartdr : public Register<0x00, 16> + { + struct Data : Bitfield<0,8> { }; + struct Fe : Bitfield<8,1> { }; + struct Pe : Bitfield<9,1> { }; + struct Be : Bitfield<10,1> { }; + struct Oe : Bitfield<11,1> { }; + }; - /** - * Flag register - */ - struct Uartfr : public Register<0x18, 16> - { - struct Cts : Bitfield<0,1> { }; - struct Dsr : Bitfield<1,1> { }; - struct Dcd : Bitfield<2,1> { }; - struct Busy : Bitfield<3,1> { }; - struct Rxfe : Bitfield<4,1> { }; - struct Txff : Bitfield<5,1> { }; - struct Rxff : Bitfield<6,1> { }; - struct Txfe : Bitfield<7,1> { }; - struct Ri : Bitfield<8,1> { }; - }; + /** + * Flag register + */ + struct Uartfr : public Register<0x18, 16> + { + struct Cts : Bitfield<0,1> { }; + struct Dsr : Bitfield<1,1> { }; + struct Dcd : Bitfield<2,1> { }; + struct Busy : Bitfield<3,1> { }; + struct Rxfe : Bitfield<4,1> { }; + struct Txff : Bitfield<5,1> { }; + struct Rxff : Bitfield<6,1> { }; + struct Txfe : Bitfield<7,1> { }; + struct Ri : Bitfield<8,1> { }; + }; - /** - * Integer baud rate register - */ - struct Uartibrd : public Register<0x24, 16> - { - struct Ibrd : Bitfield<0,15> { }; - }; + /** + * Integer baud rate register + */ + struct Uartibrd : public Register<0x24, 16> + { + struct Ibrd : Bitfield<0,15> { }; + }; - /** - * Fractional Baud Rate Register - */ - struct Uartfbrd : public Register<0x28, 8> - { - struct Fbrd : Bitfield<0,6> { }; - }; + /** + * Fractional Baud Rate Register + */ + struct Uartfbrd : public Register<0x28, 8> + { + struct Fbrd : Bitfield<0,6> { }; + }; - /** - * Line Control Register - */ - struct Uartlcrh : public Register<0x2c, 16> - { - struct Wlen : Bitfield<5,2> { - enum { - WORD_LENGTH_8BITS = 3, - WORD_LENGTH_7BITS = 2, - WORD_LENGTH_6BITS = 1, - WORD_LENGTH_5BITS = 0, - }; + /** + * Line Control Register + */ + struct Uartlcrh : public Register<0x2c, 16> + { + struct Wlen : Bitfield<5,2> { + enum { + WORD_LENGTH_8BITS = 3, + WORD_LENGTH_7BITS = 2, + WORD_LENGTH_6BITS = 1, + WORD_LENGTH_5BITS = 0, }; }; + }; - /** - * Control Register - */ - struct Uartcr : public Register<0x30, 16> - { - struct Uarten : Bitfield<0,1> { }; - struct Txe : Bitfield<8,1> { }; - struct Rxe : Bitfield<9,1> { }; - }; + /** + * Control Register + */ + struct Uartcr : public Register<0x30, 16> + { + struct Uarten : Bitfield<0,1> { }; + struct Txe : Bitfield<8,1> { }; + struct Rxe : Bitfield<9,1> { }; + }; - /** - * Interrupt Mask Set/Clear - */ - struct Uartimsc : public Register<0x38, 16> - { - struct Imsc : Bitfield<0,11> { }; - }; + /** + * Interrupt Mask Set/Clear + */ + struct Uartimsc : public Register<0x38, 16> + { + struct Imsc : Bitfield<0,11> { }; + }; - /** - * Idle until the device is ready for action - */ - void _wait_until_ready() { while (read()) ; } + /** + * Idle until the device is ready for action + */ + void _wait_until_ready() { while (read()) ; } - public: + public: - /** - * Constructor - * \param base device MMIO base - * \param clock device reference clock frequency - * \param baud_rate targeted UART baud rate - */ - inline Pl011_base(addr_t const base, uint32_t const clock, - uint32_t const baud_rate); + /** + * Constructor + * \param base device MMIO base + * \param clock device reference clock frequency + * \param baud_rate targeted UART baud rate + */ + inline Pl011_base(addr_t const base, uint32_t const clock, + uint32_t const baud_rate); - /** - * Send ASCII char 'c' over the UART interface - */ - inline void put_char(char const c); - }; -} + /** + * Send ASCII char 'c' over the UART interface + */ + inline void put_char(char const c); +}; Genode::Pl011_base::Pl011_base(addr_t const base, uint32_t const clock, diff --git a/repos/base/include/drivers/uart/tl16c750_base.h b/repos/base/include/drivers/uart/tl16c750_base.h index 91841d0c5..681170a27 100644 --- a/repos/base/include/drivers/uart/tl16c750_base.h +++ b/repos/base/include/drivers/uart/tl16c750_base.h @@ -17,231 +17,231 @@ /* Genode includes */ #include -namespace Genode +namespace Genode { class Tl16c750_base; } + + +/** + * Base driver Texas instruments TL16C750 UART module + * + * In contrast to the abilities of the TL16C750, this driver targets only + * the basic UART functionalities. + */ +class Genode::Tl16c750_base : public Mmio { - /** - * Base driver Texas instruments TL16C750 UART module - * - * In contrast to the abilities of the TL16C750, this driver targets only - * the basic UART functionalities. - */ - class Tl16c750_base : public Mmio - { - protected: - /** - * Least significant divisor part - */ - struct Uart_dll : Register<0x0, 32> - { - struct Clock_lsb : Bitfield<0, 8> { }; - }; + protected: + /** + * Least significant divisor part + */ + struct Uart_dll : Register<0x0, 32> + { + struct Clock_lsb : Bitfield<0, 8> { }; + }; - /** - * Transmit holding register - */ - struct Uart_thr : Register<0x0, 32> - { - struct Thr : Bitfield<0, 8> { }; - }; + /** + * Transmit holding register + */ + struct Uart_thr : Register<0x0, 32> + { + struct Thr : Bitfield<0, 8> { }; + }; - /** - * Receiver holding register + /** + * Receiver holding register + */ + struct Uart_rhr : Register<0x0, 32> + { + struct Rhr : Bitfield<0, 8> { }; + }; + + /** + * Most significant divisor part + */ + struct Uart_dlh : Register<0x4, 32> + { + struct Clock_msb : Bitfield<0, 6> { }; + }; + + /** + * Interrupt enable register + */ + struct Uart_ier : Register<0x4, 32> + { + struct Rhr_it : Bitfield<0, 1> { }; + struct Thr_it : Bitfield<1, 1> { }; + struct Line_sts_it : Bitfield<2, 1> { }; + struct Modem_sts_it : Bitfield<3, 1> { }; + struct Sleep_mode : Bitfield<4, 1> { }; + struct Xoff_it : Bitfield<5, 1> { }; + struct Rts_it : Bitfield<6, 1> { }; + struct Cts_it : Bitfield<7, 1> { }; + }; + + /** + * Interrupt identification register + */ + struct Uart_iir : Register<0x8, 32> + { + struct It_pending : Bitfield<0, 1> { }; + }; + + /** + * FIFO control register + */ + struct Uart_fcr : Register<0x8, 32> + { + struct Fifo_enable : Bitfield<0, 1> { }; + }; + + /** + * Line control register + */ + struct Uart_lcr : Register<0xc, 32> + { + struct Char_length : Bitfield<0, 2> + { + enum { _8_BIT = 3 }; + }; + struct Nb_stop : Bitfield<2, 1> + { + enum { _1_STOP_BIT = 0 }; + }; + struct Parity_en : Bitfield<3, 1> { }; + struct Break_en : Bitfield<6, 1> { }; + struct Div_en : Bitfield<7, 1> { }; + struct Reg_mode : Bitfield<0, 8> + { + enum { OPERATIONAL = 0, CONFIG_A = 0x80, CONFIG_B = 0xbf }; + }; + }; + + /** + * Modem control register + */ + struct Uart_mcr : Register<0x10, 32> + { + struct Tcr_tlr : Bitfield<6, 1> { }; + }; + + /** + * Line status register + */ + struct Uart_lsr : Register<0x14, 32> + { + struct Rx_fifo_empty : Bitfield<0, 1> { }; + struct Tx_fifo_empty : Bitfield<5, 1> { }; + }; + + /** + * Mode definition register 1 + */ + struct Uart_mdr1 : Register<0x20, 32> + { + struct Mode_select : Bitfield<0, 3> + { + enum { UART_16X = 0, DISABLED = 7 }; + }; + }; + + /** + * System control register + */ + struct Uart_sysc : Register<0x54, 32> + { + struct Softreset : Bitfield<1, 1> { }; + }; + + /** + * System status register + */ + struct Uart_syss : Register<0x58, 32> + { + struct Resetdone : Bitfield<0, 1> { }; + }; + + void _init(unsigned long const clock, unsigned long const baud_rate) + { + /* disable UART */ + write(Uart_mdr1::Mode_select::DISABLED); + + /* enable access to 'Uart_fcr' and 'Uart_ier' */ + write(Uart_lcr::Reg_mode::OPERATIONAL); + + /* + * Configure FIFOs, we don't use any interrupts or DMA, + * thus FIFO trigger and DMA configurations are dispensable. */ - struct Uart_rhr : Register<0x0, 32> - { - struct Rhr : Bitfield<0, 8> { }; - }; + write(1); - /** - * Most significant divisor part - */ - struct Uart_dlh : Register<0x4, 32> - { - struct Clock_msb : Bitfield<0, 6> { }; - }; + /* disable interrupts and sleep mode */ + write(Uart_ier::Rhr_it::bits(0) + | Uart_ier::Thr_it::bits(0) + | Uart_ier::Line_sts_it::bits(0) + | Uart_ier::Modem_sts_it::bits(0) + | Uart_ier::Sleep_mode::bits(0) + | Uart_ier::Xoff_it::bits(0) + | Uart_ier::Rts_it::bits(0) + | Uart_ier::Cts_it::bits(0)); - /** - * Interrupt enable register - */ - struct Uart_ier : Register<0x4, 32> - { - struct Rhr_it : Bitfield<0, 1> { }; - struct Thr_it : Bitfield<1, 1> { }; - struct Line_sts_it : Bitfield<2, 1> { }; - struct Modem_sts_it : Bitfield<3, 1> { }; - struct Sleep_mode : Bitfield<4, 1> { }; - struct Xoff_it : Bitfield<5, 1> { }; - struct Rts_it : Bitfield<6, 1> { }; - struct Cts_it : Bitfield<7, 1> { }; - }; + /* enable access to 'Uart_dlh' and 'Uart_dll' */ + write(Uart_lcr::Reg_mode::CONFIG_B); - /** - * Interrupt identification register + /* + * Load the new divisor value (this driver solely uses + * 'UART_16X' mode) */ - struct Uart_iir : Register<0x8, 32> - { - struct It_pending : Bitfield<0, 1> { }; - }; + enum { UART_16X_DIVIDER_LOG2 = 4 }; + unsigned long const adjusted_br = baud_rate << UART_16X_DIVIDER_LOG2; + double const divisor = (double)clock / adjusted_br; + unsigned long const divisor_uint = (unsigned long)divisor; + write(divisor_uint); + write(divisor_uint>>Uart_dll::Clock_lsb::WIDTH); - /** - * FIFO control register - */ - struct Uart_fcr : Register<0x8, 32> - { - struct Fifo_enable : Bitfield<0, 1> { }; - }; - - /** - * Line control register - */ - struct Uart_lcr : Register<0xc, 32> - { - struct Char_length : Bitfield<0, 2> - { - enum { _8_BIT = 3 }; - }; - struct Nb_stop : Bitfield<2, 1> - { - enum { _1_STOP_BIT = 0 }; - }; - struct Parity_en : Bitfield<3, 1> { }; - struct Break_en : Bitfield<6, 1> { }; - struct Div_en : Bitfield<7, 1> { }; - struct Reg_mode : Bitfield<0, 8> - { - enum { OPERATIONAL = 0, CONFIG_A = 0x80, CONFIG_B = 0xbf }; - }; - }; - - /** - * Modem control register - */ - struct Uart_mcr : Register<0x10, 32> - { - struct Tcr_tlr : Bitfield<6, 1> { }; - }; - - /** - * Line status register - */ - struct Uart_lsr : Register<0x14, 32> - { - struct Rx_fifo_empty : Bitfield<0, 1> { }; - struct Tx_fifo_empty : Bitfield<5, 1> { }; - }; - - /** - * Mode definition register 1 - */ - struct Uart_mdr1 : Register<0x20, 32> - { - struct Mode_select : Bitfield<0, 3> - { - enum { UART_16X = 0, DISABLED = 7 }; - }; - }; - - /** - * System control register - */ - struct Uart_sysc : Register<0x54, 32> - { - struct Softreset : Bitfield<1, 1> { }; - }; - - /** - * System status register - */ - struct Uart_syss : Register<0x58, 32> - { - struct Resetdone : Bitfield<0, 1> { }; - }; - - void _init(unsigned long const clock, unsigned long const baud_rate) - { - /* disable UART */ - write(Uart_mdr1::Mode_select::DISABLED); - - /* enable access to 'Uart_fcr' and 'Uart_ier' */ - write(Uart_lcr::Reg_mode::OPERATIONAL); - - /* - * Configure FIFOs, we don't use any interrupts or DMA, - * thus FIFO trigger and DMA configurations are dispensable. - */ - write(1); - - /* disable interrupts and sleep mode */ - write(Uart_ier::Rhr_it::bits(0) - | Uart_ier::Thr_it::bits(0) - | Uart_ier::Line_sts_it::bits(0) - | Uart_ier::Modem_sts_it::bits(0) - | Uart_ier::Sleep_mode::bits(0) - | Uart_ier::Xoff_it::bits(0) - | Uart_ier::Rts_it::bits(0) - | Uart_ier::Cts_it::bits(0)); - - /* enable access to 'Uart_dlh' and 'Uart_dll' */ - write(Uart_lcr::Reg_mode::CONFIG_B); - - /* - * Load the new divisor value (this driver solely uses - * 'UART_16X' mode) - */ - enum { UART_16X_DIVIDER_LOG2 = 4 }; - unsigned long const adjusted_br = baud_rate << UART_16X_DIVIDER_LOG2; - double const divisor = (double)clock / adjusted_br; - unsigned long const divisor_uint = (unsigned long)divisor; - write(divisor_uint); - write(divisor_uint>>Uart_dll::Clock_lsb::WIDTH); - - /* - * Configure protocol formatting and thereby return to - * operational mode. - */ - write(Uart_lcr::Char_length::bits(Uart_lcr::Char_length::_8_BIT) - | Uart_lcr::Nb_stop::bits(Uart_lcr::Nb_stop::_1_STOP_BIT) - | Uart_lcr::Parity_en::bits(0) - | Uart_lcr::Break_en::bits(0) - | Uart_lcr::Div_en::bits(0)); - - /* - * Switch to UART mode, we don't use hardware or software flow - * control, thus according configurations are dispensable - */ - write(Uart_mdr1::Mode_select::UART_16X); - } - - public: - /** - * Constructor - * - * \param base MMIO base address - * \param clock reference clock - * \param baud_rate targeted baud rate + /* + * Configure protocol formatting and thereby return to + * operational mode. */ - Tl16c750_base(addr_t const base, unsigned long const clock, - unsigned long const baud_rate) : Mmio(base) - { - /* reset and init UART */ - write(1); - while (!read()) ; - _init(clock, baud_rate); - } + write(Uart_lcr::Char_length::bits(Uart_lcr::Char_length::_8_BIT) + | Uart_lcr::Nb_stop::bits(Uart_lcr::Nb_stop::_1_STOP_BIT) + | Uart_lcr::Parity_en::bits(0) + | Uart_lcr::Break_en::bits(0) + | Uart_lcr::Div_en::bits(0)); - /** - * Transmit ASCII char 'c' + /* + * Switch to UART mode, we don't use hardware or software flow + * control, thus according configurations are dispensable */ - void put_char(char const c) - { - /* wait as long as the transmission buffer is full */ - while (!read()) ; + write(Uart_mdr1::Mode_select::UART_16X); + } - /* transmit character */ - write(c); - } - }; -} + public: + /** + * Constructor + * + * \param base MMIO base address + * \param clock reference clock + * \param baud_rate targeted baud rate + */ + Tl16c750_base(addr_t const base, unsigned long const clock, + unsigned long const baud_rate) : Mmio(base) + { + /* reset and init UART */ + write(1); + while (!read()) ; + _init(clock, baud_rate); + } + + /** + * Transmit ASCII char 'c' + */ + void put_char(char const c) + { + /* wait as long as the transmission buffer is full */ + while (!read()) ; + + /* transmit character */ + write(c); + } +}; #endif /* _INCLUDE__DRIVERS__UART__TL16C750_BASE_H_ */ diff --git a/repos/base/include/io_mem_session/client.h b/repos/base/include/io_mem_session/client.h index a99c2ff96..e5502e369 100644 --- a/repos/base/include/io_mem_session/client.h +++ b/repos/base/include/io_mem_session/client.h @@ -17,15 +17,15 @@ #include #include -namespace Genode { +namespace Genode { struct Io_mem_session_client; } - struct Io_mem_session_client : Rpc_client - { - explicit Io_mem_session_client(Io_mem_session_capability session) - : Rpc_client(session) { } - Io_mem_dataspace_capability dataspace() { return call(); } - }; -} +struct Genode::Io_mem_session_client : Rpc_client +{ + explicit Io_mem_session_client(Io_mem_session_capability session) + : Rpc_client(session) { } + + Io_mem_dataspace_capability dataspace() override { return call(); } +}; #endif /* _INCLUDE__IO_MEM_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/io_mem_session/connection.h b/repos/base/include/io_mem_session/connection.h index b4c781357..055c7a3e1 100644 --- a/repos/base/include/io_mem_session/connection.h +++ b/repos/base/include/io_mem_session/connection.h @@ -17,26 +17,26 @@ #include #include -namespace Genode { +namespace Genode { struct Io_mem_connection; } - struct Io_mem_connection : Connection, Io_mem_session_client - { - /** - * Constructor - * - * \param base physical base address of memory-mapped I/O resource - * \param size size memory-mapped I/O resource - * \param write_combined enable write-combined access to I/O memory - */ - Io_mem_connection(addr_t base, size_t size, bool write_combined = false) - : - Connection( - session("ram_quota=4K, base=0x%p, size=0x%zx, wc=%s", - base, size, write_combined ? "yes" : "no")), - Io_mem_session_client(cap()) - { } - }; -} +struct Genode::Io_mem_connection : Connection, Io_mem_session_client +{ + /** + * Constructor + * + * \param base physical base address of memory-mapped I/O resource + * \param size size memory-mapped I/O resource + * \param write_combined enable write-combined access to I/O memory + */ + Io_mem_connection(addr_t base, size_t size, bool write_combined = false) + : + Connection( + session("ram_quota=4K, base=0x%p, size=0x%zx, wc=%s", + base, size, write_combined ? "yes" : "no")), + + Io_mem_session_client(cap()) + { } +}; #endif /* _INCLUDE__IO_MEM_SESSION__CONNECTION_H_ */ diff --git a/repos/base/include/io_mem_session/io_mem_session.h b/repos/base/include/io_mem_session/io_mem_session.h index ed12cfcfe..00d7073e2 100644 --- a/repos/base/include/io_mem_session/io_mem_session.h +++ b/repos/base/include/io_mem_session/io_mem_session.h @@ -19,33 +19,37 @@ namespace Genode { - struct Io_mem_dataspace : Dataspace { }; + struct Io_mem_dataspace; + struct Io_mem_session; typedef Capability Io_mem_dataspace_capability; - - struct Io_mem_session : Session - { - static const char *service_name() { return "IO_MEM"; } - - virtual ~Io_mem_session() { } - - /** - * Request dataspace containing the IO_MEM session data - * - * \return capability to IO_MEM dataspace - * (may be invalid) - */ - virtual Io_mem_dataspace_capability dataspace() = 0; - - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC(Rpc_dataspace, Io_mem_dataspace_capability, dataspace); - - GENODE_RPC_INTERFACE(Rpc_dataspace); - }; } + +struct Genode::Io_mem_dataspace : Dataspace { }; + + +struct Genode::Io_mem_session : Session +{ + static const char *service_name() { return "IO_MEM"; } + + virtual ~Io_mem_session() { } + + /** + * Request dataspace containing the IO_MEM session data + * + * \return capability to IO_MEM dataspace + * (may be invalid) + */ + virtual Io_mem_dataspace_capability dataspace() = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_dataspace, Io_mem_dataspace_capability, dataspace); + GENODE_RPC_INTERFACE(Rpc_dataspace); +}; + #endif /* _INCLUDE__IO_MEM_SESSION__IO_MEM_SESSION_H_ */ diff --git a/repos/base/include/io_port_session/client.h b/repos/base/include/io_port_session/client.h index 2a9c283a8..78866771d 100644 --- a/repos/base/include/io_port_session/client.h +++ b/repos/base/include/io_port_session/client.h @@ -17,31 +17,31 @@ #include #include -namespace Genode { +namespace Genode { struct Io_port_session_client; } - struct Io_port_session_client : Rpc_client - { - explicit Io_port_session_client(Io_port_session_capability session) - : Rpc_client(session) { } - unsigned char inb(unsigned short address) { - return call(address); } +struct Genode::Io_port_session_client : Rpc_client +{ + explicit Io_port_session_client(Io_port_session_capability session) + : Rpc_client(session) { } - unsigned short inw(unsigned short address) { - return call(address); } + unsigned char inb(unsigned short address) override { + return call(address); } - unsigned inl(unsigned short address) { - return call(address); } + unsigned short inw(unsigned short address) override { + return call(address); } - void outb(unsigned short address, unsigned char value) { - call(address, value); } + unsigned inl(unsigned short address) override { + return call(address); } - void outw(unsigned short address, unsigned short value) { - call(address, value); } + void outb(unsigned short address, unsigned char value) override { + call(address, value); } - void outl(unsigned short address, unsigned value) { - call(address, value); } - }; -} + void outw(unsigned short address, unsigned short value) override { + call(address, value); } + + void outl(unsigned short address, unsigned value) override { + call(address, value); } +}; #endif /* _INCLUDE__IO_PORT_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/io_port_session/connection.h b/repos/base/include/io_port_session/connection.h index ef73f709c..052395fec 100644 --- a/repos/base/include/io_port_session/connection.h +++ b/repos/base/include/io_port_session/connection.h @@ -17,26 +17,26 @@ #include #include -namespace Genode { +namespace Genode { struct Io_port_connection; } - struct Io_port_connection : Connection, - Io_port_session_client - { - /** - * Constructor - * - * \param base base address of port range - * \param size size of port range - */ - Io_port_connection(unsigned base, unsigned size) - : - Connection( - session("ram_quota=4K, io_port_base=%u, io_port_size=%u", - base, size)), - Io_port_session_client(cap()) - { } - }; -} +struct Genode::Io_port_connection : Connection, + Io_port_session_client +{ + /** + * Constructor + * + * \param base base address of port range + * \param size size of port range + */ + Io_port_connection(unsigned base, unsigned size) + : + Connection( + session("ram_quota=4K, io_port_base=%u, io_port_size=%u", + base, size)), + + Io_port_session_client(cap()) + { } +}; #endif /* _INCLUDE__IO_PORT_SESSION__CONNECTION_H_ */ diff --git a/repos/base/include/io_port_session/io_port_session.h b/repos/base/include/io_port_session/io_port_session.h index 95b619c78..df5e4acd6 100644 --- a/repos/base/include/io_port_session/io_port_session.h +++ b/repos/base/include/io_port_session/io_port_session.h @@ -28,89 +28,89 @@ #include #include -namespace Genode { - - struct Io_port_session : Session - { - static const char *service_name() { return "IO_PORT"; } - - virtual ~Io_port_session() { } - - /****************************** - ** Read value from I/O port ** - ******************************/ - - /** - * Read byte (8 bit) - * - * \param address physical I/O port address - * - * \return value read from port - */ - virtual unsigned char inb(unsigned short address) = 0; - - /** - * Read word (16 bit) - * - * \param address physical I/O port address - * - * \return value read from port - */ - virtual unsigned short inw(unsigned short address) = 0; - - /** - * Read double word (32 bit) - * - * \param address physical I/O port address - * - * \return value read from port - */ - virtual unsigned inl(unsigned short address) = 0; +namespace Genode { struct Io_port_session; } - /***************************** - ** Write value to I/O port ** - *****************************/ +struct Genode::Io_port_session : Session +{ + static const char *service_name() { return "IO_PORT"; } - /** - * Write byte (8 bit) - * - * \param address physical I/O port address - * \param value value to write to port - */ - virtual void outb(unsigned short address, unsigned char value) = 0; + virtual ~Io_port_session() { } - /** - * Write word (16 bit) - * - * \param address physical I/O port address - * \param value value to write to port - */ - virtual void outw(unsigned short address, unsigned short value) = 0; + /****************************** + ** Read value from I/O port ** + ******************************/ - /** - * Write double word (32 bit) - * - * \param address physical I/O port address - * \param value value to write to port - */ - virtual void outl(unsigned short address, unsigned value) = 0; + /** + * Read byte (8 bit) + * + * \param address physical I/O port address + * + * \return value read from port + */ + virtual unsigned char inb(unsigned short address) = 0; + + /** + * Read word (16 bit) + * + * \param address physical I/O port address + * + * \return value read from port + */ + virtual unsigned short inw(unsigned short address) = 0; + + /** + * Read double word (32 bit) + * + * \param address physical I/O port address + * + * \return value read from port + */ + virtual unsigned inl(unsigned short address) = 0; - /********************* - ** RPC declaration ** - *********************/ + /***************************** + ** Write value to I/O port ** + *****************************/ - GENODE_RPC(Rpc_inb, unsigned char, inb, unsigned short); - GENODE_RPC(Rpc_inw, unsigned short, inw, unsigned short); - GENODE_RPC(Rpc_inl, unsigned, inl, unsigned short); + /** + * Write byte (8 bit) + * + * \param address physical I/O port address + * \param value value to write to port + */ + virtual void outb(unsigned short address, unsigned char value) = 0; - GENODE_RPC(Rpc_outb, void, outb, unsigned short, unsigned char); - GENODE_RPC(Rpc_outw, void, outw, unsigned short, unsigned short); - GENODE_RPC(Rpc_outl, void, outl, unsigned short, unsigned); + /** + * Write word (16 bit) + * + * \param address physical I/O port address + * \param value value to write to port + */ + virtual void outw(unsigned short address, unsigned short value) = 0; - GENODE_RPC_INTERFACE(Rpc_inb, Rpc_inw, Rpc_inl, Rpc_outb, Rpc_outw, Rpc_outl); - }; -} + /** + * Write double word (32 bit) + * + * \param address physical I/O port address + * \param value value to write to port + */ + virtual void outl(unsigned short address, unsigned value) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_inb, unsigned char, inb, unsigned short); + GENODE_RPC(Rpc_inw, unsigned short, inw, unsigned short); + GENODE_RPC(Rpc_inl, unsigned, inl, unsigned short); + + GENODE_RPC(Rpc_outb, void, outb, unsigned short, unsigned char); + GENODE_RPC(Rpc_outw, void, outw, unsigned short, unsigned short); + GENODE_RPC(Rpc_outl, void, outl, unsigned short, unsigned); + + GENODE_RPC_INTERFACE(Rpc_inb, Rpc_inw, Rpc_inl, Rpc_outb, Rpc_outw, Rpc_outl); +}; #endif /* _INCLUDE__IO_PORT_SESSION__IO_PORT_SESSION_H_ */ diff --git a/repos/base/include/irq_session/client.h b/repos/base/include/irq_session/client.h index 9a1c9d1fa..4c8996711 100644 --- a/repos/base/include/irq_session/client.h +++ b/repos/base/include/irq_session/client.h @@ -17,15 +17,15 @@ #include #include -namespace Genode { +namespace Genode { struct Irq_session_client; } - struct Irq_session_client : Rpc_client - { - explicit Irq_session_client(Irq_session_capability session) - : Rpc_client(session) { } - void wait_for_irq() { call(); } - }; -} +struct Genode::Irq_session_client : Rpc_client +{ + explicit Irq_session_client(Irq_session_capability session) + : Rpc_client(session) { } + + void wait_for_irq() override { call(); } +}; #endif /* _INCLUDE__IRQ_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/irq_session/connection.h b/repos/base/include/irq_session/connection.h index 2c47fb823..70012b2a3 100644 --- a/repos/base/include/irq_session/connection.h +++ b/repos/base/include/irq_session/connection.h @@ -17,27 +17,26 @@ #include #include -namespace Genode { +namespace Genode { struct Irq_connection; } - struct Irq_connection : Connection, Irq_session_client - { - /** - * Constructor - * - * \param irq physical interrupt number - * \param trigger interrupt trigger (e.g., level/edge) - * \param polarity interrupt trigger polarity (e.g., low/high) - */ - Irq_connection(unsigned irq, - Irq_session::Trigger trigger = Irq_session::TRIGGER_UNCHANGED, - Irq_session::Polarity polarity = Irq_session::POLARITY_UNCHANGED) - : - Connection( - session("ram_quota=4K, irq_number=%u, irq_trigger=%u, irq_polarity=%u", - irq, trigger, polarity)), - Irq_session_client(cap()) - { } - }; -} +struct Genode::Irq_connection : Connection, Irq_session_client +{ + /** + * Constructor + * + * \param irq physical interrupt number + * \param trigger interrupt trigger (e.g., level/edge) + * \param polarity interrupt trigger polarity (e.g., low/high) + */ + Irq_connection(unsigned irq, + Irq_session::Trigger trigger = Irq_session::TRIGGER_UNCHANGED, + Irq_session::Polarity polarity = Irq_session::POLARITY_UNCHANGED) + : + Connection( + session("ram_quota=4K, irq_number=%u, irq_trigger=%u, irq_polarity=%u", + irq, trigger, polarity)), + Irq_session_client(cap()) + { } +}; #endif /* _INCLUDE__IRQ_SESSION__CONNECTION_H_ */ diff --git a/repos/base/include/irq_session/irq_session.h b/repos/base/include/irq_session/irq_session.h index d42a88f9b..d3a03e51c 100644 --- a/repos/base/include/irq_session/irq_session.h +++ b/repos/base/include/irq_session/irq_session.h @@ -24,35 +24,34 @@ #include #include -namespace Genode { - - struct Irq_session : Session - { - - /** - * Interrupt trigger - */ - enum Trigger { TRIGGER_UNCHANGED = 0, TRIGGER_LEVEL, TRIGGER_EDGE }; - - /** - * Interrupt trigger polarity - */ - enum Polarity { POLARITY_UNCHANGED = 0, POLARITY_HIGH, POLARITY_LOW }; - - static const char *service_name() { return "IRQ"; } - - virtual ~Irq_session() { } - - virtual void wait_for_irq() = 0; +namespace Genode { struct Irq_session; } - /********************* - ** RPC declaration ** - *********************/ +struct Genode::Irq_session : Session +{ + /** + * Interrupt trigger + */ + enum Trigger { TRIGGER_UNCHANGED = 0, TRIGGER_LEVEL, TRIGGER_EDGE }; - GENODE_RPC(Rpc_wait_for_irq, void, wait_for_irq); - GENODE_RPC_INTERFACE(Rpc_wait_for_irq); - }; -} + /** + * Interrupt trigger polarity + */ + enum Polarity { POLARITY_UNCHANGED = 0, POLARITY_HIGH, POLARITY_LOW }; + + static const char *service_name() { return "IRQ"; } + + virtual ~Irq_session() { } + + virtual void wait_for_irq() = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_wait_for_irq, void, wait_for_irq); + GENODE_RPC_INTERFACE(Rpc_wait_for_irq); +}; #endif /* _INCLUDE__IRQ_SESSION__IRQ_SESSION_H_ */ diff --git a/repos/base/include/log_session/client.h b/repos/base/include/log_session/client.h index d2a706620..fc7354685 100644 --- a/repos/base/include/log_session/client.h +++ b/repos/base/include/log_session/client.h @@ -17,16 +17,16 @@ #include #include -namespace Genode { +namespace Genode { struct Log_session_client; } - struct Log_session_client : Rpc_client - { - explicit Log_session_client(Log_session_capability session) - : Rpc_client(session) { } - size_t write(String const &string) { - return call(string); } - }; -} +struct Genode::Log_session_client : Rpc_client +{ + explicit Log_session_client(Log_session_capability session) + : Rpc_client(session) { } + + size_t write(String const &string) override { + return call(string); } +}; #endif /* _INCLUDE__LOG_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/log_session/connection.h b/repos/base/include/log_session/connection.h index 503876633..5e923d58e 100644 --- a/repos/base/include/log_session/connection.h +++ b/repos/base/include/log_session/connection.h @@ -17,16 +17,16 @@ #include #include -namespace Genode { +namespace Genode { struct Log_connection; } - struct Log_connection : Connection, Log_session_client - { - Log_connection() - : - Connection(session("ram_quota=8K")), - Log_session_client(cap()) - { } - }; -} + +struct Genode::Log_connection : Connection, Log_session_client +{ + Log_connection() + : + Connection(session("ram_quota=8K")), + Log_session_client(cap()) + { } +}; #endif /* _INCLUDE__LOG_SESSION__CONNECTION_H_ */ diff --git a/repos/base/include/log_session/log_session.h b/repos/base/include/log_session/log_session.h index 87cd231ec..45fe8460d 100644 --- a/repos/base/include/log_session/log_session.h +++ b/repos/base/include/log_session/log_session.h @@ -19,31 +19,31 @@ #include #include -namespace Genode { - - struct Log_session : Session - { - static const char *service_name() { return "LOG"; } - - virtual ~Log_session() { } - - typedef Rpc_in_buffer<256> String; - - /** - * Output null-terminated string - * - * \return number of written characters - */ - virtual size_t write(String const &string) = 0; +namespace Genode { struct Log_session; } - /********************* - ** RPC declaration ** - *********************/ +struct Genode::Log_session : Session +{ + static const char *service_name() { return "LOG"; } - GENODE_RPC(Rpc_write, size_t, write, String const &); - GENODE_RPC_INTERFACE(Rpc_write); - }; -} + virtual ~Log_session() { } + + typedef Rpc_in_buffer<256> String; + + /** + * Output null-terminated string + * + * \return number of written characters + */ + virtual size_t write(String const &string) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_write, size_t, write, String const &); + GENODE_RPC_INTERFACE(Rpc_write); +}; #endif /* _INCLUDE__LOG_SESSION__LOG_SESSION_H_ */ diff --git a/repos/base/include/parent/client.h b/repos/base/include/parent/client.h index b69500601..d75ec89f4 100644 --- a/repos/base/include/parent/client.h +++ b/repos/base/include/parent/client.h @@ -17,44 +17,44 @@ #include #include -namespace Genode { +namespace Genode { struct Parent_client; } - struct Parent_client : Rpc_client - { - explicit Parent_client(Parent_capability parent) - : Rpc_client(parent) { } - void exit(int exit_value) { call(exit_value); } +struct Genode::Parent_client : Rpc_client +{ + explicit Parent_client(Parent_capability parent) + : Rpc_client(parent) { } - void announce(Service_name const &service, Root_capability root) { - call(service, root); } + void exit(int exit_value) override { call(exit_value); } - Session_capability session(Service_name const &service, - Session_args const &args, - Affinity const &affinity) { - return call(service, args, affinity); } + void announce(Service_name const &service, Root_capability root) override { + call(service, root); } - void upgrade(Session_capability to_session, Upgrade_args const &args) { - call(to_session, args); } + Session_capability session(Service_name const &service, + Session_args const &args, + Affinity const &affinity) override { + return call(service, args, affinity); } - void close(Session_capability session) { call(session); } + void upgrade(Session_capability to_session, Upgrade_args const &args) override { + call(to_session, args); } - Thread_capability main_thread_cap() const { - return call(); } + void close(Session_capability session) override { call(session); } - void resource_avail_sigh(Signal_context_capability sigh) { - call(sigh); } + Thread_capability main_thread_cap() const override { + return call(); } - void resource_request(Resource_args const &args) { - call(args); } + void resource_avail_sigh(Signal_context_capability sigh) override { + call(sigh); } - void yield_sigh(Signal_context_capability sigh) { - call(sigh); } + void resource_request(Resource_args const &args) override { + call(args); } - Resource_args yield_request() { return call(); } + void yield_sigh(Signal_context_capability sigh) override { + call(sigh); } - void yield_response() { call(); } - }; -} + Resource_args yield_request() override { return call(); } + + void yield_response() override { call(); } +}; #endif /* _INCLUDE__PARENT__CLIENT_H_ */ diff --git a/repos/base/include/parent/parent.h b/repos/base/include/parent/parent.h index 0799eb8ec..6bf10de39 100644 --- a/repos/base/include/parent/parent.h +++ b/repos/base/include/parent/parent.h @@ -21,249 +21,249 @@ #include #include -namespace Genode { +namespace Genode { class Parent; } - class Parent - { - private: - /** - * Recursively announce inherited service interfaces - * - * At compile time, the 'ROOT' type is inspected for the presence - * of the 'Rpc_inherited_interface' type in the corresponding - * session interface. If present, the session type gets announced. - * This works recursively. - */ - template - void _announce_base(Capability const &, Meta::Bool_to_type *) { } +class Genode::Parent +{ + private: + + /** + * Recursively announce inherited service interfaces + * + * At compile time, the 'ROOT' type is inspected for the presence + * of the 'Rpc_inherited_interface' type in the corresponding + * session interface. If present, the session type gets announced. + * This works recursively. + */ + template + void _announce_base(Capability const &, Meta::Bool_to_type *) { } + + /* + * This overload gets selected if the ROOT interface corresponds to + * an inherited session type. + */ + template + inline void _announce_base(Capability const &, Meta::Bool_to_type *); + + public: + + /********************* + ** Exception types ** + *********************/ + + class Exception : public ::Genode::Exception { }; + class Service_denied : public Exception { }; + class Quota_exceeded : public Exception { }; + class Unavailable : public Exception { }; + + typedef Rpc_in_buffer<64> Service_name; + typedef Rpc_in_buffer<160> Session_args; + typedef Rpc_in_buffer<160> Upgrade_args; + + /** + * Use 'String' instead of 'Rpc_in_buffer' because 'Resource_args' + * is used as both in and out parameter. + */ + typedef String<160> Resource_args; + + + virtual ~Parent() { } + + /** + * Tell parent to exit the program + */ + virtual void exit(int exit_value) = 0; + + /** + * Announce service to the parent + */ + virtual void announce(Service_name const &service_name, + Root_capability service_root) = 0; + + + /** + * Announce service to the parent + * + * \param service_root root capability + * + * The type of the specified 'service_root' capability match with + * an interface that provides a 'Session_type' type (i.e., a + * 'Typed_root' interface). This 'Session_type' is expected to + * host a static function called 'service_name' returning the + * name of the provided interface as null-terminated string. + */ + template + void announce(Capability const &service_root) + { + typedef typename ROOT_INTERFACE::Session_type Session; + announce(Session::service_name(), service_root); /* - * This overload gets selected if the ROOT interface corresponds to - * an inherited session type. - */ - template - inline void _announce_base(Capability const &, Meta::Bool_to_type *); - - public: - - /********************* - ** Exception types ** - *********************/ - - class Exception : public ::Genode::Exception { }; - class Service_denied : public Exception { }; - class Quota_exceeded : public Exception { }; - class Unavailable : public Exception { }; - - typedef Rpc_in_buffer<64> Service_name; - typedef Rpc_in_buffer<160> Session_args; - typedef Rpc_in_buffer<160> Upgrade_args; - - /** - * Use 'String' instead of 'Rpc_in_buffer' because 'Resource_args' - * is used as both in and out parameter. - */ - typedef String<160> Resource_args; - - - virtual ~Parent() { } - - /** - * Tell parent to exit the program - */ - virtual void exit(int exit_value) = 0; - - /** - * Announce service to the parent - */ - virtual void announce(Service_name const &service_name, - Root_capability service_root) = 0; - - - /** - * Announce service to the parent + * Announce inherited session types * - * \param service_root root capability - * - * The type of the specified 'service_root' capability match with - * an interface that provides a 'Session_type' type (i.e., a - * 'Typed_root' interface). This 'Session_type' is expected to - * host a static function called 'service_name' returning the - * name of the provided interface as null-terminated string. + * Select the overload based on the presence of the type + * 'Rpc_inherited_interface' within the session type. */ - template - void announce(Capability const &service_root) - { - typedef typename ROOT_INTERFACE::Session_type Session; - announce(Session::service_name(), service_root); + _announce_base(service_root, + (Meta::Bool_to_type::VALUE> *)0); + } - /* - * Announce inherited session types - * - * Select the overload based on the presence of the type - * 'Rpc_inherited_interface' within the session type. - */ - _announce_base(service_root, - (Meta::Bool_to_type::VALUE> *)0); - } + /** + * Create session to a service + * + * \param service_name name of the requested interface + * \param args session constructor arguments + * \param affinity preferred CPU affinity for the session + * + * \throw Service_denied parent denies session request + * \throw Quota_exceeded our own quota does not suffice for + * the creation of the new session + * \throw Unavailable + * + * \return untyped capability to new session + * + * The use of this function is discouraged. Please use the type safe + * 'session()' template instead. + */ + virtual Session_capability session(Service_name const &service_name, + Session_args const &args, + Affinity const &affinity = Affinity()) = 0; - /** - * Create session to a service - * - * \param service_name name of the requested interface - * \param args session constructor arguments - * \param affinity preferred CPU affinity for the session - * - * \throw Service_denied parent denies session request - * \throw Quota_exceeded our own quota does not suffice for - * the creation of the new session - * \throw Unavailable - * - * \return untyped capability to new session - * - * The use of this function is discouraged. Please use the type safe - * 'session()' template instead. - */ - virtual Session_capability session(Service_name const &service_name, - Session_args const &args, - Affinity const &affinity = Affinity()) = 0; + /** + * Create session to a service + * + * \param SESSION_TYPE session interface type + * \param args session constructor arguments + * \param affinity preferred CPU affinity for the session + * + * \throw Service_denied parent denies session request + * \throw Quota_exceeded our own quota does not suffice for + * the creation of the new session + * \throw Unavailable + * + * \return capability to new session + */ + template + Capability session(Session_args const &args, + Affinity const &affinity = Affinity()) + { + Session_capability cap = session(SESSION_TYPE::service_name(), + args, affinity); + return reinterpret_cap_cast(cap); + } - /** - * Create session to a service - * - * \param SESSION_TYPE session interface type - * \param args session constructor arguments - * \param affinity preferred CPU affinity for the session - * - * \throw Service_denied parent denies session request - * \throw Quota_exceeded our own quota does not suffice for - * the creation of the new session - * \throw Unavailable - * - * \return capability to new session - */ - template - Capability session(Session_args const &args, - Affinity const &affinity = Affinity()) - { - Session_capability cap = session(SESSION_TYPE::service_name(), - args, affinity); - return reinterpret_cap_cast(cap); - } + /** + * Transfer our quota to the server that provides the specified session + * + * \param to_session recipient session + * \param args description of the amount of quota to transfer + * + * \throw Quota_exceeded quota could not be transferred + * + * The 'args' argument has the same principle format as the 'args' + * argument of the 'session' function. + * The error case indicates that there is not enough unused quota on + * the source side. + */ + virtual void upgrade(Session_capability to_session, + Upgrade_args const &args) = 0; - /** - * Transfer our quota to the server that provides the specified session - * - * \param to_session recipient session - * \param args description of the amount of quota to transfer - * - * \throw Quota_exceeded quota could not be transferred - * - * The 'args' argument has the same principle format as the 'args' - * argument of the 'session' function. - * The error case indicates that there is not enough unused quota on - * the source side. - */ - virtual void upgrade(Session_capability to_session, - Upgrade_args const &args) = 0; + /** + * Close session + */ + virtual void close(Session_capability session) = 0; - /** - * Close session - */ - virtual void close(Session_capability session) = 0; + /** + * Provide thread_cap of main thread + */ + virtual Thread_capability main_thread_cap() const = 0; - /** - * Provide thread_cap of main thread - */ - virtual Thread_capability main_thread_cap() const = 0; + /** + * Register signal handler for resource notifications + */ + virtual void resource_avail_sigh(Signal_context_capability sigh) = 0; - /** - * Register signal handler for resource notifications - */ - virtual void resource_avail_sigh(Signal_context_capability sigh) = 0; + /** + * Request additional resources + * + * By invoking this function, a process is able to inform its + * parent about the need for additional resources. The argument + * string contains a resource description in the same format as + * used for session-construction arguments. In particular, for + * requesting additional RAM quota, the argument looks like + * "ram_quota=" where 'amount' is the amount of additional + * resources expected from the parent. If the parent complies with + * the request, it submits a resource-available signal to the + * handler registered via 'resource_avail_sigh()'. On the reception + * of such a signal, the process can re-evaluate its resource quota + * and resume execution. + */ + virtual void resource_request(Resource_args const &args) = 0; - /** - * Request additional resources - * - * By invoking this function, a process is able to inform its - * parent about the need for additional resources. The argument - * string contains a resource description in the same format as - * used for session-construction arguments. In particular, for - * requesting additional RAM quota, the argument looks like - * "ram_quota=" where 'amount' is the amount of additional - * resources expected from the parent. If the parent complies with - * the request, it submits a resource-available signal to the - * handler registered via 'resource_avail_sigh()'. On the reception - * of such a signal, the process can re-evaluate its resource quota - * and resume execution. - */ - virtual void resource_request(Resource_args const &args) = 0; + /** + * Register signal handler for resource yield notifications + * + * Using the yield signal, the parent is able to inform the process + * about its wish to regain resources. + */ + virtual void yield_sigh(Signal_context_capability sigh) = 0; - /** - * Register signal handler for resource yield notifications - * - * Using the yield signal, the parent is able to inform the process - * about its wish to regain resources. - */ - virtual void yield_sigh(Signal_context_capability sigh) = 0; + /** + * Obtain information about the amount of resources to free + * + * The amount of resources returned by this function is the + * goal set by the parent. It is not commanded but merely meant + * as a friendly beg to cooperate. The process is not obligated + * to comply. If the process decides to take action to free + * resources, it can inform its parent about the availability + * of freed up resources by calling 'yield_response()'. + */ + virtual Resource_args yield_request() = 0; - /** - * Obtain information about the amount of resources to free - * - * The amount of resources returned by this function is the - * goal set by the parent. It is not commanded but merely meant - * as a friendly beg to cooperate. The process is not obligated - * to comply. If the process decides to take action to free - * resources, it can inform its parent about the availability - * of freed up resources by calling 'yield_response()'. - */ - virtual Resource_args yield_request() = 0; - - /** - * Notify the parent about a response to a yield request - */ - virtual void yield_response() = 0; + /** + * Notify the parent about a response to a yield request + */ + virtual void yield_response() = 0; - /********************* - ** RPC declaration ** - *********************/ + /********************* + ** RPC declaration ** + *********************/ - GENODE_RPC(Rpc_exit, void, exit, int); - GENODE_RPC(Rpc_announce, void, announce, - Service_name const &, Root_capability); - GENODE_RPC_THROW(Rpc_session, Session_capability, session, - GENODE_TYPE_LIST(Service_denied, Quota_exceeded, Unavailable), - Service_name const &, Session_args const &, Affinity const &); - GENODE_RPC_THROW(Rpc_upgrade, void, upgrade, - GENODE_TYPE_LIST(Quota_exceeded), - Session_capability, Upgrade_args const &); - GENODE_RPC(Rpc_close, void, close, Session_capability); - GENODE_RPC(Rpc_main_thread, Thread_capability, main_thread_cap); - GENODE_RPC(Rpc_resource_avail_sigh, void, resource_avail_sigh, - Signal_context_capability); - GENODE_RPC(Rpc_resource_request, void, resource_request, - Resource_args const &); - GENODE_RPC(Rpc_yield_sigh, void, yield_sigh, Signal_context_capability); - GENODE_RPC(Rpc_yield_request, Resource_args, yield_request); - GENODE_RPC(Rpc_yield_response, void, yield_response); + GENODE_RPC(Rpc_exit, void, exit, int); + GENODE_RPC(Rpc_announce, void, announce, + Service_name const &, Root_capability); + GENODE_RPC_THROW(Rpc_session, Session_capability, session, + GENODE_TYPE_LIST(Service_denied, Quota_exceeded, Unavailable), + Service_name const &, Session_args const &, Affinity const &); + GENODE_RPC_THROW(Rpc_upgrade, void, upgrade, + GENODE_TYPE_LIST(Quota_exceeded), + Session_capability, Upgrade_args const &); + GENODE_RPC(Rpc_close, void, close, Session_capability); + GENODE_RPC(Rpc_main_thread, Thread_capability, main_thread_cap); + GENODE_RPC(Rpc_resource_avail_sigh, void, resource_avail_sigh, + Signal_context_capability); + GENODE_RPC(Rpc_resource_request, void, resource_request, + Resource_args const &); + GENODE_RPC(Rpc_yield_sigh, void, yield_sigh, Signal_context_capability); + GENODE_RPC(Rpc_yield_request, Resource_args, yield_request); + GENODE_RPC(Rpc_yield_response, void, yield_response); - typedef Meta::Type_tuple - > > > > > > > > > > Rpc_functions; - }; -} + typedef Meta::Type_tuple + > > > > > > > > > > Rpc_functions; +}; template diff --git a/repos/base/include/pd_session/client.h b/repos/base/include/pd_session/client.h index fa495e88a..ebbca5731 100644 --- a/repos/base/include/pd_session/client.h +++ b/repos/base/include/pd_session/client.h @@ -17,21 +17,21 @@ #include #include -namespace Genode { +namespace Genode { struct Pd_session_client; } - struct Pd_session_client : Rpc_client - { - explicit Pd_session_client(Pd_session_capability session) - : Rpc_client(session) { } - int bind_thread(Thread_capability thread) { - return call(thread); } +struct Genode::Pd_session_client : Rpc_client +{ + explicit Pd_session_client(Pd_session_capability session) + : Rpc_client(session) { } - int assign_parent(Parent_capability parent) { - return call(parent); } + int bind_thread(Thread_capability thread) override { + return call(thread); } - bool assign_pci(addr_t) { return false; } - }; -} + int assign_parent(Parent_capability parent) override { + return call(parent); } + + bool assign_pci(addr_t) { return false; } +}; #endif /* _INCLUDE__PD_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/pd_session/connection.h b/repos/base/include/pd_session/connection.h index 0b7a9340f..37db08a25 100644 --- a/repos/base/include/pd_session/connection.h +++ b/repos/base/include/pd_session/connection.h @@ -17,21 +17,21 @@ #include #include -namespace Genode { +namespace Genode { struct Pd_connection; } - struct Pd_connection : Connection, Pd_session_client - { - /** - * Constructor - * - * \param label session label - */ - Pd_connection(char const *label = "", Native_pd_args const *pd_args = 0) - : - Connection(session("ram_quota=4K, label=\"%s\"", label)), - Pd_session_client(cap()) - { } - }; -} + +struct Genode::Pd_connection : Connection, Pd_session_client +{ + /** + * Constructor + * + * \param label session label + */ + Pd_connection(char const *label = "", Native_pd_args const *pd_args = 0) + : + Connection(session("ram_quota=4K, label=\"%s\"", label)), + Pd_session_client(cap()) + { } +}; #endif /* _INCLUDE__PD_SESSION__CONNECTION_H_ */ diff --git a/repos/base/include/pd_session/pd_session.h b/repos/base/include/pd_session/pd_session.h index 9d63ea196..64ef234ba 100644 --- a/repos/base/include/pd_session/pd_session.h +++ b/repos/base/include/pd_session/pd_session.h @@ -20,44 +20,44 @@ #include #include -namespace Genode { - - struct Pd_session : Session - { - static const char *service_name() { return "PD"; } - - virtual ~Pd_session() { } - - /** - * Bind thread to protection domain - * - * \param thread capability of thread to bind - * - * \return 0 on success or negative error code - * - * After successful bind, the thread will execute inside this - * protection domain when started. - */ - virtual int bind_thread(Thread_capability thread) = 0; - - /** - * Assign parent to protection domain - * - * \param parent capability of parent interface - * \return 0 on success, or negative error code - */ - virtual int assign_parent(Parent_capability parent) = 0; +namespace Genode { struct Pd_session; } - /********************* - ** RPC declaration ** - *********************/ +struct Genode::Pd_session : Session +{ + static const char *service_name() { return "PD"; } - GENODE_RPC(Rpc_bind_thread, int, bind_thread, Thread_capability); - GENODE_RPC(Rpc_assign_parent, int, assign_parent, Parent_capability); + virtual ~Pd_session() { } - GENODE_RPC_INTERFACE(Rpc_bind_thread, Rpc_assign_parent); - }; -} + /** + * Bind thread to protection domain + * + * \param thread capability of thread to bind + * + * \return 0 on success or negative error code + * + * After successful bind, the thread will execute inside this + * protection domain when started. + */ + virtual int bind_thread(Thread_capability thread) = 0; + + /** + * Assign parent to protection domain + * + * \param parent capability of parent interface + * \return 0 on success, or negative error code + */ + virtual int assign_parent(Parent_capability parent) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_bind_thread, int, bind_thread, Thread_capability); + GENODE_RPC(Rpc_assign_parent, int, assign_parent, Parent_capability); + + GENODE_RPC_INTERFACE(Rpc_bind_thread, Rpc_assign_parent); +}; #endif /* _INCLUDE__PD_SESSION__PD_SESSION_H_ */ diff --git a/repos/base/include/platform/arndale/drivers/board_base.h b/repos/base/include/platform/arndale/drivers/board_base.h index 415649dcd..78040569e 100644 --- a/repos/base/include/platform/arndale/drivers/board_base.h +++ b/repos/base/include/platform/arndale/drivers/board_base.h @@ -17,34 +17,34 @@ /* Genode includes */ #include -namespace Genode +namespace Genode { struct Board_base; } + + +/** + * Board driver base + */ +struct Genode::Board_base : Exynos5 { - /** - * Board driver base - */ - struct Board_base : Exynos5 + enum { - enum - { - /* clock management unit */ - CMU_MMIO_BASE = 0x10010000, - CMU_MMIO_SIZE = 0x24000, + /* clock management unit */ + CMU_MMIO_BASE = 0x10010000, + CMU_MMIO_SIZE = 0x24000, - /* power management unit */ - PMU_MMIO_BASE = 0x10040000, - PMU_MMIO_SIZE = 0x5000, + /* power management unit */ + PMU_MMIO_BASE = 0x10040000, + PMU_MMIO_SIZE = 0x5000, - /* USB */ - USB_HOST20_IRQ = 103, - USB_DRD30_IRQ = 104, + /* USB */ + USB_HOST20_IRQ = 103, + USB_DRD30_IRQ = 104, - /* UART */ - UART_2_CLOCK = 100000000, + /* UART */ + UART_2_CLOCK = 100000000, - /* wether board provides security extension */ - SECURITY_EXTENSION = 1, - }; + /* wether board provides security extension */ + SECURITY_EXTENSION = 1, }; -} +}; #endif /* _INCLUDE__DRIVERS__BOARD_BASE_H_ */ diff --git a/repos/base/include/platform/imx53/drivers/board_base_support.h b/repos/base/include/platform/imx53/drivers/board_base_support.h index be645775e..8289dee7c 100644 --- a/repos/base/include/platform/imx53/drivers/board_base_support.h +++ b/repos/base/include/platform/imx53/drivers/board_base_support.h @@ -14,104 +14,104 @@ #ifndef _INCLUDE__PLATFORM__IMX53__DRIVERS__BOARD_BASE_SUPPORT_H_ #define _INCLUDE__PLATFORM__IMX53__DRIVERS__BOARD_BASE_SUPPORT_H_ -namespace Imx53 +namespace Imx53 { struct Board_base; } + + +/** + * i.MX53 motherboard + */ +struct Imx53::Board_base { - /** - * i.MX53 motherboard - */ - struct Board_base - { - enum { - MMIO_BASE = 0x0, - MMIO_SIZE = 0x70000000, + enum { + MMIO_BASE = 0x0, + MMIO_SIZE = 0x70000000, - UART_1_IRQ = 31, - UART_1_MMIO_BASE = 0x53fbc000, - UART_1_MMIO_SIZE = 0x00004000, + UART_1_IRQ = 31, + UART_1_MMIO_BASE = 0x53fbc000, + UART_1_MMIO_SIZE = 0x00004000, - EPIT_1_IRQ = 40, - EPIT_1_MMIO_BASE = 0x53fac000, - EPIT_1_MMIO_SIZE = 0x00004000, + EPIT_1_IRQ = 40, + EPIT_1_MMIO_BASE = 0x53fac000, + EPIT_1_MMIO_SIZE = 0x00004000, - EPIT_2_IRQ = 41, - EPIT_2_MMIO_BASE = 0x53fb0000, - EPIT_2_MMIO_SIZE = 0x00004000, + EPIT_2_IRQ = 41, + EPIT_2_MMIO_BASE = 0x53fb0000, + EPIT_2_MMIO_SIZE = 0x00004000, - GPIO1_MMIO_BASE = 0x53f84000, - GPIO1_MMIO_SIZE = 0x4000, - GPIO2_MMIO_BASE = 0x53f88000, - GPIO2_MMIO_SIZE = 0x4000, - GPIO3_MMIO_BASE = 0x53f8c000, - GPIO3_MMIO_SIZE = 0x4000, - GPIO4_MMIO_BASE = 0x53f90000, - GPIO4_MMIO_SIZE = 0x4000, - GPIO5_MMIO_BASE = 0x53fdc000, - GPIO5_MMIO_SIZE = 0x4000, - GPIO6_MMIO_BASE = 0x53fe0000, - GPIO6_MMIO_SIZE = 0x4000, - GPIO7_MMIO_BASE = 0x53fe4000, - GPIO7_MMIO_SIZE = 0x4000, - GPIO1_IRQL = 50, - GPIO1_IRQH = 51, - GPIO2_IRQL = 52, - GPIO2_IRQH = 53, - GPIO3_IRQL = 54, - GPIO3_IRQH = 55, - GPIO4_IRQL = 56, - GPIO4_IRQH = 57, - GPIO5_IRQL = 103, - GPIO5_IRQH = 104, - GPIO6_IRQL = 105, - GPIO6_IRQH = 106, - GPIO7_IRQL = 107, - GPIO7_IRQH = 108, + GPIO1_MMIO_BASE = 0x53f84000, + GPIO1_MMIO_SIZE = 0x4000, + GPIO2_MMIO_BASE = 0x53f88000, + GPIO2_MMIO_SIZE = 0x4000, + GPIO3_MMIO_BASE = 0x53f8c000, + GPIO3_MMIO_SIZE = 0x4000, + GPIO4_MMIO_BASE = 0x53f90000, + GPIO4_MMIO_SIZE = 0x4000, + GPIO5_MMIO_BASE = 0x53fdc000, + GPIO5_MMIO_SIZE = 0x4000, + GPIO6_MMIO_BASE = 0x53fe0000, + GPIO6_MMIO_SIZE = 0x4000, + GPIO7_MMIO_BASE = 0x53fe4000, + GPIO7_MMIO_SIZE = 0x4000, + GPIO1_IRQL = 50, + GPIO1_IRQH = 51, + GPIO2_IRQL = 52, + GPIO2_IRQH = 53, + GPIO3_IRQL = 54, + GPIO3_IRQH = 55, + GPIO4_IRQL = 56, + GPIO4_IRQH = 57, + GPIO5_IRQL = 103, + GPIO5_IRQH = 104, + GPIO6_IRQL = 105, + GPIO6_IRQH = 106, + GPIO7_IRQL = 107, + GPIO7_IRQH = 108, - IRQ_CONTROLLER_BASE = 0x0fffc000, - IRQ_CONTROLLER_SIZE = 0x00004000, + IRQ_CONTROLLER_BASE = 0x0fffc000, + IRQ_CONTROLLER_SIZE = 0x00004000, - AIPS_1_MMIO_BASE = 0x53f00000, - AIPS_2_MMIO_BASE = 0x63f00000, + AIPS_1_MMIO_BASE = 0x53f00000, + AIPS_2_MMIO_BASE = 0x63f00000, - IOMUXC_BASE = 0x53fa8000, - IOMUXC_SIZE = 0x00004000, + IOMUXC_BASE = 0x53fa8000, + IOMUXC_SIZE = 0x00004000, - PWM2_BASE = 0x53fb8000, - PWM2_SIZE = 0x00004000, + PWM2_BASE = 0x53fb8000, + PWM2_SIZE = 0x00004000, - IPU_BASE = 0x18000000, - IPU_SIZE = 0x08000000, + IPU_BASE = 0x18000000, + IPU_SIZE = 0x08000000, - SRC_BASE = 0x53fd0000, - SRC_SIZE = 0x00004000, + SRC_BASE = 0x53fd0000, + SRC_SIZE = 0x00004000, - CCM_BASE = 0x53FD4000, - CCM_SIZE = 0x00004000, + CCM_BASE = 0x53FD4000, + CCM_SIZE = 0x00004000, - I2C_2_IRQ = 63, - I2C_2_BASE = 0x63fc4000, - I2C_2_SIZE = 0x00004000, + I2C_2_IRQ = 63, + I2C_2_BASE = 0x63fc4000, + I2C_2_SIZE = 0x00004000, - I2C_3_IRQ = 64, - I2C_3_BASE = 0x53fec000, - I2C_3_SIZE = 0x00004000, + I2C_3_IRQ = 64, + I2C_3_BASE = 0x53fec000, + I2C_3_SIZE = 0x00004000, - IIM_BASE = 0x63f98000, - IIM_SIZE = 0x00004000, + IIM_BASE = 0x63f98000, + IIM_SIZE = 0x00004000, - CSU_BASE = 0x63f9c000, - CSU_SIZE = 0x00001000, + CSU_BASE = 0x63f9c000, + CSU_SIZE = 0x00001000, - M4IF_BASE = 0x63fd8000, - M4IF_SIZE = 0x00001000, + M4IF_BASE = 0x63fd8000, + M4IF_SIZE = 0x00001000, - /* wether board provides security extension */ - SECURITY_EXTENSION = 1, + /* wether board provides security extension */ + SECURITY_EXTENSION = 1, - /* CPU cache */ - CACHE_LINE_SIZE_LOG2 = 6, - }; + /* CPU cache */ + CACHE_LINE_SIZE_LOG2 = 6, }; -} +}; #endif /* _INCLUDE__PLATFORM__IMX53__DRIVERS__BOARD_BASE_SUPPORT_H_ */ diff --git a/repos/base/include/platform/imx53_qsb/drivers/board_base.h b/repos/base/include/platform/imx53_qsb/drivers/board_base.h index c3825b3bb..fa48e0321 100644 --- a/repos/base/include/platform/imx53_qsb/drivers/board_base.h +++ b/repos/base/include/platform/imx53_qsb/drivers/board_base.h @@ -17,21 +17,21 @@ /* Genode includes */ #include -namespace Genode +namespace Genode { struct Board_base; } + + +/** + * i.MX53 starter board + */ +struct Genode::Board_base : Imx53::Board_base { - /** - * i.MX53 starter board - */ - struct Board_base : Imx53::Board_base - { - enum { - RAM0_BASE = 0x70000000, - RAM0_SIZE = 0x20000000, - RAM1_BASE = 0xb0000000, - RAM1_SIZE = 0x20000000, - }; + enum { + RAM0_BASE = 0x70000000, + RAM0_SIZE = 0x20000000, + RAM1_BASE = 0xb0000000, + RAM1_SIZE = 0x20000000, }; -} +}; #endif /* _INCLUDE__PLATFORM__IMX53_QSB__DRIVERS__BOARD_BASE_H_ */ diff --git a/repos/base/include/platform/odroid_xu/drivers/board_base.h b/repos/base/include/platform/odroid_xu/drivers/board_base.h index f8d86d00c..1bb6c07f0 100644 --- a/repos/base/include/platform/odroid_xu/drivers/board_base.h +++ b/repos/base/include/platform/odroid_xu/drivers/board_base.h @@ -17,22 +17,22 @@ /* Genode includes */ #include -namespace Genode -{ - /** - * Board driver base - */ - struct Board_base : Exynos5 - { - enum - { - /* UART */ - UART_2_CLOCK = 62668800, +namespace Genode { struct Board_base; } - /* wether board provides security extension */ - SECURITY_EXTENSION = 0, - }; + +/** + * Board driver base + */ +struct Genode::Board_base : Exynos5 +{ + enum + { + /* UART */ + UART_2_CLOCK = 62668800, + + /* wether board provides security extension */ + SECURITY_EXTENSION = 0, }; -} +}; #endif /* _INCLUDE__DRIVERS__BOARD_BASE_H_ */ diff --git a/repos/base/include/platform/panda/drivers/board_base.h b/repos/base/include/platform/panda/drivers/board_base.h index c6cfa3a5a..ce7b962ed 100644 --- a/repos/base/include/platform/panda/drivers/board_base.h +++ b/repos/base/include/platform/panda/drivers/board_base.h @@ -14,95 +14,94 @@ #ifndef _INCLUDE__DRIVERS__BOARD_BASE_H_ #define _INCLUDE__DRIVERS__BOARD_BASE_H_ -namespace Genode +namespace Genode { struct Board_base; } + + +/** + * Driver for the OMAP4 PandaBoard revision A2 + */ +struct Genode::Board_base { - /** - * Driver for the OMAP4 PandaBoard revision A2 - */ - struct Board_base - { - enum - { - /* device IO memory */ - MMIO_0_BASE = 0x48000000, - MMIO_0_SIZE = 0x01000000, - MMIO_1_BASE = 0x4a000000, - MMIO_1_SIZE = 0x01000000, + enum { - /* normal RAM */ - RAM_0_BASE = 0x80000000, - RAM_0_SIZE = 0x40000000, + /* device IO memory */ + MMIO_0_BASE = 0x48000000, + MMIO_0_SIZE = 0x01000000, + MMIO_1_BASE = 0x4a000000, + MMIO_1_SIZE = 0x01000000, - /* clocks */ - SYS_CLK = 38400000, + /* normal RAM */ + RAM_0_BASE = 0x80000000, + RAM_0_SIZE = 0x40000000, - /* UART controllers */ - TL16C750_1_MMIO_BASE = MMIO_0_BASE + 0x6a000, - TL16C750_2_MMIO_BASE = MMIO_0_BASE + 0x6c000, - TL16C750_3_MMIO_BASE = MMIO_0_BASE + 0x20000, - TL16C750_4_MMIO_BASE = MMIO_0_BASE + 0x6e000, - TL16C750_MMIO_SIZE = 0x2000, - TL16C750_CLOCK = 48*1000*1000, - TL16C750_1_IRQ = 104, - TL16C750_2_IRQ = 105, - TL16C750_3_IRQ = 106, - TL16C750_4_IRQ = 102, + /* clocks */ + SYS_CLK = 38400000, - /* USB */ - HSUSB_EHCI_IRQ = 109, + /* UART controllers */ + TL16C750_1_MMIO_BASE = MMIO_0_BASE + 0x6a000, + TL16C750_2_MMIO_BASE = MMIO_0_BASE + 0x6c000, + TL16C750_3_MMIO_BASE = MMIO_0_BASE + 0x20000, + TL16C750_4_MMIO_BASE = MMIO_0_BASE + 0x6e000, + TL16C750_MMIO_SIZE = 0x2000, + TL16C750_CLOCK = 48*1000*1000, + TL16C750_1_IRQ = 104, + TL16C750_2_IRQ = 105, + TL16C750_3_IRQ = 106, + TL16C750_4_IRQ = 102, - /* timer modules */ - GP_TIMER_3_IRQ = 71, + /* USB */ + HSUSB_EHCI_IRQ = 109, - /* CPU */ - CORTEX_A9_PRIVATE_MEM_BASE = 0x48240000, - CORTEX_A9_PRIVATE_MEM_SIZE = 0x00002000, - CORTEX_A9_PRIVATE_TIMER_CLK = 350000000, + /* timer modules */ + GP_TIMER_3_IRQ = 71, - /* L2 cache */ - PL310_MMIO_BASE = 0x48242000, - PL310_MMIO_SIZE = 0x00001000, + /* CPU */ + CORTEX_A9_PRIVATE_MEM_BASE = 0x48240000, + CORTEX_A9_PRIVATE_MEM_SIZE = 0x00002000, + CORTEX_A9_PRIVATE_TIMER_CLK = 350000000, - /* display subsystem */ - DSS_MMIO_BASE = 0x58000000, - DSS_MMIO_SIZE = 0x00001000, - DISPC_MMIO_BASE = 0x58001000, - DISPC_MMIO_SIZE = 0x00001000, - HDMI_MMIO_BASE = 0x58006000, - HDMI_MMIO_SIZE = 0x00001000, + /* L2 cache */ + PL310_MMIO_BASE = 0x48242000, + PL310_MMIO_SIZE = 0x00001000, - /* GPIO */ - GPIO1_MMIO_BASE = 0x4a310000, - GPIO1_MMIO_SIZE = 0x1000, - GPIO1_IRQ = 29 + 32, - GPIO2_MMIO_BASE = 0x48055000, - GPIO2_MMIO_SIZE = 0x1000, - GPIO2_IRQ = 30 + 32, - GPIO3_MMIO_BASE = 0x48057000, - GPIO3_MMIO_SIZE = 0x1000, - GPIO3_IRQ = 31 + 32, - GPIO4_MMIO_BASE = 0x48059000, - GPIO4_MMIO_SIZE = 0x1000, - GPIO4_IRQ = 32 + 32, - GPIO5_MMIO_BASE = 0x4805b000, - GPIO5_MMIO_SIZE = 0x1000, - GPIO5_IRQ = 33 + 32, - GPIO6_MMIO_BASE = 0x4805d000, - GPIO6_MMIO_SIZE = 0x1000, - GPIO6_IRQ = 34 + 32, + /* display subsystem */ + DSS_MMIO_BASE = 0x58000000, + DSS_MMIO_SIZE = 0x00001000, + DISPC_MMIO_BASE = 0x58001000, + DISPC_MMIO_SIZE = 0x00001000, + HDMI_MMIO_BASE = 0x58006000, + HDMI_MMIO_SIZE = 0x00001000, - /* SD card */ - HSMMC_IRQ = 115, + /* GPIO */ + GPIO1_MMIO_BASE = 0x4a310000, + GPIO1_MMIO_SIZE = 0x1000, + GPIO1_IRQ = 29 + 32, + GPIO2_MMIO_BASE = 0x48055000, + GPIO2_MMIO_SIZE = 0x1000, + GPIO2_IRQ = 30 + 32, + GPIO3_MMIO_BASE = 0x48057000, + GPIO3_MMIO_SIZE = 0x1000, + GPIO3_IRQ = 31 + 32, + GPIO4_MMIO_BASE = 0x48059000, + GPIO4_MMIO_SIZE = 0x1000, + GPIO4_IRQ = 32 + 32, + GPIO5_MMIO_BASE = 0x4805b000, + GPIO5_MMIO_SIZE = 0x1000, + GPIO5_IRQ = 33 + 32, + GPIO6_MMIO_BASE = 0x4805d000, + GPIO6_MMIO_SIZE = 0x1000, + GPIO6_IRQ = 34 + 32, - /* CPU cache */ - CACHE_LINE_SIZE_LOG2 = 2, /* FIXME get correct value from board spec */ + /* SD card */ + HSMMC_IRQ = 115, - /* wether board provides security extension */ - SECURITY_EXTENSION = 0, + /* CPU cache */ + CACHE_LINE_SIZE_LOG2 = 2, /* FIXME get correct value from board spec */ - }; + /* wether board provides security extension */ + SECURITY_EXTENSION = 0, }; -} +}; #endif /* _INCLUDE__DRIVERS__BOARD_BASE_H_ */ diff --git a/repos/base/include/platform/pbxa9/drivers/board_base.h b/repos/base/include/platform/pbxa9/drivers/board_base.h index ec025e873..6e38cc8a3 100644 --- a/repos/base/include/platform/pbxa9/drivers/board_base.h +++ b/repos/base/include/platform/pbxa9/drivers/board_base.h @@ -14,76 +14,76 @@ #ifndef _INCLUDE__DRIVERS__BOARD_BASE_H_ #define _INCLUDE__DRIVERS__BOARD_BASE_H_ -namespace Genode +namespace Genode { struct Board_base; } + + +/** + * Driver for the Realview PBXA9 board + */ +struct Genode::Board_base { - /** - * Driver for the Realview PBXA9 board - */ - struct Board_base - { - enum - { - /* normal RAM */ - RAM_0_BASE = 0x70000000, - RAM_0_SIZE = 0x20000000, - RAM_1_BASE = 0x20000000, - RAM_1_SIZE = 0x10000000, + enum { - /* device IO memory */ - MMIO_0_BASE = 0x10000000, - MMIO_0_SIZE = 0x10000000, - MMIO_1_BASE = 0x4e000000, - MMIO_1_SIZE = 0x01000000, + /* normal RAM */ + RAM_0_BASE = 0x70000000, + RAM_0_SIZE = 0x20000000, + RAM_1_BASE = 0x20000000, + RAM_1_SIZE = 0x10000000, - NORTHBRIDGE_AHB_BASE = 0x10020000, - NORTHBRIDGE_AHB_SIZE = 768*1024, + /* device IO memory */ + MMIO_0_BASE = 0x10000000, + MMIO_0_SIZE = 0x10000000, + MMIO_1_BASE = 0x4e000000, + MMIO_1_SIZE = 0x01000000, - /* southbridge */ - SOUTHBRIDGE_APB_BASE = 0x10000000, - SOUTHBRIDGE_APB_SIZE = 128*1024, + NORTHBRIDGE_AHB_BASE = 0x10020000, + NORTHBRIDGE_AHB_SIZE = 768*1024, - /* clocks */ - OSC_6_CLOCK = 24*1000*1000, + /* southbridge */ + SOUTHBRIDGE_APB_BASE = 0x10000000, + SOUTHBRIDGE_APB_SIZE = 128*1024, - /* CPU */ - CORTEX_A9_PRIVATE_TIMER_CLK = 100000000, - CORTEX_A9_PRIVATE_MEM_BASE = 0x1f000000, - CORTEX_A9_PRIVATE_MEM_SIZE = 0x01000000, + /* clocks */ + OSC_6_CLOCK = 24*1000*1000, - /* UART */ - PL011_0_MMIO_BASE = 0x10009000, - PL011_0_MMIO_SIZE = 0x00001000, - PL011_0_CLOCK = OSC_6_CLOCK, - PL011_0_IRQ = 44, - PL011_1_IRQ = 45, - PL011_2_IRQ = 46, - PL011_3_IRQ = 47, + /* CPU */ + CORTEX_A9_PRIVATE_TIMER_CLK = 100000000, + CORTEX_A9_PRIVATE_MEM_BASE = 0x1f000000, + CORTEX_A9_PRIVATE_MEM_SIZE = 0x01000000, - /* timer */ - SP804_0_1_MMIO_BASE = 0x10011000, - SP804_0_1_MMIO_SIZE = 0x00001000, - SP804_0_1_IRQ = 36, - SP804_0_1_CLOCK = 1000*1000, + /* UART */ + PL011_0_MMIO_BASE = 0x10009000, + PL011_0_MMIO_SIZE = 0x00001000, + PL011_0_CLOCK = OSC_6_CLOCK, + PL011_0_IRQ = 44, + PL011_1_IRQ = 45, + PL011_2_IRQ = 46, + PL011_3_IRQ = 47, - /* keyboard & mouse */ - KMI_0_IRQ = 52, - KMI_1_IRQ = 53, + /* timer */ + SP804_0_1_MMIO_BASE = 0x10011000, + SP804_0_1_MMIO_SIZE = 0x00001000, + SP804_0_1_IRQ = 36, + SP804_0_1_CLOCK = 1000*1000, - /* LAN */ - ETHERNET_IRQ = 60, + /* keyboard & mouse */ + KMI_0_IRQ = 52, + KMI_1_IRQ = 53, - /* SD card */ - PL180_IRQ_0 = 49, - PL180_IRQ_1 = 50, + /* LAN */ + ETHERNET_IRQ = 60, - /* CPU cache */ - CACHE_LINE_SIZE_LOG2 = 2, /* FIXME get correct value from board spec */ + /* SD card */ + PL180_IRQ_0 = 49, + PL180_IRQ_1 = 50, - /* wether board provides security extension */ - SECURITY_EXTENSION = 0, - }; + /* CPU cache */ + CACHE_LINE_SIZE_LOG2 = 2, /* FIXME get correct value from board spec */ + + /* wether board provides security extension */ + SECURITY_EXTENSION = 0, }; -} +}; #endif /* _INCLUDE__DRIVERS__BOARD_BASE_H_ */ diff --git a/repos/base/include/platform/rpi/drivers/board_base.h b/repos/base/include/platform/rpi/drivers/board_base.h index 2cca3f64d..cca7f0687 100644 --- a/repos/base/include/platform/rpi/drivers/board_base.h +++ b/repos/base/include/platform/rpi/drivers/board_base.h @@ -17,58 +17,58 @@ /* Genode includes */ #include -namespace Genode +namespace Genode { struct Board_base; } + + +struct Genode::Board_base { - struct Board_base - { - enum { - RAM_0_BASE = 0x00000000, - RAM_0_SIZE = 0x10000000, /* XXX ? */ + enum { + RAM_0_BASE = 0x00000000, + RAM_0_SIZE = 0x10000000, /* XXX ? */ - MMIO_0_BASE = 0x20000000, - MMIO_0_SIZE = 0x02000000, + MMIO_0_BASE = 0x20000000, + MMIO_0_SIZE = 0x02000000, - /* - * IRQ numbers 0..7 refer to the basic IRQs. - * IRQ numbers 8..39 refer to GPU IRQs 0..31. - * IRQ numbers 40..71 refer to GPU IRQs 32..63. - */ - GPU_IRQ_BASE = 8, + /* + * IRQ numbers 0..7 refer to the basic IRQs. + * IRQ numbers 8..39 refer to GPU IRQs 0..31. + * IRQ numbers 40..71 refer to GPU IRQs 32..63. + */ + GPU_IRQ_BASE = 8, - SYSTEM_TIMER_IRQ = GPU_IRQ_BASE + 1, - SYSTEM_TIMER_MMIO_BASE = 0x20003000, - SYSTEM_TIMER_MMIO_SIZE = 0x1000, - SYSTEM_TIMER_CLOCK = 1000000, + SYSTEM_TIMER_IRQ = GPU_IRQ_BASE + 1, + SYSTEM_TIMER_MMIO_BASE = 0x20003000, + SYSTEM_TIMER_MMIO_SIZE = 0x1000, + SYSTEM_TIMER_CLOCK = 1000000, - PL011_0_IRQ = 57, - PL011_0_MMIO_BASE = 0x20201000, - PL011_0_MMIO_SIZE = 0x1000, - PL011_0_CLOCK = 3000000, + PL011_0_IRQ = 57, + PL011_0_MMIO_BASE = 0x20201000, + PL011_0_MMIO_SIZE = 0x1000, + PL011_0_CLOCK = 3000000, - IRQ_CONTROLLER_BASE = 0x2000b200, - IRQ_CONTROLLER_SIZE = 0x100, + IRQ_CONTROLLER_BASE = 0x2000b200, + IRQ_CONTROLLER_SIZE = 0x100, - USB_DWC_OTG_BASE = 0x20980000, - USB_DWC_OTG_SIZE = 0x20000, + USB_DWC_OTG_BASE = 0x20980000, + USB_DWC_OTG_SIZE = 0x20000, - /* timer */ - TIMER_IRQ = 0, + /* timer */ + TIMER_IRQ = 0, - /* USB host controller */ - DWC_IRQ = 17, + /* USB host controller */ + DWC_IRQ = 17, - SECURITY_EXTENSION = 0, + SECURITY_EXTENSION = 0, - /* CPU cache */ - CACHE_LINE_SIZE_LOG2 = 5, - }; - - enum Videocore_cache_policy { NON_COHERENT = 0, - COHERENT = 1, - L2_ONLY = 2, - UNCACHED = 3 }; + /* CPU cache */ + CACHE_LINE_SIZE_LOG2 = 5, }; -} + + enum Videocore_cache_policy { NON_COHERENT = 0, + COHERENT = 1, + L2_ONLY = 2, + UNCACHED = 3 }; +}; #endif /* _INCLUDE__PLATFORM__BOARD_BASE_H_ */ diff --git a/repos/base/include/platform/usb_armory/drivers/board_base.h b/repos/base/include/platform/usb_armory/drivers/board_base.h index 7e387badf..ad760b616 100644 --- a/repos/base/include/platform/usb_armory/drivers/board_base.h +++ b/repos/base/include/platform/usb_armory/drivers/board_base.h @@ -17,26 +17,26 @@ /* Genode includes */ #include -namespace Genode +namespace Genode { struct Board_base; } + + +/** + * i.MX53 starter board + */ +struct Genode::Board_base : Imx53::Board_base { - /** - * i.MX53 starter board - */ - struct Board_base : Imx53::Board_base - { - enum { - /* - * These two regions are physically one RAM region but we split it - * to keep the enum names compliant with other i.MX53 boards. This - * way, more files can be shared between the platforms. - */ - RAM0_BASE = 0x70000000, - RAM0_SIZE = 0x10000000, - RAM1_BASE = 0x80000000, - RAM1_SIZE = 0x10000000, - }; + enum { + /* + * These two regions are physically one RAM region but we split it + * to keep the enum names compliant with other i.MX53 boards. This + * way, more files can be shared between the platforms. + */ + RAM0_BASE = 0x70000000, + RAM0_SIZE = 0x10000000, + RAM1_BASE = 0x80000000, + RAM1_SIZE = 0x10000000, }; -} +}; #endif /* _INCLUDE__PLATFORM__IMX53_QSB__DRIVERS__BOARD_BASE_H_ */ diff --git a/repos/base/include/platform/vea9x4/drivers/board_base.h b/repos/base/include/platform/vea9x4/drivers/board_base.h index 3dba12142..9ec5619a1 100644 --- a/repos/base/include/platform/vea9x4/drivers/board_base.h +++ b/repos/base/include/platform/vea9x4/drivers/board_base.h @@ -14,70 +14,70 @@ #ifndef _INCLUDE__PLATFORM__VEA9X4__DRIVERS__BOARD_BASE_H_ #define _INCLUDE__PLATFORM__VEA9X4__DRIVERS__BOARD_BASE_H_ -namespace Genode +namespace Genode { struct Board_base; } + + +/** + * Driver for the Versatile Express A9X4 board + * + * Implies the uATX motherboard and the CoreTile Express A9X4 daughterboard + */ +struct Genode::Board_base { - /** - * Driver for the Versatile Express A9X4 board - * - * Implies the uATX motherboard and the CoreTile Express A9X4 daughterboard - */ - struct Board_base + enum { - enum - { - /* MMIO */ - MMIO_0_BASE = 0x10000000, - MMIO_0_SIZE = 0x10000000, - MMIO_1_BASE = 0x4C000000, - MMIO_1_SIZE = 0x04000000, + /* MMIO */ + MMIO_0_BASE = 0x10000000, + MMIO_0_SIZE = 0x10000000, + MMIO_1_BASE = 0x4C000000, + MMIO_1_SIZE = 0x04000000, - /* RAM */ - RAM_0_BASE = 0x60000000, - RAM_0_SIZE = 0x20000000, - RAM_1_BASE = 0x84000000, - RAM_1_SIZE = 0x1c000000, - RAM_2_BASE = 0x48000000, - RAM_2_SIZE = 0x02000000, + /* RAM */ + RAM_0_BASE = 0x60000000, + RAM_0_SIZE = 0x20000000, + RAM_1_BASE = 0x84000000, + RAM_1_SIZE = 0x1c000000, + RAM_2_BASE = 0x48000000, + RAM_2_SIZE = 0x02000000, - /* UART */ - PL011_0_MMIO_BASE = MMIO_0_BASE + 0x9000, - PL011_0_MMIO_SIZE = 0x1000, - PL011_0_CLOCK = 24*1000*1000, - PL011_0_IRQ = 37, - PL011_1_IRQ = 38, - PL011_2_IRQ = 39, - PL011_3_IRQ = 40, + /* UART */ + PL011_0_MMIO_BASE = MMIO_0_BASE + 0x9000, + PL011_0_MMIO_SIZE = 0x1000, + PL011_0_CLOCK = 24*1000*1000, + PL011_0_IRQ = 37, + PL011_1_IRQ = 38, + PL011_2_IRQ = 39, + PL011_3_IRQ = 40, - /* timer/counter */ - SP804_0_1_MMIO_BASE = MMIO_0_BASE + 0x11000, - SP804_0_1_MMIO_SIZE = 0x1000, - SP804_0_1_CLOCK = 1000*1000, - SP804_0_1_IRQ = 34, + /* timer/counter */ + SP804_0_1_MMIO_BASE = MMIO_0_BASE + 0x11000, + SP804_0_1_MMIO_SIZE = 0x1000, + SP804_0_1_CLOCK = 1000*1000, + SP804_0_1_IRQ = 34, - /* PS2 */ - KMI_0_IRQ = 44, - KMI_1_IRQ = 45, + /* PS2 */ + KMI_0_IRQ = 44, + KMI_1_IRQ = 45, - /* LAN */ - LAN9118_IRQ = 47, + /* LAN */ + LAN9118_IRQ = 47, - /* card reader */ - PL180_0_IRQ = 9, - PL180_1_IRQ = 10, + /* card reader */ + PL180_0_IRQ = 9, + PL180_1_IRQ = 10, - /* CPU */ - CORTEX_A9_PRIVATE_MEM_BASE = 0x1e000000, - CORTEX_A9_PRIVATE_MEM_SIZE = 0x2000, - CORTEX_A9_PRIVATE_TIMER_CLK = 200010000, + /* CPU */ + CORTEX_A9_PRIVATE_MEM_BASE = 0x1e000000, + CORTEX_A9_PRIVATE_MEM_SIZE = 0x2000, + CORTEX_A9_PRIVATE_TIMER_CLK = 200010000, - /* wether board provides security extension */ - SECURITY_EXTENSION = 1, + /* wether board provides security extension */ + SECURITY_EXTENSION = 1, - /* CPU cache */ - CACHE_LINE_SIZE_LOG2 = 2, /* FIXME get correct value from board spec */ - }; + /* CPU cache */ + CACHE_LINE_SIZE_LOG2 = 2, /* FIXME get correct value from board spec */ }; -} +}; #endif /* _INCLUDE__PLATFORM__VEA9X4__DRIVERS__BOARD_BASE_H_ */ diff --git a/repos/base/include/platform_exynos5/board_base.h b/repos/base/include/platform_exynos5/board_base.h index 595c281a8..169a2c151 100644 --- a/repos/base/include/platform_exynos5/board_base.h +++ b/repos/base/include/platform_exynos5/board_base.h @@ -14,73 +14,69 @@ #ifndef _EXYNOS5__BOARD_BASE_H_ #define _EXYNOS5__BOARD_BASE_H_ -namespace Genode +namespace Genode { struct Exynos5; } + + +/** + * Board-driver base + */ +struct Genode::Exynos5 { - /** - * Board-driver base - */ - class Exynos5; -} + enum { + /* normal RAM */ + RAM_0_BASE = 0x40000000, + RAM_0_SIZE = 0x80000000, -class Genode::Exynos5 -{ - public: + /* device IO memory */ + MMIO_0_BASE = 0x10000000, + MMIO_0_SIZE = 0x10000000, - enum { - /* normal RAM */ - RAM_0_BASE = 0x40000000, - RAM_0_SIZE = 0x80000000, + /* interrupt controller */ + IRQ_CONTROLLER_BASE = 0x10480000, + IRQ_CONTROLLER_SIZE = 0x00010000, + IRQ_CONTROLLER_VT_CTRL_BASE = 0x10484000, + IRQ_CONTROLLER_VT_CPU_BASE = 0x10486000, + IRQ_CONTROLLER_VT_CPU_SIZE = 0x1000, - /* device IO memory */ - MMIO_0_BASE = 0x10000000, - MMIO_0_SIZE = 0x10000000, + /* virtual interrupts */ + VT_MAINTAINANCE_IRQ = 25, + VT_TIMER_IRQ = 27, - /* interrupt controller */ - IRQ_CONTROLLER_BASE = 0x10480000, - IRQ_CONTROLLER_SIZE = 0x00010000, - IRQ_CONTROLLER_VT_CTRL_BASE = 0x10484000, - IRQ_CONTROLLER_VT_CPU_BASE = 0x10486000, - IRQ_CONTROLLER_VT_CPU_SIZE = 0x1000, + /* UART */ + UART_2_MMIO_BASE = 0x12C20000, + UART_2_IRQ = 85, - /* virtual interrupts */ - VT_MAINTAINANCE_IRQ = 25, - VT_TIMER_IRQ = 27, + /* pulse-width-modulation timer */ + PWM_MMIO_BASE = 0x12dd0000, + PWM_MMIO_SIZE = 0x1000, + PWM_CLOCK = 66000000, + PWM_IRQ_0 = 68, - /* UART */ - UART_2_MMIO_BASE = 0x12C20000, - UART_2_IRQ = 85, + /* multicore timer */ + MCT_MMIO_BASE = 0x101c0000, + MCT_MMIO_SIZE = 0x1000, + MCT_CLOCK = 24000000, + MCT_IRQ_L0 = 152, + MCT_IRQ_L1 = 153, - /* pulse-width-modulation timer */ - PWM_MMIO_BASE = 0x12dd0000, - PWM_MMIO_SIZE = 0x1000, - PWM_CLOCK = 66000000, - PWM_IRQ_0 = 68, + /* CPU cache */ + CACHE_LINE_SIZE_LOG2 = 6, - /* multicore timer */ - MCT_MMIO_BASE = 0x101c0000, - MCT_MMIO_SIZE = 0x1000, - MCT_CLOCK = 24000000, - MCT_IRQ_L0 = 152, - MCT_IRQ_L1 = 153, + /* IRAM */ + IRAM_BASE = 0x02020000, - /* CPU cache */ - CACHE_LINE_SIZE_LOG2 = 6, + /* hardware name of the primary processor */ + PRIMARY_MPIDR_AFF_0 = 0, - /* IRAM */ - IRAM_BASE = 0x02020000, + /* SATA/AHCI */ + SATA_IRQ = 147, - /* hardware name of the primary processor */ - PRIMARY_MPIDR_AFF_0 = 0, + /* SD card */ + SDMMC0_IRQ = 107, - /* SATA/AHCI */ - SATA_IRQ = 147, - - /* SD card */ - SDMMC0_IRQ = 107, - - /* I2C */ - I2C_HDMI_IRQ = 96, - }; + /* I2C */ + I2C_HDMI_IRQ = 96, + }; }; #endif /* _EXYNOS5__BOARD_BASE_H_ */ diff --git a/repos/base/include/ram_session/client.h b/repos/base/include/ram_session/client.h index e89989c36..4171a8eea 100644 --- a/repos/base/include/ram_session/client.h +++ b/repos/base/include/ram_session/client.h @@ -18,29 +18,29 @@ #include #include -namespace Genode { +namespace Genode { struct Ram_session_client; } - struct Ram_session_client : Rpc_client - { - explicit Ram_session_client(Ram_session_capability session) - : Rpc_client(session) { } - Ram_dataspace_capability alloc(size_t size, - Cache_attribute cached = CACHED) { - return call(size, cached); } +struct Genode::Ram_session_client : Rpc_client +{ + explicit Ram_session_client(Ram_session_capability session) + : Rpc_client(session) { } - void free(Ram_dataspace_capability ds) { call(ds); } + Ram_dataspace_capability alloc(size_t size, + Cache_attribute cached = CACHED) override { + return call(size, cached); } - int ref_account(Ram_session_capability ram_session) { - return call(ram_session); } + void free(Ram_dataspace_capability ds) override { call(ds); } - int transfer_quota(Ram_session_capability ram_session, size_t amount) { - return call(ram_session, amount); } + int ref_account(Ram_session_capability ram_session) override { + return call(ram_session); } - size_t quota() { return call(); } + int transfer_quota(Ram_session_capability ram_session, size_t amount) override { + return call(ram_session, amount); } - size_t used() { return call(); } - }; -} + size_t quota() override { return call(); } + + size_t used() override { return call(); } +}; #endif /* _INCLUDE__RAM_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/ram_session/connection.h b/repos/base/include/ram_session/connection.h index 85329a55f..755aaf2a6 100644 --- a/repos/base/include/ram_session/connection.h +++ b/repos/base/include/ram_session/connection.h @@ -17,9 +17,8 @@ #include #include -namespace Genode { - struct Ram_connection; -} +namespace Genode { struct Ram_connection; } + struct Genode::Ram_connection : Connection, Ram_session_client { diff --git a/repos/base/include/ram_session/ram_session.h b/repos/base/include/ram_session/ram_session.h index a603e4ce3..085939d4c 100644 --- a/repos/base/include/ram_session/ram_session.h +++ b/repos/base/include/ram_session/ram_session.h @@ -24,109 +24,115 @@ namespace Genode { - struct Ram_dataspace : Dataspace { }; - + struct Ram_dataspace; typedef Capability Ram_dataspace_capability; - struct Ram_session : Session - { - static const char *service_name() { return "RAM"; } - - - /********************* - ** Exception types ** - *********************/ - - class Alloc_failed : public Exception { }; - class Quota_exceeded : public Alloc_failed { }; - class Out_of_metadata : public Alloc_failed { }; - - /** - * Destructor - */ - virtual ~Ram_session() { } - - /** - * Allocate RAM dataspace - * - * \param size size of RAM dataspace - * \param cached selects cacheability attributes of the memory, - * uncached memory, i.e., for DMA buffers - * - * \throw Quota_exceeded - * \throw Out_of_metadata - * \return capability to new RAM dataspace - */ - virtual Ram_dataspace_capability alloc(size_t size, - Cache_attribute cached = CACHED) = 0; - - /** - * Free RAM dataspace - * - * \param ds dataspace capability as returned by alloc - */ - virtual void free(Ram_dataspace_capability ds) = 0; - - /** - * Define reference account for the RAM session - * - * \param ram_session reference account - * - * \return 0 on success - * - * Each RAM session requires another RAM session as reference - * account to transfer quota to and from. The reference account can - * be defined only once. - */ - virtual int ref_account(Ram_session_capability ram_session) = 0; - - /** - * Transfer quota to another RAM session - * - * \param ram_session receiver of quota donation - * \param amount amount of quota to donate - * \return 0 on success - * - * Quota can only be transfered if the specified RAM session is - * either the reference account for this session or vice versa. - */ - virtual int transfer_quota(Ram_session_capability ram_session, size_t amount) = 0; - - /** - * Return current quota limit - */ - virtual size_t quota() = 0; - - /** - * Return used quota - */ - virtual size_t used() = 0; - - /** - * Return amount of available quota - */ - size_t avail() - { - size_t q = quota(), u = used(); - return q > u ? q - u : 0; - } - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC_THROW(Rpc_alloc, Ram_dataspace_capability, alloc, - GENODE_TYPE_LIST(Quota_exceeded, Out_of_metadata), - size_t, Cache_attribute); - GENODE_RPC(Rpc_free, void, free, Ram_dataspace_capability); - GENODE_RPC(Rpc_ref_account, int, ref_account, Ram_session_capability); - GENODE_RPC(Rpc_transfer_quota, int, transfer_quota, Ram_session_capability, size_t); - GENODE_RPC(Rpc_quota, size_t, quota); - GENODE_RPC(Rpc_used, size_t, used); - - GENODE_RPC_INTERFACE(Rpc_alloc, Rpc_free, Rpc_ref_account, - Rpc_transfer_quota, Rpc_quota, Rpc_used); - }; + struct Ram_session; } + +struct Genode::Ram_dataspace : Dataspace { }; + + +struct Genode::Ram_session : Session +{ + static const char *service_name() { return "RAM"; } + + + /********************* + ** Exception types ** + *********************/ + + class Alloc_failed : public Exception { }; + class Quota_exceeded : public Alloc_failed { }; + class Out_of_metadata : public Alloc_failed { }; + + /** + * Destructor + */ + virtual ~Ram_session() { } + + /** + * Allocate RAM dataspace + * + * \param size size of RAM dataspace + * \param cached selects cacheability attributes of the memory, + * uncached memory, i.e., for DMA buffers + * + * \throw Quota_exceeded + * \throw Out_of_metadata + * \return capability to new RAM dataspace + */ + virtual Ram_dataspace_capability alloc(size_t size, + Cache_attribute cached = CACHED) = 0; + + /** + * Free RAM dataspace + * + * \param ds dataspace capability as returned by alloc + */ + virtual void free(Ram_dataspace_capability ds) = 0; + + /** + * Define reference account for the RAM session + * + * \param ram_session reference account + * + * \return 0 on success + * + * Each RAM session requires another RAM session as reference + * account to transfer quota to and from. The reference account can + * be defined only once. + */ + virtual int ref_account(Ram_session_capability ram_session) = 0; + + /** + * Transfer quota to another RAM session + * + * \param ram_session receiver of quota donation + * \param amount amount of quota to donate + * \return 0 on success + * + * Quota can only be transfered if the specified RAM session is + * either the reference account for this session or vice versa. + */ + virtual int transfer_quota(Ram_session_capability ram_session, size_t amount) = 0; + + /** + * Return current quota limit + */ + virtual size_t quota() = 0; + + /** + * Return used quota + */ + virtual size_t used() = 0; + + /** + * Return amount of available quota + */ + size_t avail() + { + size_t q = quota(), u = used(); + return q > u ? q - u : 0; + } + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC_THROW(Rpc_alloc, Ram_dataspace_capability, alloc, + GENODE_TYPE_LIST(Quota_exceeded, Out_of_metadata), + size_t, Cache_attribute); + GENODE_RPC(Rpc_free, void, free, Ram_dataspace_capability); + GENODE_RPC(Rpc_ref_account, int, ref_account, Ram_session_capability); + GENODE_RPC(Rpc_transfer_quota, int, transfer_quota, Ram_session_capability, size_t); + GENODE_RPC(Rpc_quota, size_t, quota); + GENODE_RPC(Rpc_used, size_t, used); + + GENODE_RPC_INTERFACE(Rpc_alloc, Rpc_free, Rpc_ref_account, + Rpc_transfer_quota, Rpc_quota, Rpc_used); +}; + #endif /* _INCLUDE__RAM_SESSION__RAM_SESSION_H_ */ diff --git a/repos/base/include/rm_session/client.h b/repos/base/include/rm_session/client.h index 26f9a30ca..235c96141 100644 --- a/repos/base/include/rm_session/client.h +++ b/repos/base/include/rm_session/client.h @@ -17,41 +17,41 @@ #include #include -namespace Genode { +namespace Genode { struct Rm_session_client; } - struct Rm_session_client : Rpc_client + +struct Genode::Rm_session_client : Rpc_client +{ + explicit Rm_session_client(Rm_session_capability session) + : Rpc_client(session) { } + + Local_addr attach(Dataspace_capability ds, size_t size = 0, + off_t offset = 0, bool use_local_addr = false, + Local_addr local_addr = (void *)0, + bool executable = false) override { - explicit Rm_session_client(Rm_session_capability session) - : Rpc_client(session) { } + return call(ds, size, offset, + use_local_addr, local_addr, + executable); + } - Local_addr attach(Dataspace_capability ds, size_t size = 0, - off_t offset = 0, bool use_local_addr = false, - Local_addr local_addr = (void *)0, - bool executable = false) - { - return call(ds, size, offset, - use_local_addr, local_addr, - executable); - } + void detach(Local_addr local_addr) override { + call(local_addr); } - void detach(Local_addr local_addr) { - call(local_addr); } + Pager_capability add_client(Thread_capability thread) override { + return call(thread); } - Pager_capability add_client(Thread_capability thread) { - return call(thread); } + void remove_client(Pager_capability pager) override { + call(pager); } - void remove_client(Pager_capability pager) { - call(pager); } + void fault_handler(Signal_context_capability handler) override { + call(handler); } - void fault_handler(Signal_context_capability handler) { - call(handler); } + State state() override { + return call(); } - State state() { - return call(); } - - Dataspace_capability dataspace() { - return call(); } - }; -} + Dataspace_capability dataspace() override { + return call(); } +}; #endif /* _INCLUDE__RM_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/rm_session/connection.h b/repos/base/include/rm_session/connection.h index a72a0cf58..dc3982742 100644 --- a/repos/base/include/rm_session/connection.h +++ b/repos/base/include/rm_session/connection.h @@ -17,24 +17,24 @@ #include #include -namespace Genode { +namespace Genode { struct Rm_connection; } - struct Rm_connection : Connection, Rm_session_client - { - enum { RAM_QUOTA = 64*1024 }; - /** - * Constructor - * - * \param start start of the managed VM-region - * \param size size of the VM-region to manage - */ - Rm_connection(addr_t start = ~0UL, size_t size = 0) : - Connection( - session("ram_quota=64K, start=0x%p, size=0x%zx", - start, size)), - Rm_session_client(cap()) { } - }; -} +struct Genode::Rm_connection : Connection, Rm_session_client +{ + enum { RAM_QUOTA = 64*1024 }; + + /** + * Constructor + * + * \param start start of the managed VM-region + * \param size size of the VM-region to manage + */ + Rm_connection(addr_t start = ~0UL, size_t size = 0) : + Connection( + session("ram_quota=64K, start=0x%p, size=0x%zx", + start, size)), + Rm_session_client(cap()) { } +}; #endif /* _INCLUDE__RM_SESSION__CONNECTION_H_ */ diff --git a/repos/base/include/rm_session/rm_session.h b/repos/base/include/rm_session/rm_session.h index 4af63c07c..02e012d83 100644 --- a/repos/base/include/rm_session/rm_session.h +++ b/repos/base/include/rm_session/rm_session.h @@ -22,199 +22,199 @@ #include #include -namespace Genode { +namespace Genode { struct Rm_session; } - struct Rm_session : Session + +struct Genode::Rm_session : Session +{ + enum Fault_type { + READY = 0, READ_FAULT = 1, WRITE_FAULT = 2, EXEC_FAULT = 3 }; + + /** + * State of region-manager session + * + * If a client accesses a location outside the regions attached to + * the region-manager session, a fault occurs and gets signalled to + * the registered fault handler. The fault handler, in turn needs + * the information about the fault address and fault type to + * resolve the fault. This information is represented by this + * structure. + */ + struct State { - enum Fault_type { - READY = 0, READ_FAULT = 1, WRITE_FAULT = 2, EXEC_FAULT = 3 }; + /** + * Type of occurred fault + */ + Fault_type type; /** - * State of region-manager session - * - * If a client accesses a location outside the regions attached to - * the region-manager session, a fault occurs and gets signalled to - * the registered fault handler. The fault handler, in turn needs - * the information about the fault address and fault type to - * resolve the fault. This information is represented by this - * structure. + * Fault address */ - struct State - { - /** - * Type of occurred fault - */ - Fault_type type; - - /** - * Fault address - */ - addr_t addr; - - /** - * Default constructor - */ - State() : type(READY), addr(0) { } - - /** - * Constructor - */ - State(Fault_type fault_type, addr_t fault_addr) : - type(fault_type), addr(fault_addr) { } - }; - + addr_t addr; /** - * Helper for tranferring the bit representation of a pointer as RPC - * argument. + * Default constructor */ - class Local_addr - { - private: - - void *_ptr; - - public: - - template - Local_addr(T ptr) : _ptr((void *)ptr) { } - - Local_addr() : _ptr(0) { } - - template - operator T () { return (T)_ptr; } - }; - - - static const char *service_name() { return "RM"; } - - - /********************* - ** Exception types ** - *********************/ - - class Attach_failed : public Exception { }; - class Invalid_args : public Attach_failed { }; - class Invalid_dataspace : public Attach_failed { }; - class Region_conflict : public Attach_failed { }; - class Out_of_metadata : public Attach_failed { }; - - class Invalid_thread : public Exception { }; - class Unbound_thread : public Exception { }; + State() : type(READY), addr(0) { } /** - * Destructor + * Constructor */ - virtual ~Rm_session() { } - - /** - * Map dataspace into local address space - * - * \param ds capability of dataspace to map - * \param size size of the locally mapped region - * default (0) is the whole dataspace - * \param offset start at offset in dataspace (page-aligned) - * \param use_local_addr if set to true, attach the dataspace at - * the specified 'local_addr' - * \param local_addr local destination address - * \param executable if the mapping should be executable - * - * \throw Attach_failed if dataspace or offset is invalid, - * or on region conflict - * \throw Out_of_metadata if meta-data backing store is exhausted - * - * \return local address of mapped dataspace - * - */ - virtual Local_addr attach(Dataspace_capability ds, - size_t size = 0, off_t offset = 0, - bool use_local_addr = false, - Local_addr local_addr = (void *)0, - bool executable = false) = 0; - - /** - * Shortcut for attaching a dataspace at a predefined local address - */ - Local_addr attach_at(Dataspace_capability ds, addr_t local_addr, - size_t size = 0, off_t offset = 0) { - return attach(ds, size, offset, true, local_addr); } - - /** - * Shortcut for attaching a dataspace executable at a predefined local address - */ - Local_addr attach_executable(Dataspace_capability ds, addr_t local_addr, - size_t size = 0, off_t offset = 0) { - return attach(ds, size, offset, true, local_addr, true); } - - /** - * Remove region from local address space - */ - virtual void detach(Local_addr local_addr) = 0; - - /** - * Add client to pager - * - * \param thread thread that will be paged - * \throw Invalid_thread - * \throw Out_of_metadata - * \throw Unbound_thread - * \return capability to be used for handling page faults - * - * This method must be called at least once to establish a valid - * communication channel between the pager part of the region manager - * and the client thread. - */ - virtual Pager_capability add_client(Thread_capability thread) = 0; - - /** - * Remove client from pager - * - * \param pager pager capability of client to be removed - */ - virtual void remove_client(Pager_capability) = 0; - - /** - * Register signal handler for region-manager faults - * - * On Linux, this signal is never delivered because page-fault handling - * is performed by the Linux kernel. On microkernel platforms, - * unresolvable page faults (traditionally called segmentation fault) - * will result in the delivery of the signal. - */ - virtual void fault_handler(Signal_context_capability handler) = 0; - - /** - * Request current state of RM session - */ - virtual State state() = 0; - - /** - * Return dataspace representation of region-manager session - */ - virtual Dataspace_capability dataspace() = 0; - - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC_THROW(Rpc_attach, Local_addr, attach, - GENODE_TYPE_LIST(Invalid_dataspace, Region_conflict, - Out_of_metadata, Invalid_args), - Dataspace_capability, size_t, off_t, bool, Local_addr, bool); - GENODE_RPC(Rpc_detach, void, detach, Local_addr); - GENODE_RPC_THROW(Rpc_add_client, Pager_capability, add_client, - GENODE_TYPE_LIST(Invalid_thread, Out_of_metadata), - Thread_capability); - GENODE_RPC(Rpc_remove_client, void, remove_client, Pager_capability); - GENODE_RPC(Rpc_fault_handler, void, fault_handler, Signal_context_capability); - GENODE_RPC(Rpc_state, State, state); - GENODE_RPC(Rpc_dataspace, Dataspace_capability, dataspace); - - GENODE_RPC_INTERFACE(Rpc_attach, Rpc_detach, Rpc_add_client, - Rpc_remove_client, Rpc_fault_handler, Rpc_state, - Rpc_dataspace); + State(Fault_type fault_type, addr_t fault_addr) : + type(fault_type), addr(fault_addr) { } }; -} + + + /** + * Helper for tranferring the bit representation of a pointer as RPC + * argument. + */ + class Local_addr + { + private: + + void *_ptr; + + public: + + template + Local_addr(T ptr) : _ptr((void *)ptr) { } + + Local_addr() : _ptr(0) { } + + template + operator T () { return (T)_ptr; } + }; + + + static const char *service_name() { return "RM"; } + + + /********************* + ** Exception types ** + *********************/ + + class Attach_failed : public Exception { }; + class Invalid_args : public Attach_failed { }; + class Invalid_dataspace : public Attach_failed { }; + class Region_conflict : public Attach_failed { }; + class Out_of_metadata : public Attach_failed { }; + + class Invalid_thread : public Exception { }; + class Unbound_thread : public Exception { }; + + /** + * Destructor + */ + virtual ~Rm_session() { } + + /** + * Map dataspace into local address space + * + * \param ds capability of dataspace to map + * \param size size of the locally mapped region + * default (0) is the whole dataspace + * \param offset start at offset in dataspace (page-aligned) + * \param use_local_addr if set to true, attach the dataspace at + * the specified 'local_addr' + * \param local_addr local destination address + * \param executable if the mapping should be executable + * + * \throw Attach_failed if dataspace or offset is invalid, + * or on region conflict + * \throw Out_of_metadata if meta-data backing store is exhausted + * + * \return local address of mapped dataspace + * + */ + virtual Local_addr attach(Dataspace_capability ds, + size_t size = 0, off_t offset = 0, + bool use_local_addr = false, + Local_addr local_addr = (void *)0, + bool executable = false) = 0; + + /** + * Shortcut for attaching a dataspace at a predefined local address + */ + Local_addr attach_at(Dataspace_capability ds, addr_t local_addr, + size_t size = 0, off_t offset = 0) { + return attach(ds, size, offset, true, local_addr); } + + /** + * Shortcut for attaching a dataspace executable at a predefined local address + */ + Local_addr attach_executable(Dataspace_capability ds, addr_t local_addr, + size_t size = 0, off_t offset = 0) { + return attach(ds, size, offset, true, local_addr, true); } + + /** + * Remove region from local address space + */ + virtual void detach(Local_addr local_addr) = 0; + + /** + * Add client to pager + * + * \param thread thread that will be paged + * \throw Invalid_thread + * \throw Out_of_metadata + * \throw Unbound_thread + * \return capability to be used for handling page faults + * + * This method must be called at least once to establish a valid + * communication channel between the pager part of the region manager + * and the client thread. + */ + virtual Pager_capability add_client(Thread_capability thread) = 0; + + /** + * Remove client from pager + * + * \param pager pager capability of client to be removed + */ + virtual void remove_client(Pager_capability) = 0; + + /** + * Register signal handler for region-manager faults + * + * On Linux, this signal is never delivered because page-fault handling + * is performed by the Linux kernel. On microkernel platforms, + * unresolvable page faults (traditionally called segmentation fault) + * will result in the delivery of the signal. + */ + virtual void fault_handler(Signal_context_capability handler) = 0; + + /** + * Request current state of RM session + */ + virtual State state() = 0; + + /** + * Return dataspace representation of region-manager session + */ + virtual Dataspace_capability dataspace() = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC_THROW(Rpc_attach, Local_addr, attach, + GENODE_TYPE_LIST(Invalid_dataspace, Region_conflict, + Out_of_metadata, Invalid_args), + Dataspace_capability, size_t, off_t, bool, Local_addr, bool); + GENODE_RPC(Rpc_detach, void, detach, Local_addr); + GENODE_RPC_THROW(Rpc_add_client, Pager_capability, add_client, + GENODE_TYPE_LIST(Invalid_thread, Out_of_metadata), + Thread_capability); + GENODE_RPC(Rpc_remove_client, void, remove_client, Pager_capability); + GENODE_RPC(Rpc_fault_handler, void, fault_handler, Signal_context_capability); + GENODE_RPC(Rpc_state, State, state); + GENODE_RPC(Rpc_dataspace, Dataspace_capability, dataspace); + + GENODE_RPC_INTERFACE(Rpc_attach, Rpc_detach, Rpc_add_client, + Rpc_remove_client, Rpc_fault_handler, Rpc_state, + Rpc_dataspace); +}; #endif /* _INCLUDE__RM_SESSION__RM_SESSION_H_ */ diff --git a/repos/base/include/rom_session/client.h b/repos/base/include/rom_session/client.h index fc33f5a29..5481575e4 100644 --- a/repos/base/include/rom_session/client.h +++ b/repos/base/include/rom_session/client.h @@ -19,6 +19,7 @@ namespace Genode { struct Rom_session_client; } + struct Genode::Rom_session_client : Rpc_client { explicit Rom_session_client(Rom_session_capability session) diff --git a/repos/base/include/rom_session/connection.h b/repos/base/include/rom_session/connection.h index c01598685..9dd8ae512 100644 --- a/repos/base/include/rom_session/connection.h +++ b/repos/base/include/rom_session/connection.h @@ -18,43 +18,44 @@ #include #include -namespace Genode { +namespace Genode { class Rom_connection; } - class Rom_connection : public Connection, - public Rom_session_client - { - public: - class Rom_connection_failed : public Parent::Exception { }; +class Genode::Rom_connection : public Connection, + public Rom_session_client +{ + public: - private: + class Rom_connection_failed : public Parent::Exception { }; - Rom_session_capability _create_session(const char *module_name, const char *label) - { - try { - return session("ram_quota=4K, filename=\"%s\", label=\"%s\"", - module_name, label ? label: module_name); } - catch (...) { - PERR("Could not open ROM session for module \"%s\"", module_name); - throw Rom_connection_failed(); - } + private: + + Rom_session_capability _create_session(const char *module_name, const char *label) + { + try { + return session("ram_quota=4K, filename=\"%s\", label=\"%s\"", + module_name, label ? label: module_name); } + catch (...) { + PERR("Could not open ROM session for module \"%s\"", module_name); + throw Rom_connection_failed(); } + } - public: + public: - /** - * Constructor - * - * \param filename name of ROM file - * \param label initial session label - * - * \throw Rom_connection_failed - */ - Rom_connection(const char *filename, const char *label = 0) : - Connection(_create_session(filename, label)), - Rom_session_client(cap()) - { } - }; -} + /** + * Constructor + * + * \param module_name name of ROM module + * \param label initial session label + * + * \throw Rom_connection_failed + */ + Rom_connection(const char *module_name, const char *label = 0) + : + Connection(_create_session(module_name, label)), + Rom_session_client(cap()) + { } +}; #endif /* _INCLUDE__ROM_SESSION__CONNECTION_H_ */ diff --git a/repos/base/include/rom_session/rom_session.h b/repos/base/include/rom_session/rom_session.h index 816bc7c66..d5cf419ba 100644 --- a/repos/base/include/rom_session/rom_session.h +++ b/repos/base/include/rom_session/rom_session.h @@ -23,14 +23,16 @@ namespace Genode { - struct Rom_dataspace : Dataspace { }; - + struct Rom_dataspace; struct Rom_session; typedef Capability Rom_dataspace_capability; } +struct Genode::Rom_dataspace : Dataspace { }; + + struct Genode::Rom_session : Session { static const char *service_name() { return "ROM"; } diff --git a/repos/base/include/root/client.h b/repos/base/include/root/client.h index 96b02ee85..41113ecc1 100644 --- a/repos/base/include/root/client.h +++ b/repos/base/include/root/client.h @@ -17,22 +17,22 @@ #include #include -namespace Genode { +namespace Genode { struct Root_client; } - struct Root_client : Rpc_client - { - explicit Root_client(Root_capability root) - : Rpc_client(root) { } - Session_capability session(Session_args const &args, Affinity const &affinity) { - return call(args, affinity); } +struct Genode::Root_client : Rpc_client +{ + explicit Root_client(Root_capability root) + : Rpc_client(root) { } - void upgrade(Session_capability session, Upgrade_args const &args) { - call(session, args); } + Session_capability session(Session_args const &args, Affinity const &affinity) override { + return call(args, affinity); } - void close(Session_capability session) { - call(session); } - }; -} + void upgrade(Session_capability session, Upgrade_args const &args) override { + call(session, args); } + + void close(Session_capability session) override { + call(session); } +}; #endif /* _INCLUDE__ROOT__CLIENT_H_ */ diff --git a/repos/base/include/root/component.h b/repos/base/include/root/component.h index 64d984dcd..7b2d90b37 100644 --- a/repos/base/include/root/component.h +++ b/repos/base/include/root/component.h @@ -26,239 +26,245 @@ namespace Genode { - /** - * Session creation policy for a single-client service - */ - class Single_client - { - private: - - bool _used; - - public: - - Single_client() : _used(0) { } - - void aquire(const char *) - { - if (_used) - throw Root::Unavailable(); - - _used = true; - } - - void release() { _used = false; } - }; - - - /** - * Session-creation policy for a multi-client service - */ - struct Multiple_clients - { - void aquire(const char *) { } - void release() { } - }; - - - /** - * Template for implementing the root interface - * - * \param SESSION_TYPE session-component type to manage, - * derived from 'Rpc_object' - * \param POLICY session-creation policy - * - * The 'POLICY' template parameter allows for constraining the session - * creation to only one instance at a time (using the 'Single_session' - * policy) or multiple instances (using the 'Multiple_sessions' policy). - * - * The 'POLICY' class must provide the following two functions: - * - * :'aquire(const char *args)': is called with the session arguments - * at creation time of each new session. It can therefore implement - * a session-creation policy taking session arguments into account. - * If the policy denies the creation of a new session, it throws - * one of the exceptions defined in the 'Root' interface. - * - * :'release': is called at the destruction time of a session. It enables - * the policy to keep track of and impose restrictions on the number - * of existing sessions. - * - * The default policy 'Multiple_clients' imposes no restrictions on the - * creation of new sessions. - */ - template - class Root_component : public Rpc_object >, private POLICY - { - private: - - /* - * Entry point that manages the session objects - * created by this root interface - */ - Rpc_entrypoint *_ep; - - /* - * Allocator for allocating session objects. - * This allocator must be used by the derived - * class when calling the 'new' operator for - * creating a new session. - */ - Allocator *_md_alloc; - - protected: - - /** - * Create new session (to be implemented by a derived class) - * - * Only a derived class knows the constructor arguments of - * a specific session. Therefore, we cannot unify the call - * of its 'new' operator and must implement the session - * creation at a place, where the required knowledge exist. - * - * In the implementation of this function, the heap, provided - * by 'Root_component' must be used for allocating the session - * object. - * - * If the server implementation does not evaluate the session - * affinity, it suffices to override the overload without the - * affinity argument. - * - * \throw Allocator::Out_of_memory typically caused by the - * meta-data allocator - * \throw Root::Invalid_args typically caused by the - * session-component constructor - */ - virtual SESSION_TYPE *_create_session(const char *args, - Affinity const &) - { - return _create_session(args); - } - - virtual SESSION_TYPE *_create_session(const char *args) - { - throw Root::Invalid_args(); - } - - /** - * Inform session about a quota upgrade - * - * Once a session is created, its client can successively extend - * its quota donation via the 'Parent::transfer_quota' function. - * This will result in the invokation of 'Root::upgrade' at the - * root interface the session was created with. The root interface, - * in turn, informs the session about the new resources via the - * '_upgrade_session' function. The default implementation is - * suited for sessions that use a static amount of resources - * accounted for at session-creation time. For such sessions, an - * upgrade is not useful. However, sessions that dynamically - * allocate resources on behalf of its client, should respond to - * quota upgrades by implementing this function. - * - * \param session session to upgrade - * \param args description of additional resources in the - * same format as used at session creation - */ - virtual void _upgrade_session(SESSION_TYPE *, const char *) { } - - virtual void _destroy_session(SESSION_TYPE *session) { - destroy(_md_alloc, session); } - - /** - * Return allocator to allocate server object in '_create_session()' - */ - Allocator *md_alloc() { return _md_alloc; } - Rpc_entrypoint *ep() { return _ep; } - - public: - - /** - * Constructor - * - * \param ep entry point that manages the sessions of this - * root interface. - * \param ram_session provider of dataspaces for the backing store - * of session objects and session data - */ - Root_component(Rpc_entrypoint *ep, Allocator *metadata_alloc) - : _ep(ep), _md_alloc(metadata_alloc) { } - - - /******************** - ** Root interface ** - ********************/ - - Session_capability session(Root::Session_args const &args, - Affinity const &affinity) - { - if (!args.is_valid_string()) throw Root::Invalid_args(); - - POLICY::aquire(args.string()); - - /* - * We need to decrease 'ram_quota' by - * the size of the session object. - */ - size_t ram_quota = Arg_string::find_arg(args.string(), "ram_quota").long_value(0); - size_t needed = sizeof(SESSION_TYPE) + md_alloc()->overhead(sizeof(SESSION_TYPE)); - - if (needed > ram_quota) { - PERR("Insufficient ram quota, provided=%zu, required=%zu", - ram_quota, needed); - throw Root::Quota_exceeded(); - } - - size_t const remaining_ram_quota = ram_quota - needed; - - /* - * Deduce ram quota needed for allocating the session object from the - * donated ram quota. - * - * XXX the size of the 'adjusted_args' buffer should dependent - * on the message-buffer size and stack size. - */ - enum { MAX_ARGS_LEN = 256 }; - char adjusted_args[MAX_ARGS_LEN]; - strncpy(adjusted_args, args.string(), sizeof(adjusted_args)); - char ram_quota_buf[64]; - snprintf(ram_quota_buf, sizeof(ram_quota_buf), "%zu", - remaining_ram_quota); - Arg_string::set_arg(adjusted_args, sizeof(adjusted_args), - "ram_quota", ram_quota_buf); - - SESSION_TYPE *s = 0; - try { s = _create_session(adjusted_args, affinity); } - catch (Allocator::Out_of_memory) { throw Root::Quota_exceeded(); } - - return _ep->manage(s); - } - - void upgrade(Session_capability session, Root::Upgrade_args const &args) - { - if (!args.is_valid_string()) throw Root::Invalid_args(); - - typedef typename Object_pool::Guard Object_guard; - Object_guard s(_ep->lookup_and_lock(session)); - if (!s) return; - - _upgrade_session(s, args.string()); - } - - void close(Session_capability session) - { - SESSION_TYPE * s = - dynamic_cast(_ep->lookup_and_lock(session)); - if (!s) return; - - /* let the entry point forget the session object */ - _ep->dissolve(s); - - _destroy_session(s); - - POLICY::release(); - return; - } - }; + class Single_client; + class Multiple_clients; + template class Root_component; } + +/** + * Session creation policy for a single-client service + */ +class Genode::Single_client +{ + private: + + bool _used; + + public: + + Single_client() : _used(0) { } + + void aquire(const char *) + { + if (_used) + throw Root::Unavailable(); + + _used = true; + } + + void release() { _used = false; } +}; + + +/** + * Session-creation policy for a multi-client service + */ +struct Genode::Multiple_clients +{ + void aquire(const char *) { } + void release() { } +}; + + +/** + * Template for implementing the root interface + * + * \param SESSION_TYPE session-component type to manage, + * derived from 'Rpc_object' + * \param POLICY session-creation policy + * + * The 'POLICY' template parameter allows for constraining the session + * creation to only one instance at a time (using the 'Single_session' + * policy) or multiple instances (using the 'Multiple_sessions' policy). + * + * The 'POLICY' class must provide the following two functions: + * + * :'aquire(const char *args)': is called with the session arguments + * at creation time of each new session. It can therefore implement + * a session-creation policy taking session arguments into account. + * If the policy denies the creation of a new session, it throws + * one of the exceptions defined in the 'Root' interface. + * + * :'release': is called at the destruction time of a session. It enables + * the policy to keep track of and impose restrictions on the number + * of existing sessions. + * + * The default policy 'Multiple_clients' imposes no restrictions on the + * creation of new sessions. + */ +template +class Genode::Root_component : public Rpc_object >, + private POLICY +{ + private: + + /* + * Entry point that manages the session objects + * created by this root interface + */ + Rpc_entrypoint *_ep; + + /* + * Allocator for allocating session objects. + * This allocator must be used by the derived + * class when calling the 'new' operator for + * creating a new session. + */ + Allocator *_md_alloc; + + protected: + + /** + * Create new session (to be implemented by a derived class) + * + * Only a derived class knows the constructor arguments of + * a specific session. Therefore, we cannot unify the call + * of its 'new' operator and must implement the session + * creation at a place, where the required knowledge exist. + * + * In the implementation of this function, the heap, provided + * by 'Root_component' must be used for allocating the session + * object. + * + * If the server implementation does not evaluate the session + * affinity, it suffices to override the overload without the + * affinity argument. + * + * \throw Allocator::Out_of_memory typically caused by the + * meta-data allocator + * \throw Root::Invalid_args typically caused by the + * session-component constructor + */ + virtual SESSION_TYPE *_create_session(const char *args, + Affinity const &) + { + return _create_session(args); + } + + virtual SESSION_TYPE *_create_session(const char *args) + { + throw Root::Invalid_args(); + } + + /** + * Inform session about a quota upgrade + * + * Once a session is created, its client can successively extend + * its quota donation via the 'Parent::transfer_quota' function. + * This will result in the invokation of 'Root::upgrade' at the + * root interface the session was created with. The root interface, + * in turn, informs the session about the new resources via the + * '_upgrade_session' function. The default implementation is + * suited for sessions that use a static amount of resources + * accounted for at session-creation time. For such sessions, an + * upgrade is not useful. However, sessions that dynamically + * allocate resources on behalf of its client, should respond to + * quota upgrades by implementing this function. + * + * \param session session to upgrade + * \param args description of additional resources in the + * same format as used at session creation + */ + virtual void _upgrade_session(SESSION_TYPE *, const char *) { } + + virtual void _destroy_session(SESSION_TYPE *session) { + destroy(_md_alloc, session); } + + /** + * Return allocator to allocate server object in '_create_session()' + */ + Allocator *md_alloc() { return _md_alloc; } + Rpc_entrypoint *ep() { return _ep; } + + public: + + /** + * Constructor + * + * \param ep entry point that manages the sessions of this + * root interface. + * \param ram_session provider of dataspaces for the backing store + * of session objects and session data + */ + Root_component(Rpc_entrypoint *ep, Allocator *metadata_alloc) + : _ep(ep), _md_alloc(metadata_alloc) { } + + + /******************** + ** Root interface ** + ********************/ + + Session_capability session(Root::Session_args const &args, + Affinity const &affinity) override + { + if (!args.is_valid_string()) throw Root::Invalid_args(); + + POLICY::aquire(args.string()); + + /* + * We need to decrease 'ram_quota' by + * the size of the session object. + */ + size_t ram_quota = Arg_string::find_arg(args.string(), "ram_quota").long_value(0); + size_t needed = sizeof(SESSION_TYPE) + md_alloc()->overhead(sizeof(SESSION_TYPE)); + + if (needed > ram_quota) { + PERR("Insufficient ram quota, provided=%zu, required=%zu", + ram_quota, needed); + throw Root::Quota_exceeded(); + } + + size_t const remaining_ram_quota = ram_quota - needed; + + /* + * Deduce ram quota needed for allocating the session object from the + * donated ram quota. + * + * XXX the size of the 'adjusted_args' buffer should dependent + * on the message-buffer size and stack size. + */ + enum { MAX_ARGS_LEN = 256 }; + char adjusted_args[MAX_ARGS_LEN]; + strncpy(adjusted_args, args.string(), sizeof(adjusted_args)); + char ram_quota_buf[64]; + snprintf(ram_quota_buf, sizeof(ram_quota_buf), "%zu", + remaining_ram_quota); + Arg_string::set_arg(adjusted_args, sizeof(adjusted_args), + "ram_quota", ram_quota_buf); + + SESSION_TYPE *s = 0; + try { s = _create_session(adjusted_args, affinity); } + catch (Allocator::Out_of_memory) { throw Root::Quota_exceeded(); } + + return _ep->manage(s); + } + + void upgrade(Session_capability session, Root::Upgrade_args const &args) override + { + if (!args.is_valid_string()) throw Root::Invalid_args(); + + typedef typename Object_pool::Guard Object_guard; + Object_guard s(_ep->lookup_and_lock(session)); + if (!s) return; + + _upgrade_session(s, args.string()); + } + + void close(Session_capability session) override + { + SESSION_TYPE * s = + dynamic_cast(_ep->lookup_and_lock(session)); + if (!s) return; + + /* let the entry point forget the session object */ + _ep->dissolve(s); + + _destroy_session(s); + + POLICY::release(); + return; + } +}; + #endif /* _INCLUDE__ROOT__COMPONENT_H_ */ diff --git a/repos/base/include/root/root.h b/repos/base/include/root/root.h index f11bf77c4..058fc4cc5 100644 --- a/repos/base/include/root/root.h +++ b/repos/base/include/root/root.h @@ -22,74 +22,78 @@ namespace Genode { - struct Root - { - /********************* - ** Exception types ** - *********************/ - - class Exception : public ::Genode::Exception { }; - class Unavailable : public Exception { }; - class Quota_exceeded : public Exception { }; - class Invalid_args : public Exception { }; - - typedef Rpc_in_buffer<160> Session_args; - typedef Rpc_in_buffer<160> Upgrade_args; - - virtual ~Root() { } - - /** - * Create session - * - * \throw Unavailable - * \throw Quota_exceeded - * \throw Invalid_args - * - * \return capability to new session - */ - virtual Session_capability session(Session_args const &args, - Affinity const &affinity) = 0; - - /** - * Extend resource donation to an existing session - */ - virtual void upgrade(Session_capability session, Upgrade_args const &args) = 0; - - /** - * Close session - */ - virtual void close(Session_capability session) = 0; - - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC_THROW(Rpc_session, Session_capability, session, - GENODE_TYPE_LIST(Unavailable, Quota_exceeded, Invalid_args), - Session_args const &, Affinity const &); - GENODE_RPC_THROW(Rpc_upgrade, void, upgrade, - GENODE_TYPE_LIST(Invalid_args), - Session_capability, Upgrade_args const &); - GENODE_RPC(Rpc_close, void, close, Session_capability); - - GENODE_RPC_INTERFACE(Rpc_session, Rpc_upgrade, Rpc_close); - }; - - - /** - * Root interface supplemented with information about the managed - * session type - * - * This class template is used to automatically propagate the - * correct session type to 'Parent::announce()' when announcing - * a service. - */ - template - struct Typed_root : Root - { - typedef SESSION_TYPE Session_type; - }; + struct Root; + template struct Typed_root; } + +struct Genode::Root +{ + /********************* + ** Exception types ** + *********************/ + + class Exception : public ::Genode::Exception { }; + class Unavailable : public Exception { }; + class Quota_exceeded : public Exception { }; + class Invalid_args : public Exception { }; + + typedef Rpc_in_buffer<160> Session_args; + typedef Rpc_in_buffer<160> Upgrade_args; + + virtual ~Root() { } + + /** + * Create session + * + * \throw Unavailable + * \throw Quota_exceeded + * \throw Invalid_args + * + * \return capability to new session + */ + virtual Session_capability session(Session_args const &args, + Affinity const &affinity) = 0; + + /** + * Extend resource donation to an existing session + */ + virtual void upgrade(Session_capability session, Upgrade_args const &args) = 0; + + /** + * Close session + */ + virtual void close(Session_capability session) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC_THROW(Rpc_session, Session_capability, session, + GENODE_TYPE_LIST(Unavailable, Quota_exceeded, Invalid_args), + Session_args const &, Affinity const &); + GENODE_RPC_THROW(Rpc_upgrade, void, upgrade, + GENODE_TYPE_LIST(Invalid_args), + Session_capability, Upgrade_args const &); + GENODE_RPC(Rpc_close, void, close, Session_capability); + + GENODE_RPC_INTERFACE(Rpc_session, Rpc_upgrade, Rpc_close); +}; + + +/** + * Root interface supplemented with information about the managed + * session type + * + * This class template is used to automatically propagate the + * correct session type to 'Parent::announce()' when announcing + * a service. + */ +template +struct Genode::Typed_root : Root +{ + typedef SESSION_TYPE Session_type; +}; + #endif /* _INCLUDE__ROOT__ROOT_H_ */ diff --git a/repos/base/include/session/session.h b/repos/base/include/session/session.h index 271e47cc0..9f9c44eed 100644 --- a/repos/base/include/session/session.h +++ b/repos/base/include/session/session.h @@ -21,18 +21,17 @@ */ #include -namespace Genode { +namespace Genode { class Session; } - /** - * Base class of session interfaces - * - * Each session interface must implement the function 'service_name' - * ! static const char *service_name(); - * This function returns the name of the service provided via the session - * interface. - */ - class Session { }; -} +/** + * Base class of session interfaces + * + * Each session interface must implement the function 'service_name' + * ! static const char *service_name(); + * This function returns the name of the service provided via the session + * interface. + */ +class Genode::Session { }; #endif /* _INCLUDE__SESSION_H_ */ diff --git a/repos/base/include/signal_session/client.h b/repos/base/include/signal_session/client.h index 258067b50..008fbc09f 100644 --- a/repos/base/include/signal_session/client.h +++ b/repos/base/include/signal_session/client.h @@ -19,25 +19,25 @@ #include #include -namespace Genode { +namespace Genode { struct Signal_session_client; } - struct Signal_session_client : Rpc_client - { - explicit Signal_session_client(Signal_session_capability session) - : Rpc_client(session) { } - Signal_source_capability signal_source() { - return call(); } +struct Genode::Signal_session_client : Rpc_client +{ + explicit Signal_session_client(Signal_session_capability session) + : Rpc_client(session) { } - Signal_context_capability alloc_context(long imprint) { - return call(imprint); } + Signal_source_capability signal_source() override { + return call(); } - void free_context(Signal_context_capability cap) { - call(cap); } + Signal_context_capability alloc_context(long imprint) override { + return call(imprint); } - void submit(Signal_context_capability receiver, unsigned cnt = 1) { - call(receiver, cnt); } - }; -} + void free_context(Signal_context_capability cap) override { + call(cap); } + + void submit(Signal_context_capability receiver, unsigned cnt = 1) override { + call(receiver, cnt); } +}; #endif /* _INCLUDE__CAP_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/signal_session/connection.h b/repos/base/include/signal_session/connection.h index db0971b00..5396493a2 100644 --- a/repos/base/include/signal_session/connection.h +++ b/repos/base/include/signal_session/connection.h @@ -17,16 +17,16 @@ #include #include -namespace Genode { +namespace Genode { struct Signal_connection; } - struct Signal_connection : Connection, Signal_session_client - { - Signal_connection() - : - Connection(session("ram_quota=12K")), - Signal_session_client(cap()) - { } - }; -} + +struct Genode::Signal_connection : Connection, Signal_session_client +{ + Signal_connection() + : + Connection(session("ram_quota=12K")), + Signal_session_client(cap()) + { } +}; #endif /* _INCLUDE__CAP_SESSION__CONNECTION_H_ */ diff --git a/repos/base/include/signal_session/signal_session.h b/repos/base/include/signal_session/signal_session.h index 8b344879a..d71064bbb 100644 --- a/repos/base/include/signal_session/signal_session.h +++ b/repos/base/include/signal_session/signal_session.h @@ -24,75 +24,76 @@ namespace Genode { class Signal_context; class Signal_receiver; - typedef Capability Signal_receiver_capability; typedef Capability Signal_context_capability; typedef Capability Signal_source_capability; - - struct Signal_session : Session - { - static const char *service_name() { return "SIGNAL"; } - - virtual ~Signal_session() { } - - class Out_of_metadata : public Exception { }; - - /** - * Request capability for the signal-source interface - */ - virtual Signal_source_capability signal_source() = 0; - - /** - * Allocate signal context - * - * \param imprint opaque value that gets delivered with signals - * originating from the allocated signal-context - * capability - * \return new signal-context capability - * \throw Out_of_metadata - */ - virtual Signal_context_capability alloc_context(long imprint) = 0; - - /** - * Free signal-context - * - * \param cap capability of signal-context to release - */ - virtual void free_context(Signal_context_capability cap) = 0; - - /** - * Submit signals to the specified signal context - * - * \param context signal destination - * \param cnt number of signals to submit at once - * - * Note that the 'context' argument does not necessarily belong to - * the signal session. Normally, it is a capability obtained from - * a potentially untrusted source. Because we cannot trust this - * capability, signals are not submitted by invoking 'cap' directly - * but by using it as argument to our trusted signal-session - * interface. Otherwise, a potential signal receiver could supply - * a capability with a blocking interface to compromise the - * nonblocking behaviour of the submit function. - */ - virtual void submit(Signal_context_capability context, - unsigned cnt = 1) = 0; - - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC(Rpc_signal_source, Signal_source_capability, signal_source); - GENODE_RPC_THROW(Rpc_alloc_context, Signal_context_capability, alloc_context, - GENODE_TYPE_LIST(Out_of_metadata), long); - GENODE_RPC(Rpc_free_context, void, free_context, Signal_context_capability); - GENODE_RPC(Rpc_submit, void, submit, Signal_context_capability, unsigned); - - GENODE_RPC_INTERFACE(Rpc_submit, Rpc_signal_source, Rpc_alloc_context, - Rpc_free_context); - }; + struct Signal_session; } + +struct Genode::Signal_session : Session +{ + static const char *service_name() { return "SIGNAL"; } + + virtual ~Signal_session() { } + + class Out_of_metadata : public Exception { }; + + /** + * Request capability for the signal-source interface + */ + virtual Signal_source_capability signal_source() = 0; + + /** + * Allocate signal context + * + * \param imprint opaque value that gets delivered with signals + * originating from the allocated signal-context + * capability + * \return new signal-context capability + * \throw Out_of_metadata + */ + virtual Signal_context_capability alloc_context(long imprint) = 0; + + /** + * Free signal-context + * + * \param cap capability of signal-context to release + */ + virtual void free_context(Signal_context_capability cap) = 0; + + /** + * Submit signals to the specified signal context + * + * \param context signal destination + * \param cnt number of signals to submit at once + * + * Note that the 'context' argument does not necessarily belong to + * the signal session. Normally, it is a capability obtained from + * a potentially untrusted source. Because we cannot trust this + * capability, signals are not submitted by invoking 'cap' directly + * but by using it as argument to our trusted signal-session + * interface. Otherwise, a potential signal receiver could supply + * a capability with a blocking interface to compromise the + * nonblocking behaviour of the submit function. + */ + virtual void submit(Signal_context_capability context, + unsigned cnt = 1) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_signal_source, Signal_source_capability, signal_source); + GENODE_RPC_THROW(Rpc_alloc_context, Signal_context_capability, alloc_context, + GENODE_TYPE_LIST(Out_of_metadata), long); + GENODE_RPC(Rpc_free_context, void, free_context, Signal_context_capability); + GENODE_RPC(Rpc_submit, void, submit, Signal_context_capability, unsigned); + + GENODE_RPC_INTERFACE(Rpc_submit, Rpc_signal_source, Rpc_alloc_context, + Rpc_free_context); +}; + #endif /* _INCLUDE__CAP_SESSION__CAP_SESSION_H_ */ diff --git a/repos/base/include/signal_session/source.h b/repos/base/include/signal_session/source.h index b94ea3d2a..5a6e10a9d 100644 --- a/repos/base/include/signal_session/source.h +++ b/repos/base/include/signal_session/source.h @@ -21,55 +21,55 @@ #include -namespace Genode { +namespace Genode { struct Signal_source; } + + +/** + * Blocking part of the signal-session interface + * + * The blocking 'wait_for_signal()' function cannot be part of the + * signal-session interface because otherwise, context allocations or + * signal submissions would not be possible while blocking for signals. + * Therefore, the blocking part is implemented a separate interface, + * which can be used by an independent thread. + */ +struct Genode::Signal_source +{ + class Signal + { + private: + + long _imprint; + int _num; + + public: + + Signal(long imprint, int num) : + _imprint(imprint), + _num(num) + { } + + Signal() : _imprint(0), _num(0) { } + + long imprint() { return _imprint; } + + int num() { return _num; } + }; + + virtual ~Signal_source() { } /** - * Blocking part of the signal-session interface - * - * The blocking 'wait_for_signal()' function cannot be part of the - * signal-session interface because otherwise, context allocations or - * signal submissions would not be possible while blocking for signals. - * Therefore, the blocking part is implemented a separate interface, - * which can be used by an independent thread. + * Wait for signal */ - struct Signal_source - { - class Signal - { - private: - - long _imprint; - int _num; - - public: - - Signal(long imprint, int num) : - _imprint(imprint), - _num(num) - { } - - Signal() : _imprint(0), _num(0) { } - - long imprint() { return _imprint; } - - int num() { return _num; } - }; - - virtual ~Signal_source() { } - - /** - * Wait for signal - */ - virtual Signal wait_for_signal() = 0; + virtual Signal wait_for_signal() = 0; - /********************* - ** RPC declaration ** - *********************/ + /********************* + ** RPC declaration ** + *********************/ - GENODE_RPC(Rpc_wait_for_signal, Signal, wait_for_signal); - GENODE_RPC_INTERFACE(Rpc_wait_for_signal); - }; -} + GENODE_RPC(Rpc_wait_for_signal, Signal, wait_for_signal); + GENODE_RPC_INTERFACE(Rpc_wait_for_signal); +}; #endif /* _INCLUDE__SIGNAL_SESSION__SOURCE_H_ */ diff --git a/repos/base/include/signal_session/source_client.h b/repos/base/include/signal_session/source_client.h index 4cb2a8de1..afdcc1fa4 100644 --- a/repos/base/include/signal_session/source_client.h +++ b/repos/base/include/signal_session/source_client.h @@ -19,15 +19,15 @@ #include #include -namespace Genode { +namespace Genode { struct Signal_source_client; } - struct Signal_source_client : Rpc_client - { - Signal_source_client(Signal_source_capability signal_source) - : Rpc_client(signal_source) { } - Signal wait_for_signal() { return call(); } - }; -} +struct Genode::Signal_source_client : Rpc_client +{ + Signal_source_client(Signal_source_capability signal_source) + : Rpc_client(signal_source) { } + + Signal wait_for_signal() override { return call(); } +}; #endif /* _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_ */ diff --git a/repos/base/include/signal_session/source_rpc_object.h b/repos/base/include/signal_session/source_rpc_object.h index a6bce1a46..b60ff590d 100644 --- a/repos/base/include/signal_session/source_rpc_object.h +++ b/repos/base/include/signal_session/source_rpc_object.h @@ -21,8 +21,8 @@ #include #include -namespace Genode { - struct Signal_source_rpc_object : Rpc_object { }; -} +namespace Genode { struct Signal_source_rpc_object; } + +struct Genode::Signal_source_rpc_object : Rpc_object { }; #endif /* _INCLUDE__SIGNAL_SESSION__SOURCE_RPC_OBJECT_H_ */ diff --git a/repos/base/include/trace_session/client.h b/repos/base/include/trace_session/client.h index a37b45b5f..b8882e700 100644 --- a/repos/base/include/trace_session/client.h +++ b/repos/base/include/trace_session/client.h @@ -71,35 +71,35 @@ struct Genode::Trace::Session_client : Genode::Rpc_client(size); } - Dataspace_capability policy(Policy_id policy_id) { + Dataspace_capability policy(Policy_id policy_id) override { return call(policy_id); } - void unload_policy(Policy_id policy_id) { + void unload_policy(Policy_id policy_id) override { call(policy_id); } - void trace(Subject_id s, Policy_id p, size_t buffer_size) { + void trace(Subject_id s, Policy_id p, size_t buffer_size) override { call(s, p, buffer_size); } void rule(Session_label const &label, Thread_name const &thread, - Policy_id policy, size_t buffer_size) { + Policy_id policy, size_t buffer_size) override { call(label, thread, policy, buffer_size); } - void pause(Subject_id subject) { + void pause(Subject_id subject) override { call(subject); } - void resume(Subject_id subject) { + void resume(Subject_id subject) override { call(subject); } - Subject_info subject_info(Subject_id subject) { + Subject_info subject_info(Subject_id subject) override { return call(subject); } - Dataspace_capability buffer(Subject_id subject) { + Dataspace_capability buffer(Subject_id subject) override { return call(subject); } - void free(Subject_id subject) { + void free(Subject_id subject) override { call(subject); } }; diff --git a/repos/base/include/trace_session/connection.h b/repos/base/include/trace_session/connection.h index 9afe6bb46..b1a5a6a26 100644 --- a/repos/base/include/trace_session/connection.h +++ b/repos/base/include/trace_session/connection.h @@ -19,6 +19,7 @@ namespace Genode { namespace Trace { struct Connection; } } + struct Genode::Trace::Connection : Genode::Connection, Genode::Trace::Session_client { diff --git a/repos/base/include/util/arg_string.h b/repos/base/include/util/arg_string.h index 27d4be7d1..312a197e8 100644 --- a/repos/base/include/util/arg_string.h +++ b/repos/base/include/util/arg_string.h @@ -34,292 +34,294 @@ namespace Genode { class Arg_string; - - class Arg - { - /** - * Define tokenizer used for argument-string parsing - * - * Argument-string tokens accept C-style identifiers. - */ - typedef ::Genode::Token Token; - - friend class Arg_string; - - private: - - Token _key; - Token _value; - - /** - * Return long value of argument - * - * \param out_value argument converted to unsigned long value - * \param out_sign 1 if positive; -1 if negative - * \return true if no syntactic anomaly occured - * - * This function handles the numberic modifiers G (2^30), - * M (2^20), and K (2^10). - */ - bool read_ulong(unsigned long *out_value, int *out_sign) const - { - Token t = _value; - - /* check for sign; default is positive */ - *out_sign = 1; - if (t[0] == '+') - t = t.next(); - else if (t[0] == '-') { - *out_sign = -1; - t = t.next(); - } - - /* stop if token after sign is no number */ - if (t.type() != Token::NUMBER) - return false; - - /* read numeric value and skip the corresponding tokens */ - Number_of_bytes value; - size_t n = ascii_to(t.start(), &value); - - if (n == 0) - return false; - - t = Token(t.start() + n); - *out_value = value; - - /* check for strange characters at the end of the number */ - t = t.eat_whitespace(); - if (t && (t[0] != ',')) return false; - - return true; - } - - public: - - /** - * Construct argument from Token(s) - */ - Arg(Token t = Token()) : _key(t), _value(0) - { - for (; t && (t[0] != ','); t = t.next().eat_whitespace()) - if (t[0] == '=') { - _value = t.next().eat_whitespace(); - break; - } - } - - inline bool valid() const { return _key; } - - unsigned long ulong_value(unsigned long default_value) const - { - unsigned long value = 0; - int sign = 1; - - bool valid = read_ulong(&value, &sign); - if (sign < 0) - return default_value; - - return valid ? value : default_value; - } - - long long_value(long default_value) const - { - unsigned long value = 0; - int sign = 1; - - bool valid = read_ulong(&value, &sign); - - /* FIXME we should check for overflows here! */ - return valid ? sign*value : default_value; - } - - bool bool_value(bool default_value) const - { - /* check for known idents */ - if (_value.type() == Token::IDENT) { - char *p = _value.start(); - size_t l = _value.len(); - - if (!strcmp(p, "yes", l)) return true; - if (!strcmp(p, "true", l)) return true; - if (!strcmp(p, "on", l)) return true; - - if (!strcmp(p, "no", l)) return false; - if (!strcmp(p, "false", l)) return false; - if (!strcmp(p, "off", l)) return false; - - /* saxony mode ;) */ - if (!strcmp(p, "nu", l)) return true; - if (!strcmp(p, "nee", l)) return false; - - return default_value; - } - - /* read values 0 (false) / !0 (true) */ - unsigned long value; - int sign; - bool valid = read_ulong(&value, &sign); - - return valid ? value : default_value; - } - - void key(char *dst, size_t dst_len) const - { - _key.string(dst, dst_len); - } - - void string(char *dst, size_t dst_len, const char *default_string) const - { - /* check for one-word string w/o quotes */ - if (_value.type() == Token::IDENT) { - size_t len = min(dst_len - 1, _value.len()); - memcpy(dst, _value.start(), len); - dst[len] = 0; - return; - } - - /* stop here if _value is not a string */ - if (_value.type() != Token::STRING) { - strncpy(dst, default_string, dst_len); - return; - } - - /* unpack string to dst */ - size_t num_chars = min(dst_len - 1, _value.len()); - unpack_string(_value.start(), dst, num_chars); - } - }; - - - class Arg_string - { - typedef Arg::Token Token; - - private: - - static Token _next_key(Token t) - { - for (; t; t = t.next().eat_whitespace()) - - /* if we find a comma, return token after comma */ - if (t[0] == ',') return t.next().eat_whitespace(); - - return Token(); - } - - /** - * Find key token in argument string - */ - static Token _find_key(const char *args, const char *key) - { - for (Token t(args); t; t = _next_key(t)) - - /* check if key matches */ - if ((t.type() == Token::IDENT) && !strcmp(key, t.start(), t.len())) - return t; - - return Token(); - } - - /** - * Append source string to destination string - * - * NOTE: check string length before calling this function! - * - * \return last character of result string - */ - static char *_append(char *dst, const char *src) - { - unsigned src_len = strlen(src); - while (*dst) dst++; - memcpy(dst, src, src_len + 1); - return dst + src_len; - } - - public: - - /** - * Find argument by its key - */ - static Arg find_arg(const char *args, const char *key) { - return (args && key) ? Arg(_find_key(args, key)) : Arg(); } - - static Arg first_arg(const char *args) { - return Arg(Token(args)); } - - /** - * Remove argument with the specified key - */ - static bool remove_arg(char *args, const char *key) - { - if (!args || !key) return false; - - Token beg = _find_key(args, key); - Token next = _next_key(beg); - - /* no such key to remove - we are done */ - if (!beg) return true; - - /* if argument is the last one, null-terminate string right here */ - if (!next) { - - /* eat all pending whitespaces at the end of the string */ - char *s = max(beg.start() - 1, args); - while (s > args && (*s == ' ')) s--; - - /* write string-terminating zero */ - *s = 0; - } else - memcpy(beg.start(), next.start(), strlen(next.start()) + 1); - - return true; - } - - /** - * Add new argument - */ - static bool add_arg(char *args, unsigned args_len, - const char *key, const char *value) - { - if (!args || !key || !value) return false; - - unsigned old_len = strlen(args); - - /* check if args string has enough capacity */ - if (old_len + strlen(key) + strlen(value) + 2 > args_len) - return false; - - args += old_len; - - if (old_len) - args = _append(args, ", "); - - _append(_append(_append(args, key), "="), value); - return true; - } - - /** - * Assign new value to argument - */ - static bool set_arg(char *args, unsigned args_len, - const char *key, const char *value) - { - return remove_arg(args, key) && add_arg(args, args_len, key, value); - } - - /** - * Assign new integer argument - */ - static bool set_arg(char *args, unsigned args_len, - const char *key, int value) - { - enum { STRING_LONG_MAX = 32 }; - char buf[STRING_LONG_MAX]; - snprintf(buf, sizeof(buf), "%d", value); - return remove_arg(args, key) && add_arg(args, args_len, key, buf); - } - }; + class Arg; } + +class Genode::Arg +{ + /** + * Define tokenizer used for argument-string parsing + * + * Argument-string tokens accept C-style identifiers. + */ + typedef ::Genode::Token Token; + + friend class Arg_string; + + private: + + Token _key; + Token _value; + + /** + * Return long value of argument + * + * \param out_value argument converted to unsigned long value + * \param out_sign 1 if positive; -1 if negative + * \return true if no syntactic anomaly occured + * + * This function handles the numberic modifiers G (2^30), + * M (2^20), and K (2^10). + */ + bool read_ulong(unsigned long *out_value, int *out_sign) const + { + Token t = _value; + + /* check for sign; default is positive */ + *out_sign = 1; + if (t[0] == '+') + t = t.next(); + else if (t[0] == '-') { + *out_sign = -1; + t = t.next(); + } + + /* stop if token after sign is no number */ + if (t.type() != Token::NUMBER) + return false; + + /* read numeric value and skip the corresponding tokens */ + Number_of_bytes value; + size_t n = ascii_to(t.start(), &value); + + if (n == 0) + return false; + + t = Token(t.start() + n); + *out_value = value; + + /* check for strange characters at the end of the number */ + t = t.eat_whitespace(); + if (t && (t[0] != ',')) return false; + + return true; + } + + public: + + /** + * Construct argument from Token(s) + */ + Arg(Token t = Token()) : _key(t), _value(0) + { + for (; t && (t[0] != ','); t = t.next().eat_whitespace()) + if (t[0] == '=') { + _value = t.next().eat_whitespace(); + break; + } + } + + inline bool valid() const { return _key; } + + unsigned long ulong_value(unsigned long default_value) const + { + unsigned long value = 0; + int sign = 1; + + bool valid = read_ulong(&value, &sign); + if (sign < 0) + return default_value; + + return valid ? value : default_value; + } + + long long_value(long default_value) const + { + unsigned long value = 0; + int sign = 1; + + bool valid = read_ulong(&value, &sign); + + /* FIXME we should check for overflows here! */ + return valid ? sign*value : default_value; + } + + bool bool_value(bool default_value) const + { + /* check for known idents */ + if (_value.type() == Token::IDENT) { + char *p = _value.start(); + size_t l = _value.len(); + + if (!strcmp(p, "yes", l)) return true; + if (!strcmp(p, "true", l)) return true; + if (!strcmp(p, "on", l)) return true; + + if (!strcmp(p, "no", l)) return false; + if (!strcmp(p, "false", l)) return false; + if (!strcmp(p, "off", l)) return false; + + /* saxony mode ;) */ + if (!strcmp(p, "nu", l)) return true; + if (!strcmp(p, "nee", l)) return false; + + return default_value; + } + + /* read values 0 (false) / !0 (true) */ + unsigned long value; + int sign; + bool valid = read_ulong(&value, &sign); + + return valid ? value : default_value; + } + + void key(char *dst, size_t dst_len) const + { + _key.string(dst, dst_len); + } + + void string(char *dst, size_t dst_len, const char *default_string) const + { + /* check for one-word string w/o quotes */ + if (_value.type() == Token::IDENT) { + size_t len = min(dst_len - 1, _value.len()); + memcpy(dst, _value.start(), len); + dst[len] = 0; + return; + } + + /* stop here if _value is not a string */ + if (_value.type() != Token::STRING) { + strncpy(dst, default_string, dst_len); + return; + } + + /* unpack string to dst */ + size_t num_chars = min(dst_len - 1, _value.len()); + unpack_string(_value.start(), dst, num_chars); + } +}; + + +class Genode::Arg_string +{ + typedef Arg::Token Token; + + private: + + static Token _next_key(Token t) + { + for (; t; t = t.next().eat_whitespace()) + + /* if we find a comma, return token after comma */ + if (t[0] == ',') return t.next().eat_whitespace(); + + return Token(); + } + + /** + * Find key token in argument string + */ + static Token _find_key(const char *args, const char *key) + { + for (Token t(args); t; t = _next_key(t)) + + /* check if key matches */ + if ((t.type() == Token::IDENT) && !strcmp(key, t.start(), t.len())) + return t; + + return Token(); + } + + /** + * Append source string to destination string + * + * NOTE: check string length before calling this function! + * + * \return last character of result string + */ + static char *_append(char *dst, const char *src) + { + unsigned src_len = strlen(src); + while (*dst) dst++; + memcpy(dst, src, src_len + 1); + return dst + src_len; + } + + public: + + /** + * Find argument by its key + */ + static Arg find_arg(const char *args, const char *key) { + return (args && key) ? Arg(_find_key(args, key)) : Arg(); } + + static Arg first_arg(const char *args) { + return Arg(Token(args)); } + + /** + * Remove argument with the specified key + */ + static bool remove_arg(char *args, const char *key) + { + if (!args || !key) return false; + + Token beg = _find_key(args, key); + Token next = _next_key(beg); + + /* no such key to remove - we are done */ + if (!beg) return true; + + /* if argument is the last one, null-terminate string right here */ + if (!next) { + + /* eat all pending whitespaces at the end of the string */ + char *s = max(beg.start() - 1, args); + while (s > args && (*s == ' ')) s--; + + /* write string-terminating zero */ + *s = 0; + } else + memcpy(beg.start(), next.start(), strlen(next.start()) + 1); + + return true; + } + + /** + * Add new argument + */ + static bool add_arg(char *args, unsigned args_len, + const char *key, const char *value) + { + if (!args || !key || !value) return false; + + unsigned old_len = strlen(args); + + /* check if args string has enough capacity */ + if (old_len + strlen(key) + strlen(value) + 2 > args_len) + return false; + + args += old_len; + + if (old_len) + args = _append(args, ", "); + + _append(_append(_append(args, key), "="), value); + return true; + } + + /** + * Assign new value to argument + */ + static bool set_arg(char *args, unsigned args_len, + const char *key, const char *value) + { + return remove_arg(args, key) && add_arg(args, args_len, key, value); + } + + /** + * Assign new integer argument + */ + static bool set_arg(char *args, unsigned args_len, + const char *key, int value) + { + enum { STRING_LONG_MAX = 32 }; + char buf[STRING_LONG_MAX]; + snprintf(buf, sizeof(buf), "%d", value); + return remove_arg(args, key) && add_arg(args, args_len, key, buf); + } +}; + #endif /* _INCLUDE__UTIL__ARG_STRING_H_ */ diff --git a/repos/base/include/util/avl_string.h b/repos/base/include/util/avl_string.h index 344cfca5d..b49eae49d 100644 --- a/repos/base/include/util/avl_string.h +++ b/repos/base/include/util/avl_string.h @@ -18,60 +18,64 @@ #include namespace Genode { - - class Avl_string_base : public Avl_node - { - private: - - const char *_str; - - protected: - - Avl_string_base(const char *str) : _str(str) { } - - public: - - const char *name() const { return _str; } - - - /************************ - ** Avl node interface ** - ************************/ - - bool higher(Avl_string_base *c) { return (strcmp(c->_str, _str) > 0); } - - /** - * Find by name - */ - Avl_string_base *find_by_name(const char *name) - { - if (strcmp(name, _str) == 0) return this; - - Avl_string_base *c = Avl_node::child(strcmp(name, _str) > 0); - return c ? c->find_by_name(name) : 0; - } - }; - - - /* - * The template pumps up the Avl_string_base object and - * provides the buffer for the actual string. - */ - template - class Avl_string : public Avl_string_base - { - private: - - char _str_buf[STR_LEN]; - - public: - - Avl_string(const char *str) : Avl_string_base(_str_buf) - { - strncpy(_str_buf, str, sizeof(_str_buf)); - _str_buf[STR_LEN - 1] = 0; - } - }; + + class Avl_string_base; + template class Avl_string; } + +class Genode::Avl_string_base : public Avl_node +{ + private: + + const char *_str; + + protected: + + Avl_string_base(const char *str) : _str(str) { } + + public: + + const char *name() const { return _str; } + + + /************************ + ** Avl node interface ** + ************************/ + + bool higher(Avl_string_base *c) { return (strcmp(c->_str, _str) > 0); } + + /** + * Find by name + */ + Avl_string_base *find_by_name(const char *name) + { + if (strcmp(name, _str) == 0) return this; + + Avl_string_base *c = Avl_node::child(strcmp(name, _str) > 0); + return c ? c->find_by_name(name) : 0; + } +}; + + +/* + * The template pumps up the Avl_string_base object and provides the buffer for + * the actual string. + */ +template +class Genode::Avl_string : public Avl_string_base +{ + private: + + char _str_buf[STR_LEN]; + + public: + + Avl_string(const char *str) : Avl_string_base(_str_buf) + { + strncpy(_str_buf, str, sizeof(_str_buf)); + _str_buf[STR_LEN - 1] = 0; + } +}; + #endif /* _INCLUDE__UTIL__AVL_STRING_H_ */ diff --git a/repos/base/include/util/avl_tree.h b/repos/base/include/util/avl_tree.h index efb934a83..9fe409ced 100644 --- a/repos/base/include/util/avl_tree.h +++ b/repos/base/include/util/avl_tree.h @@ -17,187 +17,192 @@ #include namespace Genode { - - class Avl_node_base - { - protected: - - /** - * Internal policy interface - * - * The implementation of this interface is provided by the AVL tree. - */ - struct Policy - { - virtual ~Policy() { } - - /** - * Compare two nodes - * - * \retval false if n2 is lower than n1 - * \retval true if n2 is higher than or equal to n1 - * - * This function must be provided by the derived class. - * It determines the order of nodes inside the avl tree. - */ - virtual bool higher(Avl_node_base *n1, Avl_node_base *n2) const = 0; - - /** - * Node recomputation hook - * - * If a node gets rearranged, this function is called. - * It can be used to update avl-tree-position dependent - * meta data. - */ - virtual void recompute(Avl_node_base *) { } - }; - - Avl_node_base *_child[2]; /* left and right subtrees */ - Avl_node_base *_parent; /* parent of subtree */ - unsigned char _depth; /* depth of subtree */ - - public: - - typedef bool Side; - - enum { LEFT = false, RIGHT = true }; - - private: - - /** - * Determine depth of subtree - */ - inline int _child_depth(Side i) { - return _child[i] ? _child[i]->_depth : 0; } - - /** - * Update depth of node - */ - void _recompute_depth(Policy &policy); - - /** - * Determine left-right bias of both subtrees - */ - inline Side _bias() { - return (_child_depth(RIGHT) > _child_depth(LEFT)); } - - /** - * Insert subtree into specified side of the node - */ - void _adopt(Avl_node_base *node, Side i, Policy &policy); - - /** - * Rotate subtree - * - * \param side direction of rotate operation - * \param node subtree to rotate - * - * The local node_* variable names describe node locations for - * the left (default) rotation. For example, node_r_l is the - * left of the right of node. - */ - void _rotate_subtree(Avl_node_base *node, Side side, Policy &policy); - - /** - * Rebalance subtree - * - * \param node immediate child that needs balancing - * - * 'this' is parent of the subtree to rebalance - */ - void _rebalance_subtree(Avl_node_base *node, Policy &policy); - - public: - - /** - * Constructor - */ - Avl_node_base(); - - /** - * Insert new node into subtree - */ - void insert(Avl_node_base *node, Policy &policy); - - /** - * Remove node from tree - */ - void remove(Policy &policy); - }; - - - /** - * AVL node - * - * \param NT type of the class derived from 'Avl_node' - * - * Each object to be stored in the avl tree must be derived from - * 'Avl_node'. The type of the derived class is to be specified as - * template argument to enable 'Avl_node' to call virtual functions - * specific for the derived class. - */ - template - class Avl_node : public Avl_node_base - { - public: - - inline NT *child(Side i) const { return static_cast(_child[i]); } - - /** - * Default policy - */ - void recompute() { } - }; - - - /** - * Root node of the AVL tree - * - * The real nodes are always attached at the left branch of - * this root node. - */ - template - class Avl_tree : Avl_node - { - private: - - /** - * Auto-generated policy class specific for NT - */ - class Policy : public Avl_node_base::Policy - { - bool higher(Avl_node_base *n1, Avl_node_base *n2) const - { - return static_cast(n1)->higher(static_cast(n2)); - } - - void recompute(Avl_node_base *node) - { - static_cast(node)->recompute(); - } - - } _policy; - - public: - - /** - * Insert node into AVL tree - */ - void insert(Avl_node *node) { Avl_node_base::insert(node, _policy); } - - /** - * Remove node from AVL tree - */ - void remove(Avl_node *node) { node->remove(_policy); } - - /** - * Request first node of the tree - * - * \return first node - * \retval NULL if tree is empty - */ - inline NT *first() const { return this->child(Avl_node::LEFT); } - }; + + class Avl_node_base; + template class Avl_node; + template class Avl_tree; } + +class Genode::Avl_node_base +{ + protected: + + /** + * Internal policy interface + * + * The implementation of this interface is provided by the AVL tree. + */ + struct Policy + { + virtual ~Policy() { } + + /** + * Compare two nodes + * + * \retval false if n2 is lower than n1 + * \retval true if n2 is higher than or equal to n1 + * + * This function must be provided by the derived class. + * It determines the order of nodes inside the avl tree. + */ + virtual bool higher(Avl_node_base *n1, Avl_node_base *n2) const = 0; + + /** + * Node recomputation hook + * + * If a node gets rearranged, this function is called. + * It can be used to update avl-tree-position dependent + * meta data. + */ + virtual void recompute(Avl_node_base *) { } + }; + + Avl_node_base *_child[2]; /* left and right subtrees */ + Avl_node_base *_parent; /* parent of subtree */ + unsigned char _depth; /* depth of subtree */ + + public: + + typedef bool Side; + + enum { LEFT = false, RIGHT = true }; + + private: + + /** + * Determine depth of subtree + */ + inline int _child_depth(Side i) { + return _child[i] ? _child[i]->_depth : 0; } + + /** + * Update depth of node + */ + void _recompute_depth(Policy &policy); + + /** + * Determine left-right bias of both subtrees + */ + inline Side _bias() { + return (_child_depth(RIGHT) > _child_depth(LEFT)); } + + /** + * Insert subtree into specified side of the node + */ + void _adopt(Avl_node_base *node, Side i, Policy &policy); + + /** + * Rotate subtree + * + * \param side direction of rotate operation + * \param node subtree to rotate + * + * The local node_* variable names describe node locations for + * the left (default) rotation. For example, node_r_l is the + * left of the right of node. + */ + void _rotate_subtree(Avl_node_base *node, Side side, Policy &policy); + + /** + * Rebalance subtree + * + * \param node immediate child that needs balancing + * + * 'this' is parent of the subtree to rebalance + */ + void _rebalance_subtree(Avl_node_base *node, Policy &policy); + + public: + + /** + * Constructor + */ + Avl_node_base(); + + /** + * Insert new node into subtree + */ + void insert(Avl_node_base *node, Policy &policy); + + /** + * Remove node from tree + */ + void remove(Policy &policy); +}; + + +/** + * AVL node + * + * \param NT type of the class derived from 'Avl_node' + * + * Each object to be stored in the avl tree must be derived from + * 'Avl_node'. The type of the derived class is to be specified as + * template argument to enable 'Avl_node' to call virtual functions + * specific for the derived class. + */ +template +class Genode::Avl_node : public Avl_node_base +{ + public: + + inline NT *child(Side i) const { return static_cast(_child[i]); } + + /** + * Default policy + */ + void recompute() { } +}; + + +/** + * Root node of the AVL tree + * + * The real nodes are always attached at the left branch of + * this root node. + */ +template +class Genode::Avl_tree : Avl_node +{ + private: + + /** + * Auto-generated policy class specific for NT + */ + class Policy : public Avl_node_base::Policy + { + bool higher(Avl_node_base *n1, Avl_node_base *n2) const + { + return static_cast(n1)->higher(static_cast(n2)); + } + + void recompute(Avl_node_base *node) + { + static_cast(node)->recompute(); + } + + } _policy; + + public: + + /** + * Insert node into AVL tree + */ + void insert(Avl_node *node) { Avl_node_base::insert(node, _policy); } + + /** + * Remove node from AVL tree + */ + void remove(Avl_node *node) { node->remove(_policy); } + + /** + * Request first node of the tree + * + * \return first node + * \retval NULL if tree is empty + */ + inline NT *first() const { return this->child(Avl_node::LEFT); } +}; + #endif /* _INCLUDE__UTIL__AVL_TREE_H_ */ diff --git a/repos/base/include/util/bit_allocator.h b/repos/base/include/util/bit_allocator.h index d97ea8bbc..559eec906 100644 --- a/repos/base/include/util/bit_allocator.h +++ b/repos/base/include/util/bit_allocator.h @@ -17,60 +17,61 @@ #include -namespace Genode { +namespace Genode { template class Bit_allocator; } - template - class Bit_allocator - { - protected: - addr_t _next; - Bit_array _array; +template +class Genode::Bit_allocator +{ + protected: - void _reserve(addr_t bit_start, size_t const num) - { - if (!num) return; + addr_t _next; + Bit_array _array; - _array.set(bit_start, num); - } + void _reserve(addr_t bit_start, size_t const num) + { + if (!num) return; - public: + _array.set(bit_start, num); + } - class Out_of_indices : Exception {}; + public: - Bit_allocator() : _next(0) { } + class Out_of_indices : Exception {}; - addr_t alloc(size_t const num_log2 = 0) - { - addr_t const step = 1UL << num_log2; - addr_t max = ~0UL; + Bit_allocator() : _next(0) { } - do { - try { - /* throws exception if array is accessed outside bounds */ - for (addr_t i = _next & ~(step - 1); i < max; i += step) { - if (_array.get(i, step)) - continue; + addr_t alloc(size_t const num_log2 = 0) + { + addr_t const step = 1UL << num_log2; + addr_t max = ~0UL; - _array.set(i, step); - _next = i + step; - return i; - } - } catch (typename Bit_array::Invalid_index_access) { } + do { + try { + /* throws exception if array is accessed outside bounds */ + for (addr_t i = _next & ~(step - 1); i < max; i += step) { + if (_array.get(i, step)) + continue; - max = _next; - _next = 0; + _array.set(i, step); + _next = i + step; + return i; + } + } catch (typename Bit_array::Invalid_index_access) { } - } while (max != 0); + max = _next; + _next = 0; - throw Out_of_indices(); - } + } while (max != 0); + + throw Out_of_indices(); + } + + void free(addr_t const bit_start, size_t const num_log2 = 0) + { + _array.clear(bit_start, 1UL << num_log2); + _next = bit_start; + } +}; - void free(addr_t const bit_start, size_t const num_log2 = 0) - { - _array.clear(bit_start, 1UL << num_log2); - _next = bit_start; - } - }; -} #endif /* _INCLUDE__UTIL__BIT_ALLOCATOR_H_ */ diff --git a/repos/base/include/util/bit_array.h b/repos/base/include/util/bit_array.h index fe4ef72fe..92398e6ea 100644 --- a/repos/base/include/util/bit_array.h +++ b/repos/base/include/util/bit_array.h @@ -20,132 +20,136 @@ #include namespace Genode { - - class Bit_array_base - { - public: - - class Invalid_bit_count : public Exception {}; - class Invalid_index_access : public Exception {}; - class Invalid_clear : public Exception {}; - class Invalid_set : public Exception {}; - - protected: - - static constexpr size_t _BITS_PER_BYTE = 8UL; - static constexpr size_t _BITS_PER_WORD = sizeof(addr_t) * - _BITS_PER_BYTE; - - private: - - unsigned _bit_cnt; - unsigned _word_cnt; - addr_t *_words; - - addr_t _word(addr_t index) const { - return index / _BITS_PER_WORD; } - - void _check_range(addr_t const index, - addr_t const width) const - { - if ((index >= _word_cnt * _BITS_PER_WORD) || - width > _word_cnt * _BITS_PER_WORD || - _word_cnt * _BITS_PER_WORD - width < index) - throw Invalid_index_access(); - } - - addr_t _mask(addr_t const index, addr_t const width, - addr_t &rest) const - { - addr_t const shift = index - _word(index) * _BITS_PER_WORD; - - rest = width + shift > _BITS_PER_WORD ? - width + shift - _BITS_PER_WORD : 0; - - return (width >= _BITS_PER_WORD) ? ~0UL << shift - : ((1UL << width) - 1) << shift; - } - - void _set(addr_t index, addr_t width, bool free) - { - _check_range(index, width); - - addr_t rest, word, mask; - do { - word = _word(index); - mask = _mask(index, width, rest); - - if (free) { - if ((_words[word] & mask) != mask) - throw Invalid_clear(); - _words[word] &= ~mask; - } else { - if (_words[word] & mask) - throw Invalid_set(); - _words[word] |= mask; - } - - index = (_word(index) + 1) * _BITS_PER_WORD; - width = rest; - } while (rest); - } - - public: - - Bit_array_base(unsigned bits, addr_t *addr, bool clear) - : _bit_cnt(bits), - _word_cnt(_bit_cnt / _BITS_PER_WORD), - _words(addr) - { - if (!bits || bits % _BITS_PER_WORD) throw Invalid_bit_count(); - - if (clear) memset(_words, 0, sizeof(addr_t)*_word_cnt); - } - - /** - * Return true if at least one bit is set between - * index until index + width - 1 - */ - bool get(addr_t index, addr_t width) const - { - _check_range(index, width); - - bool used = false; - addr_t rest, mask; - do { - mask = _mask(index, width, rest); - used = _words[_word(index)] & mask; - index = (_word(index) + 1) * _BITS_PER_WORD; - width = rest; - } while (!used && rest); - - return used; - } - - void set(addr_t const index, addr_t const width) { - _set(index, width, false); } - - void clear(addr_t const index, addr_t const width) { - _set(index, width, true); } - }; - - - template - class Bit_array : public Bit_array_base - { - private: - - static constexpr size_t _WORDS = BITS / _BITS_PER_WORD; - - static_assert(BITS % _BITS_PER_WORD == 0, - "Count of bits need to be word aligned!"); - - addr_t _array[_WORDS]; - - public: - - Bit_array() : Bit_array_base(BITS, _array, true) { } - }; - + + class Bit_array_base; + template class Bit_array; } + + +class Genode::Bit_array_base +{ + public: + + class Invalid_bit_count : public Exception {}; + class Invalid_index_access : public Exception {}; + class Invalid_clear : public Exception {}; + class Invalid_set : public Exception {}; + + protected: + + static constexpr size_t _BITS_PER_BYTE = 8UL; + static constexpr size_t _BITS_PER_WORD = sizeof(addr_t) * + _BITS_PER_BYTE; + + private: + + unsigned _bit_cnt; + unsigned _word_cnt; + addr_t *_words; + + addr_t _word(addr_t index) const { + return index / _BITS_PER_WORD; } + + void _check_range(addr_t const index, + addr_t const width) const + { + if ((index >= _word_cnt * _BITS_PER_WORD) || + width > _word_cnt * _BITS_PER_WORD || + _word_cnt * _BITS_PER_WORD - width < index) + throw Invalid_index_access(); + } + + addr_t _mask(addr_t const index, addr_t const width, + addr_t &rest) const + { + addr_t const shift = index - _word(index) * _BITS_PER_WORD; + + rest = width + shift > _BITS_PER_WORD ? + width + shift - _BITS_PER_WORD : 0; + + return (width >= _BITS_PER_WORD) ? ~0UL << shift + : ((1UL << width) - 1) << shift; + } + + void _set(addr_t index, addr_t width, bool free) + { + _check_range(index, width); + + addr_t rest, word, mask; + do { + word = _word(index); + mask = _mask(index, width, rest); + + if (free) { + if ((_words[word] & mask) != mask) + throw Invalid_clear(); + _words[word] &= ~mask; + } else { + if (_words[word] & mask) + throw Invalid_set(); + _words[word] |= mask; + } + + index = (_word(index) + 1) * _BITS_PER_WORD; + width = rest; + } while (rest); + } + + public: + + Bit_array_base(unsigned bits, addr_t *addr, bool clear) + : _bit_cnt(bits), + _word_cnt(_bit_cnt / _BITS_PER_WORD), + _words(addr) + { + if (!bits || bits % _BITS_PER_WORD) throw Invalid_bit_count(); + + if (clear) memset(_words, 0, sizeof(addr_t)*_word_cnt); + } + + /** + * Return true if at least one bit is set between + * index until index + width - 1 + */ + bool get(addr_t index, addr_t width) const + { + _check_range(index, width); + + bool used = false; + addr_t rest, mask; + do { + mask = _mask(index, width, rest); + used = _words[_word(index)] & mask; + index = (_word(index) + 1) * _BITS_PER_WORD; + width = rest; + } while (!used && rest); + + return used; + } + + void set(addr_t const index, addr_t const width) { + _set(index, width, false); } + + void clear(addr_t const index, addr_t const width) { + _set(index, width, true); } +}; + + +template +class Genode::Bit_array : public Bit_array_base +{ + private: + + static constexpr size_t _WORDS = BITS / _BITS_PER_WORD; + + static_assert(BITS % _BITS_PER_WORD == 0, + "Count of bits need to be word aligned!"); + + addr_t _array[_WORDS]; + + public: + + Bit_array() : Bit_array_base(BITS, _array, true) { } +}; + #endif /* _INCLUDE__UTIL__BIT_ARRAY_H_ */ diff --git a/repos/base/include/util/construct_at.h b/repos/base/include/util/construct_at.h index 57e83d2b4..b0fb48f73 100644 --- a/repos/base/include/util/construct_at.h +++ b/repos/base/include/util/construct_at.h @@ -18,6 +18,7 @@ #include namespace Genode { + template static inline T *construct_at(void *, ARGS &&...); } diff --git a/repos/base/include/util/fifo.h b/repos/base/include/util/fifo.h index 79302defd..a5819a875 100644 --- a/repos/base/include/util/fifo.h +++ b/repos/base/include/util/fifo.h @@ -17,169 +17,176 @@ #include namespace Genode { - - /* - * \param QT queue element type - */ - template - class Fifo - { - public: - - class Element - { - protected: - - friend class Fifo; - - QT *_next; - bool _is_enqueued; - - public: - - Element(): _next(0), _is_enqueued(false) { } - - /** - * Return true is fifo element is enqueued in a fifo - */ - bool is_enqueued() { return _is_enqueued; } - - /** - * Return next element in queue - */ - QT *next() const { return _next; } - }; - - private: - - QT *_head; /* oldest element */ - Element *_tail; /* newest element */ - - public: - - /** - * Return true if queue is empty - */ - bool empty() { return _tail == 0; } - - /** - * Constructor - * - * Start with an empty list. - */ - Fifo(): _head(0), _tail(0) { } - - /** - * Return first queue element - */ - QT *head() const { return _head; } - - /** - * Remove element explicitely from queue - */ - void remove(QT *qe) - { - if (empty()) return; - - /* if specified element is the first of the queue */ - if (qe == _head) { - _head = qe->Element::_next; - if (!_head) _tail = 0; - } - else { - - /* search specified element in the queue */ - Element *e = _head; - while (e->_next && (e->_next != qe)) - e = e->_next; - - /* element is not member of the queue */ - if (!e->_next) return; - - /* e->_next is the element to remove, skip it in list */ - e->Element::_next = e->Element::_next->Element::_next; - if (!e->Element::_next) _tail = e; - } - - qe->Element::_next = 0; - qe->Element::_is_enqueued = 0; - } - - /** - * Attach element at the end of the queue - */ - void enqueue(QT *e) - { - e->Fifo::Element::_next = 0; - e->Fifo::Element::_is_enqueued = true; - - if (empty()) { - _tail = _head = e; - return; - } - - _tail->Fifo::Element::_next = e; - _tail = e; - } - - /** - * Obtain head element of the queue and remove element from queue - * - * \return head element or 0 if queue is empty - */ - QT *dequeue() - { - QT *result = _head; - - /* check if queue has only one last element */ - if (_head == _tail) { - _head = 0; - _tail = 0; - } else - _head = _head->Fifo::Element::_next; - - /* mark fifo queue element as free */ - if (result) { - result->Fifo::Element::_next = 0; - result->Fifo::Element::_is_enqueued = false; - } - - return result; - } - }; - - /** - * Helper for using member variables as FIFO elements - * - * \param T type of compound object to be organized in a FIFO - * - * This helper allow the creation of FIFOs that use member variables to - * connect their elements. This way, the organized type does not need to - * publicly inherit 'Fifo::Element'. Furthermore objects can easily - * be organized in multiple FIFOs by embedding multiple 'Fifo_element' - * member variables. - */ - template - class Fifo_element : public Fifo >::Element - { - T *_object; - - public: - - Fifo_element(T *object) : _object(object) { } - - /** - * Get typed object pointer - * - * Zero-pointer save: Returns 0 if this pointer is 0 to - * cover the case of accessing an empty FIFO. - */ - inline T *object() - { - if (this) { return _object; } - return 0; - } - }; + + template class Fifo; + template class Fifo_element; } + +/** + * Fifo queue + * + * \param QT queue element type + */ +template +class Genode::Fifo +{ + public: + + class Element + { + protected: + + friend class Fifo; + + QT *_next; + bool _is_enqueued; + + public: + + Element(): _next(0), _is_enqueued(false) { } + + /** + * Return true is fifo element is enqueued in a fifo + */ + bool is_enqueued() { return _is_enqueued; } + + /** + * Return next element in queue + */ + QT *next() const { return _next; } + }; + + private: + + QT *_head; /* oldest element */ + Element *_tail; /* newest element */ + + public: + + /** + * Return true if queue is empty + */ + bool empty() { return _tail == 0; } + + /** + * Constructor + * + * Start with an empty list. + */ + Fifo(): _head(0), _tail(0) { } + + /** + * Return first queue element + */ + QT *head() const { return _head; } + + /** + * Remove element explicitely from queue + */ + void remove(QT *qe) + { + if (empty()) return; + + /* if specified element is the first of the queue */ + if (qe == _head) { + _head = qe->Element::_next; + if (!_head) _tail = 0; + } + else { + + /* search specified element in the queue */ + Element *e = _head; + while (e->_next && (e->_next != qe)) + e = e->_next; + + /* element is not member of the queue */ + if (!e->_next) return; + + /* e->_next is the element to remove, skip it in list */ + e->Element::_next = e->Element::_next->Element::_next; + if (!e->Element::_next) _tail = e; + } + + qe->Element::_next = 0; + qe->Element::_is_enqueued = 0; + } + + /** + * Attach element at the end of the queue + */ + void enqueue(QT *e) + { + e->Fifo::Element::_next = 0; + e->Fifo::Element::_is_enqueued = true; + + if (empty()) { + _tail = _head = e; + return; + } + + _tail->Fifo::Element::_next = e; + _tail = e; + } + + /** + * Obtain head element of the queue and remove element from queue + * + * \return head element or 0 if queue is empty + */ + QT *dequeue() + { + QT *result = _head; + + /* check if queue has only one last element */ + if (_head == _tail) { + _head = 0; + _tail = 0; + } else + _head = _head->Fifo::Element::_next; + + /* mark fifo queue element as free */ + if (result) { + result->Fifo::Element::_next = 0; + result->Fifo::Element::_is_enqueued = false; + } + + return result; + } +}; + + +/** + * Helper for using member variables as FIFO elements + * + * \param T type of compound object to be organized in a FIFO + * + * This helper allow the creation of FIFOs that use member variables to + * connect their elements. This way, the organized type does not need to + * publicly inherit 'Fifo::Element'. Furthermore objects can easily + * be organized in multiple FIFOs by embedding multiple 'Fifo_element' + * member variables. + */ +template +class Genode::Fifo_element : public Fifo >::Element +{ + T *_object; + + public: + + Fifo_element(T *object) : _object(object) { } + + /** + * Get typed object pointer + * + * Zero-pointer save: Returns 0 if this pointer is 0 to + * cover the case of accessing an empty FIFO. + */ + inline T *object() + { + if (this) { return _object; } + return 0; + } +}; + #endif /* _INCLUDE__UTIL__FIFO_H_ */ diff --git a/repos/base/include/util/list.h b/repos/base/include/util/list.h index b044305e3..4fe6cfe10 100644 --- a/repos/base/include/util/list.h +++ b/repos/base/include/util/list.h @@ -16,121 +16,127 @@ namespace Genode { - /* - * \param LT list element type - */ - template - class List - { - private: - - LT *_first; - - public: - - class Element - { - protected: - - friend class List; - - LT mutable *_next; - - public: - - Element(): _next(0) { } - - /** - * Return next element in list - */ - LT *next() const { return _next; } - }; - - public: - - /** - * Constructor - * - * Start with an empty list. - */ - List() : _first(0) { } - - /** - * Return first list element - */ - LT *first() { return _first; } - LT const *first() const { return _first; } - - /** - * Insert element after specified element into list - * - * \param le list element to insert - * \param at target position (preceding list element) - */ - void insert(LT const *le, LT const *at = 0) - { - /* insert at beginning of the list */ - if (at == 0) { - le->Element::_next = _first; - _first = const_cast(le); - } else { - le->Element::_next = at->Element::_next; - at->Element::_next = const_cast(le); - } - } - - /** - * Remove element from list - */ - void remove(LT const *le) - { - if (!_first) return; - - /* if specified element is the first of the list */ - if (le == _first) { - _first = le->Element::_next; - - } else { - - /* search specified element in the list */ - Element *e = _first; - while (e->_next && (e->_next != le)) - e = e->_next; - - /* element is not member of the list */ - if (!e->_next) return; - - /* e->_next is the element to remove, skip it in list */ - e->Element::_next = e->Element::_next->Element::_next; - } - - le->Element::_next = 0; - } - }; - - - /** - * Helper for using member variables as list elements - * - * \param T type of compound object to be organized in a list - * - * This helper allow the creation of lists that use member variables to - * connect their elements. This way, the organized type does not need to - * publicly inherit 'List::Element'. Furthermore objects can easily - * be organized in multiple lists by embedding multiple 'List_element' - * member variables. - */ - template - class List_element : public List >::Element - { - T *_object; - - public: - - List_element(T *object) : _object(object) { } - - T *object() const { return _object; } - }; + template class List; + template class List_element; } + +/** + * Single-connected list + * + * \param LT list element type + */ +template +class Genode::List +{ + private: + + LT *_first; + + public: + + class Element + { + protected: + + friend class List; + + LT mutable *_next; + + public: + + Element(): _next(0) { } + + /** + * Return next element in list + */ + LT *next() const { return _next; } + }; + + public: + + /** + * Constructor + * + * Start with an empty list. + */ + List() : _first(0) { } + + /** + * Return first list element + */ + LT *first() { return _first; } + LT const *first() const { return _first; } + + /** + * Insert element after specified element into list + * + * \param le list element to insert + * \param at target position (preceding list element) + */ + void insert(LT const *le, LT const *at = 0) + { + /* insert at beginning of the list */ + if (at == 0) { + le->Element::_next = _first; + _first = const_cast(le); + } else { + le->Element::_next = at->Element::_next; + at->Element::_next = const_cast(le); + } + } + + /** + * Remove element from list + */ + void remove(LT const *le) + { + if (!_first) return; + + /* if specified element is the first of the list */ + if (le == _first) { + _first = le->Element::_next; + + } else { + + /* search specified element in the list */ + Element *e = _first; + while (e->_next && (e->_next != le)) + e = e->_next; + + /* element is not member of the list */ + if (!e->_next) return; + + /* e->_next is the element to remove, skip it in list */ + e->Element::_next = e->Element::_next->Element::_next; + } + + le->Element::_next = 0; + } +}; + + +/** + * Helper for using member variables as list elements + * + * \param T type of compound object to be organized in a list + * + * This helper allow the creation of lists that use member variables to + * connect their elements. This way, the organized type does not need to + * publicly inherit 'List::Element'. Furthermore objects can easily + * be organized in multiple lists by embedding multiple 'List_element' + * member variables. + */ +template +class Genode::List_element : public List >::Element +{ + T *_object; + + public: + + List_element(T *object) : _object(object) { } + + T *object() const { return _object; } +}; + #endif /* _INCLUDE__UTIL__LIST_H_ */ diff --git a/repos/base/include/util/mmio.h b/repos/base/include/util/mmio.h index 332884e93..57056e025 100644 --- a/repos/base/include/util/mmio.h +++ b/repos/base/include/util/mmio.h @@ -17,631 +17,631 @@ /* Genode includes */ #include -namespace Genode +namespace Genode { class Mmio; } + + +/** + * A continuous MMIO region + * + * For correct behavior of the member functions of 'Mmio', a class that + * derives from one of the subclasses of 'Mmio' must not define members + * named 'Register_base', 'Bitfield_base', 'Register_array_base' or + * 'Array_bitfield_base'. + */ +class Genode::Mmio { - /** - * A continuous MMIO region - * - * For correct behavior of the member functions of 'Mmio', a class that - * derives from one of the subclasses of 'Mmio' must not define members - * named 'Register_base', 'Bitfield_base', 'Register_array_base' or - * 'Array_bitfield_base'. + /* + * If set 0 verbosity isn't needed at all and the enum enables the + * compiler to remove all verbosity code. If set 1 verbosity code + * gets compiled and is then switched via '*_verbose' member variables. */ - class Mmio + enum { VERBOSITY_AVAILABLE = 0 }; + + /** + * Proclaim a MMIO access + * + * \param _ACCESS_T integer type of access + * \param dst access destination + * \param v access value + * \param w 1: write access 0: read access + */ + template + inline void _access_verbosity(addr_t const dst, _ACCESS_T const v, + bool const w) const { + if (!VERBOSITY_AVAILABLE) return; + if ((w && !_write_verbose) || (!w && !_read_verbose)) return; + printf("mmio %s 0x%p: 0x", w ? "write" : "read ", (void *)dst); + Trait::Uint_type<_ACCESS_T>::print_hex(v); + printf("\n"); + } + + /** + * Write '_ACCESS_T' typed 'value' to MMIO base + 'o' + */ + template + inline void _write(off_t const o, _ACCESS_T const value) + { + addr_t const dst = (addr_t)base + o; + _access_verbosity<_ACCESS_T>(dst, value, 1); + *(_ACCESS_T volatile *)dst = value; + } + + /** + * Read '_ACCESS_T' typed from MMIO base + 'o' + */ + template + inline _ACCESS_T _read(off_t const o) const + { + addr_t const dst = (addr_t)base + o; + _ACCESS_T const value = *(_ACCESS_T volatile *)dst; + _access_verbosity<_ACCESS_T>(dst, value, 0); + return value; + } + + protected: + /* - * If set 0 verbosity isn't needed at all and the enum enables the - * compiler to remove all verbosity code. If set 1 verbosity code - * gets compiled and is then switched via '*_verbose' member variables. + * If VERBOSITY_AVAILABLE is set MMIO isn't verbose by default. + * Instead it causes this switches to be asked everytime MMIO + * could be verbose. This way the user can either enable verbosity + * locally by overwriting them in a deriving class or change their + * initialization temporarily to enable verbosity globally and + * then supress it locally by overwriting it. */ - enum { VERBOSITY_AVAILABLE = 0 }; + bool _write_verbose; + bool _read_verbose; + + public: + + enum { BYTE_WIDTH_LOG2 = 3, BYTE_WIDTH = 1 << BYTE_WIDTH_LOG2 }; /** - * Proclaim a MMIO access + * An integer like region within a MMIO region. * - * \param _ACCESS_T integer type of access - * \param dst access destination - * \param v access value - * \param w 1: write access 0: read access + * \param _OFFSET Offset of the region relative to the + * base of the compound MMIO. + * \param _ACCESS_WIDTH Bit width of the region, for a list of + * supported widths see 'Genode::Register'. + * \param _STRICT_WRITE If set to 0, when writing a bitfield, we + * read the register value, update the bits + * on it, and write it back to the register. + * If set to 1 we take an empty register + * value instead, apply the bitfield on it, + * and write it to the register. This can + * be useful if you have registers that have + * different means on reads and writes. + * + * For further details See 'Genode::Register'. */ - template - inline void _access_verbosity(addr_t const dst, _ACCESS_T const v, - bool const w) const - { - if (!VERBOSITY_AVAILABLE) return; - if ((w && !_write_verbose) || (!w && !_read_verbose)) return; - printf("mmio %s 0x%p: 0x", w ? "write" : "read ", (void *)dst); - Trait::Uint_type<_ACCESS_T>::print_hex(v); - printf("\n"); - } + template - /** - * Write '_ACCESS_T' typed 'value' to MMIO base + 'o' - */ - template - inline void _write(off_t const o, _ACCESS_T const value) + struct Register : public Genode::Register<_ACCESS_WIDTH> { - addr_t const dst = (addr_t)base + o; - _access_verbosity<_ACCESS_T>(dst, value, 1); - *(_ACCESS_T volatile *)dst = value; - } - - /** - * Read '_ACCESS_T' typed from MMIO base + 'o' - */ - template - inline _ACCESS_T _read(off_t const o) const - { - addr_t const dst = (addr_t)base + o; - _ACCESS_T const value = *(_ACCESS_T volatile *)dst; - _access_verbosity<_ACCESS_T>(dst, value, 0); - return value; - } - - protected: + enum { + OFFSET = _OFFSET, + ACCESS_WIDTH = _ACCESS_WIDTH, + STRICT_WRITE = _STRICT_WRITE, + }; /* - * If VERBOSITY_AVAILABLE is set MMIO isn't verbose by default. - * Instead it causes this switches to be asked everytime MMIO - * could be verbose. This way the user can either enable verbosity - * locally by overwriting them in a deriving class or change their - * initialization temporarily to enable verbosity globally and - * then supress it locally by overwriting it. + * GCC 4.4, in contrast to GCC versions >= 4.5, can't + * select function templates like 'write(typename + * T::Register::access_t value)' through a given 'T' + * that, in this case, derives from 'Register'. + * It seems this is due to the fact that 'T::Register' + * is a template. Thus we provide some kind of stamp + * that solely must not be redefined by the deriving + * class to ensure correct template selection. */ - bool _write_verbose; - bool _read_verbose; - - public: - - enum { BYTE_WIDTH_LOG2 = 3, BYTE_WIDTH = 1 << BYTE_WIDTH_LOG2 }; + typedef Register<_OFFSET, _ACCESS_WIDTH, _STRICT_WRITE> + Register_base; /** - * An integer like region within a MMIO region. + * A region within a register * - * \param _OFFSET Offset of the region relative to the - * base of the compound MMIO. - * \param _ACCESS_WIDTH Bit width of the region, for a list of - * supported widths see 'Genode::Register'. - * \param _STRICT_WRITE If set to 0, when writing a bitfield, we - * read the register value, update the bits - * on it, and write it back to the register. - * If set to 1 we take an empty register - * value instead, apply the bitfield on it, - * and write it to the register. This can - * be useful if you have registers that have - * different means on reads and writes. + * \param _SHIFT Bit shift of the first bit within the + * compound register. + * \param _WIDTH bit width of the region * - * For further details See 'Genode::Register'. + * For details see 'Genode::Register::Bitfield'. */ - template - - struct Register : public Genode::Register<_ACCESS_WIDTH> + template + struct Bitfield : public Genode::Register:: + template Bitfield<_SHIFT, _WIDTH> { - enum { - OFFSET = _OFFSET, - ACCESS_WIDTH = _ACCESS_WIDTH, - STRICT_WRITE = _STRICT_WRITE, - }; + /* analogous to 'Mmio::Register::Register_base' */ + typedef Bitfield<_SHIFT, _WIDTH> Bitfield_base; - /* - * GCC 4.4, in contrast to GCC versions >= 4.5, can't - * select function templates like 'write(typename - * T::Register::access_t value)' through a given 'T' - * that, in this case, derives from 'Register'. - * It seems this is due to the fact that 'T::Register' - * is a template. Thus we provide some kind of stamp - * that solely must not be redefined by the deriving - * class to ensure correct template selection. - */ + /* back reference to containing register */ typedef Register<_OFFSET, _ACCESS_WIDTH, _STRICT_WRITE> - Register_base; + Compound_reg; + }; + }; - /** - * A region within a register - * - * \param _SHIFT Bit shift of the first bit within the - * compound register. - * \param _WIDTH bit width of the region - * - * For details see 'Genode::Register::Bitfield'. - */ - template - struct Bitfield : public Genode::Register:: - template Bitfield<_SHIFT, _WIDTH> - { - /* analogous to 'Mmio::Register::Register_base' */ - typedef Bitfield<_SHIFT, _WIDTH> Bitfield_base; + /** + * An array of successive equally structured regions, called items + * + * \param _OFFSET Offset of the first item relative to + * the base of the compound MMIO. + * \param _ACCESS_WIDTH Bit width of a single access, must be at + * least the item width. + * \param _ITEMS How many times the item gets iterated + * successively. + * \param _ITEM_WIDTH bit width of an item + * \param _STRICT_WRITE If set to 0, when writing a bitfield, we + * read the register value, update the bits + * on it, and write it back to the register. + * If set to 1, we take an empty register + * value instead, apply the bitfield on it, + * and write it to the register. This can + * be useful if you have registers that have + * different means on reads and writes. + * Please note that ACCESS_WIDTH is decisive + * for the range of such strictness. + * + * The array takes all inner structures, wich are covered by an + * item width and iterates them successively. Such structures that + * are partially exceed an item range are read and written also + * partially. Structures that are completely out of the item range + * are read as '0' and trying to overwrite them has no effect. The + * array is not limited to its access width, it extends to the + * memory region of its successive items. Trying to read out read + * with an item index out of the array range returns '0', trying + * to write to such indices has no effect. + */ + template - /* back reference to containing register */ - typedef Register<_OFFSET, _ACCESS_WIDTH, _STRICT_WRITE> - Compound_reg; - }; + struct Register_array : public Register<_OFFSET, _ACCESS_WIDTH, + _STRICT_WRITE> + { + typedef typename Trait::Uint_width<_ACCESS_WIDTH>:: + template Divisor<_ITEM_WIDTH> Item; + + enum { + STRICT_WRITE = _STRICT_WRITE, + OFFSET = _OFFSET, + ACCESS_WIDTH = _ACCESS_WIDTH, + ITEMS = _ITEMS, + ITEM_WIDTH = _ITEM_WIDTH, + ITEM_WIDTH_LOG2 = Item::WIDTH_LOG2, + MAX_INDEX = ITEMS - 1, + ITEM_MASK = (1ULL << ITEM_WIDTH) - 1, }; + /* analogous to 'Mmio::Register::Register_base' */ + typedef Register_array + Register_array_base; + + typedef typename Register:: + access_t access_t; + /** - * An array of successive equally structured regions, called items + * A bitregion within a register array item * - * \param _OFFSET Offset of the first item relative to - * the base of the compound MMIO. - * \param _ACCESS_WIDTH Bit width of a single access, must be at - * least the item width. - * \param _ITEMS How many times the item gets iterated - * successively. - * \param _ITEM_WIDTH bit width of an item - * \param _STRICT_WRITE If set to 0, when writing a bitfield, we - * read the register value, update the bits - * on it, and write it back to the register. - * If set to 1, we take an empty register - * value instead, apply the bitfield on it, - * and write it to the register. This can - * be useful if you have registers that have - * different means on reads and writes. - * Please note that ACCESS_WIDTH is decisive - * for the range of such strictness. + * \param _SHIFT bit shift of the first bit within an item + * \param _WIDTH bit width of the region * - * The array takes all inner structures, wich are covered by an - * item width and iterates them successively. Such structures that - * are partially exceed an item range are read and written also - * partially. Structures that are completely out of the item range - * are read as '0' and trying to overwrite them has no effect. The - * array is not limited to its access width, it extends to the - * memory region of its successive items. Trying to read out read - * with an item index out of the array range returns '0', trying - * to write to such indices has no effect. + * For details see 'Genode::Register::Bitfield'. */ - template - - struct Register_array : public Register<_OFFSET, _ACCESS_WIDTH, - _STRICT_WRITE> + template + struct Bitfield : + public Register:: + template Bitfield<_SHIFT, _SIZE> { - typedef typename Trait::Uint_width<_ACCESS_WIDTH>:: - template Divisor<_ITEM_WIDTH> Item; - - enum { - STRICT_WRITE = _STRICT_WRITE, - OFFSET = _OFFSET, - ACCESS_WIDTH = _ACCESS_WIDTH, - ITEMS = _ITEMS, - ITEM_WIDTH = _ITEM_WIDTH, - ITEM_WIDTH_LOG2 = Item::WIDTH_LOG2, - MAX_INDEX = ITEMS - 1, - ITEM_MASK = (1ULL << ITEM_WIDTH) - 1, - }; - /* analogous to 'Mmio::Register::Register_base' */ + typedef Bitfield<_SHIFT, _SIZE> Array_bitfield_base; + + /* back reference to containing register array */ typedef Register_array - Register_array_base; - - typedef typename Register:: - access_t access_t; - - /** - * A bitregion within a register array item - * - * \param _SHIFT bit shift of the first bit within an item - * \param _WIDTH bit width of the region - * - * For details see 'Genode::Register::Bitfield'. - */ - template - struct Bitfield : - public Register:: - template Bitfield<_SHIFT, _SIZE> - { - /* analogous to 'Mmio::Register::Register_base' */ - typedef Bitfield<_SHIFT, _SIZE> Array_bitfield_base; - - /* back reference to containing register array */ - typedef Register_array - Compound_array; - }; - - /** - * Calculate destination of an array-item access - * - * \param offset Gets overridden with the offset of the - * access type instance, that contains the - * access destination, relative to the MMIO - * base. - * \param shift Gets overridden with the shift of the - * destination within the access type instance - * targeted by 'offset'. - * \param index index of the targeted array item - */ - static inline void dst(off_t & offset, - unsigned long & shift, - unsigned long const index) - { - unsigned long const bit_off = index << ITEM_WIDTH_LOG2; - offset = (off_t) ((bit_off >> BYTE_WIDTH_LOG2) - & ~(sizeof(access_t)-1) ); - shift = bit_off - ( offset << BYTE_WIDTH_LOG2 ); - offset += OFFSET; - } - - /** - * Calc destination of a simple array-item access without shift - * - * \param offset gets overridden with the offset of the the - * access destination, relative to the MMIO base - * \param index index of the targeted array item - */ - static inline void simple_dst(off_t & offset, - unsigned long const index) - { - offset = (index << ITEM_WIDTH_LOG2) >> BYTE_WIDTH_LOG2; - offset += OFFSET; - } + Compound_array; }; - addr_t const base; /* base address of targeted MMIO region */ - /** - * Constructor + * Calculate destination of an array-item access * - * \param mmio_base base address of targeted MMIO region + * \param offset Gets overridden with the offset of the + * access type instance, that contains the + * access destination, relative to the MMIO + * base. + * \param shift Gets overridden with the shift of the + * destination within the access type instance + * targeted by 'offset'. + * \param index index of the targeted array item */ - inline Mmio(addr_t mmio_base) - : _write_verbose(0), _read_verbose(0), base(mmio_base) { } - - - /************************* - ** Access to registers ** - *************************/ - - /** - * Get the address of the register 'T' typed as its access type - */ - template - inline typename T::Register_base::access_t volatile * typed_addr() const + static inline void dst(off_t & offset, + unsigned long & shift, + unsigned long const index) { - typedef typename T::Register_base Register; - typedef typename Register::access_t access_t; - return (access_t volatile *)(base + Register::OFFSET); + unsigned long const bit_off = index << ITEM_WIDTH_LOG2; + offset = (off_t) ((bit_off >> BYTE_WIDTH_LOG2) + & ~(sizeof(access_t)-1) ); + shift = bit_off - ( offset << BYTE_WIDTH_LOG2 ); + offset += OFFSET; } /** - * Read the register 'T' - */ - template - inline typename T::Register_base::access_t read() const - { - typedef typename T::Register_base Register; - typedef typename Register::access_t access_t; - return _read(Register::OFFSET); - } - - /** - * Override the register 'T' - */ - template - inline void - write(typename T::Register_base::access_t const value) - { - typedef typename T::Register_base Register; - typedef typename Register::access_t access_t; - _write(Register::OFFSET, value); - } - - /****************************************** - ** Access to bitfields within registers ** - ******************************************/ - - /** - * Read the bitfield 'T' of a register - */ - template - inline typename T::Bitfield_base::Compound_reg::access_t - read() const - { - typedef typename T::Bitfield_base Bitfield; - typedef typename Bitfield::Compound_reg Register; - typedef typename Register::access_t access_t; - return Bitfield::get(_read(Register::OFFSET)); - } - - /** - * Override to the bitfield 'T' of a register + * Calc destination of a simple array-item access without shift * - * \param value value that shall be written + * \param offset gets overridden with the offset of the the + * access destination, relative to the MMIO base + * \param index index of the targeted array item */ - template - inline void - write(typename T::Bitfield_base::Compound_reg::access_t const value) + static inline void simple_dst(off_t & offset, + unsigned long const index) { - typedef typename T::Bitfield_base Bitfield; - typedef typename Bitfield::Compound_reg Register; - typedef typename Register::access_t access_t; - - /* initialize the pattern written finally to the register */ - access_t write_value; - if (Register::STRICT_WRITE) - { - /* apply the bitfield to an empty write pattern */ - write_value = 0; - } else { - - /* apply the bitfield to the old register value */ - write_value = read(); - Bitfield::clear(write_value); - } - /* apply bitfield value and override register */ - Bitfield::set(write_value, value); - write(write_value); + offset = (index << ITEM_WIDTH_LOG2) >> BYTE_WIDTH_LOG2; + offset += OFFSET; } + }; + + addr_t const base; /* base address of targeted MMIO region */ + + /** + * Constructor + * + * \param mmio_base base address of targeted MMIO region + */ + inline Mmio(addr_t mmio_base) + : _write_verbose(0), _read_verbose(0), base(mmio_base) { } - /******************************* - ** Access to register arrays ** - *******************************/ + /************************* + ** Access to registers ** + *************************/ - /** - * Read an item of the register array 'T' - * - * \param index index of the targeted item - */ - template - inline typename T::Register_array_base::access_t - read(unsigned long const index) const + /** + * Get the address of the register 'T' typed as its access type + */ + template + inline typename T::Register_base::access_t volatile * typed_addr() const + { + typedef typename T::Register_base Register; + typedef typename Register::access_t access_t; + return (access_t volatile *)(base + Register::OFFSET); + } + + /** + * Read the register 'T' + */ + template + inline typename T::Register_base::access_t read() const + { + typedef typename T::Register_base Register; + typedef typename Register::access_t access_t; + return _read(Register::OFFSET); + } + + /** + * Override the register 'T' + */ + template + inline void + write(typename T::Register_base::access_t const value) + { + typedef typename T::Register_base Register; + typedef typename Register::access_t access_t; + _write(Register::OFFSET, value); + } + + /****************************************** + ** Access to bitfields within registers ** + ******************************************/ + + /** + * Read the bitfield 'T' of a register + */ + template + inline typename T::Bitfield_base::Compound_reg::access_t + read() const + { + typedef typename T::Bitfield_base Bitfield; + typedef typename Bitfield::Compound_reg Register; + typedef typename Register::access_t access_t; + return Bitfield::get(_read(Register::OFFSET)); + } + + /** + * Override to the bitfield 'T' of a register + * + * \param value value that shall be written + */ + template + inline void + write(typename T::Bitfield_base::Compound_reg::access_t const value) + { + typedef typename T::Bitfield_base Bitfield; + typedef typename Bitfield::Compound_reg Register; + typedef typename Register::access_t access_t; + + /* initialize the pattern written finally to the register */ + access_t write_value; + if (Register::STRICT_WRITE) { - typedef typename T::Register_array_base Array; - typedef typename Array::access_t access_t; + /* apply the bitfield to an empty write pattern */ + write_value = 0; + } else { - /* reads outside the array return 0 */ - if (index > Array::MAX_INDEX) return 0; - - /* if item width equals access width we optimize the access */ - off_t offset; - if (Array::ITEM_WIDTH == Array::ACCESS_WIDTH) { - Array::simple_dst(offset, index); - return _read(offset); - - /* access width and item width differ */ - } else { - long unsigned shift; - Array::dst(offset, shift, index); - return (_read(offset) >> shift) & - Array::ITEM_MASK; - } + /* apply the bitfield to the old register value */ + write_value = read(); + Bitfield::clear(write_value); } + /* apply bitfield value and override register */ + Bitfield::set(write_value, value); + write(write_value); + } - /** - * Override an item of the register array 'T' - * - * \param value value that shall be written - * \param index index of the targeted item - */ - template - inline void - write(typename T::Register_array_base::access_t const value, - unsigned long const index) - { - typedef typename T::Register_array_base Array; - typedef typename Array::access_t access_t; - /* ignore writes outside the array */ - if (index > Array::MAX_INDEX) return; + /******************************* + ** Access to register arrays ** + *******************************/ - /* optimize the access if item width equals access width */ - off_t offset; - if (Array::ITEM_WIDTH == Array::ACCESS_WIDTH) { - Array::simple_dst(offset, index); - _write(offset, value); + /** + * Read an item of the register array 'T' + * + * \param index index of the targeted item + */ + template + inline typename T::Register_array_base::access_t + read(unsigned long const index) const + { + typedef typename T::Register_array_base Array; + typedef typename Array::access_t access_t; - /* access width and item width differ */ - } else { - long unsigned shift; - Array::dst(offset, shift, index); + /* reads outside the array return 0 */ + if (index > Array::MAX_INDEX) return 0; - /* insert new value into old register value */ - access_t write_value; - if (Array::STRICT_WRITE) - { - /* apply bitfield to an empty write pattern */ - write_value = 0; - } else { + /* if item width equals access width we optimize the access */ + off_t offset; + if (Array::ITEM_WIDTH == Array::ACCESS_WIDTH) { + Array::simple_dst(offset, index); + return _read(offset); - /* apply bitfield to the old register value */ - write_value = _read(offset); - write_value &= ~(Array::ITEM_MASK << shift); - } - /* apply bitfield value and override register */ - write_value |= (value & Array::ITEM_MASK) << shift; - _write(offset, write_value); - } + /* access width and item width differ */ + } else { + long unsigned shift; + Array::dst(offset, shift, index); + return (_read(offset) >> shift) & + Array::ITEM_MASK; } + } + /** + * Override an item of the register array 'T' + * + * \param value value that shall be written + * \param index index of the targeted item + */ + template + inline void + write(typename T::Register_array_base::access_t const value, + unsigned long const index) + { + typedef typename T::Register_array_base Array; + typedef typename Array::access_t access_t; - /***************************************************** - ** Access to bitfields within register array items ** - *****************************************************/ + /* ignore writes outside the array */ + if (index > Array::MAX_INDEX) return; - /** - * Read the bitfield 'T' of a register array - * - * \param index index of the targeted item - */ - template - inline typename T::Array_bitfield_base::Compound_array::access_t - read(unsigned long const index) const - { - typedef typename T::Array_bitfield_base Bitfield; - typedef typename Bitfield::Compound_array Array; - return Bitfield::get(read(index)); - } + /* optimize the access if item width equals access width */ + off_t offset; + if (Array::ITEM_WIDTH == Array::ACCESS_WIDTH) { + Array::simple_dst(offset, index); + _write(offset, value); - /** - * Override the bitfield 'T' of a register array - * - * \param value value that shall be written - * \param index index of the targeted array item - */ - template - inline void - write(typename T::Array_bitfield_base::Compound_array::access_t const value, - long unsigned const index) - { - typedef typename T::Array_bitfield_base Bitfield; - typedef typename Bitfield::Compound_array Array; - typedef typename Array::access_t access_t; + /* access width and item width differ */ + } else { + long unsigned shift; + Array::dst(offset, shift, index); - /* initialize the pattern written finally to the register */ + /* insert new value into old register value */ access_t write_value; if (Array::STRICT_WRITE) { - /* apply the bitfield to an empty write pattern */ + /* apply bitfield to an empty write pattern */ write_value = 0; } else { - /* apply the bitfield to the old register value */ - write_value = read(index); - Bitfield::clear(write_value); + /* apply bitfield to the old register value */ + write_value = _read(offset); + write_value &= ~(Array::ITEM_MASK << shift); } /* apply bitfield value and override register */ - Bitfield::set(write_value, value); - write(write_value, index); + write_value |= (value & Array::ITEM_MASK) << shift; + _write(offset, write_value); } + } - /*********************** - ** Access to bitsets ** - ***********************/ + /***************************************************** + ** Access to bitfields within register array items ** + *****************************************************/ - /** - * Read bitset 'T' (composed of 2 parts) - */ - template - inline typename T::Bitset_2_base::access_t const read() + /** + * Read the bitfield 'T' of a register array + * + * \param index index of the targeted item + */ + template + inline typename T::Array_bitfield_base::Compound_array::access_t + read(unsigned long const index) const + { + typedef typename T::Array_bitfield_base Bitfield; + typedef typename Bitfield::Compound_array Array; + return Bitfield::get(read(index)); + } + + /** + * Override the bitfield 'T' of a register array + * + * \param value value that shall be written + * \param index index of the targeted array item + */ + template + inline void + write(typename T::Array_bitfield_base::Compound_array::access_t const value, + long unsigned const index) + { + typedef typename T::Array_bitfield_base Bitfield; + typedef typename Bitfield::Compound_array Array; + typedef typename Array::access_t access_t; + + /* initialize the pattern written finally to the register */ + access_t write_value; + if (Array::STRICT_WRITE) { - typedef typename T::Bitset_2_base::Bits_0 Bits_0; - typedef typename T::Bitset_2_base::Bits_1 Bits_1; - typedef typename T::Bitset_2_base::access_t access_t; - enum { V1_SHIFT = Bits_0::BITFIELD_WIDTH }; - access_t const v0 = read(); - access_t const v1 = read(); - return v0 | (v1 << V1_SHIFT); - } - - /** - * Override bitset 'T' (composed of 2 parts) - * - * \param v value that shall be written - */ - template - inline void write(typename T::Bitset_2_base::access_t v) - { - typedef typename T::Bitset_2_base::Bits_0 Bits_0; - typedef typename T::Bitset_2_base::Bits_1 Bits_1; - write(v); - write(v >> Bits_0::BITFIELD_WIDTH); - } - - /** - * Read bitset 'T' (composed of 3 parts) - */ - template - inline typename T::Bitset_3_base::access_t const read() - { - typedef typename T::Bitset_3_base::Bits_0 Bits_0; - typedef typename T::Bitset_3_base::Bits_1 Bits_1; - typedef typename T::Bitset_3_base::Bits_2 Bits_2; - typedef typename T::Bitset_3_base::access_t access_t; - enum { - BITS_0_WIDTH = Bits_0::BITFIELD_WIDTH, - BITS_1_WIDTH = Bits_1::BITFIELD_WIDTH, - V1_SHIFT = BITS_0_WIDTH + BITS_1_WIDTH, - }; - access_t const v0 = read >(); - access_t const v1 = read(); - return v0 | (v1 << V1_SHIFT); - } - - /** - * Override bitset 'T' (composed of 3 parts) - * - * \param v value that shall be written - */ - template - inline void write(typename T::Bitset_3_base::access_t v) - { - typedef typename T::Bitset_3_base::Bits_0 Bits_0; - typedef typename T::Bitset_3_base::Bits_1 Bits_1; - typedef typename T::Bitset_3_base::Bits_2 Bits_2; - write >(v); - write(v >> (Bits_0::BITFIELD_WIDTH + - Bits_1::BITFIELD_WIDTH)); + /* apply the bitfield to an empty write pattern */ + write_value = 0; + } else { + + /* apply the bitfield to the old register value */ + write_value = read(index); + Bitfield::clear(write_value); } + /* apply bitfield value and override register */ + Bitfield::set(write_value, value); + write(write_value, index); + } - /********************************* - ** Polling for bitfield states ** - *********************************/ + /*********************** + ** Access to bitsets ** + ***********************/ - /** - * Interface for delaying the execution of a calling thread - */ - struct Delayer - { - /** - * Delay execution of the caller for 'us' microseconds - */ - virtual void usleep(unsigned us) = 0; + /** + * Read bitset 'T' (composed of 2 parts) + */ + template + inline typename T::Bitset_2_base::access_t const read() + { + typedef typename T::Bitset_2_base::Bits_0 Bits_0; + typedef typename T::Bitset_2_base::Bits_1 Bits_1; + typedef typename T::Bitset_2_base::access_t access_t; + enum { V1_SHIFT = Bits_0::BITFIELD_WIDTH }; + access_t const v0 = read(); + access_t const v1 = read(); + return v0 | (v1 << V1_SHIFT); + } + + /** + * Override bitset 'T' (composed of 2 parts) + * + * \param v value that shall be written + */ + template + inline void write(typename T::Bitset_2_base::access_t v) + { + typedef typename T::Bitset_2_base::Bits_0 Bits_0; + typedef typename T::Bitset_2_base::Bits_1 Bits_1; + write(v); + write(v >> Bits_0::BITFIELD_WIDTH); + } + + /** + * Read bitset 'T' (composed of 3 parts) + */ + template + inline typename T::Bitset_3_base::access_t const read() + { + typedef typename T::Bitset_3_base::Bits_0 Bits_0; + typedef typename T::Bitset_3_base::Bits_1 Bits_1; + typedef typename T::Bitset_3_base::Bits_2 Bits_2; + typedef typename T::Bitset_3_base::access_t access_t; + enum { + BITS_0_WIDTH = Bits_0::BITFIELD_WIDTH, + BITS_1_WIDTH = Bits_1::BITFIELD_WIDTH, + V1_SHIFT = BITS_0_WIDTH + BITS_1_WIDTH, }; + access_t const v0 = read >(); + access_t const v1 = read(); + return v0 | (v1 << V1_SHIFT); + } - /** - * Wait until register 'T' contains the specified 'value' - * - * \param value value to wait for - * \param delayer sleeping facility to be used when the - * value is not reached yet - * \param max_attempts number of register probing attempts - * \param us number of microseconds between attempts - */ - template - inline bool - wait_for(typename T::Register_base::access_t const value, - Delayer & delayer, - unsigned max_attempts = 500, - unsigned us = 1000) - { - typedef typename T::Register_base Register; - for (unsigned i = 0; i < max_attempts; i++, delayer.usleep(us)) - { - if (read() == value) return true; - } - return false; - } + /** + * Override bitset 'T' (composed of 3 parts) + * + * \param v value that shall be written + */ + template + inline void write(typename T::Bitset_3_base::access_t v) + { + typedef typename T::Bitset_3_base::Bits_0 Bits_0; + typedef typename T::Bitset_3_base::Bits_1 Bits_1; + typedef typename T::Bitset_3_base::Bits_2 Bits_2; + write >(v); + write(v >> (Bits_0::BITFIELD_WIDTH + + Bits_1::BITFIELD_WIDTH)); + } + + /********************************* + ** Polling for bitfield states ** + *********************************/ + + /** + * Interface for delaying the execution of a calling thread + */ + struct Delayer + { /** - * Wait until bitfield 'T' contains the specified 'value' - * - * \param value value to wait for - * \param delayer sleeping facility to be used when the - * value is not reached yet - * \param max_attempts number of bitfield probing attempts - * \param us number of microseconds between attempts + * Delay execution of the caller for 'us' microseconds */ - template - inline bool - wait_for(typename T::Bitfield_base::Compound_reg::access_t const value, - Delayer & delayer, - unsigned max_attempts = 500, - unsigned us = 1000) + virtual void usleep(unsigned us) = 0; + }; + + /** + * Wait until register 'T' contains the specified 'value' + * + * \param value value to wait for + * \param delayer sleeping facility to be used when the + * value is not reached yet + * \param max_attempts number of register probing attempts + * \param us number of microseconds between attempts + */ + template + inline bool + wait_for(typename T::Register_base::access_t const value, + Delayer & delayer, + unsigned max_attempts = 500, + unsigned us = 1000) + { + typedef typename T::Register_base Register; + for (unsigned i = 0; i < max_attempts; i++, delayer.usleep(us)) { - typedef typename T::Bitfield_base Bitfield; - for (unsigned i = 0; i < max_attempts; i++, delayer.usleep(us)) - { - if (read() == value) return true; - } - return false; + if (read() == value) return true; } - }; -} + return false; + } + + /** + * Wait until bitfield 'T' contains the specified 'value' + * + * \param value value to wait for + * \param delayer sleeping facility to be used when the + * value is not reached yet + * \param max_attempts number of bitfield probing attempts + * \param us number of microseconds between attempts + */ + template + inline bool + wait_for(typename T::Bitfield_base::Compound_reg::access_t const value, + Delayer & delayer, + unsigned max_attempts = 500, + unsigned us = 1000) + { + typedef typename T::Bitfield_base Bitfield; + for (unsigned i = 0; i < max_attempts; i++, delayer.usleep(us)) + { + if (read() == value) return true; + } + return false; + } +}; #endif /* _INCLUDE__UTIL__MMIO_H_ */ diff --git a/repos/base/include/util/noncopyable.h b/repos/base/include/util/noncopyable.h index 5ee90a23c..656f11738 100644 --- a/repos/base/include/util/noncopyable.h +++ b/repos/base/include/util/noncopyable.h @@ -14,27 +14,27 @@ #ifndef _INCLUDE__UTIL__NONCOPYABLE_H_ #define _INCLUDE__UTIL__NONCOPYABLE_H_ -namespace Genode { +namespace Genode { class Noncopyable; } - /** - * Classes of objects not allowed to be copied, should inherit from this one. - * - * This class declares a private copy-constructor and assignment-operator. - * It's sufficient to inherit private from this class, and let the compiler - * detect any copy violations. - */ - class Noncopyable - { - private: - Noncopyable(const Noncopyable&); - const Noncopyable& operator=(const Noncopyable&); +/** + * Classes of objects not allowed to be copied, should inherit from this one. + * + * This class declares a private copy-constructor and assignment-operator. + * It's sufficient to inherit private from this class, and let the compiler + * detect any copy violations. + */ +class Genode::Noncopyable +{ + private: - protected: + Noncopyable(const Noncopyable&); + const Noncopyable& operator=(const Noncopyable&); - Noncopyable() {} - ~Noncopyable() {} - }; -} + protected: + + Noncopyable() {} + ~Noncopyable() {} +}; #endif /* _INCLUDE__UTIL__NONCOPYABLE_H_ */ diff --git a/repos/base/include/util/register.h b/repos/base/include/util/register.h index df3a6a81f..5a96ad0c3 100644 --- a/repos/base/include/util/register.h +++ b/repos/base/include/util/register.h @@ -18,10 +18,16 @@ #include #include -namespace Genode -{ - namespace Trait - { +namespace Genode { + + template struct Register; + template struct Bitset_2; + template struct Bitset_3; +} + + +namespace Genode { namespace Trait { + /** * Round bit width up to an appropriate uint width or 0 if not feasible */ @@ -109,245 +115,248 @@ namespace Genode template <> struct Uint_type : Uint_width<32> { }; template <> struct Uint_type : Uint_width<64> { }; } - - /** - * An integer like highly structured memory region - * - * \param _ACCESS_WIDTH bit width of the region - * - * The register can contain multiple bitfields. Bitfields that are - * partially exceed the register range are read and written also partially. - * Bitfields that are completely out of the register range are read as '0' - * and trying to overwrite them has no effect. - */ - template - struct Register - { - enum { - ACCESS_WIDTH = _ACCESS_WIDTH, - ACCESS_WIDTH_LOG2 = Trait::Uint_width::WIDTH_LOG2, - BITFIELD_WIDTH = ACCESS_WIDTH, - }; - - typedef typename Trait::Uint_width::Type access_t; - - /** - * A bitregion within a register - * - * \param _SHIFT bit shift of first bit within the compound register - * \param _WIDTH bit width of the region - * - * Bitfields are read and written according to their range, - * so if we have a 'Bitfield<2,3>' and write '0b11101' to it - * only '0b101' (shiftet by 2 bits) is written. - */ - template - struct Bitfield - { - enum { - - /** - * Fetch template parameters - */ - SHIFT = _SHIFT, - WIDTH = _WIDTH, - BITFIELD_WIDTH = WIDTH, - }; - - /** - * Get an unshifted mask of this field - */ - static access_t mask() { return ((access_t)1 << WIDTH) - 1; } - - /** - * Get a mask of this field shifted by its shift in the register - */ - static access_t reg_mask() { return mask() << SHIFT; } - - /** - * Get the bitwise negation of 'reg_mask' - */ - static access_t clear_mask() { return ~reg_mask(); } - - /** - * Back reference to containing register - */ - typedef Register Compound_reg; - - /** - * Get register with this bitfield set to 'value' and rest left 0 - * - * Useful to combine successive access to multiple - * bitfields into one operation. - */ - static inline access_t bits(access_t const value) { - return (value & mask()) << SHIFT; } - - /** - * Get a register value 'reg' masked according to this bitfield - * - * E.g. '0x1234' masked according to a - * 'Register<16>::Bitfield<5,7>' returns '0x0220'. - */ - static inline access_t masked(access_t const reg) - { return reg & reg_mask(); } - - /** - * Get value of this bitfield from 'reg' - */ - static inline access_t get(access_t const reg) - { return (reg >> SHIFT) & mask(); } - - /** - * Get register value 'reg' with this bitfield set to zero - */ - static inline void clear(access_t & reg) { reg &= clear_mask(); } - - /** - * Get register value 'reg' with this bitfield set to 'value' - */ - static inline void set(access_t & reg, access_t const value = ~0) - { - clear(reg); - reg |= (value & mask()) << SHIFT; - }; - }; - }; - - /** - * Bitfield that is composed of 2 separate parts - * - * \param _BITS_X Register, bitfield or/and bitset types the - * bitset is composed of. The order of arguments - * is also the order of bit significance starting - * with the least. - */ - template - struct Bitset_2 - { - typedef _BITS_0 Bits_0; - typedef _BITS_1 Bits_1; - enum { - WIDTH = Bits_0::BITFIELD_WIDTH + - Bits_1::BITFIELD_WIDTH, - BITFIELD_WIDTH = WIDTH, - ACCESS_WIDTH = Trait::Raise_to_uint_width::WIDTH, - }; - typedef typename Trait::Uint_width::Type access_t; - typedef Bitset_2 Bitset_2_base; - - /** - * Convert bitset value to register representation - * - * \param T access type of register - * \param v bitset value - */ - template - static inline T bits(T const v) - { - return Bits_0::bits(v) | Bits_1::bits(v >> Bits_0::WIDTH); - } - - /** - * Override bitset in a given register value - * - * \param T access type of register - * \param reg register value - * \param value new bitset value - */ - template - static inline void set(T & reg, access_t const value) - { - Bits_0::clear(reg); - Bits_1::clear(reg); - Bits_0::set(reg, value); - Bits_1::set(reg, value >> Bits_0::WIDTH); - }; - - /** - * Read bitset from a given register value - * - * \param T access type of register - * \param reg register value - * - * \return bitset value - */ - template - static inline access_t get(T const reg) - { - return Bits_0::get(reg) | (Bits_1::get(reg) << Bits_0::WIDTH); - } - }; - - /** - * Bitfield that is composed of 3 separate parts - * - * \param _BITS_X Register, bitfield or/and bitset types the - * bitset is composed of. The order of arguments - * is also the order of bit significance starting - * with the least. - */ - template - struct Bitset_3 - { - typedef _BITS_0 Bits_0; - typedef _BITS_1 Bits_1; - typedef _BITS_2 Bits_2; - typedef Bitset_2 Bits_0_1; - enum { - WIDTH = Bits_0::BITFIELD_WIDTH + - Bits_1::BITFIELD_WIDTH + - Bits_2::BITFIELD_WIDTH, - BITFIELD_WIDTH = WIDTH, - ACCESS_WIDTH = Trait::Raise_to_uint_width::WIDTH, - }; - typedef typename Trait::Uint_width::Type access_t; - typedef Bitset_3 Bitset_3_base; - - /** - * Convert bitset value to register representation - * - * \param T access type of register - * \param v bitset value - */ - template - static inline T bits(T const v) - { - return Bits_0_1::bits(v) | Bits_2::bits(v >> Bits_0_1::WIDTH); - } - - /** - * Override bitset in a given register value - * - * \param T access type of register - * \param reg register value - * \param value new bitset value - */ - template - static inline void set(T & reg, access_t const value) - { - Bits_0::clear(reg); - Bits_1::clear(reg); - Bits_2::clear(reg); - Bits_0_1::set(reg, value); - Bits_2::set(reg, value >> Bits_0_1::WIDTH); - }; - - /** - * Read bitset from a given register value - * - * \param T access type of register - * \param reg register value - * - * \return bitset value - */ - template - static inline access_t get(T const reg) - { - return Bits_0_1::get(reg) | (Bits_2::get(reg) << Bits_0_1::WIDTH); - } - }; } + +/** + * An integer like highly structured memory region + * + * \param _ACCESS_WIDTH bit width of the region + * + * The register can contain multiple bitfields. Bitfields that are + * partially exceed the register range are read and written also partially. + * Bitfields that are completely out of the register range are read as '0' + * and trying to overwrite them has no effect. + */ +template +struct Genode::Register +{ + enum { + ACCESS_WIDTH = _ACCESS_WIDTH, + ACCESS_WIDTH_LOG2 = Trait::Uint_width::WIDTH_LOG2, + BITFIELD_WIDTH = ACCESS_WIDTH, + }; + + typedef typename Trait::Uint_width::Type access_t; + + /** + * A bitregion within a register + * + * \param _SHIFT bit shift of first bit within the compound register + * \param _WIDTH bit width of the region + * + * Bitfields are read and written according to their range, + * so if we have a 'Bitfield<2,3>' and write '0b11101' to it + * only '0b101' (shiftet by 2 bits) is written. + */ + template + struct Bitfield + { + enum { + + /** + * Fetch template parameters + */ + SHIFT = _SHIFT, + WIDTH = _WIDTH, + BITFIELD_WIDTH = WIDTH, + }; + + /** + * Get an unshifted mask of this field + */ + static access_t mask() { return ((access_t)1 << WIDTH) - 1; } + + /** + * Get a mask of this field shifted by its shift in the register + */ + static access_t reg_mask() { return mask() << SHIFT; } + + /** + * Get the bitwise negation of 'reg_mask' + */ + static access_t clear_mask() { return ~reg_mask(); } + + /** + * Back reference to containing register + */ + typedef Register Compound_reg; + + /** + * Get register with this bitfield set to 'value' and rest left 0 + * + * Useful to combine successive access to multiple + * bitfields into one operation. + */ + static inline access_t bits(access_t const value) { + return (value & mask()) << SHIFT; } + + /** + * Get a register value 'reg' masked according to this bitfield + * + * E.g. '0x1234' masked according to a + * 'Register<16>::Bitfield<5,7>' returns '0x0220'. + */ + static inline access_t masked(access_t const reg) + { return reg & reg_mask(); } + + /** + * Get value of this bitfield from 'reg' + */ + static inline access_t get(access_t const reg) + { return (reg >> SHIFT) & mask(); } + + /** + * Get register value 'reg' with this bitfield set to zero + */ + static inline void clear(access_t & reg) { reg &= clear_mask(); } + + /** + * Get register value 'reg' with this bitfield set to 'value' + */ + static inline void set(access_t & reg, access_t const value = ~0) + { + clear(reg); + reg |= (value & mask()) << SHIFT; + }; + }; +}; + + +/** + * Bitfield that is composed of 2 separate parts + * + * \param _BITS_X Register, bitfield or/and bitset types the + * bitset is composed of. The order of arguments + * is also the order of bit significance starting + * with the least. + */ +template +struct Genode::Bitset_2 +{ + typedef _BITS_0 Bits_0; + typedef _BITS_1 Bits_1; + enum { + WIDTH = Bits_0::BITFIELD_WIDTH + + Bits_1::BITFIELD_WIDTH, + BITFIELD_WIDTH = WIDTH, + ACCESS_WIDTH = Trait::Raise_to_uint_width::WIDTH, + }; + typedef typename Trait::Uint_width::Type access_t; + typedef Bitset_2 Bitset_2_base; + + /** + * Convert bitset value to register representation + * + * \param T access type of register + * \param v bitset value + */ + template + static inline T bits(T const v) + { + return Bits_0::bits(v) | Bits_1::bits(v >> Bits_0::WIDTH); + } + + /** + * Override bitset in a given register value + * + * \param T access type of register + * \param reg register value + * \param value new bitset value + */ + template + static inline void set(T & reg, access_t const value) + { + Bits_0::clear(reg); + Bits_1::clear(reg); + Bits_0::set(reg, value); + Bits_1::set(reg, value >> Bits_0::WIDTH); + }; + + /** + * Read bitset from a given register value + * + * \param T access type of register + * \param reg register value + * + * \return bitset value + */ + template + static inline access_t get(T const reg) + { + return Bits_0::get(reg) | (Bits_1::get(reg) << Bits_0::WIDTH); + } +}; + + +/** + * Bitfield that is composed of 3 separate parts + * + * \param _BITS_X Register, bitfield or/and bitset types the + * bitset is composed of. The order of arguments + * is also the order of bit significance starting + * with the least. + */ +template +struct Genode::Bitset_3 +{ + typedef _BITS_0 Bits_0; + typedef _BITS_1 Bits_1; + typedef _BITS_2 Bits_2; + typedef Bitset_2 Bits_0_1; + enum { + WIDTH = Bits_0::BITFIELD_WIDTH + + Bits_1::BITFIELD_WIDTH + + Bits_2::BITFIELD_WIDTH, + BITFIELD_WIDTH = WIDTH, + ACCESS_WIDTH = Trait::Raise_to_uint_width::WIDTH, + }; + typedef typename Trait::Uint_width::Type access_t; + typedef Bitset_3 Bitset_3_base; + + /** + * Convert bitset value to register representation + * + * \param T access type of register + * \param v bitset value + */ + template + static inline T bits(T const v) + { + return Bits_0_1::bits(v) | Bits_2::bits(v >> Bits_0_1::WIDTH); + } + + /** + * Override bitset in a given register value + * + * \param T access type of register + * \param reg register value + * \param value new bitset value + */ + template + static inline void set(T & reg, access_t const value) + { + Bits_0::clear(reg); + Bits_1::clear(reg); + Bits_2::clear(reg); + Bits_0_1::set(reg, value); + Bits_2::set(reg, value >> Bits_0_1::WIDTH); + }; + + /** + * Read bitset from a given register value + * + * \param T access type of register + * \param reg register value + * + * \return bitset value + */ + template + static inline access_t get(T const reg) + { + return Bits_0_1::get(reg) | (Bits_2::get(reg) << Bits_0_1::WIDTH); + } +}; + #endif /* _INCLUDE__UTIL__REGISTER_H_ */ diff --git a/repos/base/include/util/string.h b/repos/base/include/util/string.h index 86658d2d3..d83ec1bec 100644 --- a/repos/base/include/util/string.h +++ b/repos/base/include/util/string.h @@ -19,6 +19,43 @@ #include #include +namespace Genode { + + class Number_of_bytes; + template class String; +} + + +/** + * Wrapper of 'size_t' for selecting 'ascii_to' specialization + */ +class Genode::Number_of_bytes +{ + size_t _n; + + public: + + /** + * Default constructor + */ + Number_of_bytes() : _n(0) { } + + /** + * Constructor, to be used implicitly via assignment operator + */ + Number_of_bytes(size_t n) : _n(n) { } + + /** + * Convert number of bytes to 'size_t' value + */ + operator size_t() const { return _n; } +}; + + +/*********************** + ** Utility functions ** + ***********************/ + namespace Genode { /** @@ -315,32 +352,6 @@ namespace Genode { } - /** - * Wrapper of 'size_t' for selecting 'ascii_to' specialization - */ - class Number_of_bytes - { - size_t _n; - - public: - - /** - * Default constructor - */ - Number_of_bytes() : _n(0) { } - - /** - * Constructor, to be used implicitly via assignment operator - */ - Number_of_bytes(size_t n) : _n(n) { } - - /** - * Convert number of bytes to 'size_t' value - */ - operator size_t() const { return _n; } - }; - - /** * Read 'Number_of_bytes' value from string and handle the size suffixes * @@ -447,54 +458,55 @@ namespace Genode { return i; } - - /** - * Buffer that contains a null-terminated string - * - * \param CAPACITY buffer size including the terminating zero - */ - template - class String - { - private: - - char _buf[CAPACITY]; - size_t _length; - - public: - - constexpr static size_t size() { return CAPACITY; } - - String() : _length(0) { } - - String(char const *str, size_t len = ~0UL - 1) - : - _length(min(len + 1, min(strlen(str) + 1, CAPACITY))) - { - strncpy(_buf, str, _length); - } - - size_t length() const { return _length; } - - static constexpr size_t capacity() { return CAPACITY; } - - bool valid() const { - return (_length <= CAPACITY) && (_length != 0) && (_buf[_length - 1] == '\0'); } - - char const *string() const { return valid() ? _buf : ""; } - - template - bool operator == (String const &other) const - { - return strcmp(string(), other.string()) == 0; - } - - template - bool operator != (String const &other) const - { - return strcmp(string(), other.string()) != 0; - } - }; } + +/** + * Buffer that contains a null-terminated string + * + * \param CAPACITY buffer size including the terminating zero + */ +template +class Genode::String +{ + private: + + char _buf[CAPACITY]; + size_t _length; + + public: + + constexpr static size_t size() { return CAPACITY; } + + String() : _length(0) { } + + String(char const *str, size_t len = ~0UL - 1) + : + _length(min(len + 1, min(strlen(str) + 1, CAPACITY))) + { + strncpy(_buf, str, _length); + } + + size_t length() const { return _length; } + + static constexpr size_t capacity() { return CAPACITY; } + + bool valid() const { + return (_length <= CAPACITY) && (_length != 0) && (_buf[_length - 1] == '\0'); } + + char const *string() const { return valid() ? _buf : ""; } + + template + bool operator == (String const &other) const + { + return strcmp(string(), other.string()) == 0; + } + + template + bool operator != (String const &other) const + { + return strcmp(string(), other.string()) != 0; + } +}; + #endif /* _INCLUDE__UTIL__STRING_H_ */ diff --git a/repos/base/include/util/token.h b/repos/base/include/util/token.h index f3733ec3f..a0396702e 100644 --- a/repos/base/include/util/token.h +++ b/repos/base/include/util/token.h @@ -18,193 +18,198 @@ namespace Genode { - /** - * Scanner policy that accepts underline characters in identifiers - */ - struct Scanner_policy_identifier_with_underline - { - /** - * Return true if character belongs to a valid identifier - * - * \param c character - * \param i index of character in token - * \return true if character is a valid identifier character - * - * Letters and underline characters are allowed anywhere in an - * identifier, digits must not appear at the beginning. - */ - static bool identifier_char(char c, unsigned i) { - return is_letter(c) || (c == '_') || (i && is_digit(c)); } - }; - - /** - * Token - * - * This class is used to group characters of a string which belong - * to one syntactical token types number, identifier, string, - * whitespace or another single character. - * - * \param SCANNER_POLICY policy that defines the way of token scanning - * - * See 'Scanner_policy_identifier_with_underline' for an example scanner - * policy. - */ - template - class Token - { - public: - - enum Type { SINGLECHAR, NUMBER, IDENT, STRING, WHITESPACE, END }; - - /** - * Constructor - * - * \param s start of string to construct a token from - * \param max_len maximum token length - * - * The 'max_len' argument is useful for processing character arrays - * that are not null-terminated. - */ - Token(const char *s = 0, size_t max_len = ~0UL) - : _start(s), _max_len(max_len), _len(s ? _calc_len(max_len) : 0) { } - - /** - * Accessors - */ - char *start() const { return (char *)_start; } - size_t len() const { return _len; } - Type type() const { return _type(_len); } - - /** - * Return token as null-terminated string - */ - void string(char *dst, size_t max_len) const { - strncpy(dst, start(), min(len() + 1, max_len)); } - - /** - * Return true if token is valid - */ - operator bool () const { return _start && _len; } - - /** - * Access single characters of token - */ - char operator [] (int idx) - { - return ((idx >= 0) && ((unsigned)idx < _len)) ? _start[idx] : 0; - } - - /** - * Return next token - */ - Token next() const { return Token(_start + _len, _max_len - _len); } - - /** - * Return next non-whitespace token - */ - Token eat_whitespace() const { return (_type(_len) == WHITESPACE) ? next() : *this; } - - private: - - const char *_start; - size_t _max_len; - size_t _len; - - /** - * Return type of token - * - * \param max_len maximum token length - * - * This function is used during the construction of 'Token' - * objects, in particular for determining the value of the '_len' - * member. Therefore, we explicitely pass the 'max_len' to the - * function. For the public interface, there exists the 'type()' - * accessor, which relies on '_len' as implicit argument. - */ - Type _type(size_t max_len) const - { - if (!_start || max_len < 1 || !*_start) return END; - - /* determine the type based on the first character */ - char c = *_start; - if (SCANNER_POLICY::identifier_char(c, 0)) return IDENT; - if (is_digit(c)) return NUMBER; - if (is_whitespace(c)) return WHITESPACE; - - /* if string is incomplete, discard it (type END) */ - if (c == '"') - return _quoted_string_len(max_len) ? STRING : END; - - return SINGLECHAR; - } - - size_t _quoted_string_len(size_t max_len) const - { - unsigned i = 0; - - for (; !end_of_quote(&_start[i]) && i < max_len; i++) - - /* string ends without final quotation mark? too bad! */ - if (!_start[i]) return 0; - - /* exceeded maximum token length */ - if (i == max_len) return 0; - - /* - * We stopped our search at the character before the - * final quotation mark but we return the number of - * characters including the quotation marks. - */ - return i + 2; - } - - /** - * Return length of token - */ - int _calc_len(size_t max_len) const - { - switch (_type(max_len)) { - - case SINGLECHAR: - return 1; - - case NUMBER: - { - unsigned i = 0; - for (; i < max_len && is_digit(_start[i]); i++); - return i; - } - - case IDENT: - { - unsigned i = 0; - for (; i < max_len; i++) { - if (SCANNER_POLICY::identifier_char(_start[i], i)) - continue; - - /* stop if any other (invalid) character occurs */ - break; - } - return i; - } - - case STRING: - - return _quoted_string_len(max_len); - - case WHITESPACE: - { - unsigned i = 0; - for (; is_whitespace(_start[i]) && i < max_len; i++); - return i; - } - - case END: - default: - return 0; - } - } - }; + struct Scanner_policy_identifier_with_underline; + template class Token; } + +/** + * Scanner policy that accepts underline characters in identifiers + */ +struct Genode::Scanner_policy_identifier_with_underline +{ + /** + * Return true if character belongs to a valid identifier + * + * \param c character + * \param i index of character in token + * \return true if character is a valid identifier character + * + * Letters and underline characters are allowed anywhere in an + * identifier, digits must not appear at the beginning. + */ + static bool identifier_char(char c, unsigned i) { + return is_letter(c) || (c == '_') || (i && is_digit(c)); } +}; + + +/** + * Token + * + * This class is used to group characters of a string which belong + * to one syntactical token types number, identifier, string, + * whitespace or another single character. + * + * \param SCANNER_POLICY policy that defines the way of token scanning + * + * See 'Scanner_policy_identifier_with_underline' for an example scanner + * policy. + */ +template +class Genode::Token +{ + public: + + enum Type { SINGLECHAR, NUMBER, IDENT, STRING, WHITESPACE, END }; + + /** + * Constructor + * + * \param s start of string to construct a token from + * \param max_len maximum token length + * + * The 'max_len' argument is useful for processing character arrays + * that are not null-terminated. + */ + Token(const char *s = 0, size_t max_len = ~0UL) + : _start(s), _max_len(max_len), _len(s ? _calc_len(max_len) : 0) { } + + /** + * Accessors + */ + char *start() const { return (char *)_start; } + size_t len() const { return _len; } + Type type() const { return _type(_len); } + + /** + * Return token as null-terminated string + */ + void string(char *dst, size_t max_len) const { + strncpy(dst, start(), min(len() + 1, max_len)); } + + /** + * Return true if token is valid + */ + operator bool () const { return _start && _len; } + + /** + * Access single characters of token + */ + char operator [] (int idx) + { + return ((idx >= 0) && ((unsigned)idx < _len)) ? _start[idx] : 0; + } + + /** + * Return next token + */ + Token next() const { return Token(_start + _len, _max_len - _len); } + + /** + * Return next non-whitespace token + */ + Token eat_whitespace() const { return (_type(_len) == WHITESPACE) ? next() : *this; } + + private: + + const char *_start; + size_t _max_len; + size_t _len; + + /** + * Return type of token + * + * \param max_len maximum token length + * + * This function is used during the construction of 'Token' + * objects, in particular for determining the value of the '_len' + * member. Therefore, we explicitely pass the 'max_len' to the + * function. For the public interface, there exists the 'type()' + * accessor, which relies on '_len' as implicit argument. + */ + Type _type(size_t max_len) const + { + if (!_start || max_len < 1 || !*_start) return END; + + /* determine the type based on the first character */ + char c = *_start; + if (SCANNER_POLICY::identifier_char(c, 0)) return IDENT; + if (is_digit(c)) return NUMBER; + if (is_whitespace(c)) return WHITESPACE; + + /* if string is incomplete, discard it (type END) */ + if (c == '"') + return _quoted_string_len(max_len) ? STRING : END; + + return SINGLECHAR; + } + + size_t _quoted_string_len(size_t max_len) const + { + unsigned i = 0; + + for (; !end_of_quote(&_start[i]) && i < max_len; i++) + + /* string ends without final quotation mark? too bad! */ + if (!_start[i]) return 0; + + /* exceeded maximum token length */ + if (i == max_len) return 0; + + /* + * We stopped our search at the character before the + * final quotation mark but we return the number of + * characters including the quotation marks. + */ + return i + 2; + } + + /** + * Return length of token + */ + int _calc_len(size_t max_len) const + { + switch (_type(max_len)) { + + case SINGLECHAR: + return 1; + + case NUMBER: + { + unsigned i = 0; + for (; i < max_len && is_digit(_start[i]); i++); + return i; + } + + case IDENT: + { + unsigned i = 0; + for (; i < max_len; i++) { + if (SCANNER_POLICY::identifier_char(_start[i], i)) + continue; + + /* stop if any other (invalid) character occurs */ + break; + } + return i; + } + + case STRING: + + return _quoted_string_len(max_len); + + case WHITESPACE: + { + unsigned i = 0; + for (; is_whitespace(_start[i]) && i < max_len; i++); + return i; + } + + case END: + default: + return 0; + } + } +}; + #endif /* _INCLUDE__UTIL__TOKEN_H_ */ diff --git a/repos/base/include/x86/cpu/consts.h b/repos/base/include/x86/cpu/consts.h index 8ca567911..2d79c1a15 100644 --- a/repos/base/include/x86/cpu/consts.h +++ b/repos/base/include/x86/cpu/consts.h @@ -31,10 +31,11 @@ namespace X86 { IOPL = 3 << 12, NESTED_TASK = 1 << 14, }; - } + namespace Abi { + /** * On x86 a call will result in a growth of the stack by machine word size */ diff --git a/repos/base/include/x86/cpu/string.h b/repos/base/include/x86/cpu/string.h index 22d42b815..e496a35b8 100644 --- a/repos/base/include/x86/cpu/string.h +++ b/repos/base/include/x86/cpu/string.h @@ -14,8 +14,8 @@ #ifndef _INCLUDE__X86__CPU__STRING_H_ #define _INCLUDE__X86__CPU__STRING_H_ -namespace Genode -{ +namespace Genode { + /** * Copy memory block * @@ -25,8 +25,7 @@ namespace Genode * * \return Number of bytes not copied */ - inline size_t memcpy_cpu(void *, const void *, size_t size) { - return size; } + inline size_t memcpy_cpu(void *, const void *, size_t size) { return size; } } #endif /* _INCLUDE__X86__CPU__STRING_H_ */ diff --git a/repos/base/include/x86_32/cpu/cpu_state.h b/repos/base/include/x86_32/cpu/cpu_state.h index ae62616c9..d58bd9fa2 100644 --- a/repos/base/include/x86_32/cpu/cpu_state.h +++ b/repos/base/include/x86_32/cpu/cpu_state.h @@ -18,31 +18,24 @@ #include -namespace Genode { +namespace Genode { struct Cpu_state; } - struct Cpu_state - { - addr_t ip; /* instruction pointer */ - addr_t sp; /* stack pointer */ - addr_t edi; - addr_t esi; - addr_t ebp; - addr_t ebx; - addr_t edx; - addr_t ecx; - addr_t eax; - addr_t gs; - addr_t fs; - addr_t eflags; - addr_t trapno; - /** - * Constructor - */ - Cpu_state(): ip(0), sp(0), edi(0), esi(0), ebp(0), - ebx(0), edx(0), ecx(0), eax(0), gs(0), - fs(0), eflags(0), trapno(0) { } - }; -} +struct Genode::Cpu_state +{ + addr_t ip = 0; /* instruction pointer */ + addr_t sp = 0; /* stack pointer */ + addr_t edi = 0; + addr_t esi = 0; + addr_t ebp = 0; + addr_t ebx = 0; + addr_t edx = 0; + addr_t ecx = 0; + addr_t eax = 0; + addr_t gs = 0; + addr_t fs = 0; + addr_t eflags = 0; + addr_t trapno = 0; +}; #endif /* _INCLUDE__X86_32__CPU__CPU_STATE_H_ */ diff --git a/repos/base/include/x86_64/cpu/cpu_state.h b/repos/base/include/x86_64/cpu/cpu_state.h index 1a34092fe..1b7eb9ef8 100644 --- a/repos/base/include/x86_64/cpu/cpu_state.h +++ b/repos/base/include/x86_64/cpu/cpu_state.h @@ -19,36 +19,30 @@ #include -namespace Genode { +namespace Genode { struct Cpu_state; } - struct Cpu_state - { - addr_t ip; - addr_t sp; - addr_t r8; - addr_t r9; - addr_t r10; - addr_t r11; - addr_t r12; - addr_t r13; - addr_t r14; - addr_t r15; - addr_t rax; - addr_t rbx; - addr_t rcx; - addr_t rdx; - addr_t rdi; - addr_t rsi; - addr_t rbp; - addr_t ss; - addr_t eflags; - addr_t trapno; - - Cpu_state() : ip(0), sp(0), r8(0), r9(0), r10(0), - r11(0), r12(0), r13(0), r14(0), r15(0), - rax(0), rbx(0), rcx(0), rdx(0), rdi(0), - rsi(0), rbp(0), ss(0), eflags(0), trapno(0) {} - }; -} +struct Genode::Cpu_state +{ + addr_t ip = 0; + addr_t sp = 0; + addr_t r8 = 0; + addr_t r9 = 0; + addr_t r10 = 0; + addr_t r11 = 0; + addr_t r12 = 0; + addr_t r13 = 0; + addr_t r14 = 0; + addr_t r15 = 0; + addr_t rax = 0; + addr_t rbx = 0; + addr_t rcx = 0; + addr_t rdx = 0; + addr_t rdi = 0; + addr_t rsi = 0; + addr_t rbp = 0; + addr_t ss = 0; + addr_t eflags = 0; + addr_t trapno = 0; +}; #endif /* _INCLUDE__X86_64__CPU__CPU_STATE_H_ */ diff --git a/repos/os/include/audio_out_session/connection.h b/repos/os/include/audio_out_session/connection.h index b320f0712..2a9ad95d0 100644 --- a/repos/os/include/audio_out_session/connection.h +++ b/repos/os/include/audio_out_session/connection.h @@ -19,9 +19,7 @@ #include -namespace Audio_out { - struct Connection; -} +namespace Audio_out { struct Connection; } struct Audio_out::Connection : Genode::Connection, Audio_out::Session_client diff --git a/repos/os/include/audio_out_session/rpc_object.h b/repos/os/include/audio_out_session/rpc_object.h index 7c61651be..fa9bb322b 100644 --- a/repos/os/include/audio_out_session/rpc_object.h +++ b/repos/os/include/audio_out_session/rpc_object.h @@ -19,9 +19,7 @@ #include -namespace Audio_out { - class Session_rpc_object; -} +namespace Audio_out { class Session_rpc_object; } class Audio_out::Session_rpc_object : public Genode::Rpc_object Tx_policy; - - typedef Packet_stream_tx::Channel Tx; - - static const char *service_name() { return "Block"; } - - virtual ~Session() { } - - /** - * Request information about the metrics of the block device - * - * \param blk_count will contain total number of blocks - * \param blk_size will contain total size in bytes - * \param ops supported operations - */ - virtual void info(sector_t *blk_count, - Genode::size_t *blk_size, - Operations *ops) = 0; - - /** - * Synchronize with block device, like ensuring data to be written - */ - virtual void sync() = 0; - - /** - * Request packet-transmission channel - */ - virtual Tx *tx_channel() { return 0; } - - /** - * Request client-side packet-stream interface of tx channel - */ - virtual Tx::Source *tx() { return 0; } - - - /******************* - ** RPC interface ** - *******************/ - - GENODE_RPC(Rpc_info, void, info, Block::sector_t *, - Genode::size_t *, Operations *); - GENODE_RPC(Rpc_tx_cap, Genode::Capability, _tx_cap); - GENODE_RPC(Rpc_sync, void, sync); - GENODE_RPC_INTERFACE(Rpc_info, Rpc_tx_cap, Rpc_sync); - }; + class Packet_descriptor; + struct Session; } + +/** + * Represents an operation request with respect to a block, + * the data associated with the 'Packet_descriptor' is either + * the data read from or written to the block indicated by + * its number. + */ +class Block::Packet_descriptor : public ::Packet_descriptor +{ + public: + + enum Opcode { READ, WRITE, END }; + enum Alignment { PACKET_ALIGNMENT = 11 }; + + private: + + Opcode _op; /* requested operation */ + sector_t _block_number; /* requested block number */ + Genode::size_t _block_count; /* number of blocks to transfer */ + unsigned _success :1; /* indicates success of operation */ + + public: + + /** + * Constructor + */ + Packet_descriptor(Genode::off_t offset=0, Genode::size_t size=0) + : ::Packet_descriptor(offset, size), + _op(READ), _block_number(0), _block_count(0), _success(false) { } + + /** + * Constructor + */ + Packet_descriptor(Packet_descriptor p, Opcode op, + sector_t blk_nr, Genode::size_t blk_count = 1) + : ::Packet_descriptor(p.offset(), p.size()), + _op(op), _block_number(blk_nr), + _block_count(blk_count), _success(false) { } + + Opcode operation() const { return _op; } + sector_t block_number() const { return _block_number; } + Genode::size_t block_count() const { return _block_count; } + bool succeeded() const { return _success; } + + void succeeded(bool b) { _success = b ? 1 : 0; } +}; + + +struct Block::Session : public Genode::Session +{ + enum { TX_QUEUE_SIZE = 256 }; + + + /** + * This class represents supported operations on a block device + */ + class Operations + { + private: + + unsigned _ops :Packet_descriptor::END; /* bitfield of ops */ + + public: + + Operations() : _ops(0) { } + + bool supported(Packet_descriptor::Opcode op) { + return (_ops & (1 << op)); } + + void set_operation(Packet_descriptor::Opcode op) { + _ops |= (1 << op); } + }; + + + typedef Packet_stream_policy Tx_policy; + + typedef Packet_stream_tx::Channel Tx; + + static const char *service_name() { return "Block"; } + + virtual ~Session() { } + + /** + * Request information about the metrics of the block device + * + * \param blk_count will contain total number of blocks + * \param blk_size will contain total size in bytes + * \param ops supported operations + */ + virtual void info(sector_t *blk_count, + Genode::size_t *blk_size, + Operations *ops) = 0; + + /** + * Synchronize with block device, like ensuring data to be written + */ + virtual void sync() = 0; + + /** + * Request packet-transmission channel + */ + virtual Tx *tx_channel() { return 0; } + + /** + * Request client-side packet-stream interface of tx channel + */ + virtual Tx::Source *tx() { return 0; } + + + /******************* + ** RPC interface ** + *******************/ + + GENODE_RPC(Rpc_info, void, info, Block::sector_t *, + Genode::size_t *, Operations *); + GENODE_RPC(Rpc_tx_cap, Genode::Capability, _tx_cap); + GENODE_RPC(Rpc_sync, void, sync); + GENODE_RPC_INTERFACE(Rpc_info, Rpc_tx_cap, Rpc_sync); +}; + #endif /* _INCLUDE__BLOCK_SESSION__BLOCK_SESSION_H_ */ diff --git a/repos/os/include/block_session/client.h b/repos/os/include/block_session/client.h index a6062d3c5..288c5a22f 100644 --- a/repos/os/include/block_session/client.h +++ b/repos/os/include/block_session/client.h @@ -18,53 +18,53 @@ #include #include -namespace Block { - - class Session_client : public Genode::Rpc_client - { - private: - - Packet_stream_tx::Client _tx; - - public: - - /** - * Constructor - * - * \param session session capability - * \param tx_buffer_alloc allocator used for managing the - * transmission buffer - */ - Session_client(Session_capability session, - Genode::Range_allocator *tx_buffer_alloc) - : - Genode::Rpc_client(session), - _tx(call(), tx_buffer_alloc) - { } +namespace Block { class Session_client; } - /***************************** - ** Block session interface ** - *****************************/ +class Block::Session_client : public Genode::Rpc_client +{ + private: - void info(sector_t *blk_count, Genode::size_t *blk_size, - Operations *ops) - { - call(blk_count, blk_size, ops); - } + Packet_stream_tx::Client _tx; - Tx *tx_channel() { return &_tx; } - Tx::Source *tx() { return _tx.source(); } - void sync() { call(); } + public: - /* - * Wrapper for alloc_packet, allocates 2KB aligned packets - */ - Packet_descriptor dma_alloc_packet(Genode::size_t size) - { - return tx()->alloc_packet(size, 11); - } - }; -} + /** + * Constructor + * + * \param session session capability + * \param tx_buffer_alloc allocator used for managing the + * transmission buffer + */ + Session_client(Session_capability session, + Genode::Range_allocator *tx_buffer_alloc) + : + Genode::Rpc_client(session), + _tx(call(), tx_buffer_alloc) + { } + + + /***************************** + ** Block session interface ** + *****************************/ + + void info(sector_t *blk_count, Genode::size_t *blk_size, + Operations *ops) override + { + call(blk_count, blk_size, ops); + } + + Tx *tx_channel() { return &_tx; } + Tx::Source *tx() { return _tx.source(); } + void sync() override { call(); } + + /* + * Wrapper for alloc_packet, allocates 2KB aligned packets + */ + Packet_descriptor dma_alloc_packet(Genode::size_t size) + { + return tx()->alloc_packet(size, 11); + } +}; #endif /* _INCLUDE__BLOCK_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/block_session/connection.h b/repos/os/include/block_session/connection.h index f753c8e5d..941d362ea 100644 --- a/repos/os/include/block_session/connection.h +++ b/repos/os/include/block_session/connection.h @@ -18,26 +18,25 @@ #include #include -namespace Block { +namespace Block { struct Connection; } - struct Connection : Genode::Connection, Session_client - { - /** - * Constructor - * - * \param tx_buffer_alloc allocator used for managing the - * transmission buffer - * \param tx_buf_size size of transmission buffer in bytes - */ - Connection(Genode::Range_allocator *tx_block_alloc, - Genode::size_t tx_buf_size = 128*1024, - const char *label = "") - : - Genode::Connection( - session("ram_quota=%zd, tx_buf_size=%zd, label=\"%s\"", - 3*4096 + tx_buf_size, tx_buf_size, label)), - Session_client(cap(), tx_block_alloc) { } - }; -} +struct Block::Connection : Genode::Connection, Session_client +{ + /** + * Constructor + * + * \param tx_buffer_alloc allocator used for managing the + * transmission buffer + * \param tx_buf_size size of transmission buffer in bytes + */ + Connection(Genode::Range_allocator *tx_block_alloc, + Genode::size_t tx_buf_size = 128*1024, + const char *label = "") + : + Genode::Connection( + session("ram_quota=%zd, tx_buf_size=%zd, label=\"%s\"", + 3*4096 + tx_buf_size, tx_buf_size, label)), + Session_client(cap(), tx_block_alloc) { } +}; #endif /* _INCLUDE__BLOCK_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/block_session/rpc_object.h b/repos/os/include/block_session/rpc_object.h index 869b32fc6..6c31fd545 100644 --- a/repos/os/include/block_session/rpc_object.h +++ b/repos/os/include/block_session/rpc_object.h @@ -18,37 +18,37 @@ #include #include -namespace Block { +namespace Block { class Session_rpc_object; } - class Session_rpc_object : public Genode::Rpc_object - { - protected: - Packet_stream_tx::Rpc_object _tx; +class Block::Session_rpc_object : public Genode::Rpc_object +{ + protected: - public: + Packet_stream_tx::Rpc_object _tx; - /** - * Constructor - * - * \param tx_ds dataspace used as communication buffer - * for the tx packet stream - * \param ep entry point used for packet-stream channel - */ - Session_rpc_object(Genode::Dataspace_capability tx_ds, - Genode::Rpc_entrypoint &ep) - : _tx(tx_ds, ep) { } + public: - /** - * Return capability to packet-stream channel - * - * This function is called by the client via an RPC call at session - * construction time. - */ - Genode::Capability _tx_cap() { return _tx.cap(); } + /** + * Constructor + * + * \param tx_ds dataspace used as communication buffer + * for the tx packet stream + * \param ep entry point used for packet-stream channel + */ + Session_rpc_object(Genode::Dataspace_capability tx_ds, + Genode::Rpc_entrypoint &ep) + : _tx(tx_ds, ep) { } - Tx::Sink *tx_sink() { return _tx.sink(); } - }; -} + /** + * Return capability to packet-stream channel + * + * This function is called by the client via an RPC call at session + * construction time. + */ + Genode::Capability _tx_cap() { return _tx.cap(); } + + Tx::Sink *tx_sink() { return _tx.sink(); } +}; #endif /* _INCLUDE__BLOCK_SESSION__SERVER_H_ */ diff --git a/repos/os/include/decorator/types.h b/repos/os/include/decorator/types.h index 8cd0a70f9..bae29143b 100644 --- a/repos/os/include/decorator/types.h +++ b/repos/os/include/decorator/types.h @@ -24,6 +24,7 @@ #include namespace Decorator { + typedef Genode::Surface_base::Point Point; typedef Genode::Surface_base::Area Area; typedef Genode::Surface_base::Rect Rect; diff --git a/repos/os/include/decorator/xml_utils.h b/repos/os/include/decorator/xml_utils.h index 3cd72e5ef..05935f5e3 100644 --- a/repos/os/include/decorator/xml_utils.h +++ b/repos/os/include/decorator/xml_utils.h @@ -18,6 +18,7 @@ namespace Decorator { + template static T attribute(Xml_node const &, char const *, T); diff --git a/repos/os/include/drivers/timer/sp804_base.h b/repos/os/include/drivers/timer/sp804_base.h index ff748291d..8c538a0fc 100644 --- a/repos/os/include/drivers/timer/sp804_base.h +++ b/repos/os/include/drivers/timer/sp804_base.h @@ -17,167 +17,167 @@ /* Genode includes */ #include -namespace Genode +namespace Genode { template class Sp804_base; } + + +/** + * Basic driver for the ARM SP804 timer + */ +template +class Genode::Sp804_base : public Mmio { - /** - * Basic driver for the ARM SP804 timer - */ - template - class Sp804_base : public Mmio - { - enum { - TICS_PER_MS = CLK / 1000, - TICS_PER_US = TICS_PER_MS / 1000, + enum { + TICS_PER_MS = CLK / 1000, + TICS_PER_US = TICS_PER_MS / 1000, - AVOID_INVALID_TEMPLATE_ARGS = 1 / TICS_PER_US, - }; - - /** - * Holds value that shall be loaded to the timer value register - */ - struct Load : Register<0x0, 32> { }; - - /** - * Raw interrupt status - */ - struct Ris : Register<0x10, 1> { }; - - /** - * Background load register - */ - struct Bgload : Register<0x18, 32> { }; - - /** - * Timer value register - */ - struct Value : Register<0x4, 32> { enum { MAX_VALUE = 0xffffffff }; }; - - /** - * Timer control register - */ - struct Control : Register<0x8, 8> - { - struct Oneshot : Bitfield<0,1> { }; - struct Size : Bitfield<1,1> { }; - struct Pre : Bitfield<2,2> { }; - struct Int_en : Bitfield<5,1> { }; - struct Mode : Bitfield<6,1> { }; - struct Timer_en : Bitfield<7,1> { }; - }; - - /** - * Clears the timer interrupt - */ - struct Int_clr : Register<0xc, 1> { }; - - public: - - /** - * Constructor, clears interrupt output - */ - Sp804_base(addr_t const mmio_base) : Mmio(mmio_base) { - clear_interrupt(); } - - /** - * Run the timer in order that it raises IRQ when - * it reaches zero, then stop - * - * \param tics native timer value used to assess the delay - * of the timer interrupt as of this call - */ - void run_and_stop(unsigned long const tics) - { - /* disable and configure timer for a one-shot */ - clear_interrupt(); - write(0); - write(Control::Timer_en::bits(0) | - Control::Mode::bits(1) | - Control::Int_en::bits(1) | - Control::Pre::bits(0) | - Control::Size::bits(1) | - Control::Oneshot::bits(1)); - - /* load value and enable timer */ - write(tics); - write(1); - } - - /** - * Run the timer in order that it raises IRQ when it reaches zero, - * then wrap and continue - * - * \param tics native timer value used to assess the delay - * of the timer interrupt as of this call - */ - void run_and_wrap(unsigned long const tics) - { - /* configure the timer in order that it reloads on 0 */ - clear_interrupt(); - write(0); - write(Control::Timer_en::bits(0) | - Control::Mode::bits(1) | - Control::Int_en::bits(1) | - Control::Pre::bits(0) | - Control::Size::bits(1) | - Control::Oneshot::bits(0)); - - /* start timer with the initial value */ - write(tics); - write(1); - - /* - * Ensure that the timer loads its max value instead of the - * initial value when it reaches 0 in order that it looks like - * it wraps. - */ - write(max_value()); - } - - /** - * Current timer value - */ - unsigned long value() const { return read(); } - - /** - * Get timer value and corresponding wrapped status of timer - */ - unsigned long value(bool & wrapped) const - { - typename Value::access_t v = read(); - wrapped = (bool)read(); - if (!wrapped) return v; - return read(); - } - - /** - * Clear interrupt output line - */ - void clear_interrupt() { write(1); } - - /** - * Translate milliseconds to a native timer value - */ - static unsigned long ms_to_tics(unsigned long const ms) { - return ms * TICS_PER_MS; } - - /** - * Translate native timer value to microseconds - */ - static unsigned long tics_to_us(unsigned long const tics) { - return tics / TICS_PER_US; } - - /** - * Translate microseconds to a native timer value - */ - static unsigned long us_to_tics(unsigned long const us) { - return us * TICS_PER_US; } - - /** - * Translate native timer value to microseconds - */ - static unsigned long max_value() { return Value::MAX_VALUE; } + AVOID_INVALID_TEMPLATE_ARGS = 1 / TICS_PER_US, }; -} + + /** + * Holds value that shall be loaded to the timer value register + */ + struct Load : Register<0x0, 32> { }; + + /** + * Raw interrupt status + */ + struct Ris : Register<0x10, 1> { }; + + /** + * Background load register + */ + struct Bgload : Register<0x18, 32> { }; + + /** + * Timer value register + */ + struct Value : Register<0x4, 32> { enum { MAX_VALUE = 0xffffffff }; }; + + /** + * Timer control register + */ + struct Control : Register<0x8, 8> + { + struct Oneshot : Bitfield<0,1> { }; + struct Size : Bitfield<1,1> { }; + struct Pre : Bitfield<2,2> { }; + struct Int_en : Bitfield<5,1> { }; + struct Mode : Bitfield<6,1> { }; + struct Timer_en : Bitfield<7,1> { }; + }; + + /** + * Clears the timer interrupt + */ + struct Int_clr : Register<0xc, 1> { }; + + public: + + /** + * Constructor, clears interrupt output + */ + Sp804_base(addr_t const mmio_base) : Mmio(mmio_base) { + clear_interrupt(); } + + /** + * Run the timer in order that it raises IRQ when + * it reaches zero, then stop + * + * \param tics native timer value used to assess the delay + * of the timer interrupt as of this call + */ + void run_and_stop(unsigned long const tics) + { + /* disable and configure timer for a one-shot */ + clear_interrupt(); + write(0); + write(Control::Timer_en::bits(0) | + Control::Mode::bits(1) | + Control::Int_en::bits(1) | + Control::Pre::bits(0) | + Control::Size::bits(1) | + Control::Oneshot::bits(1)); + + /* load value and enable timer */ + write(tics); + write(1); + } + + /** + * Run the timer in order that it raises IRQ when it reaches zero, + * then wrap and continue + * + * \param tics native timer value used to assess the delay + * of the timer interrupt as of this call + */ + void run_and_wrap(unsigned long const tics) + { + /* configure the timer in order that it reloads on 0 */ + clear_interrupt(); + write(0); + write(Control::Timer_en::bits(0) | + Control::Mode::bits(1) | + Control::Int_en::bits(1) | + Control::Pre::bits(0) | + Control::Size::bits(1) | + Control::Oneshot::bits(0)); + + /* start timer with the initial value */ + write(tics); + write(1); + + /* + * Ensure that the timer loads its max value instead of the + * initial value when it reaches 0 in order that it looks like + * it wraps. + */ + write(max_value()); + } + + /** + * Current timer value + */ + unsigned long value() const { return read(); } + + /** + * Get timer value and corresponding wrapped status of timer + */ + unsigned long value(bool & wrapped) const + { + typename Value::access_t v = read(); + wrapped = (bool)read(); + if (!wrapped) return v; + return read(); + } + + /** + * Clear interrupt output line + */ + void clear_interrupt() { write(1); } + + /** + * Translate milliseconds to a native timer value + */ + static unsigned long ms_to_tics(unsigned long const ms) { + return ms * TICS_PER_MS; } + + /** + * Translate native timer value to microseconds + */ + static unsigned long tics_to_us(unsigned long const tics) { + return tics / TICS_PER_US; } + + /** + * Translate microseconds to a native timer value + */ + static unsigned long us_to_tics(unsigned long const us) { + return us * TICS_PER_US; } + + /** + * Translate native timer value to microseconds + */ + static unsigned long max_value() { return Value::MAX_VALUE; } +}; #endif /* _INCLUDE__DRIVERS__TIMER__SP804_H_ */ diff --git a/repos/os/include/file_system_session/client.h b/repos/os/include/file_system_session/client.h index 3c52caab5..b1026a6d8 100644 --- a/repos/os/include/file_system_session/client.h +++ b/repos/os/include/file_system_session/client.h @@ -18,98 +18,98 @@ #include #include -namespace File_system { - - class Session_client : public Rpc_client - { - private: - - Packet_stream_tx::Client _tx; - - public: - - /** - * Constructor - * - * \param session session capability - * \param tx_buffer_alloc allocator used for managing the - * transmission buffer - */ - Session_client(Session_capability session, - Range_allocator &tx_buffer_alloc) - : - Rpc_client(session), - _tx(call(), &tx_buffer_alloc) - { } +namespace File_system { class Session_client; } - /*********************************** - ** File-system session interface ** - ***********************************/ +class File_system::Session_client : public Rpc_client +{ + private: - Tx::Source *tx() { return _tx.source(); } + Packet_stream_tx::Client _tx; - File_handle file(Dir_handle dir, Name const &name, Mode mode, bool create) - { - return call(dir, name, mode, create); - } + public: - Symlink_handle symlink(Dir_handle dir, Name const &name, bool create) - { - return call(dir, name, create); - } + /** + * Constructor + * + * \param session session capability + * \param tx_buffer_alloc allocator used for managing the + * transmission buffer + */ + Session_client(Session_capability session, + Range_allocator &tx_buffer_alloc) + : + Rpc_client(session), + _tx(call(), &tx_buffer_alloc) + { } - Dir_handle dir(Path const &path, bool create) - { - return call(path, create); - } - Node_handle node(Path const &path) - { - return call(path); - } + /*********************************** + ** File-system session interface ** + ***********************************/ - void close(Node_handle node) - { - call(node); - } + Tx::Source *tx() { return _tx.source(); } - Status status(Node_handle node) - { - return call(node); - } + File_handle file(Dir_handle dir, Name const &name, Mode mode, bool create) override + { + return call(dir, name, mode, create); + } - void control(Node_handle node, Control control) - { - call(node, control); - } + Symlink_handle symlink(Dir_handle dir, Name const &name, bool create) override + { + return call(dir, name, create); + } - void unlink(Dir_handle dir, Name const &name) - { - call(dir, name); - } + Dir_handle dir(Path const &path, bool create) override + { + return call(path, create); + } - void truncate(File_handle file, file_size_t size) - { - call(file, size); - } + Node_handle node(Path const &path) override + { + return call(path); + } - void move(Dir_handle from_dir, Name const &from_name, - Dir_handle to_dir, Name const &to_name) - { - call(from_dir, from_name, to_dir, to_name); - } + void close(Node_handle node) override + { + call(node); + } - void sigh(Node_handle node, Signal_context_capability sigh) - { - call(node, sigh); - } + Status status(Node_handle node) override + { + return call(node); + } - void sync() - { - call(); - } - }; -} + void control(Node_handle node, Control control) override + { + call(node, control); + } + + void unlink(Dir_handle dir, Name const &name) override + { + call(dir, name); + } + + void truncate(File_handle file, file_size_t size) override + { + call(file, size); + } + + void move(Dir_handle from_dir, Name const &from_name, + Dir_handle to_dir, Name const &to_name) override + { + call(from_dir, from_name, to_dir, to_name); + } + + void sigh(Node_handle node, Signal_context_capability sigh) override + { + call(node, sigh); + } + + void sync() override + { + call(); + } +}; #endif /* _INCLUDE__FILE_SYSTEM_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/file_system_session/connection.h b/repos/os/include/file_system_session/connection.h index 2f9f9d7a3..1eefd4579 100644 --- a/repos/os/include/file_system_session/connection.h +++ b/repos/os/include/file_system_session/connection.h @@ -18,26 +18,26 @@ #include #include -namespace File_system { +namespace File_system { struct Connection; } - struct Connection : Genode::Connection, Session_client - { - /** - * Constructor - * - * \param tx_buffer_alloc allocator used for managing the - * transmission buffer - * \param tx_buf_size size of transmission buffer in bytes - */ - Connection(Range_allocator &tx_block_alloc, - size_t tx_buf_size = 128*1024, - const char *label = "") - : - Genode::Connection( - session("ram_quota=%zd, tx_buf_size=%zd, label=\"%s\"", - 4*1024*sizeof(long) + tx_buf_size, tx_buf_size, label)), - Session_client(cap(), tx_block_alloc) { } - }; -} + +struct File_system::Connection : Genode::Connection, Session_client +{ + /** + * Constructor + * + * \param tx_buffer_alloc allocator used for managing the + * transmission buffer + * \param tx_buf_size size of transmission buffer in bytes + */ + Connection(Range_allocator &tx_block_alloc, + size_t tx_buf_size = 128*1024, + const char *label = "") + : + Genode::Connection( + session("ram_quota=%zd, tx_buf_size=%zd, label=\"%s\"", + 4*1024*sizeof(long) + tx_buf_size, tx_buf_size, label)), + Session_client(cap(), tx_block_alloc) { } +}; #endif /* _INCLUDE__FILE_SYSTEM_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/file_system_session/file_system_session.h b/repos/os/include/file_system_session/file_system_session.h index 9b8647a8c..9c8f7b77c 100644 --- a/repos/os/include/file_system_session/file_system_session.h +++ b/repos/os/include/file_system_session/file_system_session.h @@ -23,37 +23,10 @@ namespace File_system { using namespace Genode; - struct Node_handle - { - int value; - - Node_handle() : value(-1) { } - Node_handle(int v) : value(v) { } - - bool valid() const { return value != -1; } - }; - - - struct File_handle : Node_handle - { - File_handle() { } - File_handle(int v) : Node_handle(v) { } - }; - - - struct Dir_handle : Node_handle - { - Dir_handle() { } - Dir_handle(int v) : Node_handle(v) { } - }; - - - struct Symlink_handle : Node_handle - { - Symlink_handle() { } - Symlink_handle(int v) : Node_handle(v) { } - }; - + struct Node_handle; + struct File_handle; + struct Dir_handle; + struct Symlink_handle; /** * Type of client context embedded in each packet descriptor @@ -64,66 +37,10 @@ namespace File_system { */ struct Packet_ref; - typedef uint64_t seek_off_t; typedef uint64_t file_size_t; - - class Packet_descriptor : public ::Packet_descriptor - { - public: - - enum Opcode { READ, WRITE }; - - private: - - Node_handle _handle; /* node handle */ - Opcode _op; /* requested operation */ - seek_off_t _position; /* seek offset in bytes */ - size_t _length; /* transaction length in bytes */ - bool _success; /* indicates success of operation */ - Packet_ref *_ref; /* opaque reference used at the client side - for recognizing acknowledgements */ - - public: - - /** - * Constructor - */ - Packet_descriptor(off_t offset = 0, size_t size = 0) - : - ::Packet_descriptor(offset, size), _handle(-1), - _op(READ), _position(0), _length(0), _success(false) { } - - /** - * Constructor - * - * \param position seek offset in bytes (by default, append) - */ - Packet_descriptor(Packet_descriptor p, Packet_ref *ref, - Node_handle handle, Opcode op, size_t length, - seek_off_t position = ~0) - : - ::Packet_descriptor(p.offset(), p.size()), - _handle(handle), _op(op), - _position(position), _length(length), _success(false), - _ref(ref) - { } - - Node_handle handle() const { return _handle; } - Opcode operation() const { return _op; } - seek_off_t position() const { return _position; } - size_t length() const { return _length; } - bool succeeded() const { return _success; } - Packet_ref *ref() const { return _ref; } - - /* - * Accessors called at the server side - */ - void succeeded(bool b) { _success = b ? 1 : 0; } - void length(size_t length) { _length = length; } - }; - + class Packet_descriptor; /** * Flags as supplied to 'file', 'dir', and 'symlink' calls @@ -135,42 +52,9 @@ namespace File_system { typedef Rpc_in_buffer Name; typedef Rpc_in_buffer Path; - - struct Status - { - enum { - MODE_SYMLINK = 0020000, - MODE_FILE = 0100000, - MODE_DIRECTORY = 0040000, - }; - - /* - * XXX add access time - * XXX add executable bit - */ - - file_size_t size; - unsigned mode; - unsigned long inode; - - bool is_directory() const { return mode & MODE_DIRECTORY; } - bool is_symlink() const { return mode & MODE_SYMLINK; } - }; - - - struct Control { /* to manipulate the executable bit */ }; - - - /** - * Data structure returned when reading from a directory node - */ - struct Directory_entry - { - enum Type { TYPE_FILE, TYPE_DIRECTORY, TYPE_SYMLINK }; - Type type; - char name[MAX_NAME_LEN]; - }; - + struct Status; + struct Control; + struct Directory_entry; /* * Exception types @@ -186,169 +70,295 @@ namespace File_system { class Invalid_name : Exception { }; class Size_limit_reached : Exception { }; - - struct Session : public Genode::Session - { - enum { TX_QUEUE_SIZE = 16 }; - - typedef Packet_stream_policy Tx_policy; - - typedef Packet_stream_tx::Channel Tx; - - static const char *service_name() { return "File_system"; } - - virtual ~Session() { } - - /** - * Request client-side packet-stream interface of tx channel - */ - virtual Tx::Source *tx() { return 0; } - - /** - * Open or create file - * - * \throw Invalid_handle directory handle is invalid - * \throw Node_already_exists file cannot be created because a - * node with the same name already exists - * \throw Invalid_name file name contains invalid characters - * \throw Lookup_failed the name refers to a node other than a - * file - */ - virtual File_handle file(Dir_handle, Name const &name, Mode, bool create) = 0; - - /** - * Open or create symlink - */ - virtual Symlink_handle symlink(Dir_handle, Name const &name, bool create) = 0; - - /** - * Open or create directory - * - * \throw Permission_denied - * \throw Node_already_exists directory cannot be created because a - * node with the same name already exists - * \throw Lookup_failed path lookup failed because one element - * of 'path' does not exist - * \throw Name_too_long - * \throw No_space - */ - virtual Dir_handle dir(Path const &path, bool create) = 0; - - /** - * Open existing node - * - * The returned node handle can be used merely as argument for - * 'status'. - */ - virtual Node_handle node(Path const &path) = 0; - - /** - * Close file - */ - virtual void close(Node_handle) = 0; - - /** - * Request information about an open file or directory - */ - virtual Status status(Node_handle) = 0; - - /** - * Set information about an open file or directory - */ - virtual void control(Node_handle, Control) = 0; - - /** - * Delete file or directory - */ - virtual void unlink(Dir_handle, Name const &) = 0; - - /** - * Truncate or grow file to specified size - */ - virtual void truncate(File_handle, file_size_t size) = 0; - - /** - * Move and rename directory entry - */ - virtual void move(Dir_handle, Name const &from, - Dir_handle, Name const &to) = 0; - - /** - * Register handler that should be notified on node changes - */ - virtual void sigh(Node_handle, Signal_context_capability sigh) = 0; - - /** - * Synchronize file system - * - * This is only needed by file systems that maintain an internal - * cache, which needs to be flushed on certain occasions. Therefore, - * the default implementation just serves as a reminder. - */ - virtual void sync() { PWRN("sync() not implemented!"); } - - - /******************* - ** RPC interface ** - *******************/ - - GENODE_RPC(Rpc_tx_cap, Capability, _tx_cap); - GENODE_RPC_THROW(Rpc_file, File_handle, file, - GENODE_TYPE_LIST(Invalid_handle, Node_already_exists, - Invalid_name, Lookup_failed, - Permission_denied), - Dir_handle, Name const &, Mode, bool); - GENODE_RPC_THROW(Rpc_symlink, Symlink_handle, symlink, - GENODE_TYPE_LIST(Invalid_handle, Node_already_exists, - Invalid_name, Lookup_failed, Permission_denied), - Dir_handle, Name const &, bool); - GENODE_RPC_THROW(Rpc_dir, Dir_handle, dir, - GENODE_TYPE_LIST(Permission_denied, Node_already_exists, - Lookup_failed, Name_too_long, No_space), - Path const &, bool); - GENODE_RPC_THROW(Rpc_node, Node_handle, node, - GENODE_TYPE_LIST(Lookup_failed), - Path const &); - GENODE_RPC(Rpc_close, void, close, Node_handle); - GENODE_RPC(Rpc_status, Status, status, Node_handle); - GENODE_RPC(Rpc_control, void, control, Node_handle, Control); - GENODE_RPC_THROW(Rpc_unlink, void, unlink, - GENODE_TYPE_LIST(Permission_denied, Invalid_name, Lookup_failed), - Dir_handle, Name const &); - GENODE_RPC_THROW(Rpc_truncate, void, truncate, - GENODE_TYPE_LIST(Permission_denied, Invalid_handle), - File_handle, file_size_t); - GENODE_RPC_THROW(Rpc_move, void, move, - GENODE_TYPE_LIST(Permission_denied, Invalid_name, Lookup_failed), - Dir_handle, Name const &, Dir_handle, Name const &); - GENODE_RPC_THROW(Rpc_sigh, void, sigh, - GENODE_TYPE_LIST(Invalid_handle), - Node_handle, Signal_context_capability); - GENODE_RPC(Rpc_sync, void, sync); - - /* - * Manual type-list definition, needed because the RPC interface - * exceeds the maximum number of type-list elements supported by - * 'Genode::Meta::Type_list<>'. - */ - typedef Meta::Type_tuple - > > > > > > > > > > > > Rpc_functions; - }; + struct Session; } + +struct File_system::Node_handle +{ + int value; + + Node_handle() : value(-1) { } + Node_handle(int v) : value(v) { } + + bool valid() const { return value != -1; } +}; + + +struct File_system::File_handle : Node_handle +{ + File_handle() { } + File_handle(int v) : Node_handle(v) { } +}; + + +struct File_system::Dir_handle : Node_handle +{ + Dir_handle() { } + Dir_handle(int v) : Node_handle(v) { } +}; + + +struct File_system::Symlink_handle : Node_handle +{ + Symlink_handle() { } + Symlink_handle(int v) : Node_handle(v) { } +}; + + +class File_system::Packet_descriptor : public ::Packet_descriptor +{ + public: + + enum Opcode { READ, WRITE }; + + private: + + Node_handle _handle; /* node handle */ + Opcode _op; /* requested operation */ + seek_off_t _position; /* seek offset in bytes */ + size_t _length; /* transaction length in bytes */ + bool _success; /* indicates success of operation */ + Packet_ref *_ref; /* opaque reference used at the client side + for recognizing acknowledgements */ + + public: + + /** + * Constructor + */ + Packet_descriptor(off_t offset = 0, size_t size = 0) + : + ::Packet_descriptor(offset, size), _handle(-1), + _op(READ), _position(0), _length(0), _success(false) { } + + /** + * Constructor + * + * \param position seek offset in bytes (by default, append) + */ + Packet_descriptor(Packet_descriptor p, Packet_ref *ref, + Node_handle handle, Opcode op, size_t length, + seek_off_t position = ~0) + : + ::Packet_descriptor(p.offset(), p.size()), + _handle(handle), _op(op), + _position(position), _length(length), _success(false), + _ref(ref) + { } + + Node_handle handle() const { return _handle; } + Opcode operation() const { return _op; } + seek_off_t position() const { return _position; } + size_t length() const { return _length; } + bool succeeded() const { return _success; } + Packet_ref *ref() const { return _ref; } + + /* + * Accessors called at the server side + */ + void succeeded(bool b) { _success = b ? 1 : 0; } + void length(size_t length) { _length = length; } +}; + + +struct File_system::Status +{ + enum { + MODE_SYMLINK = 0020000, + MODE_FILE = 0100000, + MODE_DIRECTORY = 0040000, + }; + + /* + * XXX add access time + * XXX add executable bit + */ + + file_size_t size; + unsigned mode; + unsigned long inode; + + bool is_directory() const { return mode & MODE_DIRECTORY; } + bool is_symlink() const { return mode & MODE_SYMLINK; } +}; + + +struct File_system::Control { /* to manipulate the executable bit */ }; + + +/** + * Data structure returned when reading from a directory node + */ +struct File_system::Directory_entry +{ + enum Type { TYPE_FILE, TYPE_DIRECTORY, TYPE_SYMLINK }; + Type type; + char name[MAX_NAME_LEN]; +}; + + +struct File_system::Session : public Genode::Session +{ + enum { TX_QUEUE_SIZE = 16 }; + + typedef Packet_stream_policy Tx_policy; + + typedef Packet_stream_tx::Channel Tx; + + static const char *service_name() { return "File_system"; } + + virtual ~Session() { } + + /** + * Request client-side packet-stream interface of tx channel + */ + virtual Tx::Source *tx() { return 0; } + + /** + * Open or create file + * + * \throw Invalid_handle directory handle is invalid + * \throw Node_already_exists file cannot be created because a + * node with the same name already exists + * \throw Invalid_name file name contains invalid characters + * \throw Lookup_failed the name refers to a node other than a + * file + */ + virtual File_handle file(Dir_handle, Name const &name, Mode, bool create) = 0; + + /** + * Open or create symlink + */ + virtual Symlink_handle symlink(Dir_handle, Name const &name, bool create) = 0; + + /** + * Open or create directory + * + * \throw Permission_denied + * \throw Node_already_exists directory cannot be created because a + * node with the same name already exists + * \throw Lookup_failed path lookup failed because one element + * of 'path' does not exist + * \throw Name_too_long + * \throw No_space + */ + virtual Dir_handle dir(Path const &path, bool create) = 0; + + /** + * Open existing node + * + * The returned node handle can be used merely as argument for + * 'status'. + */ + virtual Node_handle node(Path const &path) = 0; + + /** + * Close file + */ + virtual void close(Node_handle) = 0; + + /** + * Request information about an open file or directory + */ + virtual Status status(Node_handle) = 0; + + /** + * Set information about an open file or directory + */ + virtual void control(Node_handle, Control) = 0; + + /** + * Delete file or directory + */ + virtual void unlink(Dir_handle, Name const &) = 0; + + /** + * Truncate or grow file to specified size + */ + virtual void truncate(File_handle, file_size_t size) = 0; + + /** + * Move and rename directory entry + */ + virtual void move(Dir_handle, Name const &from, + Dir_handle, Name const &to) = 0; + + /** + * Register handler that should be notified on node changes + */ + virtual void sigh(Node_handle, Signal_context_capability sigh) = 0; + + /** + * Synchronize file system + * + * This is only needed by file systems that maintain an internal + * cache, which needs to be flushed on certain occasions. Therefore, + * the default implementation just serves as a reminder. + */ + virtual void sync() { PWRN("sync() not implemented!"); } + + + /******************* + ** RPC interface ** + *******************/ + + GENODE_RPC(Rpc_tx_cap, Capability, _tx_cap); + GENODE_RPC_THROW(Rpc_file, File_handle, file, + GENODE_TYPE_LIST(Invalid_handle, Node_already_exists, + Invalid_name, Lookup_failed, + Permission_denied), + Dir_handle, Name const &, Mode, bool); + GENODE_RPC_THROW(Rpc_symlink, Symlink_handle, symlink, + GENODE_TYPE_LIST(Invalid_handle, Node_already_exists, + Invalid_name, Lookup_failed, Permission_denied), + Dir_handle, Name const &, bool); + GENODE_RPC_THROW(Rpc_dir, Dir_handle, dir, + GENODE_TYPE_LIST(Permission_denied, Node_already_exists, + Lookup_failed, Name_too_long, No_space), + Path const &, bool); + GENODE_RPC_THROW(Rpc_node, Node_handle, node, + GENODE_TYPE_LIST(Lookup_failed), + Path const &); + GENODE_RPC(Rpc_close, void, close, Node_handle); + GENODE_RPC(Rpc_status, Status, status, Node_handle); + GENODE_RPC(Rpc_control, void, control, Node_handle, Control); + GENODE_RPC_THROW(Rpc_unlink, void, unlink, + GENODE_TYPE_LIST(Permission_denied, Invalid_name, Lookup_failed), + Dir_handle, Name const &); + GENODE_RPC_THROW(Rpc_truncate, void, truncate, + GENODE_TYPE_LIST(Permission_denied, Invalid_handle), + File_handle, file_size_t); + GENODE_RPC_THROW(Rpc_move, void, move, + GENODE_TYPE_LIST(Permission_denied, Invalid_name, Lookup_failed), + Dir_handle, Name const &, Dir_handle, Name const &); + GENODE_RPC_THROW(Rpc_sigh, void, sigh, + GENODE_TYPE_LIST(Invalid_handle), + Node_handle, Signal_context_capability); + GENODE_RPC(Rpc_sync, void, sync); + + /* + * Manual type-list definition, needed because the RPC interface + * exceeds the maximum number of type-list elements supported by + * 'Genode::Meta::Type_list<>'. + */ + typedef Meta::Type_tuple + > > > > > > > > > > > > Rpc_functions; +}; + #endif /* _INCLUDE__FILE_SYSTEM_SESSION__FILE_SYSTEM_SESSION_H_ */ diff --git a/repos/os/include/file_system_session/rpc_object.h b/repos/os/include/file_system_session/rpc_object.h index 0c1ea4c9b..ab199b621 100644 --- a/repos/os/include/file_system_session/rpc_object.h +++ b/repos/os/include/file_system_session/rpc_object.h @@ -18,36 +18,35 @@ #include #include -namespace File_system { +namespace File_system { class Session_rpc_object; } - class Session_rpc_object : public Genode::Rpc_object - { - protected: +class File_system::Session_rpc_object : public Genode::Rpc_object +{ + protected: - Packet_stream_tx::Rpc_object _tx; + Packet_stream_tx::Rpc_object _tx; - public: + public: - /** - * Constructor - * - * \param tx_ds dataspace used as communication buffer - * for the tx packet stream - * \param ep entry point used for packet-stream channel - */ - Session_rpc_object(Dataspace_capability tx_ds, Rpc_entrypoint &ep) - : _tx(tx_ds, ep) { } + /** + * Constructor + * + * \param tx_ds dataspace used as communication buffer + * for the tx packet stream + * \param ep entry point used for packet-stream channel + */ + Session_rpc_object(Dataspace_capability tx_ds, Rpc_entrypoint &ep) + : _tx(tx_ds, ep) { } - /** - * Return capability to packet-stream channel - * - * This function is called by the client via an RPC call at session - * construction time. - */ - Capability _tx_cap() { return _tx.cap(); } + /** + * Return capability to packet-stream channel + * + * This function is called by the client via an RPC call at session + * construction time. + */ + Capability _tx_cap() { return _tx.cap(); } - Tx::Sink *tx_sink() { return _tx.sink(); } - }; -} + Tx::Sink *tx_sink() { return _tx.sink(); } +}; #endif /* _INCLUDE__FILE_SYSTEM_SESSION__SERVER_H_ */ diff --git a/repos/os/include/framebuffer_session/client.h b/repos/os/include/framebuffer_session/client.h index 1774403fd..bb112f2b6 100644 --- a/repos/os/include/framebuffer_session/client.h +++ b/repos/os/include/framebuffer_session/client.h @@ -17,27 +17,27 @@ #include #include -namespace Framebuffer { +namespace Framebuffer { struct Session_client; } - struct Session_client : Genode::Rpc_client - { - explicit Session_client(Session_capability session) - : Genode::Rpc_client(session) { } - Genode::Dataspace_capability dataspace() override { - return call(); } +struct Framebuffer::Session_client : Genode::Rpc_client +{ + explicit Session_client(Session_capability session) + : Genode::Rpc_client(session) { } - Mode mode() const override { return call(); } + Genode::Dataspace_capability dataspace() override { + return call(); } - void mode_sigh(Genode::Signal_context_capability sigh) override { - call(sigh); } + Mode mode() const override { return call(); } - void sync_sigh(Genode::Signal_context_capability sigh) override { - call(sigh); } + void mode_sigh(Genode::Signal_context_capability sigh) override { + call(sigh); } - void refresh(int x, int y, int w, int h) override { - call(x, y, w, h); } - }; -} + void sync_sigh(Genode::Signal_context_capability sigh) override { + call(sigh); } + + void refresh(int x, int y, int w, int h) override { + call(x, y, w, h); } +}; #endif /* _INCLUDE__FRAMEBUFFER_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/framebuffer_session/connection.h b/repos/os/include/framebuffer_session/connection.h index cab80dfc3..e759e9f49 100644 --- a/repos/os/include/framebuffer_session/connection.h +++ b/repos/os/include/framebuffer_session/connection.h @@ -18,59 +18,59 @@ #include #include -namespace Framebuffer { +namespace Framebuffer { class Connection; } - class Connection : public Genode::Connection, - public Session_client - { - private: - /** - * Create session and return typed session capability - */ - Session_capability _connect(unsigned width, unsigned height, - Mode::Format format) - { - using namespace Genode; +class Framebuffer::Connection : public Genode::Connection, + public Session_client +{ + private: - enum { ARGBUF_SIZE = 128 }; - char argbuf[ARGBUF_SIZE]; + /** + * Create session and return typed session capability + */ + Session_capability _connect(unsigned width, unsigned height, + Mode::Format format) + { + using namespace Genode; - /* donate ram quota for storing server-side meta data */ - Genode::strncpy(argbuf, "ram_quota=8K", sizeof(argbuf)); + enum { ARGBUF_SIZE = 128 }; + char argbuf[ARGBUF_SIZE]; - /* set optional session-constructor arguments */ - if (width) - Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_width", width); - if (height) - Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_height", height); - if (format != Mode::INVALID) - Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_format", format); + /* donate ram quota for storing server-side meta data */ + Genode::strncpy(argbuf, "ram_quota=8K", sizeof(argbuf)); - return session(argbuf); - } + /* set optional session-constructor arguments */ + if (width) + Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_width", width); + if (height) + Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_height", height); + if (format != Mode::INVALID) + Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_format", format); - public: + return session(argbuf); + } - /** - * Constructor - * - * \param width desired frame-buffer width - * \param height desired frame-buffer height - * \param mode desired pixel format - * - * The specified values are not enforced. After creating the - * session, you should validate the actual frame-buffer attributes - * by calling the 'info' function of the frame-buffer interface. - */ - Connection(unsigned width = 0, - unsigned height = 0, - Mode::Format format = Mode::INVALID) - : - Genode::Connection(_connect(width, height, format)), - Session_client(cap()) - { } - }; -} + public: + + /** + * Constructor + * + * \param width desired frame-buffer width + * \param height desired frame-buffer height + * \param mode desired pixel format + * + * The specified values are not enforced. After creating the + * session, you should validate the actual frame-buffer attributes + * by calling the 'info' function of the frame-buffer interface. + */ + Connection(unsigned width = 0, + unsigned height = 0, + Mode::Format format = Mode::INVALID) + : + Genode::Connection(_connect(width, height, format)), + Session_client(cap()) + { } +}; #endif /* _INCLUDE__FRAMEBUFFER_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/framebuffer_session/framebuffer_session.h b/repos/os/include/framebuffer_session/framebuffer_session.h index 4edabc05c..381452009 100644 --- a/repos/os/include/framebuffer_session/framebuffer_session.h +++ b/repos/os/include/framebuffer_session/framebuffer_session.h @@ -20,110 +20,114 @@ namespace Framebuffer { - /** - * Framebuffer mode info as returned by 'Framebuffer::Session::mode()' - */ - struct Mode - { - public: - - /** - * Pixel formats - */ - enum Format { INVALID, RGB565 }; - - static Genode::size_t bytes_per_pixel(Format format) - { - if (format == RGB565) return 2; - return 0; - } - - private: - - int _width, _height; - Format _format; - - public: - - Mode() : _width(0), _height(0), _format(INVALID) { } - - Mode(int width, int height, Format format) - : _width(width), _height(height), _format(format) { } - - int width() const { return _width; } - int height() const { return _height; } - Format format() const { return _format; } - - /** - * Return number of bytes per pixel - */ - Genode::size_t bytes_per_pixel() const { - return bytes_per_pixel(_format); } - }; - - - struct Session : Genode::Session - { - static const char *service_name() { return "Framebuffer"; } - - virtual ~Session() { } - - /** - * Request dataspace representing the logical frame buffer - * - * By calling this function, the framebuffer client enables the server - * to reallocate the framebuffer dataspace (e.g., on mode changes). - * Hence, prior calling this function, the client should make sure to - * have detached the previously requested dataspace from its local - * address space. - */ - virtual Genode::Dataspace_capability dataspace() = 0; - - /** - * Request display-mode properties of the framebuffer ready to be - * obtained via the 'dataspace()' function - */ - virtual Mode mode() const = 0; - - /** - * Register signal handler to be notified on mode changes - * - * The framebuffer server may support changing the display mode on the - * fly. For example, a virtual framebuffer presented in a window may - * get resized according to the window dimensions. By installing a - * signal handler for mode changes, the framebuffer client can respond - * to such changes. The new mode can be obtained using the 'mode()' - * function. However, from the client's perspective, the original mode - * stays in effect until the it calls 'dataspace()' again. - */ - virtual void mode_sigh(Genode::Signal_context_capability sigh) = 0; - - /** - * Flush specified pixel region - * - * \param x,y,w,h region to be updated on physical frame buffer - */ - virtual void refresh(int x, int y, int w, int h) = 0; - - /** - * Register signal handler for refresh synchronization - */ - virtual void sync_sigh(Genode::Signal_context_capability) = 0; - - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace); - GENODE_RPC(Rpc_mode, Mode, mode); - GENODE_RPC(Rpc_refresh, void, refresh, int, int, int, int); - GENODE_RPC(Rpc_mode_sigh, void, mode_sigh, Genode::Signal_context_capability); - GENODE_RPC(Rpc_sync_sigh, void, sync_sigh, Genode::Signal_context_capability); - - GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_mode, Rpc_mode_sigh, Rpc_refresh, - Rpc_sync_sigh); - }; + struct Mode; + struct Session; } + +/** + * Framebuffer mode info as returned by 'Framebuffer::Session::mode()' + */ +struct Framebuffer::Mode +{ + public: + + /** + * Pixel formats + */ + enum Format { INVALID, RGB565 }; + + static Genode::size_t bytes_per_pixel(Format format) + { + if (format == RGB565) return 2; + return 0; + } + + private: + + int _width, _height; + Format _format; + + public: + + Mode() : _width(0), _height(0), _format(INVALID) { } + + Mode(int width, int height, Format format) + : _width(width), _height(height), _format(format) { } + + int width() const { return _width; } + int height() const { return _height; } + Format format() const { return _format; } + + /** + * Return number of bytes per pixel + */ + Genode::size_t bytes_per_pixel() const { + return bytes_per_pixel(_format); } +}; + + +struct Framebuffer::Session : Genode::Session +{ + static const char *service_name() { return "Framebuffer"; } + + virtual ~Session() { } + + /** + * Request dataspace representing the logical frame buffer + * + * By calling this function, the framebuffer client enables the server + * to reallocate the framebuffer dataspace (e.g., on mode changes). + * Hence, prior calling this function, the client should make sure to + * have detached the previously requested dataspace from its local + * address space. + */ + virtual Genode::Dataspace_capability dataspace() = 0; + + /** + * Request display-mode properties of the framebuffer ready to be + * obtained via the 'dataspace()' function + */ + virtual Mode mode() const = 0; + + /** + * Register signal handler to be notified on mode changes + * + * The framebuffer server may support changing the display mode on the + * fly. For example, a virtual framebuffer presented in a window may + * get resized according to the window dimensions. By installing a + * signal handler for mode changes, the framebuffer client can respond + * to such changes. The new mode can be obtained using the 'mode()' + * function. However, from the client's perspective, the original mode + * stays in effect until the it calls 'dataspace()' again. + */ + virtual void mode_sigh(Genode::Signal_context_capability sigh) = 0; + + /** + * Flush specified pixel region + * + * \param x,y,w,h region to be updated on physical frame buffer + */ + virtual void refresh(int x, int y, int w, int h) = 0; + + /** + * Register signal handler for refresh synchronization + */ + virtual void sync_sigh(Genode::Signal_context_capability) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace); + GENODE_RPC(Rpc_mode, Mode, mode); + GENODE_RPC(Rpc_refresh, void, refresh, int, int, int, int); + GENODE_RPC(Rpc_mode_sigh, void, mode_sigh, Genode::Signal_context_capability); + GENODE_RPC(Rpc_sync_sigh, void, sync_sigh, Genode::Signal_context_capability); + + GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_mode, Rpc_mode_sigh, Rpc_refresh, + Rpc_sync_sigh); +}; + #endif /* _INCLUDE__FRAMEBUFFER_SESSION__FRAMEBUFFER_SESSION_H_ */ diff --git a/repos/os/include/gpio/component.h b/repos/os/include/gpio/component.h index b1d137318..13b541c43 100644 --- a/repos/os/include/gpio/component.h +++ b/repos/os/include/gpio/component.h @@ -20,6 +20,7 @@ #include namespace Gpio { + class Session_component; class Root; }; diff --git a/repos/os/include/gpio/config.h b/repos/os/include/gpio/config.h index 760f90303..8482cca60 100644 --- a/repos/os/include/gpio/config.h +++ b/repos/os/include/gpio/config.h @@ -32,6 +32,7 @@ #include namespace Gpio { + class Invalid_gpio_number : Genode::Exception {}; class Invalid_mode : Genode::Exception {}; @@ -39,7 +40,8 @@ namespace Gpio { } -void Gpio::process_config(Gpio::Driver &driver) { +void Gpio::process_config(Gpio::Driver &driver) +{ try { Genode::Xml_node gpio_node = Genode::config()->xml_node().sub_node("gpio"); diff --git a/repos/os/include/gpio/driver.h b/repos/os/include/gpio/driver.h index 6d675a0b0..6e5f867b8 100644 --- a/repos/os/include/gpio/driver.h +++ b/repos/os/include/gpio/driver.h @@ -17,12 +17,11 @@ /* Genode includes */ #include -namespace Gpio { - struct Driver; -} +namespace Gpio { struct Driver; } -struct Gpio::Driver { +struct Gpio::Driver +{ /** * Set direction of GPIO pin, whether it's an input or output one * diff --git a/repos/os/include/gpio_session/client.h b/repos/os/include/gpio_session/client.h index b25055574..5fa76dd7d 100644 --- a/repos/os/include/gpio_session/client.h +++ b/repos/os/include/gpio_session/client.h @@ -19,22 +19,23 @@ #include #include -namespace Gpio { +namespace Gpio { struct Session_client; } - struct Session_client : Genode::Rpc_client - { - explicit Session_client(Session_capability session) - : Genode::Rpc_client(session) { } - void direction(Direction d) { call(d); } - void write(bool level) { call(level); } - bool read() { return call(); } - void debouncing(unsigned int us) { call(us); } - void irq_type(Irq_type it) { call(it); } - void irq_enable(bool enable) { call(enable); } - void irq_sigh(Genode::Signal_context_capability cap) { - call(cap); } - }; -} +struct Gpio::Session_client : Genode::Rpc_client +{ + explicit Session_client(Session_capability session) + : Genode::Rpc_client(session) { } + + void direction(Direction d) override { call(d); } + void write(bool level) override { call(level); } + bool read() override { return call(); } + void debouncing(unsigned int us) override { call(us); } + void irq_type(Irq_type it) override { call(it); } + void irq_enable(bool enable) override { call(enable); } + + void irq_sigh(Genode::Signal_context_capability cap) override { + call(cap); } +}; #endif /* _INCLUDE__GPIO_SESSION_H__CLIENT_H_ */ diff --git a/repos/os/include/gpio_session/connection.h b/repos/os/include/gpio_session/connection.h index 78a2284e4..5a44a0f5e 100644 --- a/repos/os/include/gpio_session/connection.h +++ b/repos/os/include/gpio_session/connection.h @@ -19,14 +19,13 @@ #include #include -namespace Gpio { +namespace Gpio { struct Connection; } - struct Connection : Genode::Connection, Session_client - { - Connection(unsigned long gpio_pin) - : Genode::Connection(session("ram_quota=8K, gpio=%zd", gpio_pin)), - Session_client(cap()) { } - }; -} +struct Gpio::Connection : Genode::Connection, Session_client +{ + Connection(unsigned long gpio_pin) + : Genode::Connection(session("ram_quota=8K, gpio=%zd", gpio_pin)), + Session_client(cap()) { } +}; #endif /* _INCLUDE__GPIO_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/gpio_session/gpio_session.h b/repos/os/include/gpio_session/gpio_session.h index 9ed292607..532036c9f 100644 --- a/repos/os/include/gpio_session/gpio_session.h +++ b/repos/os/include/gpio_session/gpio_session.h @@ -20,85 +20,84 @@ #include #include -namespace Gpio { - - struct Session : Genode::Session - { - static const char *service_name() { return "Gpio"; } - - enum Direction { IN, OUT }; - - enum Irq_type { LOW_LEVEL, HIGH_LEVEL, FALLING_EDGE, RISING_EDGE }; +namespace Gpio { struct Session; } - virtual ~Session() { } +struct Gpio::Session : Genode::Session +{ + static const char *service_name() { return "Gpio"; } - /** - * Configure direction of the GPIO pin - * - * \param d direction of the pin - */ - virtual void direction(Direction d) = 0; + enum Direction { IN, OUT }; - /** - * Write the logic level of the GPIO pin - * - * \param enable logic level on the pin - */ - virtual void write(bool enable) = 0; + enum Irq_type { LOW_LEVEL, HIGH_LEVEL, FALLING_EDGE, RISING_EDGE }; - /** - * Read the logic level on a specified GPIO pin - * - * \return level on specified GPIO pin - */ - virtual bool read() = 0; + virtual ~Session() { } - /** - * Set the debouncing time - * - * \param us debouncing time in microseconds, zero means no debouncing - */ - virtual void debouncing(unsigned int us) = 0; + /** + * Configure direction of the GPIO pin + * + * \param d direction of the pin + */ + virtual void direction(Direction d) = 0; - /** - * Configure the type of interrupt for the GPIO pin - * - * \param it type of IRQ - */ - virtual void irq_type(Irq_type it) = 0; + /** + * Write the logic level of the GPIO pin + * + * \param enable logic level on the pin + */ + virtual void write(bool enable) = 0; - /** - * Enable or disable the interrupt of the GPIO pin - * - * \param enable interrupt status( true - enable, false - disable) - */ - virtual void irq_enable(bool enable) = 0; + /** + * Read the logic level on a specified GPIO pin + * + * \return level on specified GPIO pin + */ + virtual bool read() = 0; - /** - * Register signal handler to be notified on interrupt - * - * \param cap capability of signal-context to handle GPIO interrupt - */ - virtual void irq_sigh(Genode::Signal_context_capability cap) = 0; + /** + * Set the debouncing time + * + * \param us debouncing time in microseconds, zero means no debouncing + */ + virtual void debouncing(unsigned int us) = 0; + + /** + * Configure the type of interrupt for the GPIO pin + * + * \param it type of IRQ + */ + virtual void irq_type(Irq_type it) = 0; + + /** + * Enable or disable the interrupt of the GPIO pin + * + * \param enable interrupt status( true - enable, false - disable) + */ + virtual void irq_enable(bool enable) = 0; + + /** + * Register signal handler to be notified on interrupt + * + * \param cap capability of signal-context to handle GPIO interrupt + */ + virtual void irq_sigh(Genode::Signal_context_capability cap) = 0; - /******************* - ** RPC interface ** - *******************/ + /******************* + ** RPC interface ** + *******************/ - GENODE_RPC(Rpc_direction, void, direction, Direction); - GENODE_RPC(Rpc_write, void, write, bool); - GENODE_RPC(Rpc_read, bool, read); - GENODE_RPC(Rpc_debouncing, void, debouncing, unsigned int); - GENODE_RPC(Rpc_irq_type, void, irq_type, Irq_type); - GENODE_RPC(Rpc_irq_enable, void, irq_enable, bool); - GENODE_RPC(Rpc_irq_sigh, void, irq_sigh, Genode::Signal_context_capability); + GENODE_RPC(Rpc_direction, void, direction, Direction); + GENODE_RPC(Rpc_write, void, write, bool); + GENODE_RPC(Rpc_read, bool, read); + GENODE_RPC(Rpc_debouncing, void, debouncing, unsigned int); + GENODE_RPC(Rpc_irq_type, void, irq_type, Irq_type); + GENODE_RPC(Rpc_irq_enable, void, irq_enable, bool); + GENODE_RPC(Rpc_irq_sigh, void, irq_sigh, Genode::Signal_context_capability); - GENODE_RPC_INTERFACE(Rpc_direction, Rpc_write, Rpc_read, - Rpc_debouncing, Rpc_irq_type, Rpc_irq_enable, - Rpc_irq_sigh); - }; -} + GENODE_RPC_INTERFACE(Rpc_direction, Rpc_write, Rpc_read, + Rpc_debouncing, Rpc_irq_type, Rpc_irq_enable, + Rpc_irq_sigh); +}; #endif /* _INCLUDE__GPIO_SESSION__GPIO_SESSION_H_ */ diff --git a/repos/os/include/init/child.h b/repos/os/include/init/child.h index 03d24edc5..66b67b864 100644 --- a/repos/os/include/init/child.h +++ b/repos/os/include/init/child.h @@ -25,15 +25,24 @@ #include #include +namespace Init { + + class Routed_service; + class Name_registry; + class Child_registry; + class Child; +} + + +/*************** + ** Utilities ** + ***************/ + namespace Init { extern bool config_verbose; - /*************** - ** Utilities ** - ***************/ - inline long read_priority(Genode::Xml_node start_node) { long priority = Genode::Cpu_session::DEFAULT_PRIORITY; @@ -187,612 +196,609 @@ namespace Init { /* if no if-arg node exists, the condition is met */ return true; } +} +/** + * Init-specific representation of a child service + * + * For init, we introduce this 'Service' variant that distinguishes two + * phases, declared and announced. A 'Routed_service' object is created + * when a '' declaration is found in init's configuration. + * At that time, however, no children including the server do yet exist. + * If, at this stage, a client tries to open a session to this service, + * the client get enqueued in a list of applicants and blocked. When + * the server officially announces its service and passes over the root + * capability, the 'Routed_service' enters the announced stage and any + * applicants get unblocked. + */ +class Init::Routed_service : public Genode::Service +{ + private: + + Genode::Root_capability _root; + bool _announced; + Genode::Server *_server; + + struct Applicant : public Genode::Cancelable_lock, + public Genode::List::Element + { + Applicant() : Cancelable_lock(Genode::Lock::LOCKED) { } + }; + + Genode::Lock _applicants_lock; + Genode::List _applicants; + + public: + + /** + * Constructor + * + * \param name name of service + * \param server server providing the service + */ + Routed_service(const char *name, + Genode::Server *server) + : Service(name), _announced(false), _server(server) { } + + Genode::Server *server() const { return _server; } + + void announce(Genode::Root_capability root) + { + Genode::Lock::Guard guard(_applicants_lock); + + _root = root; + _announced = true; + + /* wake up aspiring clients */ + for (Applicant *a; (a = _applicants.first()); ) { + _applicants.remove(a); + a->unlock(); + } + } + + Genode::Session_capability session(const char *args, + Genode::Affinity const &affinity) + { + /* + * This function is called from the context of the client's + * activation thread. If the service is not yet announced, + * we let the client block. + */ + _applicants_lock.lock(); + if (!_announced) { + Applicant myself; + _applicants.insert(&myself); + _applicants_lock.unlock(); + myself.lock(); + } else + _applicants_lock.unlock(); + + Genode::Session_capability cap; + try { cap = Genode::Root_client(_root).session(args, affinity); } + catch (Genode::Root::Invalid_args) { throw Invalid_args(); } + catch (Genode::Root::Unavailable) { throw Unavailable(); } + catch (Genode::Root::Quota_exceeded) { throw Quota_exceeded(); } + catch (Genode::Ipc_error) { throw Unavailable(); } + + if (!cap.valid()) + throw Unavailable(); + + return cap; + } + + void upgrade(Genode::Session_capability sc, const char *args) + { + try { Genode::Root_client(_root).upgrade(sc, args); } + catch (Genode::Root::Invalid_args) { throw Invalid_args(); } + catch (Genode::Ipc_error) { throw Unavailable(); } + } + + void close(Genode::Session_capability sc) + { + try { Genode::Root_client(_root).close(sc); } + catch (Genode::Ipc_error) { throw Genode::Blocking_canceled(); } + } +}; + + +/** + * Interface for name database + */ +struct Init::Name_registry +{ + virtual ~Name_registry() { } + /** - * Init-specific representation of a child service + * Check if specified name is unique * - * For init, we introduce this 'Service' variant that distinguishes two - * phases, declared and announced. A 'Routed_service' object is created - * when a '' declaration is found in init's configuration. - * At that time, however, no children including the server do yet exist. - * If, at this stage, a client tries to open a session to this service, - * the client get enqueued in a list of applicants and blocked. When - * the server officially announces its service and passes over the root - * capability, the 'Routed_service' enters the announced stage and any - * applicants get unblocked. + * \return false if name already exists */ - class Routed_service : public Genode::Service - { - private: + virtual bool is_unique(const char *name) const = 0; - Genode::Root_capability _root; - bool _announced; - Genode::Server *_server; + /** + * Find server with specified name + */ + virtual Genode::Server *lookup_server(const char *name) const = 0; +}; - struct Applicant : public Genode::Cancelable_lock, - public Genode::List::Element - { - Applicant() : Cancelable_lock(Genode::Lock::LOCKED) { } - }; - Genode::Lock _applicants_lock; - Genode::List _applicants; +class Init::Child : Genode::Child_policy +{ + public: - public: + /** + * Exception type + */ + class Child_name_is_not_unique { }; + + private: + + friend class Child_registry; + + Genode::List_element _list_element; + + Genode::Xml_node _start_node; + + Genode::Xml_node _default_route_node; + + Name_registry *_name_registry; + + /** + * Unique child name and file name of ELF binary + */ + struct Name + { + enum { MAX_NAME_LEN = 64 }; + char file[MAX_NAME_LEN]; + char unique[MAX_NAME_LEN]; /** * Constructor * - * \param name name of service - * \param server server providing the service + * Obtains file name and unique process name from XML node + * + * \param start_node XML start node + * \param registry registry tracking unique names */ - Routed_service(const char *name, - Genode::Server *server) - : Service(name), _announced(false), _server(server) { } + Name(Genode::Xml_node start_node, Name_registry const *registry) { + try { + start_node.attribute("name").value(unique, sizeof(unique)); } + catch (Genode::Xml_node::Nonexistent_attribute) { + PWRN("Missing 'name' attribute in '' entry.\n"); + throw; } - Genode::Server *server() const { return _server; } - - void announce(Genode::Root_capability root) - { - Genode::Lock::Guard guard(_applicants_lock); - - _root = root; - _announced = true; - - /* wake up aspiring clients */ - for (Applicant *a; (a = _applicants.first()); ) { - _applicants.remove(a); - a->unlock(); + /* check for a name confict with the other children */ + if (!registry->is_unique(unique)) { + PERR("Child name \"%s\" is not unique", unique); + throw Child_name_is_not_unique(); } + + /* use name as default file name if not declared otherwise */ + Genode::strncpy(file, unique, sizeof(file)); + + /* check for a binary declaration */ + try { + Genode::Xml_node binary = start_node.sub_node("binary"); + binary.attribute("name").value(file, sizeof(file)); + } catch (...) { } + } + } _name; + + /** + * Platform-specific PD-session arguments + */ + struct Pd_args : Genode::Native_pd_args + { + Pd_args(Genode::Xml_node start_node); + } _pd_args; + + struct Read_quota + { + void warn_unsuff_quota(Genode::size_t const avail) + { + using namespace Genode; + if (!config_verbose) { return; } + Genode::printf("Warning: Specified quota exceeds available quota.\n"); + Genode::printf(" Proceeding with a quota of %zu.\n", avail); } - Genode::Session_capability session(const char *args, - Genode::Affinity const &affinity) + Read_quota(Genode::Xml_node start_node, + Genode::size_t & ram_quota, + Genode::size_t & cpu_quota, + bool & constrain_phys) { + Genode::Number_of_bytes ram_bytes = 0; + Genode::size_t cpu_percent = 0; + + try { + Genode::Xml_node rsc = start_node.sub_node("resource"); + for (;; rsc = rsc.next("resource")) { + try { + if (rsc.attribute("name").has_value("RAM")) { + rsc.attribute("quantum").value(&ram_bytes); + constrain_phys = rsc.attribute("constrain_phys").has_value("yes"); + } else if (rsc.attribute("name").has_value("CPU")) { + rsc.attribute("quantum").value(&cpu_percent); } + } catch (...) { } + } + } catch (...) { } + ram_quota = ram_bytes; + cpu_quota = Genode::Cpu_session::pc_to_quota(cpu_percent); + /* - * This function is called from the context of the client's - * activation thread. If the service is not yet announced, - * we let the client block. + * If the configured RAM quota exceeds our own quota, we donate + * all remaining quota to the child but we need to count in + * our allocation of the child meta data from the heap. + * Hence, we preserve some of our own quota. */ - _applicants_lock.lock(); - if (!_announced) { - Applicant myself; - _applicants.insert(&myself); - _applicants_lock.unlock(); - myself.lock(); - } else - _applicants_lock.unlock(); + Genode::size_t const ram_avail = avail_slack_ram_quota(); + if (ram_quota > ram_avail) { + ram_quota = ram_avail; + warn_unsuff_quota(ram_avail); + } - Genode::Session_capability cap; - try { cap = Genode::Root_client(_root).session(args, affinity); } - catch (Genode::Root::Invalid_args) { throw Invalid_args(); } - catch (Genode::Root::Unavailable) { throw Unavailable(); } - catch (Genode::Root::Quota_exceeded) { throw Quota_exceeded(); } - catch (Genode::Ipc_error) { throw Unavailable(); } - - if (!cap.valid()) - throw Unavailable(); - - return cap; + Genode::size_t const cpu_avail = avail_slack_cpu_quota(); + if (cpu_quota > cpu_avail) { + cpu_quota = cpu_avail; + warn_unsuff_quota(cpu_avail); + } } - - void upgrade(Genode::Session_capability sc, const char *args) - { - try { Genode::Root_client(_root).upgrade(sc, args); } - catch (Genode::Root::Invalid_args) { throw Invalid_args(); } - catch (Genode::Ipc_error) { throw Unavailable(); } - } - - void close(Genode::Session_capability sc) - { - try { Genode::Root_client(_root).close(sc); } - catch (Genode::Ipc_error) { throw Genode::Blocking_canceled(); } - } - }; - - - /** - * Interface for name database - */ - struct Name_registry - { - virtual ~Name_registry() { } + }; /** - * Check if specified name is unique - * - * \return false if name already exists + * Resources assigned to the child */ - virtual bool is_unique(const char *name) const = 0; + struct Resources : Read_quota + { + long prio_levels_log2; + long priority; + Genode::Affinity affinity; + Genode::size_t ram_quota; + Genode::size_t cpu_quota; + bool constrain_phys; + Genode::Ram_connection ram; + Genode::Cpu_connection cpu; + Genode::Rm_connection rm; + + Resources(Genode::Xml_node start_node, const char *label, + long prio_levels_log2, + Genode::Affinity::Space const &affinity_space) + : + Read_quota(start_node, ram_quota, cpu_quota, constrain_phys), + prio_levels_log2(prio_levels_log2), + priority(read_priority(start_node)), + affinity(affinity_space, + read_affinity_location(affinity_space, start_node)), + ram(label), + cpu(label, + priority*(Genode::Cpu_session::PRIORITY_LIMIT >> prio_levels_log2), + affinity) + { + /* deduce session costs from usable ram quota */ + Genode::size_t session_donations = Genode::Rm_connection::RAM_QUOTA + + Genode::Cpu_connection::RAM_QUOTA + + Genode::Ram_connection::RAM_QUOTA; + + if (ram_quota > session_donations) + ram_quota -= session_donations; + else ram_quota = 0; + + ram.ref_account(Genode::env()->ram_session_cap()); + Genode::env()->ram_session()->transfer_quota(ram.cap(), ram_quota); + + cpu.ref_account(Genode::env()->cpu_session_cap()); + Genode::env()->cpu_session()->transfer_quota(cpu.cap(), cpu_quota); + } + } _resources; + + /* + * Entry point used for serving the parent interface and the + * locally provided ROM sessions for the 'config' and 'binary' + * files. + */ + enum { ENTRYPOINT_STACK_SIZE = 12*1024 }; + Genode::Rpc_entrypoint _entrypoint; /** - * Find server with specified name + * ELF binary */ - virtual Genode::Server *lookup_server(const char *name) const = 0; - }; + Genode::Rom_connection _binary_rom; + Genode::Dataspace_capability _binary_rom_ds; + /** + * Private child configuration + */ + Init::Child_config _config; + /** + * Each child of init can act as a server + */ + Genode::Server _server; - class Child_registry; + Genode::Child _child; + Genode::Service_registry *_parent_services; + Genode::Service_registry *_child_services; - class Child : Genode::Child_policy - { - public: + /** + * Policy helpers + */ + Init::Child_policy_enforce_labeling _labeling_policy; + Init::Child_policy_handle_cpu_priorities _priority_policy; + Init::Child_policy_provide_rom_file _config_policy; + Init::Child_policy_provide_rom_file _binary_policy; + Init::Child_policy_redirect_rom_file _configfile_policy; + Init::Child_policy_pd_args _pd_args_policy; + Init::Child_policy_ram_phys _ram_session_policy; - /** - * Exception type - */ - class Child_name_is_not_unique { }; + public: - private: + Child(Genode::Xml_node start_node, + Genode::Xml_node default_route_node, + Name_registry *name_registry, + long prio_levels_log2, + Genode::Affinity::Space const &affinity_space, + Genode::Service_registry *parent_services, + Genode::Service_registry *child_services, + Genode::Cap_session *cap_session) + : + _list_element(this), + _start_node(start_node), + _default_route_node(default_route_node), + _name_registry(name_registry), + _name(start_node, name_registry), + _pd_args(start_node), + _resources(start_node, _name.unique, prio_levels_log2, affinity_space), + _entrypoint(cap_session, ENTRYPOINT_STACK_SIZE, _name.unique, false, _resources.affinity.location()), + _binary_rom(_name.file, _name.unique), + _binary_rom_ds(_binary_rom.dataspace()), + _config(_resources.ram.cap(), start_node), + _server(_resources.ram.cap()), + _child(_binary_rom_ds, _resources.ram.cap(), + _resources.cpu.cap(), _resources.rm.cap(), &_entrypoint, this), + _parent_services(parent_services), + _child_services(child_services), + _labeling_policy(_name.unique), + _priority_policy(_resources.prio_levels_log2, _resources.priority), + _config_policy("config", _config.dataspace(), &_entrypoint), + _binary_policy("binary", _binary_rom_ds, &_entrypoint), + _configfile_policy("config", _config.filename()), + _pd_args_policy(&_pd_args), + _ram_session_policy(_resources.constrain_phys) + { + using namespace Genode; - friend class Child_registry; + if (_resources.ram_quota == 0) + PWRN("no valid RAM resource for child \"%s\"", _name.unique); - Genode::List_element _list_element; - - Genode::Xml_node _start_node; - - Genode::Xml_node _default_route_node; - - Name_registry *_name_registry; - - /** - * Unique child name and file name of ELF binary - */ - struct Name - { - enum { MAX_NAME_LEN = 64 }; - char file[MAX_NAME_LEN]; - char unique[MAX_NAME_LEN]; - - /** - * Constructor - * - * Obtains file name and unique process name from XML node - * - * \param start_node XML start node - * \param registry registry tracking unique names - */ - Name(Genode::Xml_node start_node, Name_registry const *registry) { - try { - start_node.attribute("name").value(unique, sizeof(unique)); } - catch (Genode::Xml_node::Nonexistent_attribute) { - PWRN("Missing 'name' attribute in '' entry.\n"); - throw; } - - /* check for a name confict with the other children */ - if (!registry->is_unique(unique)) { - PERR("Child name \"%s\" is not unique", unique); - throw Child_name_is_not_unique(); - } - - /* use name as default file name if not declared otherwise */ - Genode::strncpy(file, unique, sizeof(file)); - - /* check for a binary declaration */ - try { - Genode::Xml_node binary = start_node.sub_node("binary"); - binary.attribute("name").value(file, sizeof(file)); - } catch (...) { } - } - } _name; - - /** - * Platform-specific PD-session arguments - */ - struct Pd_args : Genode::Native_pd_args - { - Pd_args(Genode::Xml_node start_node); - } _pd_args; - - struct Read_quota - { - void warn_unsuff_quota(Genode::size_t const avail) - { - using namespace Genode; - if (!config_verbose) { return; } - Genode::printf("Warning: Specified quota exceeds available quota.\n"); - Genode::printf(" Proceeding with a quota of %zu.\n", avail); - } - - Read_quota(Genode::Xml_node start_node, - Genode::size_t & ram_quota, - Genode::size_t & cpu_quota, - bool & constrain_phys) - { - Genode::Number_of_bytes ram_bytes = 0; - Genode::size_t cpu_percent = 0; - - try { - Genode::Xml_node rsc = start_node.sub_node("resource"); - for (;; rsc = rsc.next("resource")) { - try { - if (rsc.attribute("name").has_value("RAM")) { - rsc.attribute("quantum").value(&ram_bytes); - constrain_phys = rsc.attribute("constrain_phys").has_value("yes"); - } else if (rsc.attribute("name").has_value("CPU")) { - rsc.attribute("quantum").value(&cpu_percent); } - } catch (...) { } - } - } catch (...) { } - ram_quota = ram_bytes; - cpu_quota = Genode::Cpu_session::pc_to_quota(cpu_percent); - - /* - * If the configured RAM quota exceeds our own quota, we donate - * all remaining quota to the child but we need to count in - * our allocation of the child meta data from the heap. - * Hence, we preserve some of our own quota. - */ - Genode::size_t const ram_avail = avail_slack_ram_quota(); - if (ram_quota > ram_avail) { - ram_quota = ram_avail; - warn_unsuff_quota(ram_avail); - } - - Genode::size_t const cpu_avail = avail_slack_cpu_quota(); - if (cpu_quota > cpu_avail) { - cpu_quota = cpu_avail; - warn_unsuff_quota(cpu_avail); - } - } - }; - - /** - * Resources assigned to the child - */ - struct Resources : Read_quota - { - long prio_levels_log2; - long priority; - Genode::Affinity affinity; - Genode::size_t ram_quota; - Genode::size_t cpu_quota; - bool constrain_phys; - Genode::Ram_connection ram; - Genode::Cpu_connection cpu; - Genode::Rm_connection rm; - - Resources(Genode::Xml_node start_node, const char *label, - long prio_levels_log2, - Genode::Affinity::Space const &affinity_space) - : - Read_quota(start_node, ram_quota, cpu_quota, constrain_phys), - prio_levels_log2(prio_levels_log2), - priority(read_priority(start_node)), - affinity(affinity_space, - read_affinity_location(affinity_space, start_node)), - ram(label), - cpu(label, - priority*(Genode::Cpu_session::PRIORITY_LIMIT >> prio_levels_log2), - affinity) - { - /* deduce session costs from usable ram quota */ - Genode::size_t session_donations = Genode::Rm_connection::RAM_QUOTA + - Genode::Cpu_connection::RAM_QUOTA + - Genode::Ram_connection::RAM_QUOTA; - - if (ram_quota > session_donations) - ram_quota -= session_donations; - else ram_quota = 0; - - ram.ref_account(Genode::env()->ram_session_cap()); - Genode::env()->ram_session()->transfer_quota(ram.cap(), ram_quota); - - cpu.ref_account(Genode::env()->cpu_session_cap()); - Genode::env()->cpu_session()->transfer_quota(cpu.cap(), cpu_quota); - } - } _resources; + if (config_verbose) { + Genode::printf("child \"%s\"\n", _name.unique); + Genode::printf(" RAM quota: %zu\n", _resources.ram_quota); + Genode::printf(" ELF binary: %s\n", _name.file); + Genode::printf(" priority: %ld\n", _resources.priority); + } /* - * Entry point used for serving the parent interface and the - * locally provided ROM sessions for the 'config' and 'binary' - * files. + * Determine services provided by the child */ - enum { ENTRYPOINT_STACK_SIZE = 12*1024 }; - Genode::Rpc_entrypoint _entrypoint; + try { + Xml_node service_node = start_node.sub_node("provides").sub_node("service"); - /** - * ELF binary - */ - Genode::Rom_connection _binary_rom; - Genode::Dataspace_capability _binary_rom_ds; - /** - * Private child configuration - */ - Init::Child_config _config; + for (; ; service_node = service_node.next("service")) { - /** - * Each child of init can act as a server - */ - Genode::Server _server; + char name[Genode::Service::MAX_NAME_LEN]; + service_node.attribute("name").value(name, sizeof(name)); - Genode::Child _child; + if (config_verbose) + Genode::printf(" provides service %s\n", name); - Genode::Service_registry *_parent_services; - Genode::Service_registry *_child_services; + child_services->insert(new (_child.heap()) + Routed_service(name, &_server)); - /** - * Policy helpers - */ - Init::Child_policy_enforce_labeling _labeling_policy; - Init::Child_policy_handle_cpu_priorities _priority_policy; - Init::Child_policy_provide_rom_file _config_policy; - Init::Child_policy_provide_rom_file _binary_policy; - Init::Child_policy_redirect_rom_file _configfile_policy; - Init::Child_policy_pd_args _pd_args_policy; - Init::Child_policy_ram_phys _ram_session_policy; - - public: - - Child(Genode::Xml_node start_node, - Genode::Xml_node default_route_node, - Name_registry *name_registry, - long prio_levels_log2, - Genode::Affinity::Space const &affinity_space, - Genode::Service_registry *parent_services, - Genode::Service_registry *child_services, - Genode::Cap_session *cap_session) - : - _list_element(this), - _start_node(start_node), - _default_route_node(default_route_node), - _name_registry(name_registry), - _name(start_node, name_registry), - _pd_args(start_node), - _resources(start_node, _name.unique, prio_levels_log2, affinity_space), - _entrypoint(cap_session, ENTRYPOINT_STACK_SIZE, _name.unique, false, _resources.affinity.location()), - _binary_rom(_name.file, _name.unique), - _binary_rom_ds(_binary_rom.dataspace()), - _config(_resources.ram.cap(), start_node), - _server(_resources.ram.cap()), - _child(_binary_rom_ds, _resources.ram.cap(), - _resources.cpu.cap(), _resources.rm.cap(), &_entrypoint, this), - _parent_services(parent_services), - _child_services(child_services), - _labeling_policy(_name.unique), - _priority_policy(_resources.prio_levels_log2, _resources.priority), - _config_policy("config", _config.dataspace(), &_entrypoint), - _binary_policy("binary", _binary_rom_ds, &_entrypoint), - _configfile_policy("config", _config.filename()), - _pd_args_policy(&_pd_args), - _ram_session_policy(_resources.constrain_phys) - { - using namespace Genode; - - if (_resources.ram_quota == 0) - PWRN("no valid RAM resource for child \"%s\"", _name.unique); - - if (config_verbose) { - Genode::printf("child \"%s\"\n", _name.unique); - Genode::printf(" RAM quota: %zu\n", _resources.ram_quota); - Genode::printf(" ELF binary: %s\n", _name.file); - Genode::printf(" priority: %ld\n", _resources.priority); } + } catch (Xml_node::Nonexistent_sub_node) { } + } - /* - * Determine services provided by the child - */ - try { - Xml_node service_node = start_node.sub_node("provides").sub_node("service"); - - for (; ; service_node = service_node.next("service")) { - - char name[Genode::Service::MAX_NAME_LEN]; - service_node.attribute("name").value(name, sizeof(name)); - - if (config_verbose) - Genode::printf(" provides service %s\n", name); - - child_services->insert(new (_child.heap()) - Routed_service(name, &_server)); - - } - } catch (Xml_node::Nonexistent_sub_node) { } + virtual ~Child() { + Genode::Service *s; + while ((s = _child_services->find_by_server(&_server))) { + _child_services->remove(s); } + } - virtual ~Child() { - Genode::Service *s; - while ((s = _child_services->find_by_server(&_server))) { - _child_services->remove(s); - } - } + /** + * Return true if the child has the specified name + */ + bool has_name(const char *n) const { return !Genode::strcmp(name(), n); } - /** - * Return true if the child has the specified name - */ - bool has_name(const char *n) const { return !Genode::strcmp(name(), n); } + Genode::Server *server() { return &_server; } - Genode::Server *server() { return &_server; } - - /** - * Start execution of child - */ - void start() { _entrypoint.activate(); } + /** + * Start execution of child + */ + void start() { _entrypoint.activate(); } - /**************************** - ** Child-policy interface ** - ****************************/ + /**************************** + ** Child-policy interface ** + ****************************/ - const char *name() const { return _name.unique; } + const char *name() const { return _name.unique; } - Genode::Service *resolve_session_request(const char *service_name, - const char *args) - { - Genode::Service *service = 0; + Genode::Service *resolve_session_request(const char *service_name, + const char *args) + { + Genode::Service *service = 0; - /* check for config file request */ - if ((service = _config_policy.resolve_session_request(service_name, args))) - return service; - - /* check for binary file request */ - if ((service = _binary_policy.resolve_session_request(service_name, args))) - return service; - - try { - Genode::Xml_node route_node = _default_route_node; - try { - route_node = _start_node.sub_node("route"); } - catch (...) { } - Genode::Xml_node service_node = route_node.sub_node(); - - for (; ; service_node = service_node.next()) { - - bool service_wildcard = service_node.has_type("any-service"); - - if (!service_node_matches(service_node, service_name)) - continue; - - if (!service_node_args_condition_satisfied(service_node, args, name())) - continue; - - Genode::Xml_node target = service_node.sub_node(); - for (; ; target = target.next()) { - - if (target.has_type("parent")) { - service = _parent_services->find(service_name); - if (service) - return service; - - if (!service_wildcard) { - PWRN("%s: service lookup for \"%s\" at parent failed", name(), service_name); - return 0; - } - } - - if (target.has_type("child")) { - char server_name[Name::MAX_NAME_LEN]; - server_name[0] = 0; - target.attribute("name").value(server_name, sizeof(server_name)); - - Genode::Server *server = _name_registry->lookup_server(server_name); - if (!server) - PWRN("%s: invalid route to non-existing server \"%s\"", name(), server_name); - - service = _child_services->find(service_name, server); - if (service) - return service; - - if (!service_wildcard) { - PWRN("%s: lookup to child service \"%s\" failed", name(), service_name); - return 0; - } - } - - if (target.has_type("any-child")) { - if (_child_services->is_ambiguous(service_name)) { - PERR("%s: ambiguous routes to service \"%s\"", name(), service_name); - return 0; - } - service = _child_services->find(service_name); - if (service) - return service; - - if (!service_wildcard) { - PWRN("%s: lookup for service \"%s\" failed", name(), service_name); - return 0; - } - } - - if (target.is_last()) - break; - } - } - } catch (...) { - PWRN("%s: no route to service \"%s\"", name(), service_name); - } + /* check for config file request */ + if ((service = _config_policy.resolve_session_request(service_name, args))) return service; - } - void filter_session_args(const char *service, - char *args, Genode::size_t args_len) - { - _labeling_policy. filter_session_args(service, args, args_len); - _priority_policy. filter_session_args(service, args, args_len); - _configfile_policy.filter_session_args(service, args, args_len); - _pd_args_policy. filter_session_args(service, args, args_len); - _ram_session_policy.filter_session_args(service, args, args_len); - } + /* check for binary file request */ + if ((service = _binary_policy.resolve_session_request(service_name, args))) + return service; - Genode::Affinity filter_session_affinity(Genode::Affinity const &session_affinity) - { - using namespace Genode; + try { + Genode::Xml_node route_node = _default_route_node; + try { + route_node = _start_node.sub_node("route"); } + catch (...) { } + Genode::Xml_node service_node = route_node.sub_node(); - Affinity::Space const &child_space = _resources.affinity.space(); - Affinity::Location const &child_location = _resources.affinity.location(); + for (; ; service_node = service_node.next()) { - /* check if no valid affinity space was specified */ - if (session_affinity.space().total() == 0) - return Affinity(child_space, child_location); + bool service_wildcard = service_node.has_type("any-service"); - Affinity::Space const &session_space = session_affinity.space(); - Affinity::Location const &session_location = session_affinity.location(); + if (!service_node_matches(service_node, service_name)) + continue; - /* scale resolution of resulting space */ - Affinity::Space space(child_space.multiply(session_space)); + if (!service_node_args_condition_satisfied(service_node, args, name())) + continue; - /* subordinate session affinity to child affinity subspace */ - Affinity::Location location(child_location - .multiply_position(session_space) - .transpose(session_location.xpos(), - session_location.ypos())); + Genode::Xml_node target = service_node.sub_node(); + for (; ; target = target.next()) { - return Affinity(space, location); - } + if (target.has_type("parent")) { + service = _parent_services->find(service_name); + if (service) + return service; - bool announce_service(const char *service_name, - Genode::Root_capability root, - Genode::Allocator *alloc, - Genode::Server *server) - { - if (config_verbose) - Genode::printf("child \"%s\" announces service \"%s\"\n", - name(), service_name); + if (!service_wildcard) { + PWRN("%s: service lookup for \"%s\" at parent failed", name(), service_name); + return 0; + } + } - Genode::Service *s = _child_services->find(service_name, &_server); - Routed_service *rs = dynamic_cast(s); - if (!s || !rs) { - PERR("%s: illegal announcement of service \"%s\"", name(), service_name); - return false; + if (target.has_type("child")) { + char server_name[Name::MAX_NAME_LEN]; + server_name[0] = 0; + target.attribute("name").value(server_name, sizeof(server_name)); + + Genode::Server *server = _name_registry->lookup_server(server_name); + if (!server) + PWRN("%s: invalid route to non-existing server \"%s\"", name(), server_name); + + service = _child_services->find(service_name, server); + if (service) + return service; + + if (!service_wildcard) { + PWRN("%s: lookup to child service \"%s\" failed", name(), service_name); + return 0; + } + } + + if (target.has_type("any-child")) { + if (_child_services->is_ambiguous(service_name)) { + PERR("%s: ambiguous routes to service \"%s\"", name(), service_name); + return 0; + } + service = _child_services->find(service_name); + if (service) + return service; + + if (!service_wildcard) { + PWRN("%s: lookup for service \"%s\" failed", name(), service_name); + return 0; + } + } + + if (target.is_last()) + break; + } } + } catch (...) { + PWRN("%s: no route to service \"%s\"", name(), service_name); + } + return service; + } - rs->announce(root); - return true; + void filter_session_args(const char *service, + char *args, Genode::size_t args_len) + { + _labeling_policy. filter_session_args(service, args, args_len); + _priority_policy. filter_session_args(service, args, args_len); + _configfile_policy.filter_session_args(service, args, args_len); + _pd_args_policy. filter_session_args(service, args, args_len); + _ram_session_policy.filter_session_args(service, args, args_len); + } + + Genode::Affinity filter_session_affinity(Genode::Affinity const &session_affinity) + { + using namespace Genode; + + Affinity::Space const &child_space = _resources.affinity.space(); + Affinity::Location const &child_location = _resources.affinity.location(); + + /* check if no valid affinity space was specified */ + if (session_affinity.space().total() == 0) + return Affinity(child_space, child_location); + + Affinity::Space const &session_space = session_affinity.space(); + Affinity::Location const &session_location = session_affinity.location(); + + /* scale resolution of resulting space */ + Affinity::Space space(child_space.multiply(session_space)); + + /* subordinate session affinity to child affinity subspace */ + Affinity::Location location(child_location + .multiply_position(session_space) + .transpose(session_location.xpos(), + session_location.ypos())); + + return Affinity(space, location); + } + + bool announce_service(const char *service_name, + Genode::Root_capability root, + Genode::Allocator *alloc, + Genode::Server *server) + { + if (config_verbose) + Genode::printf("child \"%s\" announces service \"%s\"\n", + name(), service_name); + + Genode::Service *s = _child_services->find(service_name, &_server); + Routed_service *rs = dynamic_cast(s); + if (!s || !rs) { + PERR("%s: illegal announcement of service \"%s\"", name(), service_name); + return false; } - void resource_request(Genode::Parent::Resource_args const &args) - { - Genode::printf("child \"%s\" requests resources: %s\n", - name(), args.string()); + rs->announce(root); + return true; + } - Genode::size_t const requested_ram_quota = - Genode::Arg_string::find_arg(args.string(), "ram_quota") - .ulong_value(0); + void resource_request(Genode::Parent::Resource_args const &args) + { + Genode::printf("child \"%s\" requests resources: %s\n", + name(), args.string()); - if (avail_slack_ram_quota() < requested_ram_quota) { - PWRN("Cannot respond to resource request - out of memory"); - return; - } + Genode::size_t const requested_ram_quota = + Genode::Arg_string::find_arg(args.string(), "ram_quota") + .ulong_value(0); - /* - * XXX Synchronize quota transfers from/to env()->ram_session() - * - * If multiple children issue concurrent resource requests, the - * value reported by 'avail_slack_ram_quota' may be out of date - * when calling 'transfer_quota'. - */ - - Genode::env()->ram_session()->transfer_quota(_resources.ram.cap(), - requested_ram_quota); - - /* wake up child that was starved for resources */ - _child.notify_resource_avail(); + if (avail_slack_ram_quota() < requested_ram_quota) { + PWRN("Cannot respond to resource request - out of memory"); + return; } - Genode::Native_pd_args const *pd_args() const { return &_pd_args; } - }; -} + /* + * XXX Synchronize quota transfers from/to env()->ram_session() + * + * If multiple children issue concurrent resource requests, the + * value reported by 'avail_slack_ram_quota' may be out of date + * when calling 'transfer_quota'. + */ + + Genode::env()->ram_session()->transfer_quota(_resources.ram.cap(), + requested_ram_quota); + + /* wake up child that was starved for resources */ + _child.notify_resource_avail(); + } + + Genode::Native_pd_args const *pd_args() const { return &_pd_args; } +}; #endif /* _INCLUDE__INIT__CHILD_H_ */ diff --git a/repos/os/include/init/child_config.h b/repos/os/include/init/child_config.h index b4d76763f..285c67462 100644 --- a/repos/os/include/init/child_config.h +++ b/repos/os/include/init/child_config.h @@ -20,121 +20,121 @@ #include #include -namespace Init { +namespace Init { class Child_config; } - class Child_config - { - private: - enum { CONFIGFILE_NAME_LEN = 64 }; - char _filename[CONFIGFILE_NAME_LEN]; +class Init::Child_config +{ + private: - Genode::Ram_session_capability _ram_session_cap; - Genode::Ram_dataspace_capability _config_ram_ds; + enum { CONFIGFILE_NAME_LEN = 64 }; + char _filename[CONFIGFILE_NAME_LEN]; - public: + Genode::Ram_session_capability _ram_session_cap; + Genode::Ram_dataspace_capability _config_ram_ds; - /** - * Constructor - * - * The provided RAM session is used to obtain a dataspace for - * holding the copy of the child's configuration data unless the - * configuration is supplied via a config file. Normally, the - * child's RAM session should be used to account the consumed RAM - * quota to the child. + public: + + /** + * Constructor + * + * The provided RAM session is used to obtain a dataspace for + * holding the copy of the child's configuration data unless the + * configuration is supplied via a config file. Normally, the + * child's RAM session should be used to account the consumed RAM + * quota to the child. + */ + Child_config(Genode::Ram_session_capability ram_session, + Genode::Xml_node start_node) + : _ram_session_cap(ram_session) + { + using namespace Genode; + + /* + * If the start node contains a 'filename' entry, we only keep + * the information about the file name. */ - Child_config(Genode::Ram_session_capability ram_session, - Genode::Xml_node start_node) - : _ram_session_cap(ram_session) - { - using namespace Genode; + _filename[0] = 0; + try { + Xml_node configfile_node = start_node.sub_node("configfile"); + configfile_node.attribute("name") + .value(_filename, sizeof(_filename)); + + return; + } catch (...) { } + + /* + * If the start node contains a 'config' entry, we copy this + * entry into a fresh dataspace to be provided to our child. + */ + Ram_session_client rsc(_ram_session_cap); + try { + Xml_node config_node = start_node.sub_node("config"); + + const char *config = config_node.addr(); + Genode::size_t config_size = config_node.size(); + + if (!config || !config_size) return; /* - * If the start node contains a 'filename' entry, we only keep - * the information about the file name. + * Allocate RAM dataspace that is big enough to + * hold the configuration and the null termination. */ - _filename[0] = 0; - try { - Xml_node configfile_node = start_node.sub_node("configfile"); - configfile_node.attribute("name") - .value(_filename, sizeof(_filename)); - - return; - } catch (...) { } + _config_ram_ds = rsc.alloc(config_size + 1); /* - * If the start node contains a 'config' entry, we copy this - * entry into a fresh dataspace to be provided to our child. + * Make dataspace locally accessible, copy + * configuration into the dataspace, and append + * a string-terminating zero. */ - Ram_session_client rsc(_ram_session_cap); - try { - Xml_node config_node = start_node.sub_node("config"); + void *addr = env()->rm_session()->attach(_config_ram_ds); - const char *config = config_node.addr(); - Genode::size_t config_size = config_node.size(); + Genode::memcpy(addr, config, config_size); + static_cast(addr)[config_size] = 0; + env()->rm_session()->detach(addr); - if (!config || !config_size) return; + } catch (Rm_session::Attach_failed) { + rsc.free(_config_ram_ds); + return; + } catch (Ram_session::Alloc_failed) { + return; + } catch (Xml_node::Nonexistent_sub_node) { } + } - /* - * Allocate RAM dataspace that is big enough to - * hold the configuration and the null termination. - */ - _config_ram_ds = rsc.alloc(config_size + 1); + /** + * Destructor + */ + ~Child_config() + { + using namespace Genode; - /* - * Make dataspace locally accessible, copy - * configuration into the dataspace, and append - * a string-terminating zero. - */ - void *addr = env()->rm_session()->attach(_config_ram_ds); - - Genode::memcpy(addr, config, config_size); - static_cast(addr)[config_size] = 0; - env()->rm_session()->detach(addr); - - } catch (Rm_session::Attach_failed) { - rsc.free(_config_ram_ds); - return; - } catch (Ram_session::Alloc_failed) { - return; - } catch (Xml_node::Nonexistent_sub_node) { } - } - - /** - * Destructor + /* + * The configuration data is either provided as a ROM session + * (holding a complete configfile) or as a RAM dataspace + * holding a copy of the start node's config entry. In the + * latter case, the child's configuration resides in a + * shadow copy kept in '_config_ram_ds'. */ - ~Child_config() - { - using namespace Genode; + if (_config_ram_ds.valid()) + Ram_session_client(_ram_session_cap).free(_config_ram_ds); + } - /* - * The configuration data is either provided as a ROM session - * (holding a complete configfile) or as a RAM dataspace - * holding a copy of the start node's config entry. In the - * latter case, the child's configuration resides in a - * shadow copy kept in '_config_ram_ds'. - */ - if (_config_ram_ds.valid()) - Ram_session_client(_ram_session_cap).free(_config_ram_ds); - } + /** + * Return file name if configuration comes from a file + * + * If the configuration is provided inline, the function returns 0. + */ + char const *filename() const { + return _filename[0] != 0 ? _filename : 0; } - /** - * Return file name if configuration comes from a file - * - * If the configuration is provided inline, the function returns 0. - */ - char const *filename() const { - return _filename[0] != 0 ? _filename : 0; } - - /** - * Request dataspace holding the start node's configuration data - * - * This function returns a valid dataspace only when using an - * inline configuration (if 'filename()' returns 0). - */ - Genode::Dataspace_capability dataspace() { - return Genode::Dataspace_capability(_config_ram_ds); } - }; -} + /** + * Request dataspace holding the start node's configuration data + * + * This function returns a valid dataspace only when using an + * inline configuration (if 'filename()' returns 0). + */ + Genode::Dataspace_capability dataspace() { + return Genode::Dataspace_capability(_config_ram_ds); } +}; #endif /* _INCLUDE__INIT__CHILD_CONFIG_H_ */ diff --git a/repos/os/include/init/child_policy.h b/repos/os/include/init/child_policy.h index 8bddf90d0..5de65c385 100644 --- a/repos/os/include/init/child_policy.h +++ b/repos/os/include/init/child_policy.h @@ -23,398 +23,408 @@ namespace Init { - class Child_policy_ram_phys - { - private: - - bool _constrain_phys; - - public: - - Child_policy_ram_phys(bool constrain_phys) - : _constrain_phys(constrain_phys) { } - - /** - * Filter arguments of session request - * - * This function removes phys_start and phys_size ram_session - * parameters if the child configuration does not explicitly - * permits this. - */ - void filter_session_args(const char *service, char *args, - Genode::size_t args_len) - { - using namespace Genode; - - /* intercept only RAM session requests */ - if (Genode::strcmp(service, "RAM")) - return; - - if (_constrain_phys) - return; - - Arg_string::remove_arg(args, "phys_start"); - Arg_string::remove_arg(args, "phys_size"); - } - }; - - /** - * Policy for prepending the child name to the 'label' argument - * - * By applying this policy, the identity of the child becomes imprinted - * with each session request. - */ - class Child_policy_enforce_labeling - { - const char *_name; - - public: - - Child_policy_enforce_labeling(const char *name) : _name(name) { } - - /** - * Filter arguments of session request - * - * This function modifies the 'label' argument and leaves all other - * session arguments intact. - */ - void filter_session_args(const char *, char *args, - Genode::size_t args_len) - { - using namespace Genode; - - char label_buf[Parent::Session_args::MAX_SIZE]; - Arg_string::find_arg(args, "label").string(label_buf, sizeof(label_buf), ""); - - char value_buf[Parent::Session_args::MAX_SIZE]; - Genode::snprintf(value_buf, sizeof(value_buf), - "\"%s%s%s\"", - _name, - Genode::strcmp(label_buf, "") == 0 ? "" : " -> ", - label_buf); - - Arg_string::set_arg(args, args_len, "label", value_buf); - } - }; - - - /** - * Policy for handling platform-specific PD-session arguments - * - * This policy is used onthe Linux base platform for prepending the chroot - * path of the child. By applying this policy, the chroot path of the child - * gets supplied to PD session requests. - */ - class Child_policy_pd_args - { - private: - - Genode::Native_pd_args const *_pd_args; - - public: - - Child_policy_pd_args(Genode::Native_pd_args const *pd_args) - : _pd_args(pd_args) { } - - void filter_session_args(const char *session, char *args, - Genode::size_t args_len); - }; - - - class Child_policy_handle_cpu_priorities - { - /* priority parameters */ - long _prio_levels_log2; - long _priority; - - public: - - Child_policy_handle_cpu_priorities(long prio_levels_log2, long priority) - : _prio_levels_log2(prio_levels_log2), _priority(priority) { } - - void filter_session_args(const char *service, char *args, Genode::size_t args_len) - { - using namespace Genode; - - /* intercept only CPU session requests to scale priorities */ - if (Genode::strcmp(service, "CPU") || _prio_levels_log2 == 0) - return; - - unsigned long priority = Arg_string::find_arg(args, "priority").long_value(0); - - /* clamp priority value to valid range */ - priority = min((unsigned)Cpu_session::PRIORITY_LIMIT - 1, priority); - - long discarded_prio_lsb_bits_mask = (1 << _prio_levels_log2) - 1; - if (priority & discarded_prio_lsb_bits_mask) { - PWRN("priority band too small, losing least-significant priority bits"); - } - priority >>= _prio_levels_log2; - - /* assign child priority to the most significant priority bits */ - priority |= _priority*(Cpu_session::PRIORITY_LIMIT >> _prio_levels_log2); - - /* override priority when delegating the session request to the parent */ - char value_buf[64]; - Genode::snprintf(value_buf, sizeof(value_buf), "0x%lx", priority); - Arg_string::set_arg(args, args_len, "priority", value_buf); - } - }; - - - class Child_policy_provide_rom_file - { - private: - - struct Local_rom_session_component : Genode::Rpc_object - { - Genode::Dataspace_capability ds_cap; - - /** - * Constructor - */ - Local_rom_session_component(Genode::Dataspace_capability ds) - : ds_cap(ds) { } - - - /*************************** - ** ROM session interface ** - ***************************/ - - Genode::Rom_dataspace_capability dataspace() { - return Genode::static_cap_cast(ds_cap); } - - void sigh(Genode::Signal_context_capability) { } - - } _local_rom_session; - - Genode::Rpc_entrypoint *_ep; - Genode::Rom_session_capability _rom_session_cap; - - enum { FILENAME_MAX_LEN = 32 }; - char _filename[FILENAME_MAX_LEN]; - - struct Local_rom_service : public Genode::Service - { - Genode::Rom_session_capability _rom_cap; - bool _valid; - - /** - * Constructor - * - * \param rom_cap capability to return on session requests - * \param valid true if local rom service is backed by a - * valid dataspace - */ - Local_rom_service(Genode::Rom_session_capability rom_cap, bool valid) - : Genode::Service("ROM"), _rom_cap(rom_cap), _valid(valid) { } - - Genode::Session_capability session(char const * /*args*/, - Genode::Affinity const &) - { - if (!_valid) - throw Invalid_args(); - - return _rom_cap; - } - - void upgrade(Genode::Session_capability, const char * /*args*/) { } - void close(Genode::Session_capability) { } - - } _local_rom_service; - - public: - - /** - * Constructor - */ - Child_policy_provide_rom_file(const char *filename, - Genode::Dataspace_capability ds_cap, - Genode::Rpc_entrypoint *ep) - : - _local_rom_session(ds_cap), _ep(ep), - _rom_session_cap(_ep->manage(&_local_rom_session)), - _local_rom_service(_rom_session_cap, ds_cap.valid()) - { - Genode::strncpy(_filename, filename, sizeof(_filename)); - } - - /** - * Destructor - */ - ~Child_policy_provide_rom_file() { _ep->dissolve(&_local_rom_session); } - - Genode::Service *resolve_session_request(const char *service_name, - const char *args) - { - /* ignore session requests for non-ROM services */ - if (Genode::strcmp(service_name, "ROM")) return 0; - - /* drop out if request refers to another file name */ - char buf[FILENAME_MAX_LEN]; - Genode::Arg_string::find_arg(args, "filename").string(buf, sizeof(buf), ""); - return !Genode::strcmp(buf, _filename) ? &_local_rom_service : 0; - } - }; - - - class Child_policy_redirect_rom_file - { - private: - - char const *_from; - char const *_to; - - public: - - Child_policy_redirect_rom_file(const char *from, const char *to) - : _from(from), _to(to) { } - - void filter_session_args(const char *service, - char *args, Genode::size_t args_len) - { - if (!_from || !_to) return; - - /* ignore session requests for non-ROM services */ - if (Genode::strcmp(service, "ROM")) return; - - /* drop out if request refers to another file name */ - enum { FILENAME_MAX_LEN = 32 }; - char buf[FILENAME_MAX_LEN]; - Genode::Arg_string::find_arg(args, "filename").string(buf, sizeof(buf), ""); - if (Genode::strcmp(_from, buf) != 0) return; - - /* replace filename argument */ - Genode::snprintf(buf, sizeof(buf), "\"%s\"", _to); - Genode::Arg_string::set_arg(args, args_len, "filename", buf); - - /* replace characters after last label delimiter by filename */ - enum { LABEL_MAX_LEN = 200 }; - char label[LABEL_MAX_LEN]; - Genode::Arg_string::find_arg(args, "label").string(label, sizeof(label), ""); - unsigned last_elem = 0; - for (unsigned i = 0; i < sizeof(label) - 3 && label[i]; i++) - if (Genode::strcmp("-> ", label + i, 3) == 0) - last_elem = i + 3; - label[last_elem] = 0; - - Genode::snprintf(buf, sizeof(buf), "\"%s%s\"", label, _to); - Genode::Arg_string::set_arg(args, args_len, "label", buf); - - } - }; - - - class Traditional_child_policy : public Genode::Child_policy, - public Genode::Client - { - protected: - - enum { NAME_LEN = 64 }; - char _name[NAME_LEN]; - - char const *_root; - - Genode::Server *_server; - Genode::Service_registry *_parent_services; - Genode::Service_registry *_child_services; - Genode::Dataspace_capability _config_ds; - Genode::Rpc_entrypoint *_parent_entrypoint; - Child_policy_enforce_labeling _labeling_policy; - Child_policy_handle_cpu_priorities _priority_policy; - Child_policy_provide_rom_file _config_policy; - Child_policy_provide_rom_file _binary_policy; - - public: - - /** - * Constructor - */ - Traditional_child_policy(const char *name, - Genode::Server *server, - Genode::Service_registry *parent_services, - Genode::Service_registry *child_services, - Genode::Dataspace_capability config_ds, - Genode::Dataspace_capability binary_ds, - long prio_levels_log2, - long priority, - char const *root, - Genode::Rpc_entrypoint *parent_entrypoint) - : - _root(root), - _server(server), - _parent_services(parent_services), - _child_services(child_services), - _config_ds(config_ds), - _parent_entrypoint(parent_entrypoint), - _labeling_policy(_name), - _priority_policy(prio_levels_log2, priority), - _config_policy("config", config_ds, _parent_entrypoint), - _binary_policy("binary", binary_ds, _parent_entrypoint) - { - Genode::strncpy(_name, name, sizeof(_name)); - } - - const char *name() const { return _name; } - - Genode::Service *resolve_session_request(const char *service_name, - const char *args) - { - Genode::Service *service; - - /* check for config file request */ - if ((service = _config_policy.resolve_session_request(service_name, args))) - return service; - - /* check for binary file request */ - if ((service = _binary_policy.resolve_session_request(service_name, args))) - return service; - - /* check for services provided by the parent */ - if ((service = _parent_services->find(service_name))) - return service; - - /* - * If the service is provided by one of our children use it, - * or wait for the service to become available. - */ - return _child_services->wait_for_service(service_name, this, - name()); - } - - void filter_session_args(const char *service, char *args, - Genode::size_t args_len) - { - _labeling_policy.filter_session_args(service, args, args_len); - _priority_policy.filter_session_args(service, args, args_len); - } - - bool announce_service(const char *service_name, - Genode::Root_capability root, - Genode::Allocator *alloc, - Genode::Server * /*server*/) - { - if (_child_services->find(service_name)) { - PWRN("%s: service %s is already registered", - name(), service_name); - return false; - } - - /* XXX remove potential race between checking for and inserting service */ - - _child_services->insert(new (alloc) - Genode::Child_service(service_name, root, _server)); - Genode::printf("%s registered service %s\n", name(), service_name); - return true; - } - - void unregister_services() - { - Genode::Service *rs; - while ((rs = _child_services->find_by_server(_server))) - _child_services->remove(rs); - } - }; + class Child_policy_ram_phys; + class Child_policy_enforce_labeling; + class Child_policy_pd_args; + class Child_policy_handle_cpu_priorities; + class Child_policy_provide_rom_file; + class Child_policy_redirect_rom_file; + class Traditional_child_policy; } + +class Init::Child_policy_ram_phys +{ + private: + + bool _constrain_phys; + + public: + + Child_policy_ram_phys(bool constrain_phys) + : _constrain_phys(constrain_phys) { } + + /** + * Filter arguments of session request + * + * This function removes phys_start and phys_size ram_session + * parameters if the child configuration does not explicitly + * permits this. + */ + void filter_session_args(const char *service, char *args, + Genode::size_t args_len) + { + using namespace Genode; + + /* intercept only RAM session requests */ + if (Genode::strcmp(service, "RAM")) + return; + + if (_constrain_phys) + return; + + Arg_string::remove_arg(args, "phys_start"); + Arg_string::remove_arg(args, "phys_size"); + } +}; + + +/** + * Policy for prepending the child name to the 'label' argument + * + * By applying this policy, the identity of the child becomes imprinted + * with each session request. + */ +class Init::Child_policy_enforce_labeling +{ + const char *_name; + + public: + + Child_policy_enforce_labeling(const char *name) : _name(name) { } + + /** + * Filter arguments of session request + * + * This function modifies the 'label' argument and leaves all other + * session arguments intact. + */ + void filter_session_args(const char *, char *args, + Genode::size_t args_len) + { + using namespace Genode; + + char label_buf[Parent::Session_args::MAX_SIZE]; + Arg_string::find_arg(args, "label").string(label_buf, sizeof(label_buf), ""); + + char value_buf[Parent::Session_args::MAX_SIZE]; + Genode::snprintf(value_buf, sizeof(value_buf), + "\"%s%s%s\"", + _name, + Genode::strcmp(label_buf, "") == 0 ? "" : " -> ", + label_buf); + + Arg_string::set_arg(args, args_len, "label", value_buf); + } +}; + + +/** + * Policy for handling platform-specific PD-session arguments + * + * This policy is used onthe Linux base platform for prepending the chroot + * path of the child. By applying this policy, the chroot path of the child + * gets supplied to PD session requests. + */ +class Init::Child_policy_pd_args +{ + private: + + Genode::Native_pd_args const *_pd_args; + + public: + + Child_policy_pd_args(Genode::Native_pd_args const *pd_args) + : _pd_args(pd_args) { } + + void filter_session_args(const char *session, char *args, + Genode::size_t args_len); +}; + + +class Init::Child_policy_handle_cpu_priorities +{ + /* priority parameters */ + long _prio_levels_log2; + long _priority; + + public: + + Child_policy_handle_cpu_priorities(long prio_levels_log2, long priority) + : _prio_levels_log2(prio_levels_log2), _priority(priority) { } + + void filter_session_args(const char *service, char *args, Genode::size_t args_len) + { + using namespace Genode; + + /* intercept only CPU session requests to scale priorities */ + if (Genode::strcmp(service, "CPU") || _prio_levels_log2 == 0) + return; + + unsigned long priority = Arg_string::find_arg(args, "priority").long_value(0); + + /* clamp priority value to valid range */ + priority = min((unsigned)Cpu_session::PRIORITY_LIMIT - 1, priority); + + long discarded_prio_lsb_bits_mask = (1 << _prio_levels_log2) - 1; + if (priority & discarded_prio_lsb_bits_mask) { + PWRN("priority band too small, losing least-significant priority bits"); + } + priority >>= _prio_levels_log2; + + /* assign child priority to the most significant priority bits */ + priority |= _priority*(Cpu_session::PRIORITY_LIMIT >> _prio_levels_log2); + + /* override priority when delegating the session request to the parent */ + char value_buf[64]; + Genode::snprintf(value_buf, sizeof(value_buf), "0x%lx", priority); + Arg_string::set_arg(args, args_len, "priority", value_buf); + } +}; + + +class Init::Child_policy_provide_rom_file +{ + private: + + struct Local_rom_session_component : Genode::Rpc_object + { + Genode::Dataspace_capability ds_cap; + + /** + * Constructor + */ + Local_rom_session_component(Genode::Dataspace_capability ds) + : ds_cap(ds) { } + + + /*************************** + ** ROM session interface ** + ***************************/ + + Genode::Rom_dataspace_capability dataspace() { + return Genode::static_cap_cast(ds_cap); } + + void sigh(Genode::Signal_context_capability) { } + + } _local_rom_session; + + Genode::Rpc_entrypoint *_ep; + Genode::Rom_session_capability _rom_session_cap; + + enum { FILENAME_MAX_LEN = 32 }; + char _filename[FILENAME_MAX_LEN]; + + struct Local_rom_service : public Genode::Service + { + Genode::Rom_session_capability _rom_cap; + bool _valid; + + /** + * Constructor + * + * \param rom_cap capability to return on session requests + * \param valid true if local rom service is backed by a + * valid dataspace + */ + Local_rom_service(Genode::Rom_session_capability rom_cap, bool valid) + : Genode::Service("ROM"), _rom_cap(rom_cap), _valid(valid) { } + + Genode::Session_capability session(char const * /*args*/, + Genode::Affinity const &) + { + if (!_valid) + throw Invalid_args(); + + return _rom_cap; + } + + void upgrade(Genode::Session_capability, const char * /*args*/) { } + void close(Genode::Session_capability) { } + + } _local_rom_service; + + public: + + /** + * Constructor + */ + Child_policy_provide_rom_file(const char *filename, + Genode::Dataspace_capability ds_cap, + Genode::Rpc_entrypoint *ep) + : + _local_rom_session(ds_cap), _ep(ep), + _rom_session_cap(_ep->manage(&_local_rom_session)), + _local_rom_service(_rom_session_cap, ds_cap.valid()) + { + Genode::strncpy(_filename, filename, sizeof(_filename)); + } + + /** + * Destructor + */ + ~Child_policy_provide_rom_file() { _ep->dissolve(&_local_rom_session); } + + Genode::Service *resolve_session_request(const char *service_name, + const char *args) + { + /* ignore session requests for non-ROM services */ + if (Genode::strcmp(service_name, "ROM")) return 0; + + /* drop out if request refers to another file name */ + char buf[FILENAME_MAX_LEN]; + Genode::Arg_string::find_arg(args, "filename").string(buf, sizeof(buf), ""); + return !Genode::strcmp(buf, _filename) ? &_local_rom_service : 0; + } +}; + + +class Init::Child_policy_redirect_rom_file +{ + private: + + char const *_from; + char const *_to; + + public: + + Child_policy_redirect_rom_file(const char *from, const char *to) + : _from(from), _to(to) { } + + void filter_session_args(const char *service, + char *args, Genode::size_t args_len) + { + if (!_from || !_to) return; + + /* ignore session requests for non-ROM services */ + if (Genode::strcmp(service, "ROM")) return; + + /* drop out if request refers to another file name */ + enum { FILENAME_MAX_LEN = 32 }; + char buf[FILENAME_MAX_LEN]; + Genode::Arg_string::find_arg(args, "filename").string(buf, sizeof(buf), ""); + if (Genode::strcmp(_from, buf) != 0) return; + + /* replace filename argument */ + Genode::snprintf(buf, sizeof(buf), "\"%s\"", _to); + Genode::Arg_string::set_arg(args, args_len, "filename", buf); + + /* replace characters after last label delimiter by filename */ + enum { LABEL_MAX_LEN = 200 }; + char label[LABEL_MAX_LEN]; + Genode::Arg_string::find_arg(args, "label").string(label, sizeof(label), ""); + unsigned last_elem = 0; + for (unsigned i = 0; i < sizeof(label) - 3 && label[i]; i++) + if (Genode::strcmp("-> ", label + i, 3) == 0) + last_elem = i + 3; + label[last_elem] = 0; + + Genode::snprintf(buf, sizeof(buf), "\"%s%s\"", label, _to); + Genode::Arg_string::set_arg(args, args_len, "label", buf); + + } +}; + + +class Init::Traditional_child_policy : public Genode::Child_policy, + public Genode::Client +{ + protected: + + enum { NAME_LEN = 64 }; + char _name[NAME_LEN]; + + char const *_root; + + Genode::Server *_server; + Genode::Service_registry *_parent_services; + Genode::Service_registry *_child_services; + Genode::Dataspace_capability _config_ds; + Genode::Rpc_entrypoint *_parent_entrypoint; + Child_policy_enforce_labeling _labeling_policy; + Child_policy_handle_cpu_priorities _priority_policy; + Child_policy_provide_rom_file _config_policy; + Child_policy_provide_rom_file _binary_policy; + + public: + + /** + * Constructor + */ + Traditional_child_policy(const char *name, + Genode::Server *server, + Genode::Service_registry *parent_services, + Genode::Service_registry *child_services, + Genode::Dataspace_capability config_ds, + Genode::Dataspace_capability binary_ds, + long prio_levels_log2, + long priority, + char const *root, + Genode::Rpc_entrypoint *parent_entrypoint) + : + _root(root), + _server(server), + _parent_services(parent_services), + _child_services(child_services), + _config_ds(config_ds), + _parent_entrypoint(parent_entrypoint), + _labeling_policy(_name), + _priority_policy(prio_levels_log2, priority), + _config_policy("config", config_ds, _parent_entrypoint), + _binary_policy("binary", binary_ds, _parent_entrypoint) + { + Genode::strncpy(_name, name, sizeof(_name)); + } + + const char *name() const { return _name; } + + Genode::Service *resolve_session_request(const char *service_name, + const char *args) + { + Genode::Service *service; + + /* check for config file request */ + if ((service = _config_policy.resolve_session_request(service_name, args))) + return service; + + /* check for binary file request */ + if ((service = _binary_policy.resolve_session_request(service_name, args))) + return service; + + /* check for services provided by the parent */ + if ((service = _parent_services->find(service_name))) + return service; + + /* + * If the service is provided by one of our children use it, + * or wait for the service to become available. + */ + return _child_services->wait_for_service(service_name, this, + name()); + } + + void filter_session_args(const char *service, char *args, + Genode::size_t args_len) + { + _labeling_policy.filter_session_args(service, args, args_len); + _priority_policy.filter_session_args(service, args, args_len); + } + + bool announce_service(const char *service_name, + Genode::Root_capability root, + Genode::Allocator *alloc, + Genode::Server * /*server*/) + { + if (_child_services->find(service_name)) { + PWRN("%s: service %s is already registered", + name(), service_name); + return false; + } + + /* XXX remove potential race between checking for and inserting service */ + + _child_services->insert(new (alloc) + Genode::Child_service(service_name, root, _server)); + Genode::printf("%s registered service %s\n", name(), service_name); + return true; + } + + void unregister_services() + { + Genode::Service *rs; + while ((rs = _child_services->find_by_server(_server))) + _child_services->remove(rs); + } +}; + #endif /* _INCLUDE__INIT__CHILD_POLICY_H_ */ diff --git a/repos/os/include/input/component.h b/repos/os/include/input/component.h index a38d91526..6efe2d74e 100644 --- a/repos/os/include/input/component.h +++ b/repos/os/include/input/component.h @@ -22,9 +22,9 @@ #include #include - namespace Input { class Session_component; } + class Input::Session_component : public Genode::Rpc_object { private: diff --git a/repos/os/include/input/event.h b/repos/os/include/input/event.h index 8fb2fd1bd..0e9c0a9fe 100644 --- a/repos/os/include/input/event.h +++ b/repos/os/include/input/event.h @@ -16,67 +16,67 @@ #include -namespace Input { +namespace Input { class Event; } - class Event - { - public: - enum Type { INVALID, MOTION, PRESS, RELEASE, WHEEL, FOCUS, LEAVE }; +class Input::Event +{ + public: - private: + enum Type { INVALID, MOTION, PRESS, RELEASE, WHEEL, FOCUS, LEAVE }; - Type _type; + private: - /* - * For PRESS and RELEASE events, '_code' contains the key code. - * For FOCUS events, '_code' is set to 1 (focus) or 0 (unfocus). - */ - int _code; + Type _type; - /* - * Absolute pointer position coordinates - */ - int _ax, _ay; + /* + * For PRESS and RELEASE events, '_code' contains the key code. + * For FOCUS events, '_code' is set to 1 (focus) or 0 (unfocus). + */ + int _code; - /* - * Relative pointer motion vector - */ - int _rx, _ry; + /* + * Absolute pointer position coordinates + */ + int _ax, _ay; - public: + /* + * Relative pointer motion vector + */ + int _rx, _ry; - /** - * Constructors - */ - Event(): - _type(INVALID), _code(0), _ax(0), _ay(0), _rx(0), _ry(0) { } + public: - Event(Type type, int code, int ax, int ay, int rx, int ry): - _type(type), _code(code), - _ax(ax), _ay(ay), _rx(rx), _ry(ry) { } + /** + * Constructors + */ + Event(): + _type(INVALID), _code(0), _ax(0), _ay(0), _rx(0), _ry(0) { } - /** - * Accessors - */ - Type type() const { return _type; } - int code() const { return _code; } - int ax() const { return _ax; } - int ay() const { return _ay; } - int rx() const { return _rx; } - int ry() const { return _ry; } + Event(Type type, int code, int ax, int ay, int rx, int ry): + _type(type), _code(code), + _ax(ax), _ay(ay), _rx(rx), _ry(ry) { } - /** - * Return key code for press/release events - */ - Keycode keycode() const - { - return _type == PRESS || _type == RELEASE ? (Keycode)_code : KEY_UNKNOWN; - } + /** + * Accessors + */ + Type type() const { return _type; } + int code() const { return _code; } + int ax() const { return _ax; } + int ay() const { return _ay; } + int rx() const { return _rx; } + int ry() const { return _ry; } - bool is_absolute_motion() const { return _type == MOTION && !_rx && !_ry; } - bool is_relative_motion() const { return _type == MOTION && (_rx || _ry); } - }; -} + /** + * Return key code for press/release events + */ + Keycode keycode() const + { + return _type == PRESS || _type == RELEASE ? (Keycode)_code : KEY_UNKNOWN; + } + + bool is_absolute_motion() const { return _type == MOTION && !_rx && !_ry; } + bool is_relative_motion() const { return _type == MOTION && (_rx || _ry); } +}; #endif /* _INCLUDE__INPUT__EVENT_H_ */ diff --git a/repos/os/include/input/root.h b/repos/os/include/input/root.h index 78a658a8c..8c892be05 100644 --- a/repos/os/include/input/root.h +++ b/repos/os/include/input/root.h @@ -18,9 +18,9 @@ #include #include - namespace Input { class Root_component; } + /* * This input root component tracks if the session has been opened. If a client * is connected, the 'Event_queue::enabled' gets enabled. This is useful to diff --git a/repos/os/include/input_session/client.h b/repos/os/include/input_session/client.h index 2577b4b96..2c69a56bc 100644 --- a/repos/os/include/input_session/client.h +++ b/repos/os/include/input_session/client.h @@ -17,25 +17,25 @@ #include #include -namespace Input { +namespace Input { struct Session_client; } - struct Session_client : Genode::Rpc_client - { - explicit Session_client(Session_capability session) - : Genode::Rpc_client(session) { } - Genode::Dataspace_capability dataspace() override { - return call(); } +struct Input::Session_client : Genode::Rpc_client +{ + explicit Session_client(Session_capability session) + : Genode::Rpc_client(session) { } - bool is_pending() const override { - return call(); } + Genode::Dataspace_capability dataspace() override { + return call(); } - int flush() override { - return call(); } + bool is_pending() const override { + return call(); } - void sigh(Genode::Signal_context_capability sigh) override { - call(sigh); } - }; -} + int flush() override { + return call(); } + + void sigh(Genode::Signal_context_capability sigh) override { + call(sigh); } +}; #endif /* _INCLUDE__INPUT_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/input_session/connection.h b/repos/os/include/input_session/connection.h index 2b410c500..3eda71376 100644 --- a/repos/os/include/input_session/connection.h +++ b/repos/os/include/input_session/connection.h @@ -17,16 +17,15 @@ #include #include -namespace Input { +namespace Input { struct Connection; } - struct Connection : Genode::Connection, Session_client - { - Connection() - : - Genode::Connection(session("ram_quota=16K")), - Session_client(cap()) - { } - }; -} +struct Input::Connection : Genode::Connection, Session_client +{ + Connection() + : + Genode::Connection(session("ram_quota=16K")), + Session_client(cap()) + { } +}; #endif /* _INCLUDE__INPUT_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/input_session/input_session.h b/repos/os/include/input_session/input_session.h index 9b48f6a27..0dffd7e44 100644 --- a/repos/os/include/input_session/input_session.h +++ b/repos/os/include/input_session/input_session.h @@ -19,50 +19,50 @@ #include #include -namespace Input { - - struct Session : Genode::Session - { - static const char *service_name() { return "Input"; } - - virtual ~Session() { } - - /** - * Return capability to event buffer dataspace - */ - virtual Genode::Dataspace_capability dataspace() = 0; - - /** - * Request input state - * - * \return true if new events are available - */ - virtual bool is_pending() const = 0; - - /** - * Flush pending events to event buffer - * - * \return number of flushed events - */ - virtual int flush() = 0; - - /** - * Register signal handler to be notified on arrival of new input - */ - virtual void sigh(Genode::Signal_context_capability) = 0; +namespace Input { struct Session; } - /********************* - ** RPC declaration ** - *********************/ +struct Input::Session : Genode::Session +{ + static const char *service_name() { return "Input"; } - GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace); - GENODE_RPC(Rpc_is_pending, bool, is_pending); - GENODE_RPC(Rpc_flush, int, flush); - GENODE_RPC(Rpc_sigh, void, sigh, Genode::Signal_context_capability); + virtual ~Session() { } - GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_is_pending, Rpc_flush, Rpc_sigh); - }; -} + /** + * Return capability to event buffer dataspace + */ + virtual Genode::Dataspace_capability dataspace() = 0; + + /** + * Request input state + * + * \return true if new events are available + */ + virtual bool is_pending() const = 0; + + /** + * Flush pending events to event buffer + * + * \return number of flushed events + */ + virtual int flush() = 0; + + /** + * Register signal handler to be notified on arrival of new input + */ + virtual void sigh(Genode::Signal_context_capability) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace); + GENODE_RPC(Rpc_is_pending, bool, is_pending); + GENODE_RPC(Rpc_flush, int, flush); + GENODE_RPC(Rpc_sigh, void, sigh, Genode::Signal_context_capability); + + GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_is_pending, Rpc_flush, Rpc_sigh); +}; #endif /* _INCLUDE__INPUT_SESSION__INPUT_SESSION_H_ */ diff --git a/repos/os/include/loader_session/client.h b/repos/os/include/loader_session/client.h index 21f4ab795..cd9425424 100644 --- a/repos/os/include/loader_session/client.h +++ b/repos/os/include/loader_session/client.h @@ -19,45 +19,45 @@ #include #include -namespace Loader { +namespace Loader { struct Session_client; } - struct Session_client : Genode::Rpc_client - { - explicit Session_client(Loader::Session_capability session) - : Rpc_client(session) { } - Dataspace_capability alloc_rom_module(Name const &name, - size_t size) override { - return call(name, size); } +struct Loader::Session_client : Genode::Rpc_client +{ + explicit Session_client(Loader::Session_capability session) + : Rpc_client(session) { } - void commit_rom_module(Name const &name) override { - call(name); } + Dataspace_capability alloc_rom_module(Name const &name, + size_t size) override { + return call(name, size); } - void ram_quota(size_t quantum) override { - call(quantum); } + void commit_rom_module(Name const &name) override { + call(name); } - void constrain_geometry(Area size) override { - call(size); } + void ram_quota(size_t quantum) override { + call(quantum); } - void parent_view(Nitpicker::View_capability view) override { - call(view); } + void constrain_geometry(Area size) override { + call(size); } - void view_ready_sigh(Signal_context_capability sigh) override { - call(sigh); } + void parent_view(Nitpicker::View_capability view) override { + call(view); } - void fault_sigh(Signal_context_capability sigh) override { - call(sigh); } + void view_ready_sigh(Signal_context_capability sigh) override { + call(sigh); } - void start(Name const &binary, Name const &label = "", - Native_pd_args const &pd_args = Native_pd_args()) override { - call(binary, label, pd_args); } + void fault_sigh(Signal_context_capability sigh) override { + call(sigh); } - void view_geometry(Rect rect, Point offset) override { - call(rect, offset); } + void start(Name const &binary, Name const &label = "", + Native_pd_args const &pd_args = Native_pd_args()) override { + call(binary, label, pd_args); } - Area view_size() const override { - return call(); } - }; -} + void view_geometry(Rect rect, Point offset) override { + call(rect, offset); } + + Area view_size() const override { + return call(); } +}; #endif /* _INCLUDE__PLUGIN_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/loader_session/connection.h b/repos/os/include/loader_session/connection.h index 911766d53..eeb656dc5 100644 --- a/repos/os/include/loader_session/connection.h +++ b/repos/os/include/loader_session/connection.h @@ -18,16 +18,16 @@ #include #include -namespace Loader { +namespace Loader { struct Connection; } - struct Connection : Genode::Connection, Session_client - { - Connection(size_t ram_quota) - : - Genode::Connection(session("ram_quota=%zd", ram_quota)), - Session_client(cap()) - { } - }; -} + +struct Loader::Connection : Genode::Connection, Session_client +{ + Connection(size_t ram_quota) + : + Genode::Connection(session("ram_quota=%zd", ram_quota)), + Session_client(cap()) + { } +}; #endif /* _INCLUDE__LOADER_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/loader_session/loader_session.h b/repos/os/include/loader_session/loader_session.h index 37eb8d3b6..1b5d30786 100644 --- a/repos/os/include/loader_session/loader_session.h +++ b/repos/os/include/loader_session/loader_session.h @@ -34,170 +34,173 @@ namespace Loader { using Genode::Native_pd_args; using Genode::Meta::Type_tuple; - struct Session : Genode::Session - { - /* - * Resolve ambiguity of 'size_t' type when using 'loader_session.h' - * together with libc headers. - */ - typedef Genode::size_t size_t; - - /* - * Exception types - */ - struct Exception : Genode::Exception { }; - struct View_does_not_exist : Exception { }; - struct Rom_module_does_not_exist : Exception { }; - - typedef Genode::Rpc_in_buffer<64> Name; - typedef Genode::Rpc_in_buffer<128> Path; - - static const char *service_name() { return "Loader"; } - - virtual ~Session() { } - - /** - * Allocate dataspace to be used as ROM module by the loaded subsystem - * - * \param name designated name of the ROM module - * \param size size of ROM module - * - * \return Dataspace_capability dataspace that contains the backing - * store of the ROM module - * - * The content of the dataspace is made visible to the loaded subsystem - * not before 'commit_rom_module' has been called. This two-step - * procedure enables the client to update the content of the ROM module - * during the lifetime of the session by subsequently calling dataspace - * with the same name as argument. Each time, a new dataspace is - * allocated but not yet presented to the loaded subsystem. When - * calling 'commit_rom_module', the most recently allocated dataspace - * becomes visible. The server frees intermediate dataspaces that are - * no longer used. - */ - virtual Dataspace_capability alloc_rom_module(Name const &name, size_t size) = 0; - - /** - * Expose ROM module to loaded subsystem - * - * \throw Rom_module_does_not_exist if the ROM module name wasn't - * allocated beforehand - */ - virtual void commit_rom_module(Name const &name) = 0; - - /** - * Define RAM quota assigned to the subsystem - * - * The quantum specified must be in the bounds of the quota attached - * the session. Note that RAM resources used for ROM modules are - * accounted, too. If ROM modules are modified at runtime by subsequent - * calls of 'alloc_rom_module', the resources needed for the respective - * ROM modules are doubled. - * - * If 'ram_quota' is not called prior calling 'start', all available - * session resources will be assigned to the subsystem. - */ - virtual void ram_quota(size_t quantum) = 0; - - /** - * Constrain size of the nitpicker buffer used by the subsystem - * - * Calling this function prior 'start()' enables the virtualization - * of the nitpicker session interface. - */ - virtual void constrain_geometry(Area size) = 0; - - /** - * Set the parent view of the subsystem's view. - * - * If 'parent_view' is not called prior calling 'start', the - * subsystem's view will not have a parent view. - */ - virtual void parent_view(Nitpicker::View_capability view) = 0; - - /** - * Register signal handler notified at creation time of the first view - */ - virtual void view_ready_sigh(Signal_context_capability sigh) = 0; - - /** - * Register signal handler notified when a failure occurs in the - * loaded subsystem. - * - * This signal is delivered if any child process of the subsystem - * produces an unresolvable page fault, exists, or triggers a CPU - * exception. (e.g., division by zero) For more information about - * the possible types of faults, please refer to the documentation of - * 'Rm_session::fault_handler' and 'Cpu_session::exception_handler'. - * - * This function should not be called after the 'start' function. - */ - virtual void fault_sigh(Signal_context_capability sigh) = 0; - - /** - * Start subsystem - * - * \throw Rom_module_does_not_exist if the specified binary could - * not obtained as ROM module - */ - virtual void start(Name const &binary, Name const &label = "", - Native_pd_args const &pd_args = Native_pd_args()) = 0; - - /** - * Set view geometry and buffer offset - */ - virtual void view_geometry(Rect rect, Point offset) = 0; - - /** - * Return view size as initialized by the loaded subsystem - */ - virtual Area view_size() const = 0; - - - /******************* - ** RPC interface ** - *******************/ - - GENODE_RPC(Rpc_alloc_rom_module, Dataspace_capability, alloc_rom_module, - Name const &, size_t); - GENODE_RPC_THROW(Rpc_commit_rom_module, void, commit_rom_module, - GENODE_TYPE_LIST(Rom_module_does_not_exist), - Name const &); - GENODE_RPC(Rpc_ram_quota, void, ram_quota, size_t); - GENODE_RPC(Rpc_constrain_geometry, void, constrain_geometry, Area); - GENODE_RPC(Rpc_parent_view, void, parent_view, Nitpicker::View_capability); - GENODE_RPC(Rpc_view_ready_sigh, void, view_ready_sigh, Signal_context_capability); - GENODE_RPC(Rpc_fault_sigh, void, fault_sigh, Signal_context_capability); - GENODE_RPC_THROW(Rpc_start, void, start, - GENODE_TYPE_LIST(Rom_module_does_not_exist), - Name const &, Name const &, Native_pd_args const &); - GENODE_RPC_THROW(Rpc_view_geometry, void, view_geometry, - GENODE_TYPE_LIST(View_does_not_exist), - Rect, Point); - GENODE_RPC_THROW(Rpc_view_size, Area, view_size, - GENODE_TYPE_LIST(View_does_not_exist)); - - /* - * 'GENODE_RPC_INTERFACE' declaration done manually - * - * The number of RPC function of this interface exceeds the maximum - * number of elements supported by 'Meta::Type_list'. Therefore, we - * construct the type list by hand using nested type tuples instead - * of employing the convenience macro 'GENODE_RPC_INTERFACE'. - */ - typedef Type_tuple - > > > > > > > > > Rpc_functions; - }; + struct Session; } + +struct Loader::Session : Genode::Session +{ + /* + * Resolve ambiguity of 'size_t' type when using 'loader_session.h' + * together with libc headers. + */ + typedef Genode::size_t size_t; + + /* + * Exception types + */ + struct Exception : Genode::Exception { }; + struct View_does_not_exist : Exception { }; + struct Rom_module_does_not_exist : Exception { }; + + typedef Genode::Rpc_in_buffer<64> Name; + typedef Genode::Rpc_in_buffer<128> Path; + + static const char *service_name() { return "Loader"; } + + virtual ~Session() { } + + /** + * Allocate dataspace to be used as ROM module by the loaded subsystem + * + * \param name designated name of the ROM module + * \param size size of ROM module + * + * \return Dataspace_capability dataspace that contains the backing + * store of the ROM module + * + * The content of the dataspace is made visible to the loaded subsystem + * not before 'commit_rom_module' has been called. This two-step + * procedure enables the client to update the content of the ROM module + * during the lifetime of the session by subsequently calling dataspace + * with the same name as argument. Each time, a new dataspace is + * allocated but not yet presented to the loaded subsystem. When + * calling 'commit_rom_module', the most recently allocated dataspace + * becomes visible. The server frees intermediate dataspaces that are + * no longer used. + */ + virtual Dataspace_capability alloc_rom_module(Name const &name, size_t size) = 0; + + /** + * Expose ROM module to loaded subsystem + * + * \throw Rom_module_does_not_exist if the ROM module name wasn't + * allocated beforehand + */ + virtual void commit_rom_module(Name const &name) = 0; + + /** + * Define RAM quota assigned to the subsystem + * + * The quantum specified must be in the bounds of the quota attached + * the session. Note that RAM resources used for ROM modules are + * accounted, too. If ROM modules are modified at runtime by subsequent + * calls of 'alloc_rom_module', the resources needed for the respective + * ROM modules are doubled. + * + * If 'ram_quota' is not called prior calling 'start', all available + * session resources will be assigned to the subsystem. + */ + virtual void ram_quota(size_t quantum) = 0; + + /** + * Constrain size of the nitpicker buffer used by the subsystem + * + * Calling this function prior 'start()' enables the virtualization + * of the nitpicker session interface. + */ + virtual void constrain_geometry(Area size) = 0; + + /** + * Set the parent view of the subsystem's view. + * + * If 'parent_view' is not called prior calling 'start', the + * subsystem's view will not have a parent view. + */ + virtual void parent_view(Nitpicker::View_capability view) = 0; + + /** + * Register signal handler notified at creation time of the first view + */ + virtual void view_ready_sigh(Signal_context_capability sigh) = 0; + + /** + * Register signal handler notified when a failure occurs in the + * loaded subsystem. + * + * This signal is delivered if any child process of the subsystem + * produces an unresolvable page fault, exists, or triggers a CPU + * exception. (e.g., division by zero) For more information about + * the possible types of faults, please refer to the documentation of + * 'Rm_session::fault_handler' and 'Cpu_session::exception_handler'. + * + * This function should not be called after the 'start' function. + */ + virtual void fault_sigh(Signal_context_capability sigh) = 0; + + /** + * Start subsystem + * + * \throw Rom_module_does_not_exist if the specified binary could + * not obtained as ROM module + */ + virtual void start(Name const &binary, Name const &label = "", + Native_pd_args const &pd_args = Native_pd_args()) = 0; + + /** + * Set view geometry and buffer offset + */ + virtual void view_geometry(Rect rect, Point offset) = 0; + + /** + * Return view size as initialized by the loaded subsystem + */ + virtual Area view_size() const = 0; + + + /******************* + ** RPC interface ** + *******************/ + + GENODE_RPC(Rpc_alloc_rom_module, Dataspace_capability, alloc_rom_module, + Name const &, size_t); + GENODE_RPC_THROW(Rpc_commit_rom_module, void, commit_rom_module, + GENODE_TYPE_LIST(Rom_module_does_not_exist), + Name const &); + GENODE_RPC(Rpc_ram_quota, void, ram_quota, size_t); + GENODE_RPC(Rpc_constrain_geometry, void, constrain_geometry, Area); + GENODE_RPC(Rpc_parent_view, void, parent_view, Nitpicker::View_capability); + GENODE_RPC(Rpc_view_ready_sigh, void, view_ready_sigh, Signal_context_capability); + GENODE_RPC(Rpc_fault_sigh, void, fault_sigh, Signal_context_capability); + GENODE_RPC_THROW(Rpc_start, void, start, + GENODE_TYPE_LIST(Rom_module_does_not_exist), + Name const &, Name const &, Native_pd_args const &); + GENODE_RPC_THROW(Rpc_view_geometry, void, view_geometry, + GENODE_TYPE_LIST(View_does_not_exist), + Rect, Point); + GENODE_RPC_THROW(Rpc_view_size, Area, view_size, + GENODE_TYPE_LIST(View_does_not_exist)); + + /* + * 'GENODE_RPC_INTERFACE' declaration done manually + * + * The number of RPC function of this interface exceeds the maximum + * number of elements supported by 'Meta::Type_list'. Therefore, we + * construct the type list by hand using nested type tuples instead + * of employing the convenience macro 'GENODE_RPC_INTERFACE'. + */ + typedef Type_tuple + > > > > > > > > > Rpc_functions; +}; + #endif /* _INCLUDE__LOADER_SESSION__LOADER_SESSION_H_ */ diff --git a/repos/os/include/net/arp.h b/repos/os/include/net/arp.h index 92fa9ac2d..047f6b237 100644 --- a/repos/os/include/net/arp.h +++ b/repos/os/include/net/arp.h @@ -25,270 +25,271 @@ #include #include -namespace Net { - - /** - * The data-layout of this class conforms to an ARP-packet (RFC 826). - * It's reduced to Internet protocol (IPv4) over Ethernet. - * - * ARP-packet-format: - * - * -------------------------------------------------------------------- - * | Bit 0-7 | Bit 8-15 | Bit 16-23 | Bit 24-31 | - * -------------------------------------------------------------------- - * | hw.addr.type | prot.addr.type | - * -------------------------------------------------------------------- - * | hw.addr.size | prot.addr.size | operation | - * -------------------------------------------------------------------- - * | source-mac-address | - * -------------------------------------------------------------------- - * | source-mac-address | source-ip-address | - * -------------------------------------------------------------------- - * | source-ip-address | dest.-mac-address | - * -------------------------------------------------------------------- - * | dest.-mac-address | - * -------------------------------------------------------------------- - * | dest.-ip-address | - * -------------------------------------------------------------------- - */ - class Arp_packet - { - private: - - /*********************** - ** ARP header fields ** - ***********************/ - - Genode::uint16_t _hw_addr_type; - Genode::uint16_t _prot_addr_type; - Genode::uint8_t _hw_addr_sz; - Genode::uint8_t _prot_addr_sz; - Genode::uint16_t _opcode; - Genode::uint8_t _src_mac_addr[Ethernet_frame::ADDR_LEN]; - Genode::uint8_t _src_ip_addr[Ipv4_packet::ADDR_LEN]; - Genode::uint8_t _dst_mac_addr[Ethernet_frame::ADDR_LEN]; - Genode::uint8_t _dst_ip_addr[Ipv4_packet::ADDR_LEN]; - - public: - - /******************** - ** ARP parameters ** - ********************/ - - enum Hardware_type { - ETHERNET = 0x0001, - EXP_ETHERNET = 0x0002, - AX_25 = 0x0003, - TOKEN_RING = 0x0004, - CHAOS = 0x0005, - IEEE802_NET = 0x0006, - ARCNET = 0x0007, - HYPERCHANNEL = 0x0008, - LANSTAR = 0x0009, - AUTONET = 0x000A, - LOCALTALK = 0x000B, - LOCALNET = 0x000C, - ULTRA_LINK = 0x000D, - SMDS = 0x000E, - FRAME_RELAY = 0x000F, - ATM_1 = 0x0010, - HDLC = 0x0011, - FIBRE_CHANNEL = 0x0012, - ATM_2 = 0x0013, - SERIAL_LINE = 0x0014, - ATM_3 = 0x0015, - MIL_STD_188_220 = 0x0016, - METRICOM = 0x0017, - IEEE1394 = 0x0018, - MAPOS = 0x0019, - TWINAXIAL = 0x001A, - EUI_64 = 0x001B, - HIPARP = 0x001C, - IP_AND_ARP_OVER_ISO7816 = 0x001D, - ARPSEC = 0x001E, - IPSEC_TUNNEL = 0x001F, - INFINIBAND = 0x0020, - TIA_102 = 0x0021, - WIEGAND_INTERFACE = 0x0022, - Pure_IP = 0x0023, - HW_EXP1 = 0x0024, - HFI = 0x0025, - HW_EXP2 = 0x0100, - }; - - enum Opcode { - REQUEST = 0x0001, - REPLY = 0x0002, - REQUEST_REVERSE = 0x0003, - REPLY_REVERSE = 0x0004, - DRARP_REQUEST = 0x0005, - DRARP_REPLY = 0x0006, - DRARP_ERROR = 0x0007, - INARP_REQUEST = 0x0008, - INARP_REPLY = 0x0009, - ARP_NAK = 0x000A, - MARS_REQUEST = 0x000B, - MARS_MULTI = 0x000C, - MARS_MSERV = 0x000D, - MARS_JOIN = 0x000E, - MARS_LEAVE = 0x000F, - MARS_NAK = 0x0010, - MARS_UNSERV = 0x0011, - MARS_SJOIN = 0x0012, - MARS_SLEAVE = 0x0013, - MARS_GROUPLIST_REQUEST = 0x0014, - MARS_GROUPLIST_REPLY = 0x0015, - MARS_REDIRECT_MAP = 0x0016, - MAPOS_UNARP = 0x0017, - OP_EXP1 = 0x0018, - OP_EXP2 = 0x0019 - }; +namespace Net { class Arp_packet; } - /** - * Exception used to indicate protocol violation. - */ - class No_arp_packet : Genode::Exception {}; +/** + * Data layout of this class conforms to an ARP-packet (RFC 826) + * + * It's reduced to Internet protocol (IPv4) over Ethernet. + * + * ARP-packet-format: + * + * -------------------------------------------------------------------- + * | Bit 0-7 | Bit 8-15 | Bit 16-23 | Bit 24-31 | + * -------------------------------------------------------------------- + * | hw.addr.type | prot.addr.type | + * -------------------------------------------------------------------- + * | hw.addr.size | prot.addr.size | operation | + * -------------------------------------------------------------------- + * | source-mac-address | + * -------------------------------------------------------------------- + * | source-mac-address | source-ip-address | + * -------------------------------------------------------------------- + * | source-ip-address | dest.-mac-address | + * -------------------------------------------------------------------- + * | dest.-mac-address | + * -------------------------------------------------------------------- + * | dest.-ip-address | + * -------------------------------------------------------------------- + */ +class Net::Arp_packet +{ + private: + + /*********************** + ** ARP header fields ** + ***********************/ + + Genode::uint16_t _hw_addr_type; + Genode::uint16_t _prot_addr_type; + Genode::uint8_t _hw_addr_sz; + Genode::uint8_t _prot_addr_sz; + Genode::uint16_t _opcode; + Genode::uint8_t _src_mac_addr[Ethernet_frame::ADDR_LEN]; + Genode::uint8_t _src_ip_addr[Ipv4_packet::ADDR_LEN]; + Genode::uint8_t _dst_mac_addr[Ethernet_frame::ADDR_LEN]; + Genode::uint8_t _dst_ip_addr[Ipv4_packet::ADDR_LEN]; + + public: + + /******************** + ** ARP parameters ** + ********************/ + + enum Hardware_type { + ETHERNET = 0x0001, + EXP_ETHERNET = 0x0002, + AX_25 = 0x0003, + TOKEN_RING = 0x0004, + CHAOS = 0x0005, + IEEE802_NET = 0x0006, + ARCNET = 0x0007, + HYPERCHANNEL = 0x0008, + LANSTAR = 0x0009, + AUTONET = 0x000A, + LOCALTALK = 0x000B, + LOCALNET = 0x000C, + ULTRA_LINK = 0x000D, + SMDS = 0x000E, + FRAME_RELAY = 0x000F, + ATM_1 = 0x0010, + HDLC = 0x0011, + FIBRE_CHANNEL = 0x0012, + ATM_2 = 0x0013, + SERIAL_LINE = 0x0014, + ATM_3 = 0x0015, + MIL_STD_188_220 = 0x0016, + METRICOM = 0x0017, + IEEE1394 = 0x0018, + MAPOS = 0x0019, + TWINAXIAL = 0x001A, + EUI_64 = 0x001B, + HIPARP = 0x001C, + IP_AND_ARP_OVER_ISO7816 = 0x001D, + ARPSEC = 0x001E, + IPSEC_TUNNEL = 0x001F, + INFINIBAND = 0x0020, + TIA_102 = 0x0021, + WIEGAND_INTERFACE = 0x0022, + Pure_IP = 0x0023, + HW_EXP1 = 0x0024, + HFI = 0x0025, + HW_EXP2 = 0x0100, + }; + + enum Opcode { + REQUEST = 0x0001, + REPLY = 0x0002, + REQUEST_REVERSE = 0x0003, + REPLY_REVERSE = 0x0004, + DRARP_REQUEST = 0x0005, + DRARP_REPLY = 0x0006, + DRARP_ERROR = 0x0007, + INARP_REQUEST = 0x0008, + INARP_REPLY = 0x0009, + ARP_NAK = 0x000A, + MARS_REQUEST = 0x000B, + MARS_MULTI = 0x000C, + MARS_MSERV = 0x000D, + MARS_JOIN = 0x000E, + MARS_LEAVE = 0x000F, + MARS_NAK = 0x0010, + MARS_UNSERV = 0x0011, + MARS_SJOIN = 0x0012, + MARS_SLEAVE = 0x0013, + MARS_GROUPLIST_REQUEST = 0x0014, + MARS_GROUPLIST_REPLY = 0x0015, + MARS_REDIRECT_MAP = 0x0016, + MAPOS_UNARP = 0x0017, + OP_EXP1 = 0x0018, + OP_EXP2 = 0x0019 + }; - /***************** - ** Constructor ** - *****************/ - - Arp_packet(Genode::size_t size) { - /* arp packet needs to fit in */ - if (size < sizeof(Arp_packet)) - throw No_arp_packet(); - } + /** + * Exception used to indicate protocol violation. + */ + class No_arp_packet : Genode::Exception {}; - /****************************** - ** ARP field read-accessors ** - ******************************/ + /***************** + ** Constructor ** + *****************/ - /** - * \return link layer type (Arp_packet::Hardware_type). - */ - Genode::uint16_t hardware_address_type() { - return bswap(_hw_addr_type); } - - /** - * \return network/internet layer type (Ether_frame::EtherType). - */ - Genode::uint16_t protocol_address_type() { - return bswap(_prot_addr_type); } - - /** - * \return size in bytes of hardware address. - */ - Genode::uint8_t hardware_address_size() { return _hw_addr_sz; } - - /** - * \return size in bytes of protocol address. - */ - Genode::uint8_t protocol_address_size() { return _prot_addr_sz; } - - /** - * \return operation code (Arp_packet::Opcode). - */ - Genode::uint16_t opcode() { return bswap(_opcode); } - - /** - * \return source MAC address. - */ - Ethernet_frame::Mac_address src_mac() { - return Ethernet_frame::Mac_address(&_src_mac_addr); } - - /** - * \return source IP address. - */ - Ipv4_packet::Ipv4_address src_ip() { - return Ipv4_packet::Ipv4_address(&_src_ip_addr); } - - /** - * \return destination MAC address. - */ - Ethernet_frame::Mac_address dst_mac() { - return Ethernet_frame::Mac_address(&_dst_mac_addr); } - - /** - * \return destination IP address. - */ - Ipv4_packet::Ipv4_address dst_ip() { - return Ipv4_packet::Ipv4_address(&_dst_ip_addr); } + Arp_packet(Genode::size_t size) { + /* arp packet needs to fit in */ + if (size < sizeof(Arp_packet)) + throw No_arp_packet(); + } - /****************************** - ** ARP field write-accessors ** - ******************************/ + /****************************** + ** ARP field read-accessors ** + ******************************/ - /** - * Set Operation code. - * - * \param opcode Arp_packet::Opcode to set. - */ - void opcode(Genode::uint16_t opcode) { - _opcode = bswap(opcode); } + /** + * \return link layer type (Arp_packet::Hardware_type). + */ + Genode::uint16_t hardware_address_type() { + return bswap(_hw_addr_type); } - /** - * Set source MAC address. - * - * \param src_mac_addr MAC address to set. - */ - void src_mac(Ethernet_frame::Mac_address src_mac_addr) { - src_mac_addr.copy(&_src_mac_addr); } + /** + * \return network/internet layer type (Ether_frame::EtherType). + */ + Genode::uint16_t protocol_address_type() { + return bswap(_prot_addr_type); } - /** - * Set source IP address. - * - * \param src_ip_addr IP address to set. - */ - void src_ip(Ipv4_packet::Ipv4_address src_ip_addr) { - src_ip_addr.copy(&_src_ip_addr); } + /** + * \return size in bytes of hardware address. + */ + Genode::uint8_t hardware_address_size() { return _hw_addr_sz; } - /** - * Set destination MAC address. - * - * \param src_mac_addr MAC address to set. - */ - void dst_mac(Ethernet_frame::Mac_address dst_mac_addr) { - dst_mac_addr.copy(&_dst_mac_addr); } + /** + * \return size in bytes of protocol address. + */ + Genode::uint8_t protocol_address_size() { return _prot_addr_sz; } - /** - * Set destination IP address. - * - * \param src_ip_addr IP address to set. - */ - void dst_ip(Ipv4_packet::Ipv4_address dst_ip_addr) { - dst_ip_addr.copy(&_dst_ip_addr); } + /** + * \return operation code (Arp_packet::Opcode). + */ + Genode::uint16_t opcode() { return bswap(_opcode); } + + /** + * \return source MAC address. + */ + Ethernet_frame::Mac_address src_mac() { + return Ethernet_frame::Mac_address(&_src_mac_addr); } + + /** + * \return source IP address. + */ + Ipv4_packet::Ipv4_address src_ip() { + return Ipv4_packet::Ipv4_address(&_src_ip_addr); } + + /** + * \return destination MAC address. + */ + Ethernet_frame::Mac_address dst_mac() { + return Ethernet_frame::Mac_address(&_dst_mac_addr); } + + /** + * \return destination IP address. + */ + Ipv4_packet::Ipv4_address dst_ip() { + return Ipv4_packet::Ipv4_address(&_dst_ip_addr); } - /*************************** - ** convenience functions ** - ***************************/ + /****************************** + ** ARP field write-accessors ** + ******************************/ - /** - * \return true when ARP packet really targets ethernet - * address resolution with respect to IPv4 addresses. - */ - bool ethernet_ipv4() { - return ( bswap(_hw_addr_type) == ETHERNET - && bswap(_prot_addr_type) == Ethernet_frame::IPV4 - && _hw_addr_sz == Ethernet_frame::ADDR_LEN - && _prot_addr_sz == Ipv4_packet::ADDR_LEN); - } + /** + * Set Operation code. + * + * \param opcode Arp_packet::Opcode to set. + */ + void opcode(Genode::uint16_t opcode) { + _opcode = bswap(opcode); } + + /** + * Set source MAC address. + * + * \param src_mac_addr MAC address to set. + */ + void src_mac(Ethernet_frame::Mac_address src_mac_addr) { + src_mac_addr.copy(&_src_mac_addr); } + + /** + * Set source IP address. + * + * \param src_ip_addr IP address to set. + */ + void src_ip(Ipv4_packet::Ipv4_address src_ip_addr) { + src_ip_addr.copy(&_src_ip_addr); } + + /** + * Set destination MAC address. + * + * \param src_mac_addr MAC address to set. + */ + void dst_mac(Ethernet_frame::Mac_address dst_mac_addr) { + dst_mac_addr.copy(&_dst_mac_addr); } + + /** + * Set destination IP address. + * + * \param src_ip_addr IP address to set. + */ + void dst_ip(Ipv4_packet::Ipv4_address dst_ip_addr) { + dst_ip_addr.copy(&_dst_ip_addr); } - /*************** - ** Operators ** - ***************/ + /*************************** + ** convenience functions ** + ***************************/ - /** - * Placement new - */ - void * operator new(Genode::size_t size, void* addr) { - return addr; } - } __attribute__((packed)); -} + /** + * \return true when ARP packet really targets ethernet + * address resolution with respect to IPv4 addresses. + */ + bool ethernet_ipv4() { + return ( bswap(_hw_addr_type) == ETHERNET + && bswap(_prot_addr_type) == Ethernet_frame::IPV4 + && _hw_addr_sz == Ethernet_frame::ADDR_LEN + && _prot_addr_sz == Ipv4_packet::ADDR_LEN); + } + + + /*************** + ** Operators ** + ***************/ + + /** + * Placement new + */ + void * operator new(Genode::size_t size, void* addr) { + return addr; } +} __attribute__((packed)); #endif /* _NET__ARP_H_ */ diff --git a/repos/os/include/net/dhcp.h b/repos/os/include/net/dhcp.h index b6b8dd9cc..21330e9a8 100644 --- a/repos/os/include/net/dhcp.h +++ b/repos/os/include/net/dhcp.h @@ -23,258 +23,258 @@ #include #include -namespace Net { - - /** - * The data-layout of this class conforms to an DHCP packet (RFC 2131). - * - * DHCP packet layout: - * - * =================================== - * | 1 byte | 1 byte | 1 byte | 1 byte | - * =================================== - * | op | htype | hlen | hops | - * ----------------------------------- - * | connection-id (xid) | - * ----------------------------------- - * | seconds | flags | - * ----------------------------------- - * | client-ip-address | - * ----------------------------------- - * | your-ip-address | - * ----------------------------------- - * | server-ip-address | - * ----------------------------------- - * | relay-agent-ip-address | - * ----------------------------------- - * | client-hw-address | - * | (16 bytes) | - * ----------------------------------- - * | sname | - * | (64 bytes) | - * ----------------------------------- - * | file | - * | (128 bytes) | - * ----------------------------------- - * | options | - * | (312 bytes, optional) | - * ----------------------------------- - */ - class Dhcp_packet - { - public: - - class No_dhcp_packet : Genode::Exception {}; +namespace Net { class Dhcp_packet; } - class Client_hw_address - { - public: - Genode::uint8_t addr[16]; - }; +/** + * Data layout of this class conforms to an DHCP packet (RFC 2131) + * + * DHCP packet layout: + * + * =================================== + * | 1 byte | 1 byte | 1 byte | 1 byte | + * =================================== + * | op | htype | hlen | hops | + * ----------------------------------- + * | connection-id (xid) | + * ----------------------------------- + * | seconds | flags | + * ----------------------------------- + * | client-ip-address | + * ----------------------------------- + * | your-ip-address | + * ----------------------------------- + * | server-ip-address | + * ----------------------------------- + * | relay-agent-ip-address | + * ----------------------------------- + * | client-hw-address | + * | (16 bytes) | + * ----------------------------------- + * | sname | + * | (64 bytes) | + * ----------------------------------- + * | file | + * | (128 bytes) | + * ----------------------------------- + * | options | + * | (312 bytes, optional) | + * ----------------------------------- + */ +class Net::Dhcp_packet +{ + public: - private: - - /************************ - ** DHCP packet fields ** - ************************/ - - Genode::uint8_t _op; - Genode::uint8_t _htype; - Genode::uint8_t _hlen; - Genode::uint8_t _hops; - Genode::uint32_t _xid; - Genode::uint16_t _secs; - Genode::uint16_t _flags; - Genode::uint8_t _ciaddr[Ipv4_packet::ADDR_LEN]; - Genode::uint8_t _yiaddr[Ipv4_packet::ADDR_LEN]; - Genode::uint8_t _siaddr[Ipv4_packet::ADDR_LEN]; - Genode::uint8_t _giaddr[Ipv4_packet::ADDR_LEN]; - Client_hw_address _chaddr; - Genode::uint8_t _sname[64]; - Genode::uint8_t _file[128]; - Genode::uint32_t _magic_cookie; - Genode::uint8_t _opts[0]; - - enum Flag { - BROADCAST = 0x80 - }; - - public: - - /** - * This class represents the data layout of an DHCP option. - */ - class Option - { - private: - - Genode::uint8_t _code; - Genode::uint8_t _len; - Genode::uint8_t _value[0]; - - public: - - Option() {} - - Genode::uint8_t code() { return _code; } - Genode::size_t length() { return _len; } - void* value() { return _value; } - - /** - * Placement new. - */ - void * operator new(Genode::size_t size, void* addr) { - return addr; } - } __attribute__((packed)); + class No_dhcp_packet : Genode::Exception {}; - enum Opcode { - REQUEST = 1, - REPLY = 2, - INVALID - }; + class Client_hw_address + { + public: + Genode::uint8_t addr[16]; + }; - enum Udp_port { - BOOTPS = 67, - BOOTPC = 68 - }; + private: - enum Option_type { - REQ_IP_ADDR = 50, - IP_LEASE_TIME = 51, - OPT_OVERLOAD = 52, - MSG_TYPE = 53, - SRV_ID = 54, - REQ_PARAMETER = 55, - MESSAGE = 56, - MAX_MSG_SZ = 57, - RENEWAL = 58, - REBINDING = 59, - VENDOR = 60, - CLI_ID = 61, - TFTP_SRV_NAME = 66, - BOOT_FILE = 67, - END = 255 - }; + /************************ + ** DHCP packet fields ** + ************************/ - enum Message_type { - DHCP_DISCOVER = 1, - DHCP_OFFER = 2, - DHCP_REQUEST = 3, - DHCP_DECLINE = 4, - DHCP_ACK = 5, - DHCP_NAK = 6, - DHCP_RELEASE = 7, - DHCP_INFORM = 8 - }; + Genode::uint8_t _op; + Genode::uint8_t _htype; + Genode::uint8_t _hlen; + Genode::uint8_t _hops; + Genode::uint32_t _xid; + Genode::uint16_t _secs; + Genode::uint16_t _flags; + Genode::uint8_t _ciaddr[Ipv4_packet::ADDR_LEN]; + Genode::uint8_t _yiaddr[Ipv4_packet::ADDR_LEN]; + Genode::uint8_t _siaddr[Ipv4_packet::ADDR_LEN]; + Genode::uint8_t _giaddr[Ipv4_packet::ADDR_LEN]; + Client_hw_address _chaddr; + Genode::uint8_t _sname[64]; + Genode::uint8_t _file[128]; + Genode::uint32_t _magic_cookie; + Genode::uint8_t _opts[0]; + + enum Flag { + BROADCAST = 0x80 + }; + + public: + + /** + * This class represents the data layout of an DHCP option. + */ + class Option + { + private: + + Genode::uint8_t _code; + Genode::uint8_t _len; + Genode::uint8_t _value[0]; + + public: + + Option() {} + + Genode::uint8_t code() { return _code; } + Genode::size_t length() { return _len; } + void* value() { return _value; } + + /** + * Placement new. + */ + void * operator new(Genode::size_t size, void* addr) { + return addr; } + } __attribute__((packed)); - /***************** - ** Constructor ** - *****************/ + enum Opcode { + REQUEST = 1, + REPLY = 2, + INVALID + }; - Dhcp_packet(Genode::size_t size) { - /* dhcp packet needs to fit in */ - if (size < sizeof(Dhcp_packet)) - throw No_dhcp_packet(); + enum Udp_port { + BOOTPS = 67, + BOOTPC = 68 + }; + + enum Option_type { + REQ_IP_ADDR = 50, + IP_LEASE_TIME = 51, + OPT_OVERLOAD = 52, + MSG_TYPE = 53, + SRV_ID = 54, + REQ_PARAMETER = 55, + MESSAGE = 56, + MAX_MSG_SZ = 57, + RENEWAL = 58, + REBINDING = 59, + VENDOR = 60, + CLI_ID = 61, + TFTP_SRV_NAME = 66, + BOOT_FILE = 67, + END = 255 + }; + + enum Message_type { + DHCP_DISCOVER = 1, + DHCP_OFFER = 2, + DHCP_REQUEST = 3, + DHCP_DECLINE = 4, + DHCP_ACK = 5, + DHCP_NAK = 6, + DHCP_RELEASE = 7, + DHCP_INFORM = 8 + }; + + + /***************** + ** Constructor ** + *****************/ + + Dhcp_packet(Genode::size_t size) { + /* dhcp packet needs to fit in */ + if (size < sizeof(Dhcp_packet)) + throw No_dhcp_packet(); + } + + + /******************************* + ** DHCP field read-accessors ** + *******************************/ + + Genode::uint8_t op() { return _op; } + Genode::uint8_t htype() { return _htype; } + Genode::uint8_t hlen() { return _hlen; } + Genode::uint8_t hops() { return _hops; } + Genode::uint32_t xid() { return bswap(_xid); } + Genode::uint16_t secs() { return bswap(_secs); } + + bool broadcast() { return _flags & BROADCAST; } + + Ipv4_packet::Ipv4_address ciaddr() { + return Ipv4_packet::Ipv4_address(&_ciaddr); } + Ipv4_packet::Ipv4_address yiaddr() { + return Ipv4_packet::Ipv4_address(&_yiaddr); } + Ipv4_packet::Ipv4_address siaddr() { + return Ipv4_packet::Ipv4_address(&_siaddr); } + Ipv4_packet::Ipv4_address giaddr() { + return Ipv4_packet::Ipv4_address(&_giaddr); } + + Ethernet_frame::Mac_address client_mac() { + return Ethernet_frame::Mac_address(&_chaddr); } + + const char* server_name() { return (const char*) &_sname; } + const char* file() { return (const char*) &_file; } + + Option *option(Option_type op) + { + void *ptr = &_opts; + while (true) { + Option *ext = new (ptr) Option(); + if (ext->code() == op) + return ext; + if (ext->code() == END || ext->code() == 0) + break; + ptr = ext + ext->length(); } + return 0; + } - /******************************* - ** DHCP field read-accessors ** - *******************************/ + /******************************* + ** DHCP field write-accessors ** + *******************************/ - Genode::uint8_t op() { return _op; } - Genode::uint8_t htype() { return _htype; } - Genode::uint8_t hlen() { return _hlen; } - Genode::uint8_t hops() { return _hops; } - Genode::uint32_t xid() { return bswap(_xid); } - Genode::uint16_t secs() { return bswap(_secs); } + void op(Genode::uint8_t op) { _op = op; } + void htype(Genode::uint8_t htype) { _htype = htype; } + void hlen(Genode::uint8_t hlen) { _hlen = hlen; } + void hops(Genode::uint8_t hops) { _hops = hops; } + void xid(Genode::uint32_t xid) { _xid = bswap(_xid); } + void secs(Genode::uint16_t secs) { _secs = bswap(_secs); } - bool broadcast() { return _flags & BROADCAST; } + void broadcast(bool broadcast) { + _flags = broadcast ? BROADCAST : 0; } - Ipv4_packet::Ipv4_address ciaddr() { - return Ipv4_packet::Ipv4_address(&_ciaddr); } - Ipv4_packet::Ipv4_address yiaddr() { - return Ipv4_packet::Ipv4_address(&_yiaddr); } - Ipv4_packet::Ipv4_address siaddr() { - return Ipv4_packet::Ipv4_address(&_siaddr); } - Ipv4_packet::Ipv4_address giaddr() { - return Ipv4_packet::Ipv4_address(&_giaddr); } + void ciaddr(Ipv4_packet::Ipv4_address ciaddr) { + ciaddr.copy(&_ciaddr); } + void yiaddr(Ipv4_packet::Ipv4_address yiaddr) { + yiaddr.copy(&_yiaddr); } + void siaddr(Ipv4_packet::Ipv4_address siaddr) { + siaddr.copy(&_siaddr); } + void giaddr(Ipv4_packet::Ipv4_address giaddr) { + giaddr.copy(&_giaddr); } - Ethernet_frame::Mac_address client_mac() { - return Ethernet_frame::Mac_address(&_chaddr); } - - const char* server_name() { return (const char*) &_sname; } - const char* file() { return (const char*) &_file; } - - Option *option(Option_type op) - { - void *ptr = &_opts; - while (true) { - Option *ext = new (ptr) Option(); - if (ext->code() == op) - return ext; - if (ext->code() == END || ext->code() == 0) - break; - ptr = ext + ext->length(); - } - return 0; - } + void client_mac(Ethernet_frame::Mac_address mac) { + mac.copy(&_chaddr); } - /******************************* - ** DHCP field write-accessors ** - *******************************/ + /*************************** + ** Convenience functions ** + ***************************/ - void op(Genode::uint8_t op) { _op = op; } - void htype(Genode::uint8_t htype) { _htype = htype; } - void hlen(Genode::uint8_t hlen) { _hlen = hlen; } - void hops(Genode::uint8_t hops) { _hops = hops; } - void xid(Genode::uint32_t xid) { _xid = bswap(_xid); } - void secs(Genode::uint16_t secs) { _secs = bswap(_secs); } - - void broadcast(bool broadcast) { - _flags = broadcast ? BROADCAST : 0; } - - void ciaddr(Ipv4_packet::Ipv4_address ciaddr) { - ciaddr.copy(&_ciaddr); } - void yiaddr(Ipv4_packet::Ipv4_address yiaddr) { - yiaddr.copy(&_yiaddr); } - void siaddr(Ipv4_packet::Ipv4_address siaddr) { - siaddr.copy(&_siaddr); } - void giaddr(Ipv4_packet::Ipv4_address giaddr) { - giaddr.copy(&_giaddr); } - - void client_mac(Ethernet_frame::Mac_address mac) { - mac.copy(&_chaddr); } + static bool is_dhcp(Udp_packet *udp) + { + return ((udp->src_port() == Dhcp_packet::BOOTPC || + udp->src_port() == Dhcp_packet::BOOTPS) && + (udp->dst_port() == Dhcp_packet::BOOTPC || + udp->dst_port() == Dhcp_packet::BOOTPS)); + } - /*************************** - ** Convenience functions ** - ***************************/ + /*************** + ** Operators ** + ***************/ - static bool is_dhcp(Udp_packet *udp) - { - return ((udp->src_port() == Dhcp_packet::BOOTPC || - udp->src_port() == Dhcp_packet::BOOTPS) && - (udp->dst_port() == Dhcp_packet::BOOTPC || - udp->dst_port() == Dhcp_packet::BOOTPS)); - } + /** + * Placement new. + */ + void * operator new(Genode::size_t size, void* addr) { + return addr; } - - /*************** - ** Operators ** - ***************/ - - /** - * Placement new. - */ - void * operator new(Genode::size_t size, void* addr) { - return addr; } - - } __attribute__((packed)); -} +} __attribute__((packed)); #endif /* _DHCP_H_ */ diff --git a/repos/os/include/net/ethernet.h b/repos/os/include/net/ethernet.h index 669e7df3a..9e3c48068 100644 --- a/repos/os/include/net/ethernet.h +++ b/repos/os/include/net/ethernet.h @@ -21,161 +21,161 @@ #include #include -namespace Net { - - /** - * The data-layout of this class conforms to the Ethernet II frame - * (IEEE 802.3). - * - * Ethernet-frame-header-format: - * - * ---------------------------------------------------------- - * | destination mac address | source mac address | ethertype | - * | 6 bytes | 6 bytes | 2 bytes | - * ---------------------------------------------------------- - */ - class Ethernet_frame - { - public: - - enum Size { - ADDR_LEN = 6, /* MAC address length in bytes */ - }; - - typedef Network_address Mac_address; - - static const Mac_address BROADCAST; /* broadcast address */ - - private: - - Genode::uint8_t _dst_mac[ADDR_LEN]; /* destination mac address */ - Genode::uint8_t _src_mac[ADDR_LEN]; /* source mac address */ - Genode::uint16_t _type; /* encapsulated protocol */ - unsigned _data[0]; /* encapsulated data */ - - public: - - class No_ethernet_frame : Genode::Exception {}; +namespace Net { class Ethernet_frame; } - /** - * Id representing encapsulated protocol. - */ - enum Ether_type { - IPV4 = 0x0800, - ARP = 0x0806, - WAKE_ON_LAN = 0x0842, - SYN3 = 0x1337, - RARP = 0x8035, - APPLETALK = 0x809B, - AARP = 0x80F3, - VLAN_TAGGED = 0x8100, - IPX = 0x8137, - NOVELL = 0x8138, - IPV6 = 0x86DD, - MAC_CONTROL = 0x8808, - SLOW = 0x8809, - COBRANET = 0x8819, - MPLS_UNICAST = 0x8847, - MPLS_MULTICAST = 0x8848, - PPPOE_DISCOVERY = 0x8863, - PPPOE_STAGE = 0x8864, - NLB = 0x886F, - JUMBO_FRAMES = 0x8870, - EAP = 0x888E, - PROFINET = 0x8892, - HYPERSCSI = 0x889A, - ATAOE = 0x88A2, - ETHERCAT = 0x88A4, - PROVIDER_BRIDGING = 0x88A8, - POWERLINK = 0x88AB, - LLDP = 0x88CC, - SERCOS_III = 0x88CD, - CESOE = 0x88D8, - HOMEPLUG = 0x88E1, - MAC_SEC = 0x88E5, - PRECISION_TIME = 0x88F7, - CFM = 0x8902, - FCOE = 0x8906, - FCOE_Init = 0x8914, - Q_IN_Q = 0x9100, - LLT = 0xCAFE - }; +/** + * Data layout of this class conforms to the Ethernet II frame + * (IEEE 802.3). + * + * Ethernet-frame-header-format: + * + * ---------------------------------------------------------- + * | destination mac address | source mac address | ethertype | + * | 6 bytes | 6 bytes | 2 bytes | + * ---------------------------------------------------------- + */ +class Net::Ethernet_frame +{ + public: + + enum Size { + ADDR_LEN = 6, /* MAC address length in bytes */ + }; + + typedef Network_address Mac_address; + + static const Mac_address BROADCAST; /* broadcast address */ + + private: + + Genode::uint8_t _dst_mac[ADDR_LEN]; /* destination mac address */ + Genode::uint8_t _src_mac[ADDR_LEN]; /* source mac address */ + Genode::uint16_t _type; /* encapsulated protocol */ + unsigned _data[0]; /* encapsulated data */ + + public: + + class No_ethernet_frame : Genode::Exception {}; - /***************** - ** Constructor ** - *****************/ - - Ethernet_frame(Genode::size_t size) { - /* at least, frame header needs to fit in */ - if (size < sizeof(Ethernet_frame)) - throw No_ethernet_frame(); - } + /** + * Id representing encapsulated protocol. + */ + enum Ether_type { + IPV4 = 0x0800, + ARP = 0x0806, + WAKE_ON_LAN = 0x0842, + SYN3 = 0x1337, + RARP = 0x8035, + APPLETALK = 0x809B, + AARP = 0x80F3, + VLAN_TAGGED = 0x8100, + IPX = 0x8137, + NOVELL = 0x8138, + IPV6 = 0x86DD, + MAC_CONTROL = 0x8808, + SLOW = 0x8809, + COBRANET = 0x8819, + MPLS_UNICAST = 0x8847, + MPLS_MULTICAST = 0x8848, + PPPOE_DISCOVERY = 0x8863, + PPPOE_STAGE = 0x8864, + NLB = 0x886F, + JUMBO_FRAMES = 0x8870, + EAP = 0x888E, + PROFINET = 0x8892, + HYPERSCSI = 0x889A, + ATAOE = 0x88A2, + ETHERCAT = 0x88A4, + PROVIDER_BRIDGING = 0x88A8, + POWERLINK = 0x88AB, + LLDP = 0x88CC, + SERCOS_III = 0x88CD, + CESOE = 0x88D8, + HOMEPLUG = 0x88E1, + MAC_SEC = 0x88E5, + PRECISION_TIME = 0x88F7, + CFM = 0x8902, + FCOE = 0x8906, + FCOE_Init = 0x8914, + Q_IN_Q = 0x9100, + LLT = 0xCAFE + }; - /*********************************** - ** Ethernet field read-accessors ** - ***********************************/ + /***************** + ** Constructor ** + *****************/ - /** - * \return destination MAC address of frame. - */ - Mac_address dst() { return Mac_address(&_dst_mac); } - - /** - * \return source MAC address of frame. - */ - Mac_address src() { return Mac_address(&_src_mac); } - - /** - * \return EtherType - type of encapsulated protocol. - */ - Genode::uint16_t type() { return bswap(_type); } - - /** - * \return payload data. - */ - void *data() { return &_data; } + Ethernet_frame(Genode::size_t size) { + /* at least, frame header needs to fit in */ + if (size < sizeof(Ethernet_frame)) + throw No_ethernet_frame(); + } - /*********************************** - ** Ethernet field write-accessors ** - ***********************************/ + /*********************************** + ** Ethernet field read-accessors ** + ***********************************/ - /** - * Set the destination MAC address of this frame. - * - * \param mac MAC address to be set. - */ - void dst(Mac_address mac) { mac.copy(&_dst_mac); } + /** + * \return destination MAC address of frame. + */ + Mac_address dst() { return Mac_address(&_dst_mac); } - /** - * Set the source MAC address of this frame. - * - * \param mac MAC address to be set. - */ - void src(Mac_address mac) { mac.copy(&_src_mac); } + /** + * \return source MAC address of frame. + */ + Mac_address src() { return Mac_address(&_src_mac); } - /** - * Set type of encapsulated protocol. - * - * \param type the EtherType to be set. - */ - void type(Genode::uint16_t type) { _type = bswap(type); } + /** + * \return EtherType - type of encapsulated protocol. + */ + Genode::uint16_t type() { return bswap(_type); } + + /** + * \return payload data. + */ + void *data() { return &_data; } - /*************** - ** Operators ** - ***************/ + /*********************************** + ** Ethernet field write-accessors ** + ***********************************/ - /** - * Placement new operator. - */ - void * operator new(Genode::size_t size, void* addr) { - return addr; } + /** + * Set the destination MAC address of this frame. + * + * \param mac MAC address to be set. + */ + void dst(Mac_address mac) { mac.copy(&_dst_mac); } - } __attribute__((packed)); -} + /** + * Set the source MAC address of this frame. + * + * \param mac MAC address to be set. + */ + void src(Mac_address mac) { mac.copy(&_src_mac); } + + /** + * Set type of encapsulated protocol. + * + * \param type the EtherType to be set. + */ + void type(Genode::uint16_t type) { _type = bswap(type); } + + + /*************** + ** Operators ** + ***************/ + + /** + * Placement new operator. + */ + void * operator new(Genode::size_t size, void* addr) { + return addr; } + +} __attribute__((packed)); #endif /* _NET__ETHERNET_H_ */ diff --git a/repos/os/include/net/ipv4.h b/repos/os/include/net/ipv4.h index b512f1829..ba20c4fcd 100644 --- a/repos/os/include/net/ipv4.h +++ b/repos/os/include/net/ipv4.h @@ -21,153 +21,153 @@ #include #include -namespace Net { - - /** - * The data-layout of this class conforms to an IPv4 packet (RFC 791). - * - * IPv4-header-format: - * - * ---------------------------------------------------------------- - * | 0-3 | 4-7 | 8-11 | 12-15 | 16-18 | 19-23 | 24-27 | 28-31 | - * ---------------------------------------------------------------- - * | version | IHL | service-type | total-length | - * ---------------------------------------------------------------- - * | identifikation | flags | fragment-offset | - * ---------------------------------------------------------------- - * | ttl | protocol | header-checksum | - * ---------------------------------------------------------------- - * | source-ip-address | - * ---------------------------------------------------------------- - * | destination-ip-address | - * ---------------------------------------------------------------- - * | options ... | - * ---------------------------------------------------------------- - */ - class Ipv4_packet - { - public: - - enum Size { - ADDR_LEN = 4, /* Ip address length in bytes */ - }; - - typedef Network_address Ipv4_address; - - static const Ipv4_address CURRENT; /* current network */ - static const Ipv4_address BROADCAST; /* broadcast address */ - - static Ipv4_address ip_from_string(const char *ip); - - private: - - /************************ - ** IPv4 header fields ** - ************************/ - - unsigned _version : 4; - unsigned _header_length : 4; - Genode::uint8_t _diff_service; - Genode::uint16_t _total_length; - Genode::uint16_t _identification; - unsigned _flags : 3; - unsigned _fragment_offset : 13; - Genode::uint8_t _time_to_live; - Genode::uint8_t _protocol; - Genode::uint16_t _header_checksum; - Genode::uint8_t _src_addr[ADDR_LEN]; - Genode::uint8_t _dst_addr[ADDR_LEN]; - unsigned _data[0]; - - /** - * Bitmasks for differentiated services field. - */ - enum Differentiated_services { - PRECEDENCE = 0x7, - DELAY = 0x8, - THROUGHPUT = 0x10, - RELIABILITY = 0x20, - COST = 0x40 - }; - - public: - - enum Precedence { - NETWORK_CONTROL = 7, - INTERNETWORK_CONTROL = 6, - CRITIC_ECP = 5, - FLASH_OVERRIDE = 4, - FLASH = 3, - IMMEDIATE = 2, - PRIORITY = 1, - ROUTINE = 0 - }; - - enum Flags { - NO_FRAGMENT = 0x2, - MORE_FRAGMENTS = 0x4 - }; +namespace Net { class Ipv4_packet; } - /** - * Exception used to indicate protocol violation. - */ - class No_ip_packet : Genode::Exception {}; +/** + * Data layout of this class conforms to an IPv4 packet (RFC 791) + * + * IPv4-header-format: + * + * ---------------------------------------------------------------- + * | 0-3 | 4-7 | 8-11 | 12-15 | 16-18 | 19-23 | 24-27 | 28-31 | + * ---------------------------------------------------------------- + * | version | IHL | service-type | total-length | + * ---------------------------------------------------------------- + * | identifikation | flags | fragment-offset | + * ---------------------------------------------------------------- + * | ttl | protocol | header-checksum | + * ---------------------------------------------------------------- + * | source-ip-address | + * ---------------------------------------------------------------- + * | destination-ip-address | + * ---------------------------------------------------------------- + * | options ... | + * ---------------------------------------------------------------- + */ +class Net::Ipv4_packet +{ + public: + + enum Size { + ADDR_LEN = 4, /* Ip address length in bytes */ + }; + + typedef Network_address Ipv4_address; + + static const Ipv4_address CURRENT; /* current network */ + static const Ipv4_address BROADCAST; /* broadcast address */ + + static Ipv4_address ip_from_string(const char *ip); + + private: + + /************************ + ** IPv4 header fields ** + ************************/ + + unsigned _version : 4; + unsigned _header_length : 4; + Genode::uint8_t _diff_service; + Genode::uint16_t _total_length; + Genode::uint16_t _identification; + unsigned _flags : 3; + unsigned _fragment_offset : 13; + Genode::uint8_t _time_to_live; + Genode::uint8_t _protocol; + Genode::uint16_t _header_checksum; + Genode::uint8_t _src_addr[ADDR_LEN]; + Genode::uint8_t _dst_addr[ADDR_LEN]; + unsigned _data[0]; + + /** + * Bitmasks for differentiated services field. + */ + enum Differentiated_services { + PRECEDENCE = 0x7, + DELAY = 0x8, + THROUGHPUT = 0x10, + RELIABILITY = 0x20, + COST = 0x40 + }; + + public: + + enum Precedence { + NETWORK_CONTROL = 7, + INTERNETWORK_CONTROL = 6, + CRITIC_ECP = 5, + FLASH_OVERRIDE = 4, + FLASH = 3, + IMMEDIATE = 2, + PRIORITY = 1, + ROUTINE = 0 + }; + + enum Flags { + NO_FRAGMENT = 0x2, + MORE_FRAGMENTS = 0x4 + }; - /***************** - ** Constructor ** - *****************/ - - Ipv4_packet(Genode::size_t size) { - /* ip header needs to fit in */ - if (size < sizeof(Ipv4_packet)) - throw No_ip_packet(); - } + /** + * Exception used to indicate protocol violation. + */ + class No_ip_packet : Genode::Exception {}; - /******************************* - ** IPv4 field read-accessors ** - *******************************/ + /***************** + ** Constructor ** + *****************/ - Genode::size_t version() { return _version; } - Genode::size_t header_length() { return _header_length / 4; } - Genode::uint8_t precedence() { return _diff_service & PRECEDENCE; } - - bool low_delay() { return _diff_service & DELAY; } - bool high_throughput() { return _diff_service & THROUGHPUT; } - bool high_reliability() { return _diff_service & RELIABILITY;} - bool minimize_monetary_cost() { return _diff_service & COST; } - - Genode::uint16_t total_length() { return bswap(_total_length); } - Genode::uint16_t identification() { return bswap(_identification); } - - bool no_fragmentation() { return _flags & NO_FRAGMENT; } - bool more_fragments() { return _flags & MORE_FRAGMENTS; } - - Genode::size_t fragment_offset() { return _fragment_offset; } - Genode::uint8_t time_to_live() { return _time_to_live; } - Genode::uint8_t protocol() { return _protocol; } - - Genode::uint16_t checksum() { return bswap(_header_checksum); } - - Ipv4_address dst() { return Ipv4_address(&_dst_addr); } - Ipv4_address src() { return Ipv4_address(&_src_addr); } - - void *data() { return &_data; } + Ipv4_packet(Genode::size_t size) { + /* ip header needs to fit in */ + if (size < sizeof(Ipv4_packet)) + throw No_ip_packet(); + } - /*************** - ** Operators ** - ***************/ + /******************************* + ** IPv4 field read-accessors ** + *******************************/ - /** - * Placement new. - */ - void * operator new(Genode::size_t size, void* addr) { - return addr; } + Genode::size_t version() { return _version; } + Genode::size_t header_length() { return _header_length / 4; } + Genode::uint8_t precedence() { return _diff_service & PRECEDENCE; } - } __attribute__((packed)); -} + bool low_delay() { return _diff_service & DELAY; } + bool high_throughput() { return _diff_service & THROUGHPUT; } + bool high_reliability() { return _diff_service & RELIABILITY;} + bool minimize_monetary_cost() { return _diff_service & COST; } + + Genode::uint16_t total_length() { return bswap(_total_length); } + Genode::uint16_t identification() { return bswap(_identification); } + + bool no_fragmentation() { return _flags & NO_FRAGMENT; } + bool more_fragments() { return _flags & MORE_FRAGMENTS; } + + Genode::size_t fragment_offset() { return _fragment_offset; } + Genode::uint8_t time_to_live() { return _time_to_live; } + Genode::uint8_t protocol() { return _protocol; } + + Genode::uint16_t checksum() { return bswap(_header_checksum); } + + Ipv4_address dst() { return Ipv4_address(&_dst_addr); } + Ipv4_address src() { return Ipv4_address(&_src_addr); } + + void *data() { return &_data; } + + + /*************** + ** Operators ** + ***************/ + + /** + * Placement new. + */ + void * operator new(Genode::size_t size, void* addr) { + return addr; } + +} __attribute__((packed)); #endif /* _IPV4_H_ */ diff --git a/repos/os/include/net/netaddress.h b/repos/os/include/net/netaddress.h index 9c3f51f47..d18427967 100644 --- a/repos/os/include/net/netaddress.h +++ b/repos/os/include/net/netaddress.h @@ -18,56 +18,56 @@ #include #include -namespace Net { - - /** - * Generic form of a network address. - */ - template - class Network_address - { - public: - - Genode::uint8_t addr[LEN]; +namespace Net { template class Network_address; } - /****************** - ** Constructors ** - ******************/ +/** + * Generic form of a network address. + */ +template +class Net::Network_address +{ + public: - Network_address(Genode::uint8_t value = 0) { - Genode::memset(&addr, value, LEN); } - - Network_address(void *src) { - Genode::memcpy(&addr, src, LEN); } + Genode::uint8_t addr[LEN]; - /*********************** - ** Helper functions ** - ***********************/ + /****************** + ** Constructors ** + ******************/ - void copy(void *dst) { Genode::memcpy(dst, addr, LEN); } + Network_address(Genode::uint8_t value = 0) { + Genode::memset(&addr, value, LEN); } + + Network_address(void *src) { + Genode::memcpy(&addr, src, LEN); } - /*************** - ** Operators ** - ***************/ + /*********************** + ** Helper functions ** + ***********************/ - bool operator==(const Network_address &other) const { + void copy(void *dst) { Genode::memcpy(dst, addr, LEN); } - /* - * We compare from lowest address segment to highest - * one, because in a local context, the higher segments - * of two addresses normally don't distinguish. - * (e.g. in an IPv4 local subnet) - */ - for (int i = LEN-1; i >= 0; --i) { - if (addr[i] != other.addr[i]) - return false; - } - return true; + + /*************** + ** Operators ** + ***************/ + + bool operator==(const Network_address &other) const { + + /* + * We compare from lowest address segment to highest + * one, because in a local context, the higher segments + * of two addresses normally don't distinguish. + * (e.g. in an IPv4 local subnet) + */ + for (int i = LEN-1; i >= 0; --i) { + if (addr[i] != other.addr[i]) + return false; } - }; -} + return true; + } +}; #endif /* _NET__NETADDRESS_H_ */ diff --git a/repos/os/include/net/udp.h b/repos/os/include/net/udp.h index 3973516d7..697ac442d 100644 --- a/repos/os/include/net/udp.h +++ b/repos/os/include/net/udp.h @@ -22,135 +22,135 @@ #include #include -namespace Net { - - /** - * The data-layout of this class conforms to an UDP packet (RFC 768). - * - * UDP-header-format: - * - * ----------------------------------------------------------------------- - * | source-port | destination-port | length | checksum | - * | 2 bytes | 2 bytes | 2 bytes | 2 bytes | - * ----------------------------------------------------------------------- - */ - class Udp_packet - { - private: - - /*********************** - ** UDP header fields ** - ***********************/ - - Genode::uint16_t _src_port; - Genode::uint16_t _dst_port; - Genode::uint16_t _length; - Genode::uint16_t _checksum; - unsigned _data[0]; - - public: - - enum Protocol_id { IP_ID = 0x11 }; +namespace Net { class Udp_packet; } - /** - * Exception used to indicate protocol violation. +/** + * Data layout of this class conforms to an UDP packet (RFC 768) + * + * UDP-header-format: + * + * ----------------------------------------------------------------------- + * | source-port | destination-port | length | checksum | + * | 2 bytes | 2 bytes | 2 bytes | 2 bytes | + * ----------------------------------------------------------------------- + */ +class Net::Udp_packet +{ + private: + + /*********************** + ** UDP header fields ** + ***********************/ + + Genode::uint16_t _src_port; + Genode::uint16_t _dst_port; + Genode::uint16_t _length; + Genode::uint16_t _checksum; + unsigned _data[0]; + + public: + + enum Protocol_id { IP_ID = 0x11 }; + + + /** + * Exception used to indicate protocol violation. + */ + class No_udp_packet : Genode::Exception {}; + + + /***************** + ** Constructor ** + *****************/ + + Udp_packet(Genode::size_t size) { + /* Udp header needs to fit in */ + if (size < sizeof(Udp_packet)) + throw No_udp_packet(); + } + + + /****************************** + ** UDP field read-accessors ** + ******************************/ + + Genode::uint16_t src_port() { return bswap(_src_port); } + Genode::uint16_t dst_port() { return bswap(_dst_port); } + Genode::uint16_t length() { return bswap(_length); } + Genode::uint16_t checksum() { return bswap(_checksum); } + void* data() { return &_data; } + + + /*************** + ** Operators ** + ***************/ + + /** + * Placement new. + */ + void * operator new(Genode::size_t size, void* addr) { + return addr; } + + + /*************************** + ** Convenience functions ** + ***************************/ + + /** + * UDP checksum is calculated over the udp datagram + an IPv4 + * pseudo header. + * + * IPv4 pseudo header: + * + * -------------------------------------------------------------- + * | src-ipaddr | dst-ipaddr | zero-field | prot.-id | udp-length | + * | 4 bytes | 4 bytes | 1 byte | 1 byte | 2 bytes | + * -------------------------------------------------------------- + */ + void calc_checksum(Ipv4_packet::Ipv4_address src, + Ipv4_packet::Ipv4_address dst) + { + /* have to reset the checksum field for calculation */ + _checksum = 0; + + /* + * sum up pseudo header */ - class No_udp_packet : Genode::Exception {}; + Genode::uint32_t sum = 0; + for (unsigned i = 0; i < Ipv4_packet::ADDR_LEN; i=i+2) { + Genode::uint16_t s = src.addr[i] << 8 | src.addr[i + 1]; + Genode::uint16_t d = dst.addr[i] << 8 | dst.addr[i + 1]; + sum += s + d; + } + Genode::uint8_t prot[] = { 0, IP_ID }; + sum += bswap(*(Genode::uint16_t*)&prot) + length(); + /* + * sum up udp packet itself + */ + unsigned max = (length() & 1) ? (length() - 1) : length(); + Genode::uint16_t *udp = (Genode::uint16_t*) this; + for (unsigned i = 0; i < max; i=i+2) + sum += bswap(*udp++); - /***************** - ** Constructor ** - *****************/ - - Udp_packet(Genode::size_t size) { - /* Udp header needs to fit in */ - if (size < sizeof(Udp_packet)) - throw No_udp_packet(); + /* if udp length is odd, append a zero byte */ + if (length() & 1) { + Genode::uint8_t last[] = + { *((Genode::uint8_t*)this + (length()-1)), 0 }; + sum += bswap(*(Genode::uint16_t*)&last); } - - /****************************** - ** UDP field read-accessors ** - ******************************/ - - Genode::uint16_t src_port() { return bswap(_src_port); } - Genode::uint16_t dst_port() { return bswap(_dst_port); } - Genode::uint16_t length() { return bswap(_length); } - Genode::uint16_t checksum() { return bswap(_checksum); } - void* data() { return &_data; } - - - /*************** - ** Operators ** - ***************/ - - /** - * Placement new. + /* + * keep only the last 16 bits of the 32 bit calculated sum + * and add the carries */ - void * operator new(Genode::size_t size, void* addr) { - return addr; } + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); - - /*************************** - ** Convenience functions ** - ***************************/ - - /** - * UDP checksum is calculated over the udp datagram + an IPv4 - * pseudo header. - * - * IPv4 pseudo header: - * - * -------------------------------------------------------------- - * | src-ipaddr | dst-ipaddr | zero-field | prot.-id | udp-length | - * | 4 bytes | 4 bytes | 1 byte | 1 byte | 2 bytes | - * -------------------------------------------------------------- - */ - void calc_checksum(Ipv4_packet::Ipv4_address src, - Ipv4_packet::Ipv4_address dst) - { - /* have to reset the checksum field for calculation */ - _checksum = 0; - - /* - * sum up pseudo header - */ - Genode::uint32_t sum = 0; - for (unsigned i = 0; i < Ipv4_packet::ADDR_LEN; i=i+2) { - Genode::uint16_t s = src.addr[i] << 8 | src.addr[i + 1]; - Genode::uint16_t d = dst.addr[i] << 8 | dst.addr[i + 1]; - sum += s + d; - } - Genode::uint8_t prot[] = { 0, IP_ID }; - sum += bswap(*(Genode::uint16_t*)&prot) + length(); - - /* - * sum up udp packet itself - */ - unsigned max = (length() & 1) ? (length() - 1) : length(); - Genode::uint16_t *udp = (Genode::uint16_t*) this; - for (unsigned i = 0; i < max; i=i+2) - sum += bswap(*udp++); - - /* if udp length is odd, append a zero byte */ - if (length() & 1) { - Genode::uint8_t last[] = - { *((Genode::uint8_t*)this + (length()-1)), 0 }; - sum += bswap(*(Genode::uint16_t*)&last); - } - - /* - * keep only the last 16 bits of the 32 bit calculated sum - * and add the carries - */ - while (sum >> 16) - sum = (sum & 0xffff) + (sum >> 16); - - /* one's complement of sum */ - _checksum = bswap((Genode::uint16_t) ~sum); - } - } __attribute__((packed)); -} + /* one's complement of sum */ + _checksum = bswap((Genode::uint16_t) ~sum); + } +} __attribute__((packed)); #endif /* _UDP_H_ */ diff --git a/repos/os/include/nic/component.h b/repos/os/include/nic/component.h index 5a1f88e70..f9470d2e0 100644 --- a/repos/os/include/nic/component.h +++ b/repos/os/include/nic/component.h @@ -26,214 +26,221 @@ enum { VERBOSE_RX = false }; namespace Nic { - class Session_component : public Genode::Allocator_avl, - public Session_rpc_object, public Rx_buffer_alloc - { - private: - - Driver_factory &_driver_factory; - Driver &_driver; - - /* rx packet descriptor */ - Packet_descriptor _curr_rx_packet; - - enum { TX_STACK_SIZE = 8*1024 }; - class Tx_thread : public Genode::Thread - { - private: - - Tx::Sink *_tx_sink; - Driver &_driver; - - public: - - Tx_thread(Tx::Sink *tx_sink, Driver &driver) - : - Genode::Thread("tx"), - _tx_sink(tx_sink), _driver(driver) - { - start(); - } - - void entry() - { - using namespace Genode; - - while (true) { - - /* block for packet from client */ - Packet_descriptor packet = _tx_sink->get_packet(); - if (!packet.valid()) { - PWRN("received invalid packet"); - continue; - } - - _driver.tx(_tx_sink->packet_content(packet), - packet.size()); - - /* acknowledge packet to the client */ - if (!_tx_sink->ready_to_ack()) - PDBG("need to wait until ready-for-ack"); - _tx_sink->acknowledge_packet(packet); - } - } - } _tx_thread; - - void dump() - { - using namespace Genode; - - if (!VERBOSE_RX) return; - - char *buf = (char *)_rx.source()->packet_content(_curr_rx_packet); - size_t size = _curr_rx_packet.size(); - - printf("rx packet:"); - for (unsigned i = 0; i < size; i++) - printf("%02x,", buf[i]); - printf("\n"); - } - - public: - - /** - * Constructor - * - * \param tx_buf_size buffer size for tx channel - * \param rx_buf_size buffer size for rx channel - * \param rx_block_alloc rx block allocator - * \param ep entry point used for packet stream - */ - Session_component(Genode::size_t tx_buf_size, - Genode::size_t rx_buf_size, - Nic::Driver_factory &driver_factory, - Genode::Rpc_entrypoint &ep) - : - Genode::Allocator_avl(Genode::env()->heap()), - Session_rpc_object(Genode::env()->ram_session()->alloc(tx_buf_size), - Genode::env()->ram_session()->alloc(rx_buf_size), - static_cast(this), ep), - _driver_factory(driver_factory), - _driver(*driver_factory.create(*this)), - _tx_thread(_tx.sink(), _driver) - { } - - /** - * Destructor - */ - ~Session_component() - { - _driver_factory.destroy(&_driver); - } - - - /******************************* - ** Rx_buffer_alloc interface ** - *******************************/ - - void *alloc(Genode::size_t size) - { - /* assign rx packet descriptor */ - _curr_rx_packet = _rx.source()->alloc_packet(size); - - return _rx.source()->packet_content(_curr_rx_packet); - } - - void submit() - { - /* check for acknowledgements from the client */ - while (_rx.source()->ack_avail()) { - Packet_descriptor packet = _rx.source()->get_acked_packet(); - - /* free packet buffer */ - _rx.source()->release_packet(packet); - } - - dump(); - - _rx.source()->submit_packet(_curr_rx_packet); - - /* invalidate rx packet descriptor */ - _curr_rx_packet = Packet_descriptor(); - } - - - /**************************** - ** Nic::Session interface ** - ****************************/ - - Mac_address mac_address() { return _driver.mac_address(); } - Tx::Sink* tx_sink() { return _tx.sink(); } - Rx::Source* rx_source() { return _rx.source(); } - }; + class Session_component; /** - * Shortcut for single-client root component + * Shortcut for single-client NIC root component */ - typedef Genode::Root_component Root_component; + typedef Genode::Root_component + Root_component; - /* - * Root component, handling new session requests. - */ - class Root : public Root_component - { - private: + class Root; +} - Driver_factory &_driver_factory; - Genode::Rpc_entrypoint &_ep; - protected: +class Nic::Session_component : public Genode::Allocator_avl, + public Session_rpc_object, public Rx_buffer_alloc +{ + private: - /* - * Always returns the singleton nic-session component. - */ - Session_component *_create_session(const char *args) - { - using namespace Genode; + Driver_factory &_driver_factory; + Driver &_driver; - Genode::size_t ram_quota = - Arg_string::find_arg(args, "ram_quota" ).ulong_value(0); - Genode::size_t tx_buf_size = - Arg_string::find_arg(args, "tx_buf_size").ulong_value(0); - Genode::size_t rx_buf_size = - Arg_string::find_arg(args, "rx_buf_size").ulong_value(0); + /* rx packet descriptor */ + Packet_descriptor _curr_rx_packet; - /* delete ram quota by the memory needed for the session */ - Genode::size_t session_size = max((Genode::size_t)4096, sizeof(Session_component) - + sizeof(Allocator_avl)); - if (ram_quota < session_size) - throw Root::Quota_exceeded(); + enum { TX_STACK_SIZE = 8*1024 }; + class Tx_thread : public Genode::Thread + { + private: - /* - * Check if donated ram quota suffices for both - * communication buffers. Also check both sizes separately - * to handle a possible overflow of the sum of both sizes. - */ - if (tx_buf_size > ram_quota - session_size - || rx_buf_size > ram_quota - session_size - || tx_buf_size + rx_buf_size > ram_quota - session_size) { - PERR("insufficient 'ram_quota', got %zd, need %zd", - ram_quota, tx_buf_size + rx_buf_size + session_size); - throw Root::Quota_exceeded(); + Tx::Sink *_tx_sink; + Driver &_driver; + + public: + + Tx_thread(Tx::Sink *tx_sink, Driver &driver) + : + Genode::Thread("tx"), + _tx_sink(tx_sink), _driver(driver) + { + start(); } - return new (md_alloc()) Session_component(tx_buf_size, - rx_buf_size, - _driver_factory, - _ep); + void entry() + { + using namespace Genode; + + while (true) { + + /* block for packet from client */ + Packet_descriptor packet = _tx_sink->get_packet(); + if (!packet.valid()) { + PWRN("received invalid packet"); + continue; + } + + _driver.tx(_tx_sink->packet_content(packet), + packet.size()); + + /* acknowledge packet to the client */ + if (!_tx_sink->ready_to_ack()) + PDBG("need to wait until ready-for-ack"); + _tx_sink->acknowledge_packet(packet); + } + } + } _tx_thread; + + void dump() + { + using namespace Genode; + + if (!VERBOSE_RX) return; + + char *buf = (char *)_rx.source()->packet_content(_curr_rx_packet); + size_t size = _curr_rx_packet.size(); + + printf("rx packet:"); + for (unsigned i = 0; i < size; i++) + printf("%02x,", buf[i]); + printf("\n"); + } + + public: + + /** + * Constructor + * + * \param tx_buf_size buffer size for tx channel + * \param rx_buf_size buffer size for rx channel + * \param rx_block_alloc rx block allocator + * \param ep entry point used for packet stream + */ + Session_component(Genode::size_t tx_buf_size, + Genode::size_t rx_buf_size, + Nic::Driver_factory &driver_factory, + Genode::Rpc_entrypoint &ep) + : + Genode::Allocator_avl(Genode::env()->heap()), + Session_rpc_object(Genode::env()->ram_session()->alloc(tx_buf_size), + Genode::env()->ram_session()->alloc(rx_buf_size), + static_cast(this), ep), + _driver_factory(driver_factory), + _driver(*driver_factory.create(*this)), + _tx_thread(_tx.sink(), _driver) + { } + + /** + * Destructor + */ + ~Session_component() + { + _driver_factory.destroy(&_driver); + } + + + /******************************* + ** Rx_buffer_alloc interface ** + *******************************/ + + void *alloc(Genode::size_t size) + { + /* assign rx packet descriptor */ + _curr_rx_packet = _rx.source()->alloc_packet(size); + + return _rx.source()->packet_content(_curr_rx_packet); + } + + void submit() + { + /* check for acknowledgements from the client */ + while (_rx.source()->ack_avail()) { + Packet_descriptor packet = _rx.source()->get_acked_packet(); + + /* free packet buffer */ + _rx.source()->release_packet(packet); } - public: + dump(); - Root(Genode::Rpc_entrypoint *session_ep, - Genode::Allocator *md_alloc, - Nic::Driver_factory &driver_factory) - : - Root_component(session_ep, md_alloc), - _driver_factory(driver_factory), - _ep(*session_ep) - { } - }; + _rx.source()->submit_packet(_curr_rx_packet); + + /* invalidate rx packet descriptor */ + _curr_rx_packet = Packet_descriptor(); + } + + + /**************************** + ** Nic::Session interface ** + ****************************/ + + Mac_address mac_address() { return _driver.mac_address(); } + Tx::Sink* tx_sink() { return _tx.sink(); } + Rx::Source* rx_source() { return _rx.source(); } +}; + + +/* + * Root component, handling new session requests. + */ +class Nic::Root : public Root_component +{ + private: + + Driver_factory &_driver_factory; + Genode::Rpc_entrypoint &_ep; + + protected: + + /* + * Always returns the singleton nic-session component. + */ + Session_component *_create_session(const char *args) + { + using namespace Genode; + + Genode::size_t ram_quota = + Arg_string::find_arg(args, "ram_quota" ).ulong_value(0); + Genode::size_t tx_buf_size = + Arg_string::find_arg(args, "tx_buf_size").ulong_value(0); + Genode::size_t rx_buf_size = + Arg_string::find_arg(args, "rx_buf_size").ulong_value(0); + + /* delete ram quota by the memory needed for the session */ + Genode::size_t session_size = max((Genode::size_t)4096, sizeof(Session_component) + + sizeof(Allocator_avl)); + if (ram_quota < session_size) + throw Root::Quota_exceeded(); + + /* + * Check if donated ram quota suffices for both + * communication buffers. Also check both sizes separately + * to handle a possible overflow of the sum of both sizes. + */ + if (tx_buf_size > ram_quota - session_size + || rx_buf_size > ram_quota - session_size + || tx_buf_size + rx_buf_size > ram_quota - session_size) { + PERR("insufficient 'ram_quota', got %zd, need %zd", + ram_quota, tx_buf_size + rx_buf_size + session_size); + throw Root::Quota_exceeded(); + } + + return new (md_alloc()) Session_component(tx_buf_size, + rx_buf_size, + _driver_factory, + _ep); + } + + public: + + Root(Genode::Rpc_entrypoint *session_ep, + Genode::Allocator *md_alloc, + Nic::Driver_factory &driver_factory) + : + Root_component(session_ep, md_alloc), + _driver_factory(driver_factory), + _ep(*session_ep) + { } }; #endif /* _INCLUDE__NIC__COMPONENT_H_ */ diff --git a/repos/os/include/nic/driver.h b/repos/os/include/nic/driver.h index c1da2908d..1960a283a 100644 --- a/repos/os/include/nic/driver.h +++ b/repos/os/include/nic/driver.h @@ -19,72 +19,77 @@ namespace Nic { - /** - * Interface for allocating the backing store for incoming packets - */ - struct Rx_buffer_alloc - { - /** - * Allocate packet buffer - */ - virtual void *alloc(Genode::size_t) = 0; - - /** - * Submit packet to client - */ - virtual void submit() = 0; - }; - - - /** - * Interface to be implemented by the device-specific driver code - */ - struct Driver : Genode::Irq_handler - { - /** - * Return MAC address of the network interface - */ - virtual Mac_address mac_address() = 0; - - /** - * Transmit packet - * - * \param packet start of packet - * \param size packet size - * - * If the packet size is not a multiple of 4 bytes, this function - * accesses the bytes after the packet buffer up to the next 4-byte - * length (in the worst case, 3 bytes after the packet end). - */ - virtual void tx(char const *packet, Genode::size_t size) = 0; - }; - - - /** - * Interface for constructing the driver object - * - * The driver object requires an rx-packet allocator at construction time. - * This allocator, however, exists not before the creation of a NIC session - * because the client pays for it. Therefore, the driver must be created at - * session-construction time. Because drivers may differ with regard to - * their constructor arguments, the 'Driver_factory' interface allows for - * unifying the session-creation among these drivers. - */ - struct Driver_factory - { - /** - * Construct new driver - * - * \param rx_buffer_alloc buffer allocator used for storing incoming - * packets - */ - virtual Driver *create(Rx_buffer_alloc &rx_buffer_alloc) = 0; - - /** - * Destroy driver - */ - virtual void destroy(Driver *driver) = 0; - }; + struct Rx_buffer_alloc; + struct Driver; + struct Driver_factory; } + +/** + * Interface for allocating the backing store for incoming packets + */ +struct Nic::Rx_buffer_alloc +{ + /** + * Allocate packet buffer + */ + virtual void *alloc(Genode::size_t) = 0; + + /** + * Submit packet to client + */ + virtual void submit() = 0; +}; + + +/** + * Interface to be implemented by the device-specific driver code + */ +struct Nic::Driver : Genode::Irq_handler +{ + /** + * Return MAC address of the network interface + */ + virtual Mac_address mac_address() = 0; + + /** + * Transmit packet + * + * \param packet start of packet + * \param size packet size + * + * If the packet size is not a multiple of 4 bytes, this function + * accesses the bytes after the packet buffer up to the next 4-byte + * length (in the worst case, 3 bytes after the packet end). + */ + virtual void tx(char const *packet, Genode::size_t size) = 0; +}; + + +/** + * Interface for constructing the driver object + * + * The driver object requires an rx-packet allocator at construction time. + * This allocator, however, exists not before the creation of a NIC session + * because the client pays for it. Therefore, the driver must be created at + * session-construction time. Because drivers may differ with regard to + * their constructor arguments, the 'Driver_factory' interface allows for + * unifying the session-creation among these drivers. + */ +struct Nic::Driver_factory +{ + /** + * Construct new driver + * + * \param rx_buffer_alloc buffer allocator used for storing incoming + * packets + */ + virtual Driver *create(Rx_buffer_alloc &rx_buffer_alloc) = 0; + + /** + * Destroy driver + */ + virtual void destroy(Driver *driver) = 0; +}; + #endif /* _INCLUDE__NIC__DRIVER_H_ */ diff --git a/repos/os/include/nic/packet_allocator.h b/repos/os/include/nic/packet_allocator.h index 1b17e2b9c..16e9a8d65 100644 --- a/repos/os/include/nic/packet_allocator.h +++ b/repos/os/include/nic/packet_allocator.h @@ -18,25 +18,23 @@ #include -namespace Nic { +namespace Nic { struct Packet_allocator; } + + +/** + * Packet allocator used for packet streaming in nic sessions. + */ +struct Nic::Packet_allocator : Genode::Packet_allocator +{ + enum { DEFAULT_PACKET_SIZE = 1600 }; /** - * Packet allocator used for packet streaming in nic sessions. + * Constructor + * + * \param md_alloc Meta-data allocator */ - class Packet_allocator : public Genode::Packet_allocator - { - public: - - enum { DEFAULT_PACKET_SIZE = 1600 }; - - /** - * Constructor - * - * \param md_alloc Meta-data allocator - */ - Packet_allocator(Genode::Allocator *md_alloc) - : Genode::Packet_allocator(md_alloc, DEFAULT_PACKET_SIZE) {} - }; + Packet_allocator(Genode::Allocator *md_alloc) + : Genode::Packet_allocator(md_alloc, DEFAULT_PACKET_SIZE) {} }; #endif /* _INCLUDE__NIC__PACKET_ALLOCATOR__ */ diff --git a/repos/os/include/nic/stat.h b/repos/os/include/nic/stat.h index 6d69ea36f..a6755c1d5 100644 --- a/repos/os/include/nic/stat.h +++ b/repos/os/include/nic/stat.h @@ -20,49 +20,47 @@ #include -namespace Nic { +namespace Nic { class Measurement; } - /** - * - */ - class Measurement - { - private: - Timer::Connection &_timer; +class Nic::Measurement +{ + private: - Net::Ethernet_frame::Mac_address _mac; + Timer::Connection &_timer; - struct stat { - Genode::uint64_t size; - unsigned long count; - } _stat, _drop; + Net::Ethernet_frame::Mac_address _mac; - Genode::addr_t _timestamp; + struct stat + { + Genode::uint64_t size; + unsigned long count; + } _stat, _drop; - enum status { - FOR_US, - IS_MAGIC, - UNKNOWN - }; + Genode::addr_t _timestamp; - enum status _check(Net::Ethernet_frame *, Genode::size_t); - public: + enum status { + FOR_US, + IS_MAGIC, + UNKNOWN + }; - Measurement(Timer::Connection &timer) - : - _timer(timer), _timestamp(0) - { - _stat.size = _stat.count = _drop.size = _drop.count = 0; - } + enum status _check(Net::Ethernet_frame *, Genode::size_t); + public: - void set_mac(void * mac) { - Genode::memcpy(_mac.addr, mac, 6); - } + Measurement(Timer::Connection &timer) + : + _timer(timer), _timestamp(0) + { + _stat.size = _stat.count = _drop.size = _drop.count = 0; + } - void data(Net::Ethernet_frame *, Genode::size_t); - }; + void set_mac(void * mac) + { + Genode::memcpy(_mac.addr, mac, 6); + } -} + void data(Net::Ethernet_frame *, Genode::size_t); +}; #endif /* _INCLUDE__NIC__STAT_H_ */ diff --git a/repos/os/include/nic_session/client.h b/repos/os/include/nic_session/client.h index 6fb051d55..718f945b7 100644 --- a/repos/os/include/nic_session/client.h +++ b/repos/os/include/nic_session/client.h @@ -19,43 +19,43 @@ #include #include -namespace Nic { - - class Session_client : public Genode::Rpc_client - { - private: - - Packet_stream_tx::Client _tx; - Packet_stream_rx::Client _rx; - - public: - - /** - * Constructor - * - * \param tx_buffer_alloc allocator used for managing the - * transmission buffer - */ - Session_client(Session_capability session, - Genode::Range_allocator *tx_buffer_alloc) - : - Genode::Rpc_client(session), - _tx(call(), tx_buffer_alloc), - _rx(call()) - { } +namespace Nic { class Session_client; } - /*************************** - ** NIC session interface ** - ***************************/ +class Nic::Session_client : public Genode::Rpc_client +{ + private: - Mac_address mac_address() { return call(); } + Packet_stream_tx::Client _tx; + Packet_stream_rx::Client _rx; - Tx *tx_channel() { return &_tx; } - Rx *rx_channel() { return &_rx; } - Tx::Source *tx() { return _tx.source(); } - Rx::Sink *rx() { return _rx.sink(); } - }; -} + public: + + /** + * Constructor + * + * \param tx_buffer_alloc allocator used for managing the + * transmission buffer + */ + Session_client(Session_capability session, + Genode::Range_allocator *tx_buffer_alloc) + : + Genode::Rpc_client(session), + _tx(call(), tx_buffer_alloc), + _rx(call()) + { } + + + /*************************** + ** NIC session interface ** + ***************************/ + + Mac_address mac_address() override { return call(); } + + Tx *tx_channel() { return &_tx; } + Rx *rx_channel() { return &_rx; } + Tx::Source *tx() { return _tx.source(); } + Rx::Sink *rx() { return _rx.sink(); } +}; #endif /* _INCLUDE__NIC_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/nic_session/connection.h b/repos/os/include/nic_session/connection.h index 17778a2ee..7612ac621 100644 --- a/repos/os/include/nic_session/connection.h +++ b/repos/os/include/nic_session/connection.h @@ -18,29 +18,29 @@ #include #include -namespace Nic { +namespace Nic { struct Connection; } - struct Connection : Genode::Connection, Session_client - { - /** - * Constructor - * - * \param tx_buffer_alloc allocator used for managing the - * transmission buffer - * \param tx_buf_size size of transmission buffer in bytes - * \param rx_buf_size size of reception buffer in bytes - */ - Connection(Genode::Range_allocator *tx_block_alloc, - Genode::size_t tx_buf_size, - Genode::size_t rx_buf_size) - : - Genode::Connection( - session("ram_quota=%zd, tx_buf_size=%zd, rx_buf_size=%zd", - 6*4096 + tx_buf_size + rx_buf_size, - tx_buf_size, rx_buf_size)), - Session_client(cap(), tx_block_alloc) - { } - }; -} + +struct Nic::Connection : Genode::Connection, Session_client +{ + /** + * Constructor + * + * \param tx_buffer_alloc allocator used for managing the + * transmission buffer + * \param tx_buf_size size of transmission buffer in bytes + * \param rx_buf_size size of reception buffer in bytes + */ + Connection(Genode::Range_allocator *tx_block_alloc, + Genode::size_t tx_buf_size, + Genode::size_t rx_buf_size) + : + Genode::Connection( + session("ram_quota=%zd, tx_buf_size=%zd, rx_buf_size=%zd", + 6*4096 + tx_buf_size + rx_buf_size, + tx_buf_size, rx_buf_size)), + Session_client(cap(), tx_block_alloc) + { } +}; #endif /* _INCLUDE__NIC_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/nic_session/nic_session.h b/repos/os/include/nic_session/nic_session.h index 597027050..0b6aedb8d 100644 --- a/repos/os/include/nic_session/nic_session.h +++ b/repos/os/include/nic_session/nic_session.h @@ -35,64 +35,69 @@ namespace Nic { - struct Mac_address { char addr[6]; }; - - struct Session : Genode::Session - { - enum { QUEUE_SIZE = 1024 }; - - /* - * Types used by the client stub code and server implementation - * - * The acknowledgement queue has always the same size as the submit - * queue. We access the packet content as a char pointer. - */ - typedef Packet_stream_policy Policy; - - typedef Packet_stream_tx::Channel Tx; - typedef Packet_stream_rx::Channel Rx; - - static const char *service_name() { return "Nic"; } - - virtual ~Session() { } - - /** - * Request MAC address of network adapter - */ - virtual Mac_address mac_address() = 0; - - /** - * Request packet-transmission channel - */ - virtual Tx *tx_channel() { return 0; } - - /** - * Request packet-reception channel - */ - virtual Rx *rx_channel() { return 0; } - - /** - * Request client-side packet-stream interface of tx channel - */ - virtual Tx::Source *tx() { return 0; } - - /** - * Request client-side packet-stream interface of rx channel - */ - virtual Rx::Sink *rx() { return 0; } - - - /******************* - ** RPC interface ** - *******************/ - - GENODE_RPC(Rpc_mac_address, Mac_address, mac_address); - GENODE_RPC(Rpc_tx_cap, Genode::Capability, _tx_cap); - GENODE_RPC(Rpc_rx_cap, Genode::Capability, _rx_cap); - - GENODE_RPC_INTERFACE(Rpc_mac_address, Rpc_tx_cap, Rpc_rx_cap); - }; + struct Mac_address; + struct Session; } + +struct Nic::Mac_address { char addr[6]; }; + + +struct Nic::Session : Genode::Session +{ + enum { QUEUE_SIZE = 1024 }; + + /* + * Types used by the client stub code and server implementation + * + * The acknowledgement queue has always the same size as the submit + * queue. We access the packet content as a char pointer. + */ + typedef Packet_stream_policy Policy; + + typedef Packet_stream_tx::Channel Tx; + typedef Packet_stream_rx::Channel Rx; + + static const char *service_name() { return "Nic"; } + + virtual ~Session() { } + + /** + * Request MAC address of network adapter + */ + virtual Mac_address mac_address() = 0; + + /** + * Request packet-transmission channel + */ + virtual Tx *tx_channel() { return 0; } + + /** + * Request packet-reception channel + */ + virtual Rx *rx_channel() { return 0; } + + /** + * Request client-side packet-stream interface of tx channel + */ + virtual Tx::Source *tx() { return 0; } + + /** + * Request client-side packet-stream interface of rx channel + */ + virtual Rx::Sink *rx() { return 0; } + + + /******************* + ** RPC interface ** + *******************/ + + GENODE_RPC(Rpc_mac_address, Mac_address, mac_address); + GENODE_RPC(Rpc_tx_cap, Genode::Capability, _tx_cap); + GENODE_RPC(Rpc_rx_cap, Genode::Capability, _rx_cap); + + GENODE_RPC_INTERFACE(Rpc_mac_address, Rpc_tx_cap, Rpc_rx_cap); +}; + #endif /* _INCLUDE__NIC_SESSION__NIC_SESSION_H_ */ diff --git a/repos/os/include/nic_session/rpc_object.h b/repos/os/include/nic_session/rpc_object.h index 3505951e8..f641495c9 100644 --- a/repos/os/include/nic_session/rpc_object.h +++ b/repos/os/include/nic_session/rpc_object.h @@ -18,38 +18,38 @@ #include #include -namespace Nic { +namespace Nic { class Session_rpc_object; } - class Session_rpc_object : public Genode::Rpc_object - { - protected: - Packet_stream_tx::Rpc_object _tx; - Packet_stream_rx::Rpc_object _rx; +class Nic::Session_rpc_object : public Genode::Rpc_object +{ + protected: - public: + Packet_stream_tx::Rpc_object _tx; + Packet_stream_rx::Rpc_object _rx; - /** - * Constructor - * - * \param tx_ds dataspace used as communication buffer - * for the tx packet stream - * \param rx_ds dataspace used as communication buffer - * for the rx packet stream - * \param rx_buffer_alloc allocator used for managing the communication - * buffer of the rx packet stream - * \param ep entry point used for packet-stream channels - */ - Session_rpc_object(Genode::Dataspace_capability tx_ds, - Genode::Dataspace_capability rx_ds, - Genode::Range_allocator *rx_buffer_alloc, - Genode::Rpc_entrypoint &ep) - : - _tx(tx_ds, ep), _rx(rx_ds, rx_buffer_alloc, ep) { } + public: - Genode::Capability _tx_cap() { return _tx.cap(); } - Genode::Capability _rx_cap() { return _rx.cap(); } - }; -} + /** + * Constructor + * + * \param tx_ds dataspace used as communication buffer + * for the tx packet stream + * \param rx_ds dataspace used as communication buffer + * for the rx packet stream + * \param rx_buffer_alloc allocator used for managing the communication + * buffer of the rx packet stream + * \param ep entry point used for packet-stream channels + */ + Session_rpc_object(Genode::Dataspace_capability tx_ds, + Genode::Dataspace_capability rx_ds, + Genode::Range_allocator *rx_buffer_alloc, + Genode::Rpc_entrypoint &ep) + : + _tx(tx_ds, ep), _rx(rx_ds, rx_buffer_alloc, ep) { } + + Genode::Capability _tx_cap() { return _tx.cap(); } + Genode::Capability _rx_cap() { return _rx.cap(); } +}; #endif /* _INCLUDE__NIC_SESSION__RPC_OBJECT_H_ */ diff --git a/repos/os/include/nitpicker_session/capability.h b/repos/os/include/nitpicker_session/capability.h index d8f86c5e6..ac72a1da1 100644 --- a/repos/os/include/nitpicker_session/capability.h +++ b/repos/os/include/nitpicker_session/capability.h @@ -19,8 +19,7 @@ namespace Nitpicker { - typedef Genode::Capability - Session_capability; + typedef Genode::Capability Session_capability; } #endif /* _INCLUDE__NITPICKER_SESSION__CAPABILITY_H_ */ diff --git a/repos/os/include/os/alarm.h b/repos/os/include/os/alarm.h index b2c1f0206..ab27638f3 100644 --- a/repos/os/include/os/alarm.h +++ b/repos/os/include/os/alarm.h @@ -17,129 +17,130 @@ #include namespace Genode { - class Alarm_scheduler; - - class Alarm - { - public: - - typedef unsigned long Time; - - private: - - friend class Alarm_scheduler; - - Lock _dispatch_lock; /* taken during handle function */ - Time _deadline; /* next deadline */ - Time _period; /* duration between alarms */ - int _active; /* set to one when active */ - Alarm *_next; /* next alarm in alarm list */ - Alarm_scheduler *_scheduler; /* currently assigned scheduler */ - - void _assign(Time period, Time deadline, Alarm_scheduler *scheduler) { - _period = period, _deadline = deadline, _scheduler = scheduler; } - - void _reset() { - _assign(0, 0, 0), _active = 0, _next = 0; } - - protected: - - /** - * Function to be called on when deadline is reached - * - * This function must be implemented by a derived class. If the - * return value is 'true' and the alarm is periodically scheduled, - * the alarm is scheduled again. - */ - virtual bool on_alarm(unsigned) { return false; } - - public: - - Alarm() { _reset(); } - - virtual ~Alarm(); - }; - - - class Alarm_scheduler - { - private: - - Lock _lock; /* protect alarm list */ - Alarm *_head; /* head of alarm list */ - Alarm::Time _now; /* recent time (updated by handle function) */ - - /** - * Enqueue alarm into alarm queue - * - * This is a helper function for 'schedule' and 'handle'. - */ - void _unsynchronized_enqueue(Alarm *alarm); - - /** - * Dequeue alarm from alarm queue - */ - void _unsynchronized_dequeue(Alarm *alarm); - - /** - * Dequeue next pending alarm from alarm list - * - * \return dequeued pending alarm - * \retval 0 no alarm pending - */ - Alarm *_get_pending_alarm(); - - public: - - Alarm_scheduler() : _head(0), _now(0) { } - ~Alarm_scheduler(); - - /** - * Schedule absolute timeout - * - * \param timeout absolute point in time for execution - */ - void schedule_absolute(Alarm *alarm, Alarm::Time timeout); - - /** - * Schedule alarm (periodic timeout) - * - * \param period alarm period - * - * The first deadline is overdue after this call, i.e. on_alarm() is - * called immediately. - */ - void schedule(Alarm *alarm, Alarm::Time period); - - /** - * Remove alarm from schedule - */ - void discard(Alarm *alarm); - - /** - * Handle alarms - * - * \param now current time - */ - void handle(Alarm::Time now); - - /** - * Determine next deadline (absolute) - * - * \param deadline out parameter for storing the next deadline - * \return true if an alarm is scheduled - */ - bool next_deadline(Alarm::Time *deadline); - - /** - * Determine if given alarm object is current head element - * - * \param alarm alarm object - * \return true if alarm is head element of timeout queue - */ - bool head_timeout(const Alarm * alarm) { return _head == alarm; } - }; + class Alarm; } + +class Genode::Alarm +{ + public: + + typedef unsigned long Time; + + private: + + friend class Alarm_scheduler; + + Lock _dispatch_lock; /* taken during handle function */ + Time _deadline; /* next deadline */ + Time _period; /* duration between alarms */ + int _active; /* set to one when active */ + Alarm *_next; /* next alarm in alarm list */ + Alarm_scheduler *_scheduler; /* currently assigned scheduler */ + + void _assign(Time period, Time deadline, Alarm_scheduler *scheduler) { + _period = period, _deadline = deadline, _scheduler = scheduler; } + + void _reset() { + _assign(0, 0, 0), _active = 0, _next = 0; } + + protected: + + /** + * Function to be called on when deadline is reached + * + * This function must be implemented by a derived class. If the + * return value is 'true' and the alarm is periodically scheduled, + * the alarm is scheduled again. + */ + virtual bool on_alarm(unsigned) { return false; } + + public: + + Alarm() { _reset(); } + + virtual ~Alarm(); +}; + + +class Genode::Alarm_scheduler +{ + private: + + Lock _lock; /* protect alarm list */ + Alarm *_head; /* head of alarm list */ + Alarm::Time _now; /* recent time (updated by handle function) */ + + /** + * Enqueue alarm into alarm queue + * + * This is a helper function for 'schedule' and 'handle'. + */ + void _unsynchronized_enqueue(Alarm *alarm); + + /** + * Dequeue alarm from alarm queue + */ + void _unsynchronized_dequeue(Alarm *alarm); + + /** + * Dequeue next pending alarm from alarm list + * + * \return dequeued pending alarm + * \retval 0 no alarm pending + */ + Alarm *_get_pending_alarm(); + + public: + + Alarm_scheduler() : _head(0), _now(0) { } + ~Alarm_scheduler(); + + /** + * Schedule absolute timeout + * + * \param timeout absolute point in time for execution + */ + void schedule_absolute(Alarm *alarm, Alarm::Time timeout); + + /** + * Schedule alarm (periodic timeout) + * + * \param period alarm period + * + * The first deadline is overdue after this call, i.e. on_alarm() is + * called immediately. + */ + void schedule(Alarm *alarm, Alarm::Time period); + + /** + * Remove alarm from schedule + */ + void discard(Alarm *alarm); + + /** + * Handle alarms + * + * \param now current time + */ + void handle(Alarm::Time now); + + /** + * Determine next deadline (absolute) + * + * \param deadline out parameter for storing the next deadline + * \return true if an alarm is scheduled + */ + bool next_deadline(Alarm::Time *deadline); + + /** + * Determine if given alarm object is current head element + * + * \param alarm alarm object + * \return true if alarm is head element of timeout queue + */ + bool head_timeout(const Alarm * alarm) { return _head == alarm; } +}; + #endif /* _INCLUDE__OS__ALARM_H_ */ diff --git a/repos/os/include/os/attached_io_mem_dataspace.h b/repos/os/include/os/attached_io_mem_dataspace.h index 4dca411d9..2b907216e 100644 --- a/repos/os/include/os/attached_io_mem_dataspace.h +++ b/repos/os/include/os/attached_io_mem_dataspace.h @@ -17,67 +17,67 @@ #include #include -namespace Genode { +namespace Genode { class Attached_io_mem_dataspace; } - /** - * Request and locally attach a memory-mapped I/O resource - * - * This class is a wrapper for a typical sequence of operations performed - * by device drivers to access memory-mapped device resources. Its sole - * purpose is to avoid duplicated code. - */ - class Attached_io_mem_dataspace - { - private: - Io_mem_connection _mmio; - Io_mem_dataspace_capability _ds; - void *_local_addr; +/** + * Request and locally attach a memory-mapped I/O resource + * + * This class is a wrapper for a typical sequence of operations performed + * by device drivers to access memory-mapped device resources. Its sole + * purpose is to avoid duplicated code. + */ +class Genode::Attached_io_mem_dataspace +{ + private: - public: + Io_mem_connection _mmio; + Io_mem_dataspace_capability _ds; + void *_local_addr; - /** - * Constructor - * - * \param base base address of memory-mapped I/O resource - * \param size size of resource - * \param write_combined enable write combining for the resource - * - * \throw Parent::Service_denied - * \throw Parent::Quota_exceeded - * \throw Parent::Unavailable - * \throw Rm_session::Attach_failed - */ - Attached_io_mem_dataspace(Genode::addr_t base, Genode::size_t size, - bool write_combined = false) - : - _mmio(base, size, write_combined), - _ds(_mmio.dataspace()), - _local_addr(env()->rm_session()->attach(_ds)) - { } + public: - /** - * Destructor - */ - ~Attached_io_mem_dataspace() - { - env()->rm_session()->detach(_local_addr); - } + /** + * Constructor + * + * \param base base address of memory-mapped I/O resource + * \param size size of resource + * \param write_combined enable write combining for the resource + * + * \throw Parent::Service_denied + * \throw Parent::Quota_exceeded + * \throw Parent::Unavailable + * \throw Rm_session::Attach_failed + */ + Attached_io_mem_dataspace(Genode::addr_t base, Genode::size_t size, + bool write_combined = false) + : + _mmio(base, size, write_combined), + _ds(_mmio.dataspace()), + _local_addr(env()->rm_session()->attach(_ds)) + { } - /** - * Return capability of the used RAM dataspace - */ - Io_mem_dataspace_capability cap() { return _ds; } + /** + * Destructor + */ + ~Attached_io_mem_dataspace() + { + env()->rm_session()->detach(_local_addr); + } - /** - * Request local address - * - * This is a template to avoid inconvenient casts at the caller. - * A newly allocated I/O MEM dataspace is untyped memory anyway. - */ - template - T *local_addr() { return static_cast(_local_addr); } - }; -} + /** + * Return capability of the used RAM dataspace + */ + Io_mem_dataspace_capability cap() { return _ds; } + + /** + * Request local address + * + * This is a template to avoid inconvenient casts at the caller. + * A newly allocated I/O MEM dataspace is untyped memory anyway. + */ + template + T *local_addr() { return static_cast(_local_addr); } +}; #endif /* _INCLUDE__OS__ATTACHED_IO_MEM_DATASPACE_H_ */ diff --git a/repos/os/include/os/attached_mmio.h b/repos/os/include/os/attached_mmio.h index 1879cc0e1..7774366d7 100644 --- a/repos/os/include/os/attached_mmio.h +++ b/repos/os/include/os/attached_mmio.h @@ -18,39 +18,39 @@ #include #include -namespace Genode -{ - /** - * Eases the application of the MMIO framework - * - * In the classical case the user wants device memory to be structured - * by inheriting from Genode::Mmio and using its subclasses. As - * prerequisite one needs to alloc the IO dataspace, attach it locally - * and cast the received address. This helper undertakes all of this - * generic work when inheriting from it. - */ - class Attached_mmio : public Attached_io_mem_dataspace, - public Mmio - { - public: +namespace Genode { class Attached_mmio; } - /** - * Constructor - * - * \param base base address of memory-mapped I/O resource - * \param size size of resource - * \param write_combined enable write combining for the resource - * - * \throw Parent::Service_denied - * \throw Parent::Quota_exceeded - * \throw Parent::Unavailable - * \throw Rm_session::Attach_failed - */ - Attached_mmio(addr_t base, size_t size, - bool write_combined = false) - : Attached_io_mem_dataspace(base, size, write_combined), - Mmio((addr_t)local_addr() | (base & 0xfff)) { } - }; -} + +/** + * Eases the application of the MMIO framework + * + * In the classical case the user wants device memory to be structured + * by inheriting from Genode::Mmio and using its subclasses. As + * prerequisite one needs to alloc the IO dataspace, attach it locally + * and cast the received address. This helper undertakes all of this + * generic work when inheriting from it. + */ +class Genode::Attached_mmio : public Attached_io_mem_dataspace, + public Mmio +{ + public: + + /** + * Constructor + * + * \param base base address of memory-mapped I/O resource + * \param size size of resource + * \param write_combined enable write combining for the resource + * + * \throw Parent::Service_denied + * \throw Parent::Quota_exceeded + * \throw Parent::Unavailable + * \throw Rm_session::Attach_failed + */ + Attached_mmio(addr_t base, size_t size, + bool write_combined = false) + : Attached_io_mem_dataspace(base, size, write_combined), + Mmio((addr_t)local_addr() | (base & 0xfff)) { } +}; #endif /* _INCLUDE__OS__ATTACHED_MMIO_H_ */ diff --git a/repos/os/include/os/attached_ram_dataspace.h b/repos/os/include/os/attached_ram_dataspace.h index fd36984aa..ddc2c0601 100644 --- a/repos/os/include/os/attached_ram_dataspace.h +++ b/repos/os/include/os/attached_ram_dataspace.h @@ -25,129 +25,129 @@ #include #include -namespace Genode { +namespace Genode { class Attached_ram_dataspace; } - class Attached_ram_dataspace - { - private: - size_t _size; - Ram_session *_ram_session; - Ram_dataspace_capability _ds; - void *_local_addr; - Cache_attribute const _cached; +class Genode::Attached_ram_dataspace +{ + private: - template - static void _swap(T &v1, T &v2) { T tmp = v1; v1 = v2; v2 = tmp; } + size_t _size; + Ram_session *_ram_session; + Ram_dataspace_capability _ds; + void *_local_addr; + Cache_attribute const _cached; - void _detach_and_free_dataspace() - { - if (_local_addr) - env()->rm_session()->detach(_local_addr); + template + static void _swap(T &v1, T &v2) { T tmp = v1; v1 = v2; v2 = tmp; } - if (_ram_session && _ds.valid()) - _ram_session->free(_ds); + void _detach_and_free_dataspace() + { + if (_local_addr) + env()->rm_session()->detach(_local_addr); + + if (_ram_session && _ds.valid()) + _ram_session->free(_ds); + } + + void _alloc_and_attach() + { + if (!_size || !_ram_session) return; + + try { + _ds = _ram_session->alloc(_size, _cached); + _local_addr = env()->rm_session()->attach(_ds); + + /* revert allocation if attaching the dataspace failed */ + } catch (Rm_session::Attach_failed) { + _ram_session->free(_ds); + throw; } - void _alloc_and_attach() - { - if (!_size || !_ram_session) return; - - try { - _ds = _ram_session->alloc(_size, _cached); - _local_addr = env()->rm_session()->attach(_ds); - - /* revert allocation if attaching the dataspace failed */ - } catch (Rm_session::Attach_failed) { - _ram_session->free(_ds); - throw; - } - - /* - * Eagerly map dataspace if used for DMA - * - * On some platforms, namely Fiasco.OC on ARMv7, the handling - * of page faults interferes with the caching attributes used - * for uncached DMA memory. See issue #452 for more details - * (https://github.com/genodelabs/genode/issues/452). As a - * work-around for this issues, we eagerly map the whole - * dataspace before writing actual content to it. - */ - if (_cached != CACHED) { - enum { PAGE_SIZE = 4096 }; - unsigned char volatile *base = (unsigned char volatile *)_local_addr; - for (size_t i = 0; i < _size; i += PAGE_SIZE) - touch_read_write(base + i); - } - } - - public: - - /** - * Constructor + /* + * Eagerly map dataspace if used for DMA * - * \throw Ram_session::Alloc_failed - * \throw Rm_session::Attach_failed + * On some platforms, namely Fiasco.OC on ARMv7, the handling + * of page faults interferes with the caching attributes used + * for uncached DMA memory. See issue #452 for more details + * (https://github.com/genodelabs/genode/issues/452). As a + * work-around for this issues, we eagerly map the whole + * dataspace before writing actual content to it. */ - Attached_ram_dataspace(Ram_session *ram_session, size_t size, - Cache_attribute cached = CACHED) - : - _size(size), _ram_session(ram_session), _local_addr(0), - _cached(cached) - { - _alloc_and_attach(); + if (_cached != CACHED) { + enum { PAGE_SIZE = 4096 }; + unsigned char volatile *base = (unsigned char volatile *)_local_addr; + for (size_t i = 0; i < _size; i += PAGE_SIZE) + touch_read_write(base + i); } + } - /** - * Destructor - */ - ~Attached_ram_dataspace() { _detach_and_free_dataspace(); } + public: - /** - * Return capability of the used RAM dataspace - */ - Ram_dataspace_capability cap() const { return _ds; } + /** + * Constructor + * + * \throw Ram_session::Alloc_failed + * \throw Rm_session::Attach_failed + */ + Attached_ram_dataspace(Ram_session *ram_session, size_t size, + Cache_attribute cached = CACHED) + : + _size(size), _ram_session(ram_session), _local_addr(0), + _cached(cached) + { + _alloc_and_attach(); + } - /** - * Request local address - * - * This is a template to avoid inconvenient casts at - * the caller. A newly allocated RAM dataspace is - * untyped memory anyway. - */ - template - T *local_addr() const { return static_cast(_local_addr); } + /** + * Destructor + */ + ~Attached_ram_dataspace() { _detach_and_free_dataspace(); } - /** - * Return size - */ - size_t size() const { return _size; } + /** + * Return capability of the used RAM dataspace + */ + Ram_dataspace_capability cap() const { return _ds; } - void swap(Attached_ram_dataspace &other) - { - _swap(_size, other._size); - _swap(_ram_session, other._ram_session); - _swap(_ds, other._ds); - _swap(_local_addr, other._local_addr); - } + /** + * Request local address + * + * This is a template to avoid inconvenient casts at + * the caller. A newly allocated RAM dataspace is + * untyped memory anyway. + */ + template + T *local_addr() const { return static_cast(_local_addr); } - /** - * Re-allocate dataspace with a new size - * - * The content of the original dataspace is not retained. - */ - void realloc(Ram_session *ram_session, size_t new_size) - { - if (new_size < _size) return; + /** + * Return size + */ + size_t size() const { return _size; } - _detach_and_free_dataspace(); + void swap(Attached_ram_dataspace &other) + { + _swap(_size, other._size); + _swap(_ram_session, other._ram_session); + _swap(_ds, other._ds); + _swap(_local_addr, other._local_addr); + } - _size = new_size; - _ram_session = ram_session; + /** + * Re-allocate dataspace with a new size + * + * The content of the original dataspace is not retained. + */ + void realloc(Ram_session *ram_session, size_t new_size) + { + if (new_size < _size) return; - _alloc_and_attach(); - } - }; -} + _detach_and_free_dataspace(); + + _size = new_size; + _ram_session = ram_session; + + _alloc_and_attach(); + } +}; #endif /* _INCLUDE__OS__ATTACHED_RAM_DATASPACE_H_ */ diff --git a/repos/os/include/os/child_policy_dynamic_rom.h b/repos/os/include/os/child_policy_dynamic_rom.h index 08a01e564..b2c2c562f 100644 --- a/repos/os/include/os/child_policy_dynamic_rom.h +++ b/repos/os/include/os/child_policy_dynamic_rom.h @@ -19,160 +19,160 @@ #include #include -namespace Genode { +namespace Genode { class Child_policy_dynamic_rom_file; } - class Child_policy_dynamic_rom_file : public Rpc_object, - public Service - { - private: - Ram_session *_ram; +class Genode::Child_policy_dynamic_rom_file : public Rpc_object, + public Service +{ + private: + + Ram_session *_ram; + + /* + * The ROM module may be written and consumed by different threads, + * e.g., written by the main thread and consumed by the child's + * entrypoint that manages the local ROM service for handing out a + * dynamic config. Hence, the '_lock' is used to synchronize the + * 'load' and 'dataspace' functions. + */ + Lock _lock; + + /* + * We keep two dataspaces around. The foreground ('_fg') dataspace + * is the one we present to the client. While the foreground + * dataspace is in use, we perform all modifications of the data + * in the background dataspace (which is invisible to the client). + * Once the client calls 'dataspace()', we promote the old + * background dataspace to the new foreground and thereby hand out + * the former background dataspace. + */ + Attached_ram_dataspace _fg; + Attached_ram_dataspace _bg; + + bool _bg_has_pending_data; + + Signal_context_capability _sigh_cap; + + Rpc_entrypoint &_ep; + Rom_session_capability _rom_session_cap; + + enum { FILENAME_MAX_LEN = 32 }; + char _filename[FILENAME_MAX_LEN]; + + public: + + /** + * Constructor + * + * \param ram RAM session used to allocate the backing store + * for buffering ROM module data + * + * If 'ram' is 0, the child policy is ineffective. + */ + Child_policy_dynamic_rom_file(const char *filename, + Rpc_entrypoint &ep, + Ram_session *ram) + : + Service("ROM"), + _ram(ram), + _fg(0, 0), _bg(0, 0), + _bg_has_pending_data(false), + _ep(ep), + _rom_session_cap(_ep.manage(this)) + { + strncpy(_filename, filename, sizeof(_filename)); + } + + /** + * Destructor + */ + ~Child_policy_dynamic_rom_file() { _ep.dissolve(this); } + + /** + * Load new content into ROM module + * + * \throw Ram_session::Alloc_failed + * \throw Rm_session::Attach_failed + */ + void load(void const *data, size_t data_len) + { + Lock::Guard guard(_lock); + + if (!_ram) { + PERR("Error: No backing store for loading ROM data"); + return; + } + + /* let background buffer grow if needed */ + if (_bg.size() < data_len) + _bg.realloc(_ram, data_len); + + memcpy(_bg.local_addr(), data, data_len); + _bg_has_pending_data = true; + + if (_sigh_cap.valid()) + Signal_transmitter(_sigh_cap).submit(); + } + + + /*************************** + ** ROM session interface ** + ***************************/ + + Rom_dataspace_capability dataspace() + { + Lock::Guard guard(_lock); + + if (!_fg.size() && !_bg_has_pending_data) { + PERR("Error: no data loaded"); + return Rom_dataspace_capability(); + } /* - * The ROM module may be written and consumed by different threads, - * e.g., written by the main thread and consumed by the child's - * entrypoint that manages the local ROM service for handing out a - * dynamic config. Hence, the '_lock' is used to synchronize the - * 'load' and 'dataspace' functions. + * Keep foreground if no background exists. Otherwise, use + * old background as new foreground. */ - Lock _lock; - - /* - * We keep two dataspaces around. The foreground ('_fg') dataspace - * is the one we present to the client. While the foreground - * dataspace is in use, we perform all modifications of the data - * in the background dataspace (which is invisible to the client). - * Once the client calls 'dataspace()', we promote the old - * background dataspace to the new foreground and thereby hand out - * the former background dataspace. - */ - Attached_ram_dataspace _fg; - Attached_ram_dataspace _bg; - - bool _bg_has_pending_data; - - Signal_context_capability _sigh_cap; - - Rpc_entrypoint &_ep; - Rom_session_capability _rom_session_cap; - - enum { FILENAME_MAX_LEN = 32 }; - char _filename[FILENAME_MAX_LEN]; - - public: - - /** - * Constructor - * - * \param ram RAM session used to allocate the backing store - * for buffering ROM module data - * - * If 'ram' is 0, the child policy is ineffective. - */ - Child_policy_dynamic_rom_file(const char *filename, - Rpc_entrypoint &ep, - Ram_session *ram) - : - Service("ROM"), - _ram(ram), - _fg(0, 0), _bg(0, 0), - _bg_has_pending_data(false), - _ep(ep), - _rom_session_cap(_ep.manage(this)) - { - strncpy(_filename, filename, sizeof(_filename)); + if (_bg_has_pending_data) { + _fg.swap(_bg); + _bg_has_pending_data = false; } - /** - * Destructor - */ - ~Child_policy_dynamic_rom_file() { _ep.dissolve(this); } + Dataspace_capability ds_cap = _fg.cap(); + return static_cap_cast(ds_cap); + } - /** - * Load new content into ROM module - * - * \throw Ram_session::Alloc_failed - * \throw Rm_session::Attach_failed - */ - void load(void const *data, size_t data_len) - { - Lock::Guard guard(_lock); - - if (!_ram) { - PERR("Error: No backing store for loading ROM data"); - return; - } - - /* let background buffer grow if needed */ - if (_bg.size() < data_len) - _bg.realloc(_ram, data_len); - - memcpy(_bg.local_addr(), data, data_len); - _bg_has_pending_data = true; - - if (_sigh_cap.valid()) - Signal_transmitter(_sigh_cap).submit(); - } + void sigh(Signal_context_capability cap) { _sigh_cap = cap; } - /*************************** - ** ROM session interface ** - ***************************/ + /*********************** + ** Service interface ** + ***********************/ - Rom_dataspace_capability dataspace() - { - Lock::Guard guard(_lock); + Session_capability session(const char *, Affinity const &) { + return _rom_session_cap; } - if (!_fg.size() && !_bg_has_pending_data) { - PERR("Error: no data loaded"); - return Rom_dataspace_capability(); - } - - /* - * Keep foreground if no background exists. Otherwise, use - * old background as new foreground. - */ - if (_bg_has_pending_data) { - _fg.swap(_bg); - _bg_has_pending_data = false; - } - - Dataspace_capability ds_cap = _fg.cap(); - return static_cap_cast(ds_cap); - } - - void sigh(Signal_context_capability cap) { _sigh_cap = cap; } + void upgrade(Session_capability, const char *) { } + void close(Session_capability) { } - /*********************** - ** Service interface ** - ***********************/ + /********************* + ** Policy function ** + *********************/ - Session_capability session(const char *, Affinity const &) { - return _rom_session_cap; } + Service *resolve_session_request(const char *service_name, + const char *args) + { + if (!_ram) return 0; - void upgrade(Session_capability, const char *) { } - void close(Session_capability) { } + /* ignore session requests for non-ROM services */ + if (strcmp(service_name, "ROM")) return 0; - - /********************* - ** Policy function ** - *********************/ - - Service *resolve_session_request(const char *service_name, - const char *args) - { - if (!_ram) return 0; - - /* ignore session requests for non-ROM services */ - if (strcmp(service_name, "ROM")) return 0; - - /* drop out if request refers to another file name */ - char buf[FILENAME_MAX_LEN]; - Arg_string::find_arg(args, "filename").string(buf, sizeof(buf), ""); - return !strcmp(buf, _filename) ? this : 0; - } - }; -} + /* drop out if request refers to another file name */ + char buf[FILENAME_MAX_LEN]; + Arg_string::find_arg(args, "filename").string(buf, sizeof(buf), ""); + return !strcmp(buf, _filename) ? this : 0; + } +}; #endif /* _INCLUDE__OS__CHILD_POLICY_DYNAMIC_ROM_H_ */ diff --git a/repos/os/include/os/irq_activation.h b/repos/os/include/os/irq_activation.h index ac7020be3..47c422559 100644 --- a/repos/os/include/os/irq_activation.h +++ b/repos/os/include/os/irq_activation.h @@ -20,64 +20,68 @@ namespace Genode { - struct Irq_handler - { - /** - * Called by IRQ activation on interrupt - */ - virtual void handle_irq(int irq_number) = 0; - }; - - /** - * Thread activated by IRQ - */ - class Irq_activation : Thread_base - { - private: - - int _number; - Irq_connection _connection; - Irq_handler &_handler; - char _thread_name[8]; - - char const *_create_thread_name(unsigned irq_number) - { - snprintf(_thread_name, sizeof(_thread_name), "irq.%02x", irq_number); - return _thread_name; - } - - public: - - /** - * Constructor - * - * \param irq_number interrupt number - * \param handler interrupt handler - * \param stack_size size of stack or interrupt thread - */ - Irq_activation(int irq_number, Irq_handler &handler, size_t stack_size) - : - Thread_base(0, _create_thread_name(irq_number), stack_size), - _number(irq_number), _connection(irq_number), _handler(handler) - { - start(); - } - - /** - * Thread entry function - * - * The interrupt thread infinitely waits for interrupts and calls - * the handler on occurrence. - */ - void entry() - { - while (true) { - _connection.wait_for_irq(); - _handler.handle_irq(_number); - } - } - }; - + struct Irq_handler; + struct Irq_activation; } + +struct Genode::Irq_handler +{ + /** + * Called by IRQ activation on interrupt + */ + virtual void handle_irq(int irq_number) = 0; +}; + + +/** + * Thread activated by IRQ + */ +class Genode::Irq_activation : Thread_base +{ + private: + + int _number; + Irq_connection _connection; + Irq_handler &_handler; + char _thread_name[8]; + + char const *_create_thread_name(unsigned irq_number) + { + snprintf(_thread_name, sizeof(_thread_name), "irq.%02x", irq_number); + return _thread_name; + } + + public: + + /** + * Constructor + * + * \param irq_number interrupt number + * \param handler interrupt handler + * \param stack_size size of stack or interrupt thread + */ + Irq_activation(int irq_number, Irq_handler &handler, size_t stack_size) + : + Thread_base(0, _create_thread_name(irq_number), stack_size), + _number(irq_number), _connection(irq_number), _handler(handler) + { + start(); + } + + /** + * Thread entry function + * + * The interrupt thread infinitely waits for interrupts and calls + * the handler on occurrence. + */ + void entry() + { + while (true) { + _connection.wait_for_irq(); + _handler.handle_irq(_number); + } + } +}; + #endif /* _INCLUDE__OS__IRQ_ACTIVATION_H_ */ diff --git a/repos/os/include/os/packet_allocator.h b/repos/os/include/os/packet_allocator.h index f7663e16d..f03a1f09f 100644 --- a/repos/os/include/os/packet_allocator.h +++ b/repos/os/include/os/packet_allocator.h @@ -18,9 +18,7 @@ #include #include -namespace Genode { - class Packet_allocator; -} +namespace Genode { class Packet_allocator; } /** diff --git a/repos/os/include/os/path.h b/repos/os/include/os/path.h index 3ecc7fa82..eb48b9e19 100644 --- a/repos/os/include/os/path.h +++ b/repos/os/include/os/path.h @@ -19,301 +19,305 @@ namespace Genode { - class Path_base - { - public: - - class Path_too_long { }; - - protected: - - static bool is_absolute(char const *path) - { - return path[0] == '/'; - } - - static bool ends_with(char c, char const *path) - { - return path[0] && (path[strlen(path) - 1] == c); - } - - static void remove_char(char *buf) - { - for (; *buf; buf++) - buf[0] = buf[1]; - } - - static void remove_trailing(char c, char *path) - { - int i = 0; - while (path[i] && path[i + 1]) i++; - - /* - * Never touch the first character to preserve the invariant of - * the leading slash. - */ - if (i > 0 && path[i] == c) - path[i] = 0; - } - - template - static T *last_element(T *path) - { - T *result = path; - for (; *path; path++) - if (path[0] == '/' && path[1] != 0) - result = path; - return result; - } - - static bool is_empty(char const *path) - { - return strlen(path) == 0; - } - - /** - * Remove superfluous single dots followed by a slash from path - */ - static void strip_superfluous_dotslashes(char *path) - { - for (; *path; path++) { - if (path[0] != '/') continue; - - /* strip superfluous dots, e.g., "/abs/./path/" -> "/abs/path" */ - while (path[1] == '.' && path[2] == '/') { - remove_char(path); - remove_char(path); - } - } - } - - static void strip_superfluous_slashes(char *path) - { - for (; *path; path++) { - if (path[0] != '/') continue; - - /* strip superfluous slashes, e.g., "//path/" -> "/path" */ - while (path[1] == '/') - remove_char(path); - } - } - - /** - * Find double-dot path element - * - * \return index of the first dot of the found path element, or - * 0 if no double-dot path element could be found. - */ - static unsigned find_double_dot_dir(char *path) - { - for (unsigned i = 0; path[i]; i++) - if (path[i] == '/' && path[i + 1] == '.' && path[i + 2] == '.' - && (path[i + 3] == 0 || path[i + 3] == '/')) - return i + 1; - - return 0; - } - - static void strip(char *dst, unsigned count) - { - for (char const *src = dst + count; *src; ) - *dst++ = *src++; - *dst = 0; - } - - static void strip_double_dot_dirs(char *path) - { - unsigned i; - while ((i = find_double_dot_dir(path))) { - - /* skip slash prepending the double dot */ - unsigned cut_start = i - 1; - unsigned cut_end = i + 2; - - /* skip previous path element */ - while (cut_start > 0 && path[cut_start - 1] != '/') - cut_start--; - - /* skip slash in front of the pair of dots */ - if (cut_start > 0) - cut_start--; - - strip(path + cut_start, cut_end - cut_start); - } - } - - private: - - Path_base(const Path_base &); - - char * const _path; - size_t const _path_max_len; - - /** - * Append 'path' - * - * \throw Path_too_long - */ - void _append(char const *path) - { - size_t const orig_len = strlen(_path); - - if (strlen(path) + orig_len + 1 >= _path_max_len) - throw Path_too_long(); - - strncpy(_path + orig_len, path, _path_max_len - orig_len); - } - - void _append_slash_if_needed() - { - if (!ends_with('/', _path)) - _append("/"); - } - - void _strip_from_begin(unsigned count) { strip(_path, count); } - - /** - * Remove superfluous artifacts from absolute path - */ - void _canonicalize() - { - strip_superfluous_slashes(_path); - strip_superfluous_dotslashes(_path); - strip_double_dot_dirs(_path); - remove_trailing('.', _path); - } - - void _import(char const *path, char const *pwd = 0) - { - /* - * Validate 'pwd' argument, if not supplied, enforce invariant - * that 'pwd' is an absolute path. - */ - if (!pwd || strlen(pwd) == 0) - pwd = "/"; - - /* - * Use argument path if absolute - */ - if (is_absolute(path)) - strncpy(_path, path, _path_max_len); - - /* - * Otherwise, concatenate current working directory with - * relative path. - */ - else { - const char *const relative_path = path; - - strncpy(_path, pwd, _path_max_len); - - if (!is_empty(relative_path)) { - - /* make sure to have a slash separating both portions */ - _append_slash_if_needed(); - _append(relative_path); - } - } - _canonicalize(); - } - - public: - - Path_base(char *buf, size_t buf_len, - char const *path, char const *pwd = 0) - : - _path(buf), _path_max_len(buf_len) - { - _import(path, pwd); - } - - void import(char const *path, char const *pwd = 0) { _import(path, pwd); } - - char *base() { return _path; } - char const *base() const { return _path; } - - size_t max_len() { return _path_max_len; } - - void remove_trailing(char c) { remove_trailing(c, _path); } - - void keep_only_last_element() - { - char *dst = _path; - for (char const *src = last_element(_path) ; *src; ) - *dst++ = *src++; - - *dst = 0; - } - - void strip_last_element() - { - last_element(_path)[1] = 0; - } - - bool equals(Path_base const &ref) const { return strcmp(ref._path, _path) == 0; } - - bool equals(char const *str) const { return strcmp(str, _path) == 0; } - - bool strip_prefix(char const *prefix) - { - unsigned prefix_len = strlen(prefix); - - if (strcmp(prefix, _path, prefix_len) != 0) - return false; - - if (prefix_len > 0 && ends_with('/', prefix)) - prefix_len--; - - if (prefix[prefix_len] && prefix[prefix_len] != '/') - return false; - - if (_path[prefix_len] && _path[prefix_len] != '/') - return false; - - _strip_from_begin(prefix_len); - return true; - } - - bool has_single_element() const - { - /* count number of non-trailing slashes */ - unsigned num_slashes = 0; - for (char const *p = _path; *p; p++) - num_slashes += (p[0] == '/' && p[1] != 0); - - /* - * Check if the leading slash is the only one, also check the - * absence of any element. - */ - return (num_slashes == 1) && !equals("/"); - } - - void append(char const *str) { _append(str); _canonicalize(); } - }; - - - template - class Path : public Path_base { - - private: - - char _buf[MAX_LEN]; - - public: - - /** - * Default constuctor - * - * Initializes the path to '/'. - */ - Path() : Path_base(_buf, sizeof(_buf), "/") { } - - /** - * Constructor - */ - Path(char const *path, char const *pwd = 0) - : Path_base(_buf, sizeof(_buf), path, pwd) { } - }; + class Path_base; + template class Path; } + +class Genode::Path_base +{ + public: + + class Path_too_long { }; + + protected: + + static bool is_absolute(char const *path) + { + return path[0] == '/'; + } + + static bool ends_with(char c, char const *path) + { + return path[0] && (path[strlen(path) - 1] == c); + } + + static void remove_char(char *buf) + { + for (; *buf; buf++) + buf[0] = buf[1]; + } + + static void remove_trailing(char c, char *path) + { + int i = 0; + while (path[i] && path[i + 1]) i++; + + /* + * Never touch the first character to preserve the invariant of + * the leading slash. + */ + if (i > 0 && path[i] == c) + path[i] = 0; + } + + template + static T *last_element(T *path) + { + T *result = path; + for (; *path; path++) + if (path[0] == '/' && path[1] != 0) + result = path; + return result; + } + + static bool is_empty(char const *path) + { + return strlen(path) == 0; + } + + /** + * Remove superfluous single dots followed by a slash from path + */ + static void strip_superfluous_dotslashes(char *path) + { + for (; *path; path++) { + if (path[0] != '/') continue; + + /* strip superfluous dots, e.g., "/abs/./path/" -> "/abs/path" */ + while (path[1] == '.' && path[2] == '/') { + remove_char(path); + remove_char(path); + } + } + } + + static void strip_superfluous_slashes(char *path) + { + for (; *path; path++) { + if (path[0] != '/') continue; + + /* strip superfluous slashes, e.g., "//path/" -> "/path" */ + while (path[1] == '/') + remove_char(path); + } + } + + /** + * Find double-dot path element + * + * \return index of the first dot of the found path element, or + * 0 if no double-dot path element could be found. + */ + static unsigned find_double_dot_dir(char *path) + { + for (unsigned i = 0; path[i]; i++) + if (path[i] == '/' && path[i + 1] == '.' && path[i + 2] == '.' + && (path[i + 3] == 0 || path[i + 3] == '/')) + return i + 1; + + return 0; + } + + static void strip(char *dst, unsigned count) + { + for (char const *src = dst + count; *src; ) + *dst++ = *src++; + *dst = 0; + } + + static void strip_double_dot_dirs(char *path) + { + unsigned i; + while ((i = find_double_dot_dir(path))) { + + /* skip slash prepending the double dot */ + unsigned cut_start = i - 1; + unsigned cut_end = i + 2; + + /* skip previous path element */ + while (cut_start > 0 && path[cut_start - 1] != '/') + cut_start--; + + /* skip slash in front of the pair of dots */ + if (cut_start > 0) + cut_start--; + + strip(path + cut_start, cut_end - cut_start); + } + } + + private: + + Path_base(const Path_base &); + + char * const _path; + size_t const _path_max_len; + + /** + * Append 'path' + * + * \throw Path_too_long + */ + void _append(char const *path) + { + size_t const orig_len = strlen(_path); + + if (strlen(path) + orig_len + 1 >= _path_max_len) + throw Path_too_long(); + + strncpy(_path + orig_len, path, _path_max_len - orig_len); + } + + void _append_slash_if_needed() + { + if (!ends_with('/', _path)) + _append("/"); + } + + void _strip_from_begin(unsigned count) { strip(_path, count); } + + /** + * Remove superfluous artifacts from absolute path + */ + void _canonicalize() + { + strip_superfluous_slashes(_path); + strip_superfluous_dotslashes(_path); + strip_double_dot_dirs(_path); + remove_trailing('.', _path); + } + + void _import(char const *path, char const *pwd = 0) + { + /* + * Validate 'pwd' argument, if not supplied, enforce invariant + * that 'pwd' is an absolute path. + */ + if (!pwd || strlen(pwd) == 0) + pwd = "/"; + + /* + * Use argument path if absolute + */ + if (is_absolute(path)) + strncpy(_path, path, _path_max_len); + + /* + * Otherwise, concatenate current working directory with + * relative path. + */ + else { + const char *const relative_path = path; + + strncpy(_path, pwd, _path_max_len); + + if (!is_empty(relative_path)) { + + /* make sure to have a slash separating both portions */ + _append_slash_if_needed(); + _append(relative_path); + } + } + _canonicalize(); + } + + public: + + Path_base(char *buf, size_t buf_len, + char const *path, char const *pwd = 0) + : + _path(buf), _path_max_len(buf_len) + { + _import(path, pwd); + } + + void import(char const *path, char const *pwd = 0) { _import(path, pwd); } + + char *base() { return _path; } + char const *base() const { return _path; } + + size_t max_len() { return _path_max_len; } + + void remove_trailing(char c) { remove_trailing(c, _path); } + + void keep_only_last_element() + { + char *dst = _path; + for (char const *src = last_element(_path) ; *src; ) + *dst++ = *src++; + + *dst = 0; + } + + void strip_last_element() + { + last_element(_path)[1] = 0; + } + + bool equals(Path_base const &ref) const { return strcmp(ref._path, _path) == 0; } + + bool equals(char const *str) const { return strcmp(str, _path) == 0; } + + bool strip_prefix(char const *prefix) + { + unsigned prefix_len = strlen(prefix); + + if (strcmp(prefix, _path, prefix_len) != 0) + return false; + + if (prefix_len > 0 && ends_with('/', prefix)) + prefix_len--; + + if (prefix[prefix_len] && prefix[prefix_len] != '/') + return false; + + if (_path[prefix_len] && _path[prefix_len] != '/') + return false; + + _strip_from_begin(prefix_len); + return true; + } + + bool has_single_element() const + { + /* count number of non-trailing slashes */ + unsigned num_slashes = 0; + for (char const *p = _path; *p; p++) + num_slashes += (p[0] == '/' && p[1] != 0); + + /* + * Check if the leading slash is the only one, also check the + * absence of any element. + */ + return (num_slashes == 1) && !equals("/"); + } + + void append(char const *str) { _append(str); _canonicalize(); } +}; + + +template +class Genode::Path : public Path_base { + + private: + + char _buf[MAX_LEN]; + + public: + + /** + * Default constuctor + * + * Initializes the path to '/'. + */ + Path() : Path_base(_buf, sizeof(_buf), "/") { } + + /** + * Constructor + */ + Path(char const *path, char const *pwd = 0) + : Path_base(_buf, sizeof(_buf), path, pwd) { } +}; + #endif /* _INCLUDE__OS__PATH_H_ */ diff --git a/repos/os/include/os/server.h b/repos/os/include/os/server.h index fe26bc2a9..68f5fddf5 100644 --- a/repos/os/include/os/server.h +++ b/repos/os/include/os/server.h @@ -19,51 +19,8 @@ namespace Server { using namespace Genode; + class Entrypoint; - class Entrypoint - { - private: - - Rpc_entrypoint &_rpc_ep; - - public: - - Entrypoint(); - - /** - * Associate RPC object with the entry point - */ - template - Capability - manage(Rpc_object &obj) - { - return _rpc_ep.manage(&obj); - } - - /** - * Dissolve RPC object from entry point - */ - template - void dissolve(Rpc_object &obj) - { - _rpc_ep.dissolve(&obj); - } - - /** - * Associate signal dispatcher with entry point - */ - Signal_context_capability manage(Signal_rpc_dispatcher_base &); - - /** - * Disassociate signal dispatcher from entry point - */ - void dissolve(Signal_rpc_dispatcher_base &); - - /** - * Return RPC entrypoint - */ - Rpc_entrypoint &rpc_ep() { return _rpc_ep; } - }; void wait_and_dispatch_one_signal(); @@ -77,6 +34,52 @@ namespace Server { char const *name(); void construct(Entrypoint &); +} + + +class Server::Entrypoint +{ + private: + + Rpc_entrypoint &_rpc_ep; + + public: + + Entrypoint(); + + /** + * Associate RPC object with the entry point + */ + template + Capability + manage(Rpc_object &obj) + { + return _rpc_ep.manage(&obj); + } + + /** + * Dissolve RPC object from entry point + */ + template + void dissolve(Rpc_object &obj) + { + _rpc_ep.dissolve(&obj); + } + + /** + * Associate signal dispatcher with entry point + */ + Signal_context_capability manage(Signal_rpc_dispatcher_base &); + + /** + * Disassociate signal dispatcher from entry point + */ + void dissolve(Signal_rpc_dispatcher_base &); + + /** + * Return RPC entrypoint + */ + Rpc_entrypoint &rpc_ep() { return _rpc_ep; } }; #endif /* _INCLUDE__OS__SERVER_H_ */ diff --git a/repos/os/include/os/session_policy.h b/repos/os/include/os/session_policy.h index 732223614..b5cc46721 100644 --- a/repos/os/include/os/session_policy.h +++ b/repos/os/include/os/session_policy.h @@ -18,115 +18,120 @@ #include namespace Genode { - - class Session_label - { - public: - - enum { MAX_LEN = 128 }; - - private: - - char _buf[MAX_LEN]; - - public: - - Session_label() { _buf[0] = 0; } - - /** - * Constructor - * - * \param args session arguments as null-terminated string - */ - explicit Session_label(char const *args) - { - Arg_string::find_arg(args, "label").string(_buf, sizeof(_buf), - ""); - } - - char const *string() const { return _buf; } - }; - - /** - * Query server-side policy for a session request - */ - class Session_policy : public Xml_node - { - public: - - /** - * Exception type - */ - class No_policy_defined { }; - - private: - - /** - * Returns true if the start of the label matches the specified - * match string - */ - static bool _label_matches(Session_label const &label, char const *match) { - return strcmp(label.string(), match, strlen(match)) == 0; } - - /** - * Query session policy from session label - */ - static Xml_node _query_policy(Session_label const &label) - { - /* find index of policy node that matches best */ - int best_match = -1; - try { - unsigned label_len = 0; - Xml_node policy = config()->xml_node().sub_node(); - - for (int i = 0;; i++, policy = policy.next()) { - - if (!policy.has_type("policy")) - continue; - - /* label attribute from policy node */ - char policy_label[Session_label::MAX_LEN]; - policy.attribute("label").value(policy_label, - sizeof(policy_label)); - - if (!_label_matches(label, policy_label) - || strlen(policy_label) < label_len) - continue; - - label_len = strlen(policy_label); - best_match = i; - } - } catch (...) { } - - if (best_match != -1) - return config()->xml_node().sub_node(best_match); - - throw No_policy_defined(); - } - - public: - - /** - * Constructor - * - * \param args session arguments - * - * \throw No_policy_defined if the server configuration has no - * policy defined for the session - * request - * - * On construction, the 'Session_policy' looks up the 'policy' XML - * node that matches the label provided as argument. The - * server-side policies are defined in one or more policy subnodes - * of the server's 'config' node. Each policy node has a label - * attribute. If the policy label matches the first part of the - * label delivered as session argument, the policy matches. If - * multiple policies match, the one with the largest label is - * selected. - */ - explicit Session_policy(Session_label const &label) - : Xml_node(_query_policy(label)) { } - }; + + class Session_label; + class Session_policy; } + +class Genode::Session_label +{ + public: + + enum { MAX_LEN = 128 }; + + private: + + char _buf[MAX_LEN]; + + public: + + Session_label() { _buf[0] = 0; } + + /** + * Constructor + * + * \param args session arguments as null-terminated string + */ + explicit Session_label(char const *args) + { + Arg_string::find_arg(args, "label").string(_buf, sizeof(_buf), + ""); + } + + char const *string() const { return _buf; } +}; + + +/** + * Query server-side policy for a session request + */ +class Genode::Session_policy : public Xml_node +{ + public: + + /** + * Exception type + */ + class No_policy_defined { }; + + private: + + /** + * Returns true if the start of the label matches the specified + * match string + */ + static bool _label_matches(Session_label const &label, char const *match) { + return strcmp(label.string(), match, strlen(match)) == 0; } + + /** + * Query session policy from session label + */ + static Xml_node _query_policy(Session_label const &label) + { + /* find index of policy node that matches best */ + int best_match = -1; + try { + unsigned label_len = 0; + Xml_node policy = config()->xml_node().sub_node(); + + for (int i = 0;; i++, policy = policy.next()) { + + if (!policy.has_type("policy")) + continue; + + /* label attribute from policy node */ + char policy_label[Session_label::MAX_LEN]; + policy.attribute("label").value(policy_label, + sizeof(policy_label)); + + if (!_label_matches(label, policy_label) + || strlen(policy_label) < label_len) + continue; + + label_len = strlen(policy_label); + best_match = i; + } + } catch (...) { } + + if (best_match != -1) + return config()->xml_node().sub_node(best_match); + + throw No_policy_defined(); + } + + public: + + /** + * Constructor + * + * \param args session arguments + * + * \throw No_policy_defined if the server configuration has no + * policy defined for the session + * request + * + * On construction, the 'Session_policy' looks up the 'policy' XML + * node that matches the label provided as argument. The + * server-side policies are defined in one or more policy subnodes + * of the server's 'config' node. Each policy node has a label + * attribute. If the policy label matches the first part of the + * label delivered as session argument, the policy matches. If + * multiple policies match, the one with the largest label is + * selected. + */ + explicit Session_policy(Session_label const &label) + : Xml_node(_query_policy(label)) { } +}; + #endif /* _INCLUDE__OS__SESSION_POLICY_H_ */ diff --git a/repos/os/include/os/slave.h b/repos/os/include/os/slave.h index 5fb58297e..92a18d41f 100644 --- a/repos/os/include/os/slave.h +++ b/repos/os/include/os/slave.h @@ -26,184 +26,188 @@ namespace Genode { - /** - * Slave-policy class - * - * This class provides a convenience policy for single-service slaves using a - * white list of parent services. - */ - class Slave_policy : public Genode::Child_policy - { - protected: - - /** - * Return white list of services the slave is permitted to use - * - * The list is terminated via a NULL pointer. - */ - virtual char const **_permitted_services() const = 0; - - private: - - char const *_label; - Genode::Service_registry _parent_services; - Genode::Rpc_entrypoint &_entrypoint; - Genode::Rom_connection _binary_rom; - Init::Child_policy_enforce_labeling _labeling_policy; - Init::Child_policy_provide_rom_file _binary_policy; - Genode::Child_policy_dynamic_rom_file _config_policy; - - bool _service_permitted(const char *service_name) - { - for (const char **s = _permitted_services(); *s; ++s) - if (!Genode::strcmp(service_name, *s)) - return true; - - return false; - } - - public: - - /** - * Slave-policy constructor - * - * \param label name of the program to start - * \param entrypoint entrypoint used to provide local services - * such as the config ROM service - * \param ram RAM session used for buffering config data - * - * If 'ram' is set to 0, no configuration can be supplied to the - * slave. - */ - Slave_policy(const char *label, - Genode::Rpc_entrypoint &entrypoint, - Genode::Ram_session *ram = 0) - : - _label(label), - _entrypoint(entrypoint), - _binary_rom(_label, _label), - _labeling_policy(_label), - _binary_policy("binary", _binary_rom.dataspace(), &_entrypoint), - _config_policy("config", _entrypoint, ram) - { } - - Genode::Dataspace_capability binary() { return _binary_rom.dataspace(); } - - /** - * Assign new configuration to slave - */ - void configure(char const *config) - { - _config_policy.load(config, Genode::strlen(config) + 1); - } - - void configure(char const *config, size_t len) - { - _config_policy.load(config, len); - } - - - /**************************** - ** Child_policy interface ** - ****************************/ - - const char *name() const { return _label; } - - Genode::Service *resolve_session_request(const char *service_name, - const char *args) - { - Genode::Service *service = 0; - - /* check for binary file request */ - if ((service = _binary_policy.resolve_session_request(service_name, args))) - return service; - - /* check for config file request */ - if ((service = _config_policy.resolve_session_request(service_name, args))) - return service; - - if (!_service_permitted(service_name)) { - PERR("%s: illegal session request of service \"%s\"", - name(), service_name); - return 0; - } - - /* fill parent service registry on demand */ - if (!(service = _parent_services.find(service_name))) { - service = new (Genode::env()->heap()) - Genode::Parent_service(service_name); - _parent_services.insert(service); - } - - /* return parent service */ - return service; - } - - void filter_session_args(const char *service, - char *args, Genode::size_t args_len) - { - _labeling_policy.filter_session_args(service, args, args_len); - } - }; - - - class Slave - { - private: - - struct Resources - { - Genode::Ram_connection ram; - Genode::Cpu_connection cpu; - Genode::Rm_connection rm; - - class Quota_exceeded : public Genode::Exception { }; - - Resources(const char *label, Genode::size_t ram_quota) - : ram(label), cpu(label) - { - /* - * XXX derive donated quota from information to be provided by - * the used 'Connection' interfaces - */ - enum { DONATED_RAM_QUOTA = 128*1024 }; - if (ram_quota > DONATED_RAM_QUOTA) - ram_quota -= DONATED_RAM_QUOTA; - else - throw Quota_exceeded(); - ram.ref_account(Genode::env()->ram_session_cap()); - Genode::env()->ram_session()->transfer_quota(ram.cap(), ram_quota); - } - }; - - Resources _resources; - Genode::Child _child; - - public: - - Slave(Genode::Rpc_entrypoint &entrypoint, - Slave_policy &slave_policy, - Genode::size_t ram_quota) - : - _resources(slave_policy.name(), ram_quota), - _child(slave_policy.binary(), - _resources.ram.cap(), _resources.cpu.cap(), - _resources.rm.cap(), &entrypoint, &slave_policy) - { } - - Genode::Ram_connection &ram() { return _resources.ram; } - - - /*************************************** - ** Wrappers of the 'Child' interface ** - ***************************************/ - - void yield(Genode::Parent::Resource_args const &args) { - _child.yield(args); } - - void notify_resource_avail() const { - _child.notify_resource_avail(); } - }; + class Slave_policy; + class Slave; } + +/** + * Slave-policy class + * + * This class provides a convenience policy for single-service slaves using a + * white list of parent services. + */ +class Genode::Slave_policy : public Genode::Child_policy +{ + protected: + + /** + * Return white list of services the slave is permitted to use + * + * The list is terminated via a NULL pointer. + */ + virtual char const **_permitted_services() const = 0; + + private: + + char const *_label; + Genode::Service_registry _parent_services; + Genode::Rpc_entrypoint &_entrypoint; + Genode::Rom_connection _binary_rom; + Init::Child_policy_enforce_labeling _labeling_policy; + Init::Child_policy_provide_rom_file _binary_policy; + Genode::Child_policy_dynamic_rom_file _config_policy; + + bool _service_permitted(const char *service_name) + { + for (const char **s = _permitted_services(); *s; ++s) + if (!Genode::strcmp(service_name, *s)) + return true; + + return false; + } + + public: + + /** + * Slave-policy constructor + * + * \param label name of the program to start + * \param entrypoint entrypoint used to provide local services + * such as the config ROM service + * \param ram RAM session used for buffering config data + * + * If 'ram' is set to 0, no configuration can be supplied to the + * slave. + */ + Slave_policy(const char *label, + Genode::Rpc_entrypoint &entrypoint, + Genode::Ram_session *ram = 0) + : + _label(label), + _entrypoint(entrypoint), + _binary_rom(_label, _label), + _labeling_policy(_label), + _binary_policy("binary", _binary_rom.dataspace(), &_entrypoint), + _config_policy("config", _entrypoint, ram) + { } + + Genode::Dataspace_capability binary() { return _binary_rom.dataspace(); } + + /** + * Assign new configuration to slave + */ + void configure(char const *config) + { + _config_policy.load(config, Genode::strlen(config) + 1); + } + + void configure(char const *config, size_t len) + { + _config_policy.load(config, len); + } + + + /**************************** + ** Child_policy interface ** + ****************************/ + + const char *name() const { return _label; } + + Genode::Service *resolve_session_request(const char *service_name, + const char *args) + { + Genode::Service *service = 0; + + /* check for binary file request */ + if ((service = _binary_policy.resolve_session_request(service_name, args))) + return service; + + /* check for config file request */ + if ((service = _config_policy.resolve_session_request(service_name, args))) + return service; + + if (!_service_permitted(service_name)) { + PERR("%s: illegal session request of service \"%s\"", + name(), service_name); + return 0; + } + + /* fill parent service registry on demand */ + if (!(service = _parent_services.find(service_name))) { + service = new (Genode::env()->heap()) + Genode::Parent_service(service_name); + _parent_services.insert(service); + } + + /* return parent service */ + return service; + } + + void filter_session_args(const char *service, + char *args, Genode::size_t args_len) + { + _labeling_policy.filter_session_args(service, args, args_len); + } +}; + + +class Genode::Slave +{ + private: + + struct Resources + { + Genode::Ram_connection ram; + Genode::Cpu_connection cpu; + Genode::Rm_connection rm; + + class Quota_exceeded : public Genode::Exception { }; + + Resources(const char *label, Genode::size_t ram_quota) + : ram(label), cpu(label) + { + /* + * XXX derive donated quota from information to be provided by + * the used 'Connection' interfaces + */ + enum { DONATED_RAM_QUOTA = 128*1024 }; + if (ram_quota > DONATED_RAM_QUOTA) + ram_quota -= DONATED_RAM_QUOTA; + else + throw Quota_exceeded(); + ram.ref_account(Genode::env()->ram_session_cap()); + Genode::env()->ram_session()->transfer_quota(ram.cap(), ram_quota); + } + }; + + Resources _resources; + Genode::Child _child; + + public: + + Slave(Genode::Rpc_entrypoint &entrypoint, + Slave_policy &slave_policy, + Genode::size_t ram_quota) + : + _resources(slave_policy.name(), ram_quota), + _child(slave_policy.binary(), + _resources.ram.cap(), _resources.cpu.cap(), + _resources.rm.cap(), &entrypoint, &slave_policy) + { } + + Genode::Ram_connection &ram() { return _resources.ram; } + + + /*************************************** + ** Wrappers of the 'Child' interface ** + ***************************************/ + + void yield(Genode::Parent::Resource_args const &args) { + _child.yield(args); } + + void notify_resource_avail() const { + _child.notify_resource_avail(); } +}; + #endif /* _INCLUDE__OS__SLAVE_H_ */ diff --git a/repos/os/include/os/surface.h b/repos/os/include/os/surface.h index b0ec88a2d..6e476a4e6 100644 --- a/repos/os/include/os/surface.h +++ b/repos/os/include/os/surface.h @@ -18,6 +18,7 @@ #include namespace Genode { + class Surface_base; template class Surface; } diff --git a/repos/os/include/os/synced_interface.h b/repos/os/include/os/synced_interface.h index 0c290c43f..8dcfc6ea6 100644 --- a/repos/os/include/os/synced_interface.h +++ b/repos/os/include/os/synced_interface.h @@ -19,48 +19,51 @@ namespace Genode { - template - class Synced_interface - { - public: - - class Guard - { - private: - - LOCK &_lock; - IF *_interface; - - Guard(LOCK &lock, IF *interface) - : _lock(lock), _interface(interface) - { - _lock.lock(); - } - - friend class Synced_interface; - - public: - - ~Guard() { _lock.unlock(); } - - IF *operator -> () { return _interface; } - }; - - private: - - LOCK &_lock; - IF *_interface; - - public: - - Synced_interface(LOCK &lock, IF *interface) - : _lock(lock), _interface(interface) { } - - Guard operator () () - { - return Guard(_lock, _interface); - } - }; + template class Synced_interface; } + +template +class Genode::Synced_interface +{ + public: + + class Guard + { + private: + + LOCK &_lock; + IF *_interface; + + Guard(LOCK &lock, IF *interface) + : _lock(lock), _interface(interface) + { + _lock.lock(); + } + + friend class Synced_interface; + + public: + + ~Guard() { _lock.unlock(); } + + IF *operator -> () { return _interface; } + }; + + private: + + LOCK &_lock; + IF *_interface; + + public: + + Synced_interface(LOCK &lock, IF *interface) + : _lock(lock), _interface(interface) { } + + Guard operator () () + { + return Guard(_lock, _interface); + } +}; + #endif /* _INCLUDE__OS__SYNCED_INTERFACE_H_ */ diff --git a/repos/os/include/os/timed_semaphore.h b/repos/os/include/os/timed_semaphore.h index 4fb07e939..b46cd7ce7 100644 --- a/repos/os/include/os/timed_semaphore.h +++ b/repos/os/include/os/timed_semaphore.h @@ -26,217 +26,227 @@ namespace Genode { - /** - * Alarm thread, which counts jiffies and triggers timeout events. - */ - class Timeout_thread : public Thread<4096>, - public Alarm_scheduler - { - private: - - enum { JIFFIES_STEP_MS = 10 }; - - Timer::Connection _timer; /* timer session */ - Signal_context _context; - Signal_receiver _receiver; - - void entry(void); - - public: - - Timeout_thread() : Thread<4096>("alarm-timer") - { - _timer.sigh(_receiver.manage(&_context)); - _timer.trigger_periodic(JIFFIES_STEP_MS*1000); - start(); - } - - Genode::Alarm::Time time(void) { return _timer.elapsed_ms(); } - - /* - * Returns the singleton timeout-thread used for all timeouts. - */ - static Timeout_thread *alarm_timer(); - }; - - - class Timeout_exception : public Exception { }; - class Nonblocking_exception : public Exception { }; - + class Timeout_thread; + class Timed_semaphore; /** - * Semaphore with timeout on down operation. + * Exception types */ - class Timed_semaphore : public Semaphore - { - private: - - typedef Fifo_semaphore_queue::Element Element; - - /** - * Aborts blocking on the semaphore, raised when a timeout occured. - * - * \param element the waiting-queue element associated with a timeout. - * \return true if a thread was aborted/woken up - */ - bool _abort(Element *element) - { - Lock::Guard lock_guard(Semaphore::_meta_lock); - - /* potentially, the queue is empty */ - if (++Semaphore::_cnt <= 0) { - - /* - * Iterate through the queue and find the thread, - * with the corresponding timeout. - */ - Element *first = Semaphore::_queue.dequeue(); - Element *e = first; - - while (true) { - - /* - * Wakeup the thread. - */ - if (element == e) { - e->wake_up(); - return true; - } - - /* - * Noninvolved threads are enqueued again. - */ - Semaphore::_queue.enqueue(e); - e = Semaphore::_queue.dequeue(); - - /* - * Maybe, the alarm was triggered just after the corresponding - * thread was already dequeued, that's why we have to track - * whether we processed the whole queue. - */ - if (e == first) - break; - } - } - - /* The right element was not found, so decrease counter again */ - --Semaphore::_cnt; - return false; - } - - - /** - * Represents a timeout associated with the blocking- - * operation on a semaphore. - */ - class Timeout : public Alarm - { - private: - - Timed_semaphore *_sem; /* Semaphore we block on */ - Element *_element; /* Queue element timeout belongs to */ - bool _triggered; /* Timeout expired */ - Time _start; - - public: - - Timeout(Time duration, Timed_semaphore *s, Element *e) - : _sem(s), _element(e), _triggered(false) - { - Timeout_thread *tt = Timeout_thread::alarm_timer(); - _start = tt->time(); - tt->schedule_absolute(this, _start + duration); - } - - void discard(void) { Timeout_thread::alarm_timer()->discard(this); } - bool triggered(void) { return _triggered; } - Time start() { return _start; } - - protected: - - bool on_alarm(unsigned) override - { - /* Abort blocking operation */ - _triggered = _sem->_abort(_element); - return false; - } - }; - - - public: - - /** - * Constructor - * - * \param n initial counter value of the semphore - */ - Timed_semaphore(int n = 0) : Semaphore(n) { } - - /** - * Decrements semaphore and blocks when it's already zero. - * - * \param t after t milliseconds of blocking a Timeout_exception is thrown. - * if t is zero do not block, instead raise an - * Nonblocking_exception. - * \return milliseconds the caller was blocked - */ - Alarm::Time down(Alarm::Time t) - { - Semaphore::_meta_lock.lock(); - - if (--Semaphore::_cnt < 0) { - - /* If t==0 we shall not block */ - if (t == 0) { - ++_cnt; - Semaphore::_meta_lock.unlock(); - throw Genode::Nonblocking_exception(); - } - - /* - * Create semaphore queue element representing the thread - * in the wait queue. - */ - Element queue_element; - Semaphore::_queue.enqueue(&queue_element); - Semaphore::_meta_lock.unlock(); - - /* Create the timeout */ - Timeout to(t, this, &queue_element); - - /* - * The thread is going to block on a local lock now, - * waiting for getting waked from another thread - * calling 'up()' - * */ - queue_element.block(); - - /* Deactivate timeout */ - to.discard(); - - /* - * When we were only woken up, because of a timeout, - * throw an exception. - */ - if (to.triggered()) - throw Genode::Timeout_exception(); - - /* return blocking time */ - return Timeout_thread::alarm_timer()->time() - to.start(); - } else { - Semaphore::_meta_lock.unlock(); - } - return 0; - } - - - /******************************** - ** Base class implementations ** - ********************************/ - - void down() { Semaphore::down(); } - void up() { Semaphore::up(); } - }; + class Timeout_exception; + class Nonblocking_exception; } + +/** + * Alarm thread, which counts jiffies and triggers timeout events. + */ +class Genode::Timeout_thread : public Thread<4096>, + public Alarm_scheduler +{ + private: + + enum { JIFFIES_STEP_MS = 10 }; + + Timer::Connection _timer; /* timer session */ + Signal_context _context; + Signal_receiver _receiver; + + void entry(void); + + public: + + Timeout_thread() : Thread<4096>("alarm-timer") + { + _timer.sigh(_receiver.manage(&_context)); + _timer.trigger_periodic(JIFFIES_STEP_MS*1000); + start(); + } + + Genode::Alarm::Time time(void) { return _timer.elapsed_ms(); } + + /* + * Returns the singleton timeout-thread used for all timeouts. + */ + static Timeout_thread *alarm_timer(); +}; + + +class Genode::Timeout_exception : public Exception { }; +class Genode::Nonblocking_exception : public Exception { }; + + +/** + * Semaphore with timeout on down operation. + */ +class Genode::Timed_semaphore : public Semaphore +{ + private: + + typedef Fifo_semaphore_queue::Element Element; + + /** + * Aborts blocking on the semaphore, raised when a timeout occured. + * + * \param element the waiting-queue element associated with a timeout. + * \return true if a thread was aborted/woken up + */ + bool _abort(Element *element) + { + Lock::Guard lock_guard(Semaphore::_meta_lock); + + /* potentially, the queue is empty */ + if (++Semaphore::_cnt <= 0) { + + /* + * Iterate through the queue and find the thread, + * with the corresponding timeout. + */ + Element *first = Semaphore::_queue.dequeue(); + Element *e = first; + + while (true) { + + /* + * Wakeup the thread. + */ + if (element == e) { + e->wake_up(); + return true; + } + + /* + * Noninvolved threads are enqueued again. + */ + Semaphore::_queue.enqueue(e); + e = Semaphore::_queue.dequeue(); + + /* + * Maybe, the alarm was triggered just after the corresponding + * thread was already dequeued, that's why we have to track + * whether we processed the whole queue. + */ + if (e == first) + break; + } + } + + /* The right element was not found, so decrease counter again */ + --Semaphore::_cnt; + return false; + } + + + /** + * Represents a timeout associated with the blocking- + * operation on a semaphore. + */ + class Timeout : public Alarm + { + private: + + Timed_semaphore *_sem; /* Semaphore we block on */ + Element *_element; /* Queue element timeout belongs to */ + bool _triggered; /* Timeout expired */ + Time _start; + + public: + + Timeout(Time duration, Timed_semaphore *s, Element *e) + : _sem(s), _element(e), _triggered(false) + { + Timeout_thread *tt = Timeout_thread::alarm_timer(); + _start = tt->time(); + tt->schedule_absolute(this, _start + duration); + } + + void discard(void) { Timeout_thread::alarm_timer()->discard(this); } + bool triggered(void) { return _triggered; } + Time start() { return _start; } + + protected: + + bool on_alarm(unsigned) override + { + /* Abort blocking operation */ + _triggered = _sem->_abort(_element); + return false; + } + }; + + + public: + + /** + * Constructor + * + * \param n initial counter value of the semphore + */ + Timed_semaphore(int n = 0) : Semaphore(n) { } + + /** + * Decrements semaphore and blocks when it's already zero. + * + * \param t after t milliseconds of blocking a Timeout_exception is thrown. + * if t is zero do not block, instead raise an + * Nonblocking_exception. + * \return milliseconds the caller was blocked + */ + Alarm::Time down(Alarm::Time t) + { + Semaphore::_meta_lock.lock(); + + if (--Semaphore::_cnt < 0) { + + /* If t==0 we shall not block */ + if (t == 0) { + ++_cnt; + Semaphore::_meta_lock.unlock(); + throw Genode::Nonblocking_exception(); + } + + /* + * Create semaphore queue element representing the thread + * in the wait queue. + */ + Element queue_element; + Semaphore::_queue.enqueue(&queue_element); + Semaphore::_meta_lock.unlock(); + + /* Create the timeout */ + Timeout to(t, this, &queue_element); + + /* + * The thread is going to block on a local lock now, + * waiting for getting waked from another thread + * calling 'up()' + * */ + queue_element.block(); + + /* Deactivate timeout */ + to.discard(); + + /* + * When we were only woken up, because of a timeout, + * throw an exception. + */ + if (to.triggered()) + throw Genode::Timeout_exception(); + + /* return blocking time */ + return Timeout_thread::alarm_timer()->time() - to.start(); + } else { + Semaphore::_meta_lock.unlock(); + } + return 0; + } + + + /******************************** + ** Base class implementations ** + ********************************/ + + void down() { Semaphore::down(); } + void up() { Semaphore::up(); } +}; + #endif /* _INCLUDE__OS__TIMED_SEMAPHORE_H_ */ diff --git a/repos/os/include/packet_stream_rx/client.h b/repos/os/include/packet_stream_rx/client.h index 8bc3dbcc4..2da33904a 100644 --- a/repos/os/include/packet_stream_rx/client.h +++ b/repos/os/include/packet_stream_rx/client.h @@ -17,50 +17,50 @@ #include #include -namespace Packet_stream_rx { +namespace Packet_stream_rx { template class Client; } - template - class Client : public Genode::Rpc_client - { - private: - typename CHANNEL::Sink _sink; +template +class Packet_stream_rx::Client : public Genode::Rpc_client +{ + private: - /* - * Type shortcuts - */ - typedef Genode::Rpc_client Base; - typedef typename Base::Rpc_dataspace Rpc_dataspace; - typedef typename Base::Rpc_packet_avail Rpc_packet_avail; - typedef typename Base::Rpc_ready_to_ack Rpc_ready_to_ack; - typedef typename Base::Rpc_ready_to_submit Rpc_ready_to_submit; - typedef typename Base::Rpc_ack_avail Rpc_ack_avail; + typename CHANNEL::Sink _sink; - public: + /* + * Type shortcuts + */ + typedef Genode::Rpc_client Base; + typedef typename Base::Rpc_dataspace Rpc_dataspace; + typedef typename Base::Rpc_packet_avail Rpc_packet_avail; + typedef typename Base::Rpc_ready_to_ack Rpc_ready_to_ack; + typedef typename Base::Rpc_ready_to_submit Rpc_ready_to_submit; + typedef typename Base::Rpc_ack_avail Rpc_ack_avail; - /** - * Constructor - */ - Client(Genode::Capability channel_cap) : - Genode::Rpc_client(channel_cap), - _sink(Base::template call()) - { - /* wire data-flow signals for the packet receiver */ - _sink.register_sigh_ack_avail(Base::template call()); - _sink.register_sigh_ready_to_submit(Base::template call()); + public: - sigh_ready_to_ack(_sink.sigh_ready_to_ack()); - sigh_packet_avail(_sink.sigh_packet_avail()); - } + /** + * Constructor + */ + Client(Genode::Capability channel_cap) : + Genode::Rpc_client(channel_cap), + _sink(Base::template call()) + { + /* wire data-flow signals for the packet receiver */ + _sink.register_sigh_ack_avail(Base::template call()); + _sink.register_sigh_ready_to_submit(Base::template call()); - void sigh_ready_to_ack(Genode::Signal_context_capability sigh) { - Base::template call(sigh); } + sigh_ready_to_ack(_sink.sigh_ready_to_ack()); + sigh_packet_avail(_sink.sigh_packet_avail()); + } - void sigh_packet_avail(Genode::Signal_context_capability sigh) { - Base::template call(sigh); } + void sigh_ready_to_ack(Genode::Signal_context_capability sigh) { + Base::template call(sigh); } - typename CHANNEL::Sink *sink() { return &_sink; } - }; -} + void sigh_packet_avail(Genode::Signal_context_capability sigh) { + Base::template call(sigh); } + + typename CHANNEL::Sink *sink() { return &_sink; } +}; #endif /* _INCLUDE__PACKET_STREAM_RX__CLIENT_H_ */ diff --git a/repos/os/include/packet_stream_rx/packet_stream_rx.h b/repos/os/include/packet_stream_rx/packet_stream_rx.h index de5ef299f..b5a216720 100644 --- a/repos/os/include/packet_stream_rx/packet_stream_rx.h +++ b/repos/os/include/packet_stream_rx/packet_stream_rx.h @@ -17,45 +17,45 @@ #include #include -namespace Packet_stream_rx { - - template - struct Channel - { - typedef ::Packet_stream_source Source; - typedef ::Packet_stream_sink Sink; - - /** - * Request reception interface - * - * See documentation of 'Packet_stream_tx::Cannel::source'. - */ - virtual Sink *sink() { return 0; } - - /** - * Register signal handler for receiving 'ready_to_ack' signals - */ - virtual void sigh_ready_to_ack(Genode::Signal_context_capability sigh) = 0; - - /** - * Register signal handler for receiving 'packet_avail' signals - */ - virtual void sigh_packet_avail(Genode::Signal_context_capability sigh) = 0; +namespace Packet_stream_rx { template struct Channel; } - /********************* - ** RPC declaration ** - *********************/ +template +struct Packet_stream_rx::Channel +{ + typedef ::Packet_stream_source Source; + typedef ::Packet_stream_sink Sink; - GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace); - GENODE_RPC(Rpc_packet_avail, void, sigh_packet_avail, Genode::Signal_context_capability); - GENODE_RPC(Rpc_ready_to_ack, void, sigh_ready_to_ack, Genode::Signal_context_capability); - GENODE_RPC(Rpc_ready_to_submit, Genode::Signal_context_capability, sigh_ready_to_submit); - GENODE_RPC(Rpc_ack_avail, Genode::Signal_context_capability, sigh_ack_avail); + /** + * Request reception interface + * + * See documentation of 'Packet_stream_tx::Cannel::source'. + */ + virtual Sink *sink() { return 0; } - GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_packet_avail, Rpc_ready_to_ack, - Rpc_ready_to_submit, Rpc_ack_avail); - }; -} + /** + * Register signal handler for receiving 'ready_to_ack' signals + */ + virtual void sigh_ready_to_ack(Genode::Signal_context_capability sigh) = 0; + + /** + * Register signal handler for receiving 'packet_avail' signals + */ + virtual void sigh_packet_avail(Genode::Signal_context_capability sigh) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace); + GENODE_RPC(Rpc_packet_avail, void, sigh_packet_avail, Genode::Signal_context_capability); + GENODE_RPC(Rpc_ready_to_ack, void, sigh_ready_to_ack, Genode::Signal_context_capability); + GENODE_RPC(Rpc_ready_to_submit, Genode::Signal_context_capability, sigh_ready_to_submit); + GENODE_RPC(Rpc_ack_avail, Genode::Signal_context_capability, sigh_ack_avail); + + GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_packet_avail, Rpc_ready_to_ack, + Rpc_ready_to_submit, Rpc_ack_avail); +}; #endif /* _INCLUDE__PACKET_STREAM_RX__PACKET_STREAM_RX_H_ */ diff --git a/repos/os/include/packet_stream_rx/rpc_object.h b/repos/os/include/packet_stream_rx/rpc_object.h index 543da4ba8..a28de1ffd 100644 --- a/repos/os/include/packet_stream_rx/rpc_object.h +++ b/repos/os/include/packet_stream_rx/rpc_object.h @@ -17,100 +17,100 @@ #include #include -namespace Packet_stream_rx { - - template - class Rpc_object : public Genode::Rpc_object > - { - private: - - Genode::Rpc_entrypoint &_ep; - Genode::Capability _cap; - typename CHANNEL::Source _source; - - Genode::Signal_context_capability _sigh_ready_to_submit; - Genode::Signal_context_capability _sigh_ack_avail; - - public: - - /** - * Constructor - * - * \param ds dataspace used as communication buffer - * for the receive packet stream - * \param buffer_alloc allocator used for managing the communication - * buffer of the receive packet stream - * \param ep entry point used for serving the channel's RPC - * interface - */ - Rpc_object(Genode::Dataspace_capability ds, - Genode::Range_allocator *buffer_alloc, - Genode::Rpc_entrypoint &ep) - : _ep(ep), _cap(_ep.manage(this)), _source(buffer_alloc, ds), - - /* init signal handlers with default handlers of source */ - _sigh_ready_to_submit(_source.sigh_ready_to_submit()), - _sigh_ack_avail(_source.sigh_ack_avail()) { } - - /** - * Destructor - */ - ~Rpc_object() { _ep.dissolve(this); } - - /* - * The 'sigh_ack_avail()' and 'sigh_ready_to_submit()' functions - * may be called at session-creation time to override the default - * data-flow signal handlers as provided by the packet-stream source. - * The default handlers let the server block in the event of data - * congestion. By installing custom signal handlers, a server - * implementation is able to avoid blocking for a single event by - * facilitating the use of a select-like mode of operation. - * - * Note that calling these functions after the finished creation of - * the session has no effect because the client queries the signal - * handlers only once at session-creation time. - */ - - /** - * Override default handler for server-side ready-to-submit signals - * - * Must be called at constuction time only. - */ - void sigh_ready_to_submit(Genode::Signal_context_capability sigh) { - _sigh_ready_to_submit = sigh; } - - /** - * Override default handler for server-side ack-avail signals - * - * Must be called at constuction time only. - */ - void sigh_ack_avail(Genode::Signal_context_capability sigh) { - _sigh_ack_avail = sigh; } - - typename CHANNEL::Source *source() { return &_source; } - - Genode::Capability cap() const { return _cap; } +namespace Packet_stream_rx { template class Rpc_object; } - /******************* - ** RPC functions ** - *******************/ +template +class Packet_stream_rx::Rpc_object : public Genode::Rpc_object > +{ + private: - Genode::Dataspace_capability dataspace() { return _source.dataspace(); } + Genode::Rpc_entrypoint &_ep; + Genode::Capability _cap; + typename CHANNEL::Source _source; - void sigh_ready_to_ack(Genode::Signal_context_capability sigh) { - _source.register_sigh_ready_to_ack(sigh); } + Genode::Signal_context_capability _sigh_ready_to_submit; + Genode::Signal_context_capability _sigh_ack_avail; - void sigh_packet_avail(Genode::Signal_context_capability sigh) { - _source.register_sigh_packet_avail(sigh); } + public: - virtual Genode::Signal_context_capability sigh_ready_to_submit() { - return _sigh_ready_to_submit; } + /** + * Constructor + * + * \param ds dataspace used as communication buffer + * for the receive packet stream + * \param buffer_alloc allocator used for managing the communication + * buffer of the receive packet stream + * \param ep entry point used for serving the channel's RPC + * interface + */ + Rpc_object(Genode::Dataspace_capability ds, + Genode::Range_allocator *buffer_alloc, + Genode::Rpc_entrypoint &ep) + : _ep(ep), _cap(_ep.manage(this)), _source(buffer_alloc, ds), - virtual Genode::Signal_context_capability sigh_ack_avail() { - return _sigh_ack_avail; } + /* init signal handlers with default handlers of source */ + _sigh_ready_to_submit(_source.sigh_ready_to_submit()), + _sigh_ack_avail(_source.sigh_ack_avail()) { } - }; -} + /** + * Destructor + */ + ~Rpc_object() { _ep.dissolve(this); } + + /* + * The 'sigh_ack_avail()' and 'sigh_ready_to_submit()' functions + * may be called at session-creation time to override the default + * data-flow signal handlers as provided by the packet-stream source. + * The default handlers let the server block in the event of data + * congestion. By installing custom signal handlers, a server + * implementation is able to avoid blocking for a single event by + * facilitating the use of a select-like mode of operation. + * + * Note that calling these functions after the finished creation of + * the session has no effect because the client queries the signal + * handlers only once at session-creation time. + */ + + /** + * Override default handler for server-side ready-to-submit signals + * + * Must be called at constuction time only. + */ + void sigh_ready_to_submit(Genode::Signal_context_capability sigh) { + _sigh_ready_to_submit = sigh; } + + /** + * Override default handler for server-side ack-avail signals + * + * Must be called at constuction time only. + */ + void sigh_ack_avail(Genode::Signal_context_capability sigh) { + _sigh_ack_avail = sigh; } + + typename CHANNEL::Source *source() { return &_source; } + + Genode::Capability cap() const { return _cap; } + + + /******************* + ** RPC functions ** + *******************/ + + Genode::Dataspace_capability dataspace() { return _source.dataspace(); } + + void sigh_ready_to_ack(Genode::Signal_context_capability sigh) { + _source.register_sigh_ready_to_ack(sigh); } + + void sigh_packet_avail(Genode::Signal_context_capability sigh) { + _source.register_sigh_packet_avail(sigh); } + + virtual Genode::Signal_context_capability sigh_ready_to_submit() { + return _sigh_ready_to_submit; } + + virtual Genode::Signal_context_capability sigh_ack_avail() { + return _sigh_ack_avail; } + +}; #endif /* _INCLUDE__PACKET_STREAM_RX__RPC_OBJECT_H_ */ diff --git a/repos/os/include/packet_stream_tx/client.h b/repos/os/include/packet_stream_tx/client.h index 929960dff..da7f0287e 100644 --- a/repos/os/include/packet_stream_tx/client.h +++ b/repos/os/include/packet_stream_tx/client.h @@ -17,57 +17,57 @@ #include #include -namespace Packet_stream_tx { +namespace Packet_stream_tx { template class Client; } - template - class Client : public Genode::Rpc_client - { - private: - /* - * Type shortcuts - */ - typedef Genode::Rpc_client Base; - typedef typename Base::Rpc_dataspace Rpc_dataspace; - typedef typename Base::Rpc_packet_avail Rpc_packet_avail; - typedef typename Base::Rpc_ready_to_ack Rpc_ready_to_ack; - typedef typename Base::Rpc_ready_to_submit Rpc_ready_to_submit; - typedef typename Base::Rpc_ack_avail Rpc_ack_avail; +template +class Packet_stream_tx::Client : public Genode::Rpc_client +{ + private: - /** - * Packet-stream source - */ - typename CHANNEL::Source _source; + /* + * Type shortcuts + */ + typedef Genode::Rpc_client Base; + typedef typename Base::Rpc_dataspace Rpc_dataspace; + typedef typename Base::Rpc_packet_avail Rpc_packet_avail; + typedef typename Base::Rpc_ready_to_ack Rpc_ready_to_ack; + typedef typename Base::Rpc_ready_to_submit Rpc_ready_to_submit; + typedef typename Base::Rpc_ack_avail Rpc_ack_avail; - public: + /** + * Packet-stream source + */ + typename CHANNEL::Source _source; - /** - * Constructor - * - * \param buffer_alloc allocator used for managing the - * transmission buffer - */ - Client(Genode::Capability channel_cap, - Genode::Range_allocator *buffer_alloc) - : - Genode::Rpc_client(channel_cap), - _source(buffer_alloc, Base::template call()) - { - /* wire data-flow signals for the packet transmitter */ - _source.register_sigh_packet_avail(Base::template call()); - _source.register_sigh_ready_to_ack(Base::template call()); - sigh_ready_to_submit(_source.sigh_ready_to_submit()); - sigh_ack_avail(_source.sigh_ack_avail()); - } + public: - void sigh_ready_to_submit(Genode::Signal_context_capability sigh) { - Base::template call(sigh); } + /** + * Constructor + * + * \param buffer_alloc allocator used for managing the + * transmission buffer + */ + Client(Genode::Capability channel_cap, + Genode::Range_allocator *buffer_alloc) + : + Genode::Rpc_client(channel_cap), + _source(buffer_alloc, Base::template call()) + { + /* wire data-flow signals for the packet transmitter */ + _source.register_sigh_packet_avail(Base::template call()); + _source.register_sigh_ready_to_ack(Base::template call()); + sigh_ready_to_submit(_source.sigh_ready_to_submit()); + sigh_ack_avail(_source.sigh_ack_avail()); + } - void sigh_ack_avail(Genode::Signal_context_capability sigh) { - Base::template call(sigh); } + void sigh_ready_to_submit(Genode::Signal_context_capability sigh) { + Base::template call(sigh); } - typename CHANNEL::Source *source() { return &_source; } - }; -} + void sigh_ack_avail(Genode::Signal_context_capability sigh) { + Base::template call(sigh); } + + typename CHANNEL::Source *source() { return &_source; } +}; #endif /* _INCLUDE__PACKET_STREAM_TX__CLIENT_H_ */ diff --git a/repos/os/include/packet_stream_tx/packet_stream_tx.h b/repos/os/include/packet_stream_tx/packet_stream_tx.h index 4bb739fb4..bc8ccf0ac 100644 --- a/repos/os/include/packet_stream_tx/packet_stream_tx.h +++ b/repos/os/include/packet_stream_tx/packet_stream_tx.h @@ -17,49 +17,49 @@ #include #include -namespace Packet_stream_tx { - - template - struct Channel - { - typedef Packet_stream_source Source; - typedef Packet_stream_sink Sink; - - /** - * Request transmission interface - * - * This function enables the client-side use of the 'Channel' using - * the abstract 'Channel' interface only. This is useful in cases - * where both source and sink of the 'Channel' are co-located in - * one program. At the server side of the 'Channel', this function - * has no meaning. - */ - virtual Source *source() { return 0; } - - /** - * Register signal handler for receiving 'ready_to_submit' signals - */ - virtual void sigh_ready_to_submit(Genode::Signal_context_capability sigh) = 0; - - /** - * Register signal handler for receiving 'ack_avail' signals - */ - virtual void sigh_ack_avail(Genode::Signal_context_capability sigh) = 0; +namespace Packet_stream_tx { template struct Channel; } - /******************* - ** RPC interface ** - *******************/ +template +struct Packet_stream_tx::Channel +{ + typedef Packet_stream_source Source; + typedef Packet_stream_sink Sink; - GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace); - GENODE_RPC(Rpc_ack_avail, void, sigh_ack_avail, Genode::Signal_context_capability); - GENODE_RPC(Rpc_ready_to_submit, void, sigh_ready_to_submit, Genode::Signal_context_capability); - GENODE_RPC(Rpc_ready_to_ack, Genode::Signal_context_capability, sigh_ready_to_ack); - GENODE_RPC(Rpc_packet_avail, Genode::Signal_context_capability, sigh_packet_avail); - - GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_ack_avail, Rpc_ready_to_submit, - Rpc_ready_to_ack, Rpc_packet_avail); - }; -} + /** + * Request transmission interface + * + * This function enables the client-side use of the 'Channel' using + * the abstract 'Channel' interface only. This is useful in cases + * where both source and sink of the 'Channel' are co-located in + * one program. At the server side of the 'Channel', this function + * has no meaning. + */ + virtual Source *source() { return 0; } + + /** + * Register signal handler for receiving 'ready_to_submit' signals + */ + virtual void sigh_ready_to_submit(Genode::Signal_context_capability sigh) = 0; + + /** + * Register signal handler for receiving 'ack_avail' signals + */ + virtual void sigh_ack_avail(Genode::Signal_context_capability sigh) = 0; + + + /******************* + ** RPC interface ** + *******************/ + + GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace); + GENODE_RPC(Rpc_ack_avail, void, sigh_ack_avail, Genode::Signal_context_capability); + GENODE_RPC(Rpc_ready_to_submit, void, sigh_ready_to_submit, Genode::Signal_context_capability); + GENODE_RPC(Rpc_ready_to_ack, Genode::Signal_context_capability, sigh_ready_to_ack); + GENODE_RPC(Rpc_packet_avail, Genode::Signal_context_capability, sigh_packet_avail); + + GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_ack_avail, Rpc_ready_to_submit, + Rpc_ready_to_ack, Rpc_packet_avail); +}; #endif /* _INCLUDE__PACKET_STREAM_TX__PACKET_STREAM_TX_H_ */ diff --git a/repos/os/include/packet_stream_tx/rpc_object.h b/repos/os/include/packet_stream_tx/rpc_object.h index 52da52a59..8a38eb46f 100644 --- a/repos/os/include/packet_stream_tx/rpc_object.h +++ b/repos/os/include/packet_stream_tx/rpc_object.h @@ -17,97 +17,96 @@ #include #include -namespace Packet_stream_tx { - - template - class Rpc_object : public Genode::Rpc_object > - { - private: - - Genode::Rpc_entrypoint &_ep; - Genode::Capability _cap; - typename CHANNEL::Sink _sink; - - Genode::Signal_context_capability _sigh_ready_to_ack; - Genode::Signal_context_capability _sigh_packet_avail; - - public: - - /** - * Constructor - * - * \param ds dataspace used as communication buffer - * for the transmission packet stream - * \param ep entry point used for serving the channel's RPC - * interface - */ - Rpc_object(Genode::Dataspace_capability ds, - Genode::Rpc_entrypoint &ep) - : - _ep(ep), _cap(_ep.manage(this)), _sink(ds), - - /* init signal handlers with default handlers of sink */ - _sigh_ready_to_ack(_sink.sigh_ready_to_ack()), - _sigh_packet_avail(_sink.sigh_packet_avail()) - { } - - /** - * Destructor - */ - ~Rpc_object() { _ep.dissolve(this); } - - /* - * The 'sigh_packet_avail()' and 'sigh_ready_to_ack()' functions - * may be called at session-creation time to override the default - * data-flow signal handlers as provided by the packet-stream sink. - * The default handlers let the server block in the event of data - * congestion. By installing custom signal handlers, a server - * implementation is able to avoid blocking for a single event by - * facilitating the use of a select-like mode of operation. - * - * Note that calling these functions after the finished creation of - * the session has no effect because the client queries the signal - * handlers only once at session-creation time. - */ - - /** - * Override default handler for server-side ready-to-ack signals - */ - void sigh_ready_to_ack(Genode::Signal_context_capability sigh) { - _sigh_ready_to_ack = sigh; } - - /** - * Override default handler for server-side packet-avail signals - * - * Must be called at constuction time only. - */ - void sigh_packet_avail(Genode::Signal_context_capability sigh) { - _sigh_packet_avail = sigh; } - - typename CHANNEL::Sink *sink() { return &_sink; } - - Genode::Capability cap() const { return _cap; } +namespace Packet_stream_tx { template class Rpc_object; } - /******************* - ** RPC functions ** - *******************/ +template +class Packet_stream_tx::Rpc_object : public Genode::Rpc_object > +{ + private: - Genode::Dataspace_capability dataspace() { return _sink.dataspace(); } + Genode::Rpc_entrypoint &_ep; + Genode::Capability _cap; + typename CHANNEL::Sink _sink; - void sigh_ready_to_submit(Genode::Signal_context_capability sigh) { - _sink.register_sigh_ready_to_submit(sigh); } + Genode::Signal_context_capability _sigh_ready_to_ack; + Genode::Signal_context_capability _sigh_packet_avail; - void sigh_ack_avail(Genode::Signal_context_capability sigh) { - _sink.register_sigh_ack_avail(sigh); } + public: - virtual Genode::Signal_context_capability sigh_ready_to_ack() { - return _sigh_ready_to_ack; } + /** + * Constructor + * + * \param ds dataspace used as communication buffer + * for the transmission packet stream + * \param ep entry point used for serving the channel's RPC + * interface + */ + Rpc_object(Genode::Dataspace_capability ds, + Genode::Rpc_entrypoint &ep) + : + _ep(ep), _cap(_ep.manage(this)), _sink(ds), - virtual Genode::Signal_context_capability sigh_packet_avail() { - return _sigh_packet_avail; } + /* init signal handlers with default handlers of sink */ + _sigh_ready_to_ack(_sink.sigh_ready_to_ack()), + _sigh_packet_avail(_sink.sigh_packet_avail()) + { } - }; -} + /** + * Destructor + */ + ~Rpc_object() { _ep.dissolve(this); } + + /* + * The 'sigh_packet_avail()' and 'sigh_ready_to_ack()' functions + * may be called at session-creation time to override the default + * data-flow signal handlers as provided by the packet-stream sink. + * The default handlers let the server block in the event of data + * congestion. By installing custom signal handlers, a server + * implementation is able to avoid blocking for a single event by + * facilitating the use of a select-like mode of operation. + * + * Note that calling these functions after the finished creation of + * the session has no effect because the client queries the signal + * handlers only once at session-creation time. + */ + + /** + * Override default handler for server-side ready-to-ack signals + */ + void sigh_ready_to_ack(Genode::Signal_context_capability sigh) { + _sigh_ready_to_ack = sigh; } + + /** + * Override default handler for server-side packet-avail signals + * + * Must be called at constuction time only. + */ + void sigh_packet_avail(Genode::Signal_context_capability sigh) { + _sigh_packet_avail = sigh; } + + typename CHANNEL::Sink *sink() { return &_sink; } + + Genode::Capability cap() const { return _cap; } + + + /******************* + ** RPC functions ** + *******************/ + + Genode::Dataspace_capability dataspace() { return _sink.dataspace(); } + + void sigh_ready_to_submit(Genode::Signal_context_capability sigh) { + _sink.register_sigh_ready_to_submit(sigh); } + + void sigh_ack_avail(Genode::Signal_context_capability sigh) { + _sink.register_sigh_ack_avail(sigh); } + + virtual Genode::Signal_context_capability sigh_ready_to_ack() { + return _sigh_ready_to_ack; } + + virtual Genode::Signal_context_capability sigh_packet_avail() { + return _sigh_packet_avail; } +}; #endif /* _INCLUDE__PACKET_STREAM_TX__RPC_OBJECT_H_ */ diff --git a/repos/os/include/pci_device/client.h b/repos/os/include/pci_device/client.h index 643c34a1d..8244955d7 100644 --- a/repos/os/include/pci_device/client.h +++ b/repos/os/include/pci_device/client.h @@ -19,34 +19,34 @@ #include #include -namespace Pci { +namespace Pci { struct Device_client; } - struct Device_client : public Genode::Rpc_client - { - Device_client(Device_capability device) - : Genode::Rpc_client(device) { } - void bus_address(unsigned char *bus, unsigned char *dev, unsigned char *fn) { - call(bus, dev, fn); } +struct Pci::Device_client : public Genode::Rpc_client +{ + Device_client(Device_capability device) + : Genode::Rpc_client(device) { } - unsigned short vendor_id() { - return call(); } + void bus_address(unsigned char *bus, unsigned char *dev, unsigned char *fn) override { + call(bus, dev, fn); } - unsigned short device_id() { - return call(); } + unsigned short vendor_id() override { + return call(); } - unsigned class_code() { - return call(); } + unsigned short device_id() override { + return call(); } - Resource resource(int resource_id) { - return call(resource_id); } + unsigned class_code() override { + return call(); } - unsigned config_read(unsigned char address, Access_size size) { - return call(address, size); } + Resource resource(int resource_id) override { + return call(resource_id); } - void config_write(unsigned char address, unsigned value, Access_size size) { - call(address, value, size); } - }; -} + unsigned config_read(unsigned char address, Access_size size) override { + return call(address, size); } + + void config_write(unsigned char address, unsigned value, Access_size size) override { + call(address, value, size); } +}; #endif /* _INCLUDE__PCI_DEVICE__CLIENT_H_ */ diff --git a/repos/os/include/pci_device/pci_device.h b/repos/os/include/pci_device/pci_device.h index a86cd0c5f..85a07eea3 100644 --- a/repos/os/include/pci_device/pci_device.h +++ b/repos/os/include/pci_device/pci_device.h @@ -17,191 +17,191 @@ #include #include -namespace Pci { +namespace Pci { struct Device; } - struct Device + +struct Pci::Device +{ + class Resource { - class Resource - { - private: + private: - unsigned _bar; /* content of base-address register */ - unsigned _size; /* resource size */ + unsigned _bar; /* content of base-address register */ + unsigned _size; /* resource size */ - public: + public: - /** - * Resource type, either port I/O resource or memory-mapped resource + /** + * Resource type, either port I/O resource or memory-mapped resource + */ + enum Type { IO, MEMORY, INVALID }; + + /** + * Default constructor + */ + Resource() { } + + /** + * Constructor + * + * \param bar content of base-address register + * \param size resource size + * + * This constructor is only used by the PCI bus driver + * that implements the server-side of the the PCI session. + * If bar is set to zero, the constructed resource description + * represents an INVALID resource. + */ + Resource(unsigned bar, unsigned size) + : _bar(bar), _size(size) { } + + /** + * Return base address of resource + */ + unsigned base() + { + /* + * Mask out the resource-description bits of the base + * address register. I/O resources use the lowest 3 + * bits, memory resources use the lowest 4 bits. */ - enum Type { IO, MEMORY, INVALID }; + return _bar & ((type() == IO) ? ~7 : ~15); + } - /** - * Default constructor - */ - Resource() { } + /** + * Return resource size in bytes + */ + unsigned size() { return _size; } - /** - * Constructor - * - * \param bar content of base-address register - * \param size resource size - * - * This constructor is only used by the PCI bus driver - * that implements the server-side of the the PCI session. - * If bar is set to zero, the constructed resource description - * represents an INVALID resource. - */ - Resource(unsigned bar, unsigned size) - : _bar(bar), _size(size) { } + /** + * Return true if resource is prefetchable memory + */ + bool prefetchable() + { + return type() == MEMORY && (_bar & (1 << 3)); + } - /** - * Return base address of resource - */ - unsigned base() - { - /* - * Mask out the resource-description bits of the base - * address register. I/O resources use the lowest 3 - * bits, memory resources use the lowest 4 bits. - */ - return _bar & ((type() == IO) ? ~7 : ~15); - } + /** + * Return resource type + */ + Type type() + { + if (_bar == 0) + return INVALID; - /** - * Return resource size in bytes - */ - unsigned size() { return _size; } + return (_bar & 1) ? IO : MEMORY; + } - /** - * Return true if resource is prefetchable memory - */ - bool prefetchable() - { - return type() == MEMORY && (_bar & (1 << 3)); - } - - /** - * Return resource type - */ - Type type() - { - if (_bar == 0) - return INVALID; - - return (_bar & 1) ? IO : MEMORY; - } - - /** - * Return raw register content - */ - unsigned bar() const { return _bar; } - }; - - enum { NUM_RESOURCES = 6 }; - - virtual ~Device() { } - - /** - * Return bus, device, and function number of the device - */ - virtual void bus_address(unsigned char *bus, unsigned char *dev, - unsigned char *fn) = 0; - - /** - * Return vendor ID obtained from the PCI config space - */ - virtual unsigned short vendor_id() = 0; - - /** - * Return device ID obtained from the PCI config space - */ - virtual unsigned short device_id() = 0; - - /** - * Return device class code from the PCI config space - */ - virtual unsigned class_code() = 0; - - /** - * Query PCI-resource information - * - * \param resource_id index of according PCI resource of the device - * - * \return resource description - * \retval INVALID the supplied resource ID is invalid - */ - virtual Resource resource(int resource_id) = 0; - - /** - * Access size for operations directly accessing the config space - */ - enum Access_size { ACCESS_8BIT, ACCESS_16BIT, ACCESS_32BIT }; - - /** - * Read configuration space - */ - virtual unsigned config_read(unsigned char address, Access_size size) = 0; - - /** - * Write configuration space - */ - virtual void config_write(unsigned char address, unsigned value, - Access_size size) = 0; - - - /*************************** - ** Convenience functions ** - ***************************/ - - /* - * The base classes are defined as follows: - * - * 0x00 | legacy device - * 0x01 | mass-storage controller - * 0x02 | network controller - * 0x03 | display controller - * 0x04 | multimedia device - * 0x05 | memory controller - * 0x06 | bridge device - * 0x07 | simple-communication controller - * 0x08 | base-system peripheral - * 0x09 | input device - * 0x0a | docking station - * 0x0b | processor - * 0x0c | serial bus controller - * 0x0d | wireless controller - * 0x0e | intelligent I/O controller - * 0x0f | satellite-communications controller - * 0x10 | encryption/decryption controller - * 0x11 | data-acquisition and signal-processing controller - * 0x12 | reserved - * ... | - * 0xff | device does not fit in any of the defined classes - */ - - unsigned base_class() { return class_code() >> 16; } - unsigned sub_class() { return (class_code() >> 8) & 0xff; } - - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC(Rpc_bus_address, void, bus_address, - unsigned char *, unsigned char *, unsigned char *); - GENODE_RPC(Rpc_vendor_id, unsigned short, vendor_id); - GENODE_RPC(Rpc_device_id, unsigned short, device_id); - GENODE_RPC(Rpc_class_code, unsigned, class_code); - GENODE_RPC(Rpc_resource, Resource, resource, int); - GENODE_RPC(Rpc_config_read, unsigned, config_read, - unsigned char, Access_size); - GENODE_RPC(Rpc_config_write, void, config_write, - unsigned char, unsigned, Access_size); - - GENODE_RPC_INTERFACE(Rpc_bus_address, Rpc_vendor_id, Rpc_device_id, - Rpc_class_code, Rpc_resource, Rpc_config_read, - Rpc_config_write); + /** + * Return raw register content + */ + unsigned bar() const { return _bar; } }; -} + + enum { NUM_RESOURCES = 6 }; + + virtual ~Device() { } + + /** + * Return bus, device, and function number of the device + */ + virtual void bus_address(unsigned char *bus, unsigned char *dev, + unsigned char *fn) = 0; + + /** + * Return vendor ID obtained from the PCI config space + */ + virtual unsigned short vendor_id() = 0; + + /** + * Return device ID obtained from the PCI config space + */ + virtual unsigned short device_id() = 0; + + /** + * Return device class code from the PCI config space + */ + virtual unsigned class_code() = 0; + + /** + * Query PCI-resource information + * + * \param resource_id index of according PCI resource of the device + * + * \return resource description + * \retval INVALID the supplied resource ID is invalid + */ + virtual Resource resource(int resource_id) = 0; + + /** + * Access size for operations directly accessing the config space + */ + enum Access_size { ACCESS_8BIT, ACCESS_16BIT, ACCESS_32BIT }; + + /** + * Read configuration space + */ + virtual unsigned config_read(unsigned char address, Access_size size) = 0; + + /** + * Write configuration space + */ + virtual void config_write(unsigned char address, unsigned value, + Access_size size) = 0; + + + /*************************** + ** Convenience functions ** + ***************************/ + + /* + * The base classes are defined as follows: + * + * 0x00 | legacy device + * 0x01 | mass-storage controller + * 0x02 | network controller + * 0x03 | display controller + * 0x04 | multimedia device + * 0x05 | memory controller + * 0x06 | bridge device + * 0x07 | simple-communication controller + * 0x08 | base-system peripheral + * 0x09 | input device + * 0x0a | docking station + * 0x0b | processor + * 0x0c | serial bus controller + * 0x0d | wireless controller + * 0x0e | intelligent I/O controller + * 0x0f | satellite-communications controller + * 0x10 | encryption/decryption controller + * 0x11 | data-acquisition and signal-processing controller + * 0x12 | reserved + * ... | + * 0xff | device does not fit in any of the defined classes + */ + + unsigned base_class() { return class_code() >> 16; } + unsigned sub_class() { return (class_code() >> 8) & 0xff; } + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_bus_address, void, bus_address, + unsigned char *, unsigned char *, unsigned char *); + GENODE_RPC(Rpc_vendor_id, unsigned short, vendor_id); + GENODE_RPC(Rpc_device_id, unsigned short, device_id); + GENODE_RPC(Rpc_class_code, unsigned, class_code); + GENODE_RPC(Rpc_resource, Resource, resource, int); + GENODE_RPC(Rpc_config_read, unsigned, config_read, + unsigned char, Access_size); + GENODE_RPC(Rpc_config_write, void, config_write, + unsigned char, unsigned, Access_size); + + GENODE_RPC_INTERFACE(Rpc_bus_address, Rpc_vendor_id, Rpc_device_id, + Rpc_class_code, Rpc_resource, Rpc_config_read, + Rpc_config_write); +}; #endif /* _INCLUDE__PCI_DEVICE__PCI_DEVICE_H_ */ diff --git a/repos/os/include/pci_session/client.h b/repos/os/include/pci_session/client.h index 667fccdfe..cc9c1deb0 100644 --- a/repos/os/include/pci_session/client.h +++ b/repos/os/include/pci_session/client.h @@ -17,36 +17,36 @@ #include #include -namespace Pci { +namespace Pci { struct Session_client; } - struct Session_client : public Genode::Rpc_client - { - Session_client(Session_capability session) - : Genode::Rpc_client(session) { } - Device_capability first_device(unsigned device_class = 0, - unsigned class_mask = 0) { - return call(device_class, class_mask); } +struct Pci::Session_client : public Genode::Rpc_client +{ + Session_client(Session_capability session) + : Genode::Rpc_client(session) { } - Device_capability next_device(Device_capability prev_device, - unsigned device_class = 0, - unsigned class_mask = 0) { - return call(prev_device, device_class, class_mask); } + Device_capability first_device(unsigned device_class = 0, + unsigned class_mask = 0) { + return call(device_class, class_mask); } - void release_device(Device_capability device) { - call(device); } + Device_capability next_device(Device_capability prev_device, + unsigned device_class = 0, + unsigned class_mask = 0) { + return call(prev_device, device_class, class_mask); } - Genode::Io_mem_dataspace_capability config_extended(Device_capability device_cap) { - return call(device_cap); } + void release_device(Device_capability device) { + call(device); } - Genode::Ram_dataspace_capability alloc_dma_buffer(Device_capability device_cap, - Genode::size_t size) { - return call(device_cap, size); } + Genode::Io_mem_dataspace_capability config_extended(Device_capability device_cap) { + return call(device_cap); } - void free_dma_buffer(Device_capability device_cap, - Genode::Ram_dataspace_capability cap) { - call(device_cap, cap); } - }; -} + Genode::Ram_dataspace_capability alloc_dma_buffer(Device_capability device_cap, + Genode::size_t size) { + return call(device_cap, size); } + + void free_dma_buffer(Device_capability device_cap, + Genode::Ram_dataspace_capability cap) { + call(device_cap, cap); } +}; #endif /* _INCLUDE__PCI_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/pci_session/connection.h b/repos/os/include/pci_session/connection.h index 231c68532..e75a13b45 100644 --- a/repos/os/include/pci_session/connection.h +++ b/repos/os/include/pci_session/connection.h @@ -17,16 +17,16 @@ #include #include -namespace Pci { +namespace Pci { struct Connection; } - struct Connection : Genode::Connection, Session_client - { - Connection() - : - Genode::Connection(session("ram_quota=4K")), - Session_client(cap()) - { } - }; -} + +struct Pci::Connection : Genode::Connection, Session_client +{ + Connection() + : + Genode::Connection(session("ram_quota=4K")), + Session_client(cap()) + { } +}; #endif /* _INCLUDE__PCI_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/pci_session/pci_session.h b/repos/os/include/pci_session/pci_session.h index 7d5191092..6aa5d933d 100644 --- a/repos/os/include/pci_session/pci_session.h +++ b/repos/os/include/pci_session/pci_session.h @@ -22,75 +22,78 @@ namespace Pci { typedef Genode::Capability Device_capability; - struct Session : Genode::Session - { - static const char *service_name() { return "PCI"; } - - virtual ~Session() { } - - /** - * Find first accessible device - */ - virtual Device_capability first_device(unsigned, unsigned) = 0; - - /** - * Find next accessible device - * - * \param prev_device previous device - * - * The 'prev_device' argument is used to iterate through all - * devices. - */ - virtual Device_capability next_device(Device_capability prev_device, - unsigned, unsigned) = 0; - - /** - * Free server-internal data structures representing the device - * - * Use this function to relax the heap partition of your PCI session. - */ - virtual void release_device(Device_capability device) = 0; - - /** - * Provide mapping to device configuration space of 4k, known as - * "Enhanced Configuration Access Mechanism (ECAM) for PCI Express - */ - virtual Genode::Io_mem_dataspace_capability config_extended(Device_capability) = 0; - - /** - * Allocate memory suitable for DMA. - */ - virtual Genode::Ram_dataspace_capability alloc_dma_buffer(Device_capability, - Genode::size_t) = 0; - - /** - * Free previously allocated DMA memory - */ - virtual void free_dma_buffer(Device_capability, - Genode::Ram_dataspace_capability) = 0; - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC(Rpc_first_device, Device_capability, first_device, - unsigned, unsigned); - GENODE_RPC(Rpc_next_device, Device_capability, next_device, - Device_capability, unsigned, unsigned); - GENODE_RPC(Rpc_release_device, void, release_device, Device_capability); - GENODE_RPC(Rpc_config_extended, Genode::Io_mem_dataspace_capability, - config_extended, Device_capability); - GENODE_RPC_THROW(Rpc_alloc_dma_buffer, Genode::Ram_dataspace_capability, - alloc_dma_buffer, - GENODE_TYPE_LIST(Genode::Ram_session::Quota_exceeded), - Device_capability, Genode::size_t); - GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer, - Device_capability, Genode::Ram_dataspace_capability); - - GENODE_RPC_INTERFACE(Rpc_first_device, Rpc_next_device, - Rpc_release_device, Rpc_config_extended, - Rpc_alloc_dma_buffer, Rpc_free_dma_buffer); - }; + struct Session; } + +struct Pci::Session : Genode::Session +{ + static const char *service_name() { return "PCI"; } + + virtual ~Session() { } + + /** + * Find first accessible device + */ + virtual Device_capability first_device(unsigned, unsigned) = 0; + + /** + * Find next accessible device + * + * \param prev_device previous device + * + * The 'prev_device' argument is used to iterate through all + * devices. + */ + virtual Device_capability next_device(Device_capability prev_device, + unsigned, unsigned) = 0; + + /** + * Free server-internal data structures representing the device + * + * Use this function to relax the heap partition of your PCI session. + */ + virtual void release_device(Device_capability device) = 0; + + /** + * Provide mapping to device configuration space of 4k, known as + * "Enhanced Configuration Access Mechanism (ECAM) for PCI Express + */ + virtual Genode::Io_mem_dataspace_capability config_extended(Device_capability) = 0; + + /** + * Allocate memory suitable for DMA. + */ + virtual Genode::Ram_dataspace_capability alloc_dma_buffer(Device_capability, + Genode::size_t) = 0; + + /** + * Free previously allocated DMA memory + */ + virtual void free_dma_buffer(Device_capability, + Genode::Ram_dataspace_capability) = 0; + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_first_device, Device_capability, first_device, + unsigned, unsigned); + GENODE_RPC(Rpc_next_device, Device_capability, next_device, + Device_capability, unsigned, unsigned); + GENODE_RPC(Rpc_release_device, void, release_device, Device_capability); + GENODE_RPC(Rpc_config_extended, Genode::Io_mem_dataspace_capability, + config_extended, Device_capability); + GENODE_RPC_THROW(Rpc_alloc_dma_buffer, Genode::Ram_dataspace_capability, + alloc_dma_buffer, + GENODE_TYPE_LIST(Genode::Ram_session::Quota_exceeded), + Device_capability, Genode::size_t); + GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer, + Device_capability, Genode::Ram_dataspace_capability); + + GENODE_RPC_INTERFACE(Rpc_first_device, Rpc_next_device, + Rpc_release_device, Rpc_config_extended, + Rpc_alloc_dma_buffer, Rpc_free_dma_buffer); +}; + #endif /* _INCLUDE__PCI_SESSION__PCI_SESSION_H_ */ diff --git a/repos/os/include/platform/imx53/imx_framebuffer_session/client.h b/repos/os/include/platform/imx53/imx_framebuffer_session/client.h index 3d991e17d..ae120a37b 100644 --- a/repos/os/include/platform/imx53/imx_framebuffer_session/client.h +++ b/repos/os/include/platform/imx53/imx_framebuffer_session/client.h @@ -18,30 +18,30 @@ #include #include -namespace Framebuffer { +namespace Framebuffer { struct Imx_client; } - struct Imx_client : Genode::Rpc_client - { - explicit Imx_client(Capability session) - : Genode::Rpc_client(session) { } - Genode::Dataspace_capability dataspace() override { - return call(); } +struct Framebuffer::Imx_client : Genode::Rpc_client +{ + explicit Imx_client(Capability session) + : Genode::Rpc_client(session) { } - Mode mode() const override { return call(); } + Genode::Dataspace_capability dataspace() override { + return call(); } - void mode_sigh(Genode::Signal_context_capability sigh) override { - call(sigh); } + Mode mode() const override { return call(); } - void sync_sigh(Genode::Signal_context_capability sigh) override { - call(sigh); } + void mode_sigh(Genode::Signal_context_capability sigh) override { + call(sigh); } - void refresh(int x, int y, int w, int h) override { - call(x, y, w, h); } + void sync_sigh(Genode::Signal_context_capability sigh) override { + call(sigh); } - void overlay(Genode::addr_t phys_addr, int x, int y, int alpha) override { - call(phys_addr, x, y, alpha); } - }; -} + void refresh(int x, int y, int w, int h) override { + call(x, y, w, h); } + + void overlay(Genode::addr_t phys_addr, int x, int y, int alpha) override { + call(phys_addr, x, y, alpha); } +}; #endif /* _INCLUDE__IMX_FRAMEBUFFER_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/platform/imx53/imx_framebuffer_session/connection.h b/repos/os/include/platform/imx53/imx_framebuffer_session/connection.h index 24855dda1..a1410cda8 100644 --- a/repos/os/include/platform/imx53/imx_framebuffer_session/connection.h +++ b/repos/os/include/platform/imx53/imx_framebuffer_session/connection.h @@ -18,57 +18,57 @@ #include #include -namespace Framebuffer { +namespace Framebuffer { class Imx_connection; } - class Imx_connection : public Genode::Connection, - public Imx_client - { - private: - /** - * Create session and return typed session capability - */ - Capability _connect(unsigned width, unsigned height, - Mode::Format format) - { - using namespace Genode; +class Framebuffer::Imx_connection : public Genode::Connection, + public Imx_client +{ + private: - enum { ARGBUF_SIZE = 128 }; - char argbuf[ARGBUF_SIZE]; + /** + * Create session and return typed session capability + */ + Capability _connect(unsigned width, unsigned height, + Mode::Format format) + { + using namespace Genode; - /* donate ram quota for storing server-side meta data */ - strncpy(argbuf, "ram_quota=8K", sizeof(argbuf)); + enum { ARGBUF_SIZE = 128 }; + char argbuf[ARGBUF_SIZE]; - /* set optional session-constructor arguments */ - if (width) - Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_width", width); - if (height) - Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_height", height); - if (format != Mode::INVALID) - Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_format", format); + /* donate ram quota for storing server-side meta data */ + strncpy(argbuf, "ram_quota=8K", sizeof(argbuf)); - return session(argbuf); - } + /* set optional session-constructor arguments */ + if (width) + Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_width", width); + if (height) + Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_height", height); + if (format != Mode::INVALID) + Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_format", format); - public: + return session(argbuf); + } - /** - * Constructor - * - * \param width desired frame-buffer width - * \param height desired frame-buffer height - * \param mode desired pixel format - * - * The specified values are not enforced. After creating the - * session, you should validate the actual frame-buffer attributes - * by calling the 'info' function of the frame-buffer interface. - */ - Imx_connection(unsigned width = 0, - unsigned height = 0, - Mode::Format format = Mode::INVALID) - : Genode::Connection(_connect(width, height, format)), - Imx_client(cap()) { } - }; -} + public: + + /** + * Constructor + * + * \param width desired frame-buffer width + * \param height desired frame-buffer height + * \param mode desired pixel format + * + * The specified values are not enforced. After creating the + * session, you should validate the actual frame-buffer attributes + * by calling the 'info' function of the frame-buffer interface. + */ + Imx_connection(unsigned width = 0, + unsigned height = 0, + Mode::Format format = Mode::INVALID) + : Genode::Connection(_connect(width, height, format)), + Imx_client(cap()) { } +}; #endif /* _INCLUDE__IMX_FRAMEBUFFER_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/platform/imx53/imx_framebuffer_session/imx_framebuffer_session.h b/repos/os/include/platform/imx53/imx_framebuffer_session/imx_framebuffer_session.h index 873ebb3fb..1c0d8730f 100644 --- a/repos/os/include/platform/imx53/imx_framebuffer_session/imx_framebuffer_session.h +++ b/repos/os/include/platform/imx53/imx_framebuffer_session/imx_framebuffer_session.h @@ -18,31 +18,31 @@ #include #include -namespace Framebuffer { - - struct Imx_session : Session - { - virtual ~Imx_session() { } - - /** - * Set overlay properties - * - * \param phys_base physical base address of overlay framebuffer - * \param x horizontal position in pixel - * \param y vertical position in pixel - * \param alpha alpha transparency value of overlay (0-255) - */ - virtual void overlay(Genode::addr_t phys_base, int x, int y, int alpha) = 0; +namespace Framebuffer { struct Imx_session; } - /********************* - ** RPC declaration ** - *********************/ +struct Framebuffer::Imx_session : Session +{ + virtual ~Imx_session() { } - GENODE_RPC(Rpc_overlay, void, overlay, Genode::addr_t, int, int, int); + /** + * Set overlay properties + * + * \param phys_base physical base address of overlay framebuffer + * \param x horizontal position in pixel + * \param y vertical position in pixel + * \param alpha alpha transparency value of overlay (0-255) + */ + virtual void overlay(Genode::addr_t phys_base, int x, int y, int alpha) = 0; - GENODE_RPC_INTERFACE_INHERIT(Session, Rpc_overlay); - }; -} + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_overlay, void, overlay, Genode::addr_t, int, int, int); + + GENODE_RPC_INTERFACE_INHERIT(Session, Rpc_overlay); +}; #endif /* _INCLUDE__IMX_FRAMEBUFFER_SESSION__IMX_FRAMEBUFFER_SESSION_H_ */ diff --git a/repos/os/include/platform/imx53/platform_session/client.h b/repos/os/include/platform/imx53/platform_session/client.h index 840c6df1a..6766bd943 100644 --- a/repos/os/include/platform/imx53/platform_session/client.h +++ b/repos/os/include/platform/imx53/platform_session/client.h @@ -18,19 +18,19 @@ #include #include -namespace Platform { +namespace Platform { struct Client; } - struct Client : Genode::Rpc_client - { - explicit Client(Capability session) - : Genode::Rpc_client(session) { } - void enable(Device dev) { call(dev); } - void disable(Device dev) { call(dev); } - void clock_rate(Device dev, unsigned long rate) { - call(dev, rate); } - Board_revision revision() { return call(); } - }; -} +struct Platform::Client : Genode::Rpc_client +{ + explicit Client(Capability session) + : Genode::Rpc_client(session) { } + + void enable(Device dev) override { call(dev); } + void disable(Device dev) override { call(dev); } + void clock_rate(Device dev, unsigned long rate) override { + call(dev, rate); } + Board_revision revision() override { return call(); } +}; #endif /* _INCLUDE__PLATFORM_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/platform/imx53/platform_session/platform_session.h b/repos/os/include/platform/imx53/platform_session/platform_session.h index 6201be9bb..8aeb97342 100644 --- a/repos/os/include/platform/imx53/platform_session/platform_session.h +++ b/repos/os/include/platform/imx53/platform_session/platform_session.h @@ -17,46 +17,46 @@ #include #include -namespace Platform { - - struct Session : Genode::Session - { - enum Device { - IPU, - I2C_2, - I2C_3, - BUTTONS, - PWM, - }; - - enum Board_revision { - SMD = 2, /* Freescale i.MX53 SMD Tablet */ - QSB = 3, /* Freescale i.MX53 low-cost Quickstart board */ - UNKNOWN, - }; - - static const char *service_name() { return "Platform"; } - - virtual ~Session() { } - - virtual void enable(Device dev) = 0; - virtual void disable(Device dev) = 0; - virtual void clock_rate(Device dev, unsigned long rate) = 0; - virtual Board_revision revision() = 0; +namespace Platform { struct Session; } - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC(Rpc_enable, void, enable, Device); - GENODE_RPC(Rpc_disable, void, disable, Device); - GENODE_RPC(Rpc_clock_rate, void, clock_rate, Device, unsigned long); - GENODE_RPC(Rpc_revision, Board_revision, revision); - - GENODE_RPC_INTERFACE(Rpc_enable, Rpc_disable, Rpc_clock_rate, - Rpc_revision); +struct Platform::Session : Genode::Session +{ + enum Device { + IPU, + I2C_2, + I2C_3, + BUTTONS, + PWM, }; -} + + enum Board_revision { + SMD = 2, /* Freescale i.MX53 SMD Tablet */ + QSB = 3, /* Freescale i.MX53 low-cost Quickstart board */ + UNKNOWN, + }; + + static const char *service_name() { return "Platform"; } + + virtual ~Session() { } + + virtual void enable(Device dev) = 0; + virtual void disable(Device dev) = 0; + virtual void clock_rate(Device dev, unsigned long rate) = 0; + virtual Board_revision revision() = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_enable, void, enable, Device); + GENODE_RPC(Rpc_disable, void, disable, Device); + GENODE_RPC(Rpc_clock_rate, void, clock_rate, Device, unsigned long); + GENODE_RPC(Rpc_revision, Board_revision, revision); + + GENODE_RPC_INTERFACE(Rpc_enable, Rpc_disable, Rpc_clock_rate, + Rpc_revision); +}; #endif /* _INCLUDE__PLATFORM_SESSION__PLATFORM_SESSION_H_ */ diff --git a/repos/os/include/platform/rpi/platform_session/client.h b/repos/os/include/platform/rpi/platform_session/client.h index 8971de419..d2a285599 100644 --- a/repos/os/include/platform/rpi/platform_session/client.h +++ b/repos/os/include/platform/rpi/platform_session/client.h @@ -25,13 +25,13 @@ struct Platform::Client : Genode::Rpc_client explicit Client(Capability session) : Genode::Rpc_client(session) { } - void setup_framebuffer(Framebuffer_info &info) { + void setup_framebuffer(Framebuffer_info &info) override { call(info); } - bool power_state(Power power) { + bool power_state(Power power) override { return call(power); } - void power_state(Power power, bool enable) { + void power_state(Power power, bool enable) override { call(power, enable); } }; diff --git a/repos/os/include/platform_session/connection.h b/repos/os/include/platform_session/connection.h index d0949e909..ba6b0f48b 100644 --- a/repos/os/include/platform_session/connection.h +++ b/repos/os/include/platform_session/connection.h @@ -18,20 +18,14 @@ #include #include -namespace Platform { +namespace Platform { class Connection; } - class Connection : public Genode::Connection, - public Client - { - public: - /** - * Constructor - */ - Connection() - : Genode::Connection(session("ram_quota=4K")), - Client(cap()) { } - }; -} +struct Platform::Connection : Genode::Connection, Client +{ + Connection() + : Genode::Connection(session("ram_quota=4K")), + Client(cap()) { } +}; #endif /* _INCLUDE__PLATFORM_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/regulator/driver.h b/repos/os/include/regulator/driver.h index 56412ede6..d5f6850d0 100644 --- a/repos/os/include/regulator/driver.h +++ b/repos/os/include/regulator/driver.h @@ -18,33 +18,37 @@ namespace Regulator { - /** - * Interface to be implemented by the device-specific driver code - */ - struct Driver - { - virtual void level(Regulator_id id, unsigned long level) = 0; - virtual unsigned long level(Regulator_id id) = 0; - virtual void state(Regulator_id id, bool enable) = 0; - virtual bool state(Regulator_id id) = 0; - }; - - - /** - * Interface for constructing the driver object - */ - struct Driver_factory - { - /** - * Construct new driver - */ - virtual Driver &create(Regulator_id regulator) = 0; - - /** - * Destroy driver - */ - virtual void destroy(Driver &driver) = 0; - }; + struct Driver; + struct Driver_factory; } + +/** + * Interface to be implemented by the device-specific driver code + */ +struct Regulator::Driver +{ + virtual void level(Regulator_id id, unsigned long level) = 0; + virtual unsigned long level(Regulator_id id) = 0; + virtual void state(Regulator_id id, bool enable) = 0; + virtual bool state(Regulator_id id) = 0; +}; + + +/** + * Interface for constructing the driver object + */ +struct Regulator::Driver_factory +{ + /** + * Construct new driver + */ + virtual Driver &create(Regulator_id regulator) = 0; + + /** + * Destroy driver + */ + virtual void destroy(Driver &driver) = 0; +}; + #endif /* _REGULATOR__DRIVER_H_ */ diff --git a/repos/os/include/regulator_session/client.h b/repos/os/include/regulator_session/client.h index de7ea25f7..a50e35e3e 100644 --- a/repos/os/include/regulator_session/client.h +++ b/repos/os/include/regulator_session/client.h @@ -17,30 +17,28 @@ #include #include -namespace Regulator { - - class Session_client : public Genode::Rpc_client - { - public: - - /** - * Constructor - * - * \param session session capability - */ - Session_client(Session_capability session) - : Genode::Rpc_client(session) { } +namespace Regulator { struct Session_client; } - /********************************* - ** Regulator session interface ** - *********************************/ +struct Regulator::Session_client : public Genode::Rpc_client +{ + /** + * Constructor + * + * \param session session capability + */ + Session_client(Session_capability session) + : Genode::Rpc_client(session) { } - void level(unsigned long level) { call(level); } - unsigned long level() { return call(); } - void state(bool enable) { call(enable); } - bool state() { return call(); } - }; -} + + /********************************* + ** Regulator session interface ** + *********************************/ + + void level(unsigned long level) override { call(level); } + unsigned long level() override { return call(); } + void state(bool enable) override { call(enable); } + bool state() override { return call(); } +}; #endif /* _INCLUDE__REGULATOR_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/regulator_session/connection.h b/repos/os/include/regulator_session/connection.h index afacfd7de..9323722c0 100644 --- a/repos/os/include/regulator_session/connection.h +++ b/repos/os/include/regulator_session/connection.h @@ -18,22 +18,22 @@ #include #include -namespace Regulator { +namespace Regulator { struct Connection; } - struct Connection : Genode::Connection, Session_client - { - /** - * Constructor - * - * \param regulator identifier for the specific regulator - * \param label string identifier of the client - */ - Connection(Regulator_id regulator, const char * label = "") - : Genode::Connection( - session("ram_quota=8K, regulator=\"%s\", label=\"%s\"", - regulator_name_by_id(regulator), label)), - Session_client(cap()) { } - }; -} + +struct Regulator::Connection : Genode::Connection, Session_client +{ + /** + * Constructor + * + * \param regulator identifier for the specific regulator + * \param label string identifier of the client + */ + Connection(Regulator_id regulator, const char * label = "") + : Genode::Connection( + session("ram_quota=8K, regulator=\"%s\", label=\"%s\"", + regulator_name_by_id(regulator), label)), + Session_client(cap()) { } +}; #endif /* _INCLUDE__REGULATOR_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/regulator_session/regulator_session.h b/repos/os/include/regulator_session/regulator_session.h index ec500ccfe..1e0960f95 100644 --- a/repos/os/include/regulator_session/regulator_session.h +++ b/repos/os/include/regulator_session/regulator_session.h @@ -16,45 +16,45 @@ #include -namespace Regulator { - - struct Session : public Genode::Session - { - static const char *service_name() { return "Regulator"; } - - virtual ~Session() { } - - /** - * Set regulator specific level - */ - virtual void level(unsigned long level) = 0; - - /** - * Returns current regulator level - */ - virtual unsigned long level() = 0; - - /** - * Enable/disable regulator - */ - virtual void state(bool enable) = 0; - - /** - * Returns whether regulator is enabled or not - */ - virtual bool state() = 0; +namespace Regulator { struct Session; } - /******************* - ** RPC interface ** - *******************/ +struct Regulator::Session : public Genode::Session +{ + static const char *service_name() { return "Regulator"; } - GENODE_RPC(Rpc_set_level, void, level, unsigned long); - GENODE_RPC(Rpc_level, unsigned long, level); - GENODE_RPC(Rpc_set_state, void, state, bool); - GENODE_RPC(Rpc_state, bool, state); - GENODE_RPC_INTERFACE(Rpc_set_level, Rpc_level, Rpc_set_state, Rpc_state); - }; -} + virtual ~Session() { } + + /** + * Set regulator specific level + */ + virtual void level(unsigned long level) = 0; + + /** + * Returns current regulator level + */ + virtual unsigned long level() = 0; + + /** + * Enable/disable regulator + */ + virtual void state(bool enable) = 0; + + /** + * Returns whether regulator is enabled or not + */ + virtual bool state() = 0; + + + /******************* + ** RPC interface ** + *******************/ + + GENODE_RPC(Rpc_set_level, void, level, unsigned long); + GENODE_RPC(Rpc_level, unsigned long, level); + GENODE_RPC(Rpc_set_state, void, state, bool); + GENODE_RPC(Rpc_state, bool, state); + GENODE_RPC_INTERFACE(Rpc_set_level, Rpc_level, Rpc_set_state, Rpc_state); +}; #endif /* _INCLUDE__REGULATOR_SESSION__REGULATOR_SESSION_H_ */ diff --git a/repos/os/include/regulator_session/rpc_object.h b/repos/os/include/regulator_session/rpc_object.h index 7d37e99f7..4200bb197 100644 --- a/repos/os/include/regulator_session/rpc_object.h +++ b/repos/os/include/regulator_session/rpc_object.h @@ -18,23 +18,23 @@ #include #include -namespace Regulator { +namespace Regulator { class Session_rpc_object; } - class Session_rpc_object : public Genode::Rpc_object - { - protected: - Regulator_id _id; /* regulator identifier */ +class Regulator::Session_rpc_object : public Genode::Rpc_object +{ + protected: - public: + Regulator_id _id; /* regulator identifier */ - /** - * Constructor - * - * \param id identifies the specific regulator - */ - Session_rpc_object(Regulator_id id) : _id(id) { } - }; -} + public: + + /** + * Constructor + * + * \param id identifies the specific regulator + */ + Session_rpc_object(Regulator_id id) : _id(id) { } +}; #endif /* _INCLUDE__REGULATOR_SESSION__SERVER_H_ */ diff --git a/repos/os/include/rtc_session/client.h b/repos/os/include/rtc_session/client.h index 477855380..a801e87be 100644 --- a/repos/os/include/rtc_session/client.h +++ b/repos/os/include/rtc_session/client.h @@ -18,18 +18,15 @@ #include #include -namespace Rtc { +namespace Rtc { struct Session_client; } - struct Session_client : Genode::Rpc_client - { - Session_client(Genode::Capability cap) - : Genode::Rpc_client(cap) {} - Timestamp current_time() - { - return call(); - } - }; -} +struct Rtc::Session_client : Genode::Rpc_client +{ + Session_client(Genode::Capability cap) + : Genode::Rpc_client(cap) {} + + Timestamp current_time() { return call(); } +}; #endif /* _INCLUDE__RTC_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/rtc_session/connection.h b/repos/os/include/rtc_session/connection.h index 13cd6d698..8e78af87d 100644 --- a/repos/os/include/rtc_session/connection.h +++ b/repos/os/include/rtc_session/connection.h @@ -18,14 +18,14 @@ #include #include -namespace Rtc { +namespace Rtc { struct Connection; } - struct Connection : Genode::Connection, Session_client - { - Connection() : - Genode::Connection(session("foo, ram_quota=4K")), - Session_client(cap()) { } - }; -} + +struct Rtc::Connection : Genode::Connection, Session_client +{ + Connection() : + Genode::Connection(session("foo, ram_quota=4K")), + Session_client(cap()) { } +}; #endif /* _INCLUDE__RTC_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/rtc_session/rtc_session.h b/repos/os/include/rtc_session/rtc_session.h index fb3886412..3088f6fa1 100644 --- a/repos/os/include/rtc_session/rtc_session.h +++ b/repos/os/include/rtc_session/rtc_session.h @@ -21,28 +21,31 @@ #include namespace Rtc { - - struct Timestamp - { - unsigned microsecond; - unsigned second; - unsigned minute; - unsigned hour; - unsigned day; - unsigned month; - unsigned year; - }; - - - struct Session : Genode::Session - { - static const char *service_name() { return "Rtc"; } - - virtual Timestamp current_time() = 0; - - GENODE_RPC(Rpc_current_time, Timestamp, current_time); - GENODE_RPC_INTERFACE(Rpc_current_time); - }; + struct Timestamp; + struct Session; } + +struct Rtc::Timestamp +{ + unsigned microsecond; + unsigned second; + unsigned minute; + unsigned hour; + unsigned day; + unsigned month; + unsigned year; +}; + + +struct Rtc::Session : Genode::Session +{ + static const char *service_name() { return "Rtc"; } + + virtual Timestamp current_time() = 0; + + GENODE_RPC(Rpc_current_time, Timestamp, current_time); + GENODE_RPC_INTERFACE(Rpc_current_time); +}; + #endif /* _INCLUDE__RTC_SESSION__RTC_SESSION_H_ */ diff --git a/repos/os/include/terminal/character_screen.h b/repos/os/include/terminal/character_screen.h index 3ee5bd072..6289fa9ab 100644 --- a/repos/os/include/terminal/character_screen.h +++ b/repos/os/include/terminal/character_screen.h @@ -16,214 +16,214 @@ #include -namespace Terminal { +namespace Terminal { struct Character_screen; } + + +/** + * Character-screen interface called by input-stream decoder + */ +struct Terminal::Character_screen +{ + virtual void output(Character c) = 0; + + + /******************* + ** VT Operations ** + *******************/ + + /* + * The VT operations are named according to the command names used by + * their respective terminfo definitions. See 'man 5 terminfo' for a + * thorough description of these commands. + */ /** - * Character-screen interface called by input-stream decoder + * Make cursor invisible */ - struct Character_screen - { - virtual void output(Character c) = 0; + virtual void civis() = 0; + /** + * Make cursor normal + */ + virtual void cnorm() = 0; - /******************* - ** VT Operations ** - *******************/ + /** + * Make cursor very visible + */ + virtual void cvvis() = 0; - /* - * The VT operations are named according to the command names used by - * their respective terminfo definitions. See 'man 5 terminfo' for a - * thorough description of these commands. - */ + /** + * Reset string + */ + virtual void cpr() = 0; - /** - * Make cursor invisible - */ - virtual void civis() = 0; + /** + * Change region to line #1 ... line #2 + */ + virtual void csr(int, int) = 0; - /** - * Make cursor normal - */ - virtual void cnorm() = 0; + /** + * Move cursor backwards + */ + virtual void cub(int) = 0; - /** - * Make cursor very visible - */ - virtual void cvvis() = 0; + /** + * Non-destructive space - move right #1 spaces + */ + virtual void cuf(int) = 0; - /** - * Reset string - */ - virtual void cpr() = 0; + /** + * Move cursor to row #1 column #2 + */ + virtual void cup(int, int) = 0; - /** - * Change region to line #1 ... line #2 - */ - virtual void csr(int, int) = 0; + /** + * Move cursor up one line + */ + virtual void cuu1() = 0; - /** - * Move cursor backwards - */ - virtual void cub(int) = 0; + /** + * Delete #1 characters + */ + virtual void dch(int) = 0; - /** - * Non-destructive space - move right #1 spaces - */ - virtual void cuf(int) = 0; + /** + * Delete #1 lines + */ + virtual void dl(int) = 0; - /** - * Move cursor to row #1 column #2 - */ - virtual void cup(int, int) = 0; + /** + * Erase #1 characters + */ + virtual void ech(int) = 0; - /** - * Move cursor up one line - */ - virtual void cuu1() = 0; + /** + * Clear to end of screen + */ + virtual void ed() = 0; - /** - * Delete #1 characters - */ - virtual void dch(int) = 0; + /** + * Clear to end of line + */ + virtual void el() = 0; - /** - * Delete #1 lines - */ - virtual void dl(int) = 0; + /** + * Clear to beginning of line + */ + virtual void el1() = 0; - /** - * Erase #1 characters - */ - virtual void ech(int) = 0; + /** + * Home cursor + */ + virtual void home() = 0; - /** - * Clear to end of screen - */ - virtual void ed() = 0; + /** + * Horizontal position #1 absolute + */ + virtual void hpa(int) = 0; - /** - * Clear to end of line - */ - virtual void el() = 0; + /** + * Set a tab in every row, current column + */ + virtual void hts() = 0; - /** - * Clear to beginning of line - */ - virtual void el1() = 0; + /** + * Insert #1 characters + */ + virtual void ich(int) = 0; - /** - * Home cursor - */ - virtual void home() = 0; + /** + * Insert #1 lines + */ + virtual void il(int) = 0; - /** - * Horizontal position #1 absolute - */ - virtual void hpa(int) = 0; + /** + * Set all color pairs to the original ones + */ + virtual void oc() = 0; - /** - * Set a tab in every row, current column - */ - virtual void hts() = 0; + /** + * Set default pair to its original value + */ + virtual void op() = 0; - /** - * Insert #1 characters - */ - virtual void ich(int) = 0; + /** + * Restore cursor to position of last save_cursor + */ + virtual void rc() = 0; - /** - * Insert #1 lines - */ - virtual void il(int) = 0; + /** + * Scroll text down + */ + virtual void ri() = 0; - /** - * Set all color pairs to the original ones - */ - virtual void oc() = 0; + /** + * Reset string + */ + virtual void ris() = 0; - /** - * Set default pair to its original value - */ - virtual void op() = 0; + /** + * Turn off automatic margins + */ + virtual void rmam() = 0; - /** - * Restore cursor to position of last save_cursor - */ - virtual void rc() = 0; + /** + * Exit insert mode + */ + virtual void rmir() = 0; - /** - * Scroll text down - */ - virtual void ri() = 0; + /** + * Set background color to #1, using ANSI escape + */ + virtual void setab(int) = 0; - /** - * Reset string - */ - virtual void ris() = 0; + /** + * Set foreground color to #1, using ANSI escape + */ + virtual void setaf(int) = 0; - /** - * Turn off automatic margins - */ - virtual void rmam() = 0; + /** + * Set attribute + */ + virtual void sgr(int) = 0; - /** - * Exit insert mode - */ - virtual void rmir() = 0; + /** + * Turn of all attributes + */ + virtual void sgr0() = 0; - /** - * Set background color to #1, using ANSI escape - */ - virtual void setab(int) = 0; + /** + * Save current cursor position + */ + virtual void sc() = 0; - /** - * Set foreground color to #1, using ANSI escape - */ - virtual void setaf(int) = 0; + /** + * Turn on automatic margins + */ + virtual void smam() = 0; - /** - * Set attribute - */ - virtual void sgr(int) = 0; + /** + * Enter insert mode + */ + virtual void smir() = 0; - /** - * Turn of all attributes - */ - virtual void sgr0() = 0; + /** + * Clear all tab stops + */ + virtual void tbc() = 0; - /** - * Save current cursor position - */ - virtual void sc() = 0; + /** + * User strings + */ + virtual void u6(int, int) = 0; + virtual void u7() = 0; + virtual void u8() = 0; + virtual void u9() = 0; - /** - * Turn on automatic margins - */ - virtual void smam() = 0; - - /** - * Enter insert mode - */ - virtual void smir() = 0; - - /** - * Clear all tab stops - */ - virtual void tbc() = 0; - - /** - * User strings - */ - virtual void u6(int, int) = 0; - virtual void u7() = 0; - virtual void u8() = 0; - virtual void u9() = 0; - - /** - * Vertical position #1 absolute) - */ - virtual void vpa(int) = 0; - }; -} + /** + * Vertical position #1 absolute) + */ + virtual void vpa(int) = 0; +}; #endif /* _TERMINAL__CHARACTER_SCREEN_H_ */ diff --git a/repos/os/include/terminal/character_screen_tracer.h b/repos/os/include/terminal/character_screen_tracer.h index 6da026ad0..8c9935233 100644 --- a/repos/os/include/terminal/character_screen_tracer.h +++ b/repos/os/include/terminal/character_screen_tracer.h @@ -23,56 +23,56 @@ #define CS_TRACE_OP_1(name) void name(int p1) { printf(#name "(%d)\n", p1); } #define CS_TRACE_OP_2(name) void name(int p1, int p2) { printf(#name "(%d,%d)\n", p1, p2); } -namespace Terminal { +namespace Terminal { struct Character_screen_tracer }; - /** - * Character screen implementation that prints a trace of operations - */ - struct Character_screen_tracer : Character_screen - { - void output(char c) { printf("output('%c')\n", c); } - CS_TRACE_OP(civis); - CS_TRACE_OP(cnorm); - CS_TRACE_OP(cvvis); - CS_TRACE_OP(cpr); - CS_TRACE_OP_2(csr); - CS_TRACE_OP_1(cub); - CS_TRACE_OP(cuf1); - CS_TRACE_OP_2(cup); - CS_TRACE_OP(cuu1); - CS_TRACE_OP_1(dch); - CS_TRACE_OP_1(dl); - CS_TRACE_OP_1(ech); - CS_TRACE_OP(ed); - CS_TRACE_OP(el); - CS_TRACE_OP(el1); - CS_TRACE_OP(home); - CS_TRACE_OP_1(hpa); - CS_TRACE_OP(hts); - CS_TRACE_OP_1(ich); - CS_TRACE_OP_1(il); - CS_TRACE_OP(oc); - CS_TRACE_OP(op); - CS_TRACE_OP(rc); - CS_TRACE_OP(ri); - CS_TRACE_OP(ris); - CS_TRACE_OP(rmam); - CS_TRACE_OP(rmir); - CS_TRACE_OP_1(setab); - CS_TRACE_OP_1(setaf); - CS_TRACE_OP_1(sgr); - CS_TRACE_OP(sc); - CS_TRACE_OP(smam); - CS_TRACE_OP(smir); - CS_TRACE_OP(tbc); - CS_TRACE_OP_2(u6); - CS_TRACE_OP(u7); - CS_TRACE_OP(u8); - CS_TRACE_OP(u9); - CS_TRACE_OP_1(vpa); - }; -} +/** + * Character screen implementation that prints a trace of operations + */ +struct Terminal::Character_screen_tracer : Character_screen +{ + void output(char c) { printf("output('%c')\n", c); } + + CS_TRACE_OP(civis); + CS_TRACE_OP(cnorm); + CS_TRACE_OP(cvvis); + CS_TRACE_OP(cpr); + CS_TRACE_OP_2(csr); + CS_TRACE_OP_1(cub); + CS_TRACE_OP(cuf1); + CS_TRACE_OP_2(cup); + CS_TRACE_OP(cuu1); + CS_TRACE_OP_1(dch); + CS_TRACE_OP_1(dl); + CS_TRACE_OP_1(ech); + CS_TRACE_OP(ed); + CS_TRACE_OP(el); + CS_TRACE_OP(el1); + CS_TRACE_OP(home); + CS_TRACE_OP_1(hpa); + CS_TRACE_OP(hts); + CS_TRACE_OP_1(ich); + CS_TRACE_OP_1(il); + CS_TRACE_OP(oc); + CS_TRACE_OP(op); + CS_TRACE_OP(rc); + CS_TRACE_OP(ri); + CS_TRACE_OP(ris); + CS_TRACE_OP(rmam); + CS_TRACE_OP(rmir); + CS_TRACE_OP_1(setab); + CS_TRACE_OP_1(setaf); + CS_TRACE_OP_1(sgr); + CS_TRACE_OP(sc); + CS_TRACE_OP(smam); + CS_TRACE_OP(smir); + CS_TRACE_OP(tbc); + CS_TRACE_OP_2(u6); + CS_TRACE_OP(u7); + CS_TRACE_OP(u8); + CS_TRACE_OP(u9); + CS_TRACE_OP_1(vpa); +}; #undef CS_TRACE_OP #undef CS_TRACE_OP_1 diff --git a/repos/os/include/terminal/decoder.h b/repos/os/include/terminal/decoder.h index 4e83b77e2..c9ba3faa7 100644 --- a/repos/os/include/terminal/decoder.h +++ b/repos/os/include/terminal/decoder.h @@ -16,470 +16,470 @@ #include -namespace Terminal { +namespace Terminal { class Decoder; } - class Decoder - { - private: - /** - * Return digit value of character - */ - static inline int digit(char c) - { - if (c >= '0' && c <= '9') return c - '0'; - return -1; - } +class Terminal::Decoder +{ + private: - /** - * Return true if character is a digit - */ - static inline bool is_digit(char c) - { - return (digit(c) >= 0); - } + /** + * Return digit value of character + */ + static inline int digit(char c) + { + if (c >= '0' && c <= '9') return c - '0'; + return -1; + } - /** - * Return true if number starts with the specified digit - * - * \param digit digit 0..9 to test for - */ - static inline bool starts_with_digit(int digit, int number) - { - for (; number > 9; number /= 10); - return (number == digit); - } + /** + * Return true if character is a digit + */ + static inline bool is_digit(char c) + { + return (digit(c) >= 0); + } - /** - * Return number with the first digit removed - */ - static inline int remove_first_digit(int number) - { - int factor = 1; - for (; number/factor > 9; factor *= 10); - return number % factor; - } + /** + * Return true if number starts with the specified digit + * + * \param digit digit 0..9 to test for + */ + static inline bool starts_with_digit(int digit, int number) + { + for (; number > 9; number /= 10); + return (number == digit); + } - /** - * Buffer used for collecting escape sequences - */ - class Escape_stack - { - public: + /** + * Return number with the first digit removed + */ + static inline int remove_first_digit(int number) + { + int factor = 1; + for (; number/factor > 9; factor *= 10); + return number % factor; + } - struct Entry - { - enum { INVALID, NUMBER, CODE }; + /** + * Buffer used for collecting escape sequences + */ + class Escape_stack + { + public: - int type = INVALID; - int value = 0; - }; + struct Entry + { + enum { INVALID, NUMBER, CODE }; - struct Number_entry : Entry - { - Number_entry(int number) { type = NUMBER, value = number; } - }; + int type = INVALID; + int value = 0; + }; - struct Code_entry : Entry - { - Code_entry(int code) { type = CODE, value = code; } - }; + struct Number_entry : Entry + { + Number_entry(int number) { type = NUMBER, value = number; } + }; - struct Invalid_entry : Entry { }; + struct Code_entry : Entry + { + Code_entry(int code) { type = CODE, value = code; } + }; - private: + struct Invalid_entry : Entry { }; - enum { MAX_ENTRIES = 16 }; - Entry _entries[MAX_ENTRIES]; - int _index; + private: - void _dump() const - { - Genode::printf("--- escape stack follows ---\n"); - for (int i = 0; i < _index; i++) { - int type = _entries[i].type; - int value = _entries[i].value; - Genode::printf("%s %d (0x%x '%c')\n", - type == Entry::INVALID ? " INVALID" : - type == Entry::NUMBER ? " NUMBER " - : " CODE ", - value, value, value); - } + enum { MAX_ENTRIES = 16 }; + Entry _entries[MAX_ENTRIES]; + int _index; + + void _dump() const + { + Genode::printf("--- escape stack follows ---\n"); + for (int i = 0; i < _index; i++) { + int type = _entries[i].type; + int value = _entries[i].value; + Genode::printf("%s %d (0x%x '%c')\n", + type == Entry::INVALID ? " INVALID" : + type == Entry::NUMBER ? " NUMBER " + : " CODE ", + value, value, value); } + } - public: + public: - Escape_stack() : _index(0) { } + Escape_stack() : _index(0) { } - void reset() { _index = 0; } + void reset() { _index = 0; } - void push(Entry const &entry) - { - if (_index == MAX_ENTRIES - 1) { - Genode::printf("Error: escape stack overflow\n"); - _dump(); - reset(); - return; - } - _entries[_index++] = entry; + void push(Entry const &entry) + { + if (_index == MAX_ENTRIES - 1) { + Genode::printf("Error: escape stack overflow\n"); + _dump(); + reset(); + return; } + _entries[_index++] = entry; + } - /** - * Return number of stack elements - */ - unsigned num_elem() const { return _index; } + /** + * Return number of stack elements + */ + unsigned num_elem() const { return _index; } - /** - * Return Nth stack entry - * - * 'index' is relative to the bottom of the stack. - */ - Entry operator [] (int index) - { - return (index <= _index) ? _entries[index] : Invalid_entry(); - } + /** + * Return Nth stack entry + * + * 'index' is relative to the bottom of the stack. + */ + Entry operator [] (int index) + { + return (index <= _index) ? _entries[index] : Invalid_entry(); + } - } _escape_stack; + } _escape_stack; - enum State { - STATE_IDLE, - STATE_ESC_SEQ, /* read escape sequence */ - STATE_ESC_NUMBER /* read number argument within escape sequence */ - } _state; + enum State { + STATE_IDLE, + STATE_ESC_SEQ, /* read escape sequence */ + STATE_ESC_NUMBER /* read number argument within escape sequence */ + } _state; - Character_screen &_screen; + Character_screen &_screen; - int _number; /* current number argument supplied in escape sequence */ + int _number; /* current number argument supplied in escape sequence */ - void _append_to_number(char c) - { - _number = _number*10 + digit(c); + void _append_to_number(char c) + { + _number = _number*10 + digit(c); + } + + void _enter_state_idle() + { + _state = STATE_IDLE; + _escape_stack.reset(); + } + + void _enter_state_esc_seq() + { + _state = STATE_ESC_SEQ; + _escape_stack.reset(); + } + + void _enter_state_esc_number() + { + _state = STATE_ESC_NUMBER; + _number = 0; + } + + /** + * Try to handle single-element escape sequence + * + * \return true if escape sequence was handled + */ + bool _handle_esc_seq_1() + { + switch (_escape_stack[0].value) { + case '7': return (_screen.sc(), true); + case 'c': return (_screen.ris(), true); + case 'H': return (_screen.hts(), true); + case 'M': return (_screen.ri(), true); + default: return false; } + } - void _enter_state_idle() - { - _state = STATE_IDLE; - _escape_stack.reset(); - } + bool _handle_esc_seq_2() + { + switch (_escape_stack[0].value) { - void _enter_state_esc_seq() - { - _state = STATE_ESC_SEQ; - _escape_stack.reset(); - } + case '[': - void _enter_state_esc_number() - { - _state = STATE_ESC_NUMBER; - _number = 0; - } - - /** - * Try to handle single-element escape sequence - * - * \return true if escape sequence was handled - */ - bool _handle_esc_seq_1() - { - switch (_escape_stack[0].value) { - case '7': return (_screen.sc(), true); - case 'c': return (_screen.ris(), true); - case 'H': return (_screen.hts(), true); - case 'M': return (_screen.ri(), true); + switch (_escape_stack[1].value) { + case 'A': return (_screen.cuu1(), true); + case 'C': return (_screen.cuf(1), true); + case 'c': return (_screen.u9(), true); + case 'H': return (_screen.home(), true); + case 'J': return (_screen.ed(), true); + case 'K': return (_screen.el(), true); + case 'L': return (_screen.il(1), true); + case 'M': return (_screen.dl(1), true); + case 'P': return (_screen.dch(1), true); + case '@': return (_screen.ich(1), true); + case 'R': return (_screen.cpr(), true); default: return false; } - } + break; - bool _handle_esc_seq_2() - { - switch (_escape_stack[0].value) { + case ']': - case '[': - - switch (_escape_stack[1].value) { - case 'A': return (_screen.cuu1(), true); - case 'C': return (_screen.cuf(1), true); - case 'c': return (_screen.u9(), true); - case 'H': return (_screen.home(), true); - case 'J': return (_screen.ed(), true); - case 'K': return (_screen.el(), true); - case 'L': return (_screen.il(1), true); - case 'M': return (_screen.dl(1), true); - case 'P': return (_screen.dch(1), true); - case '@': return (_screen.ich(1), true); - case 'R': return (_screen.cpr(), true); - default: return false; - } - break; - - case ']': - - switch (_escape_stack[1].value) { - case 'R': return (_screen.oc(), true); - default : return false; - } - - case 8: - - return (_escape_stack[1].value == 'A') && (_screen.rc(), true); - - default: return false; + switch (_escape_stack[1].value) { + case 'R': return (_screen.oc(), true); + default : return false; } + + case 8: + + return (_escape_stack[1].value == 'A') && (_screen.rc(), true); + + default: return false; + } + return false; + } + + bool _handle_esc_seq_3() + { + + /* + * All three-element sequences have the form \E[ + */ + if ((_escape_stack[0].value != '[') + || (_escape_stack[1].type != Escape_stack::Entry::NUMBER)) return false; - } - bool _handle_esc_seq_3() - { + int const p1 = _escape_stack[1].value; + char const command = _escape_stack[2].value; + + switch (command) { + case 'm': + if (p1 < 30) + return (_screen.sgr(p1), true); + + /* p1 starting with digit '3' -> set foreground color */ + if (starts_with_digit(3, p1)) + return (_screen.setaf(remove_first_digit(p1)), true); + + /* p1 starting with digit '4' -> set background color */ + if (starts_with_digit(4, p1)) + return (_screen.setab(remove_first_digit(p1)), true); + + case 'D': return (_screen.cub(p1), true); + case 'd': return (_screen.vpa(p1), true); + case 'g': return (p1 == 3) && (_screen.tbc(), true); + case 'G': return (_screen.hpa(p1), true); + case 'h': return (p1 == 4) && (_screen.smir(), true); + case 'K': return ((p1 == 0) && (_screen.el(), true)) + || ((p1 == 1) && (_screen.el1(), true)); + case 'l': return (p1 == 4) && (_screen.rmir(), true); + case 'L': return (_screen.il(p1), true); + case 'M': return (_screen.dl(p1), true); + case 'n': return (p1 == 6) && (_screen.u7(), true); + case 'P': return (_screen.dch(p1), true); + case '@': return (_screen.ich(p1), true); + case 'X': return (_screen.ech(p1), true); + case 'C': return (_screen.cuf(p1), true); + + default: return false; + } + } + + bool _handle_esc_seq_4() + { + /* + * All four-element escape sequences have the form + * \E[? + */ + if ((_escape_stack[0].value != '[') + || (_escape_stack[1].value != '?') + || (_escape_stack[2].type != Escape_stack::Entry::NUMBER)) + return false; + + int const p1 = _escape_stack[2].value; + char const command = _escape_stack[3].value; + + switch (command) { + case 'l': + if (p1 == 7) return (_screen.rmam(), true); + if (p1 == 25) return (_screen.civis(), true); + return false; + case 'h': + if (p1 == 7) return (_screen.smam(), true); + if (p1 == 25) return (_screen.cnorm(), true); + return false; + case 'c': + if (p1 == 0) return true; /* appended to cnorm */ + if (p1 == 1) return true; /* appended to civis */ + if (p1 == 6) return (_screen.u8(), true); + if (p1 == 8) return (_screen.cvvis(), true); + return false; + default: return false; + } + } + + bool _handle_esc_seq_5() + { + /* + * All five-element escape sequences have the form + * \E[; + */ + if ((_escape_stack[0].value != '[') + || (_escape_stack[1].type != Escape_stack::Entry::NUMBER) + || (_escape_stack[2].value != ';') + || (_escape_stack[3].type != Escape_stack::Entry::NUMBER)) + return false; + + int const p[2] = { _escape_stack[1].value, + _escape_stack[3].value }; + int const command = _escape_stack[4].value; + + switch (command) { + case 'r': return (_screen.csr(p[0], p[1]), true); + case 'H': return (_screen.cup(p[0], p[1]), true); + case 'm': { + bool result = false; + + for (int i = 0; i < 2; i++) { + + if (p[i] == 0) { + /* turn off all attributes */ + _screen.sgr0(); + result = true; + + } else if (p[i] == 1) { + /* + * attribute + * 1 bold (turn into highlight) + */ + _screen.sgr(p[i]); + result = true; + + } else if ((p[i] >= 30) && (p[i] <= 37)) { + /* + * color + * 30...37 text colors + * 40...47 background colors + */ + _screen.setaf(p[i] - 30); + return true; + + } else if ((p[i] == 39) && (p[!i] == 49)) + return (_screen.op(), true); + + } + return result; + } + case 'R': return (_screen.u6(p[0], p[1]), true); + default: return false; + } + } + + bool _handle_esc_seq_7() + { + /* + * All six-element escape sequences have the form + * \E[;; + */ + + if ((_escape_stack[0].value != '[') + || (_escape_stack[1].type != Escape_stack::Entry::NUMBER) + || (_escape_stack[2].value != ';') + || (_escape_stack[3].type != Escape_stack::Entry::NUMBER) + || (_escape_stack[4].value != ';') + || (_escape_stack[5].type != Escape_stack::Entry::NUMBER)) + return false; + + int const p1 = _escape_stack[1].value; + int const p2 = _escape_stack[2].value; + int const p3 = _escape_stack[3].value; + int const command = _escape_stack[6].value; + + switch (command) { + case 'm': /* - * All three-element sequences have the form \E[ + * Currently returning true w/o actually handling the + * sequence */ - if ((_escape_stack[0].value != '[') - || (_escape_stack[1].type != Escape_stack::Entry::NUMBER)) - return false; - - int const p1 = _escape_stack[1].value; - char const command = _escape_stack[2].value; - - switch (command) { - case 'm': - if (p1 < 30) - return (_screen.sgr(p1), true); - - /* p1 starting with digit '3' -> set foreground color */ - if (starts_with_digit(3, p1)) - return (_screen.setaf(remove_first_digit(p1)), true); - - /* p1 starting with digit '4' -> set background color */ - if (starts_with_digit(4, p1)) - return (_screen.setab(remove_first_digit(p1)), true); - - case 'D': return (_screen.cub(p1), true); - case 'd': return (_screen.vpa(p1), true); - case 'g': return (p1 == 3) && (_screen.tbc(), true); - case 'G': return (_screen.hpa(p1), true); - case 'h': return (p1 == 4) && (_screen.smir(), true); - case 'K': return ((p1 == 0) && (_screen.el(), true)) - || ((p1 == 1) && (_screen.el1(), true)); - case 'l': return (p1 == 4) && (_screen.rmir(), true); - case 'L': return (_screen.il(p1), true); - case 'M': return (_screen.dl(p1), true); - case 'n': return (p1 == 6) && (_screen.u7(), true); - case 'P': return (_screen.dch(p1), true); - case '@': return (_screen.ich(p1), true); - case 'X': return (_screen.ech(p1), true); - case 'C': return (_screen.cuf(p1), true); - - default: return false; - } - } - - bool _handle_esc_seq_4() - { - /* - * All four-element escape sequences have the form - * \E[? - */ - if ((_escape_stack[0].value != '[') - || (_escape_stack[1].value != '?') - || (_escape_stack[2].type != Escape_stack::Entry::NUMBER)) - return false; - - int const p1 = _escape_stack[2].value; - char const command = _escape_stack[3].value; - - switch (command) { - case 'l': - if (p1 == 7) return (_screen.rmam(), true); - if (p1 == 25) return (_screen.civis(), true); - return false; - case 'h': - if (p1 == 7) return (_screen.smam(), true); - if (p1 == 25) return (_screen.cnorm(), true); - return false; - case 'c': - if (p1 == 0) return true; /* appended to cnorm */ - if (p1 == 1) return true; /* appended to civis */ - if (p1 == 6) return (_screen.u8(), true); - if (p1 == 8) return (_screen.cvvis(), true); - return false; - default: return false; - } - } - - bool _handle_esc_seq_5() - { - /* - * All five-element escape sequences have the form - * \E[; - */ - if ((_escape_stack[0].value != '[') - || (_escape_stack[1].type != Escape_stack::Entry::NUMBER) - || (_escape_stack[2].value != ';') - || (_escape_stack[3].type != Escape_stack::Entry::NUMBER)) - return false; - - int const p[2] = { _escape_stack[1].value, - _escape_stack[3].value }; - int const command = _escape_stack[4].value; - - switch (command) { - case 'r': return (_screen.csr(p[0], p[1]), true); - case 'H': return (_screen.cup(p[0], p[1]), true); - case 'm': { - bool result = false; - - for (int i = 0; i < 2; i++) { - - if (p[i] == 0) { - /* turn off all attributes */ - _screen.sgr0(); - result = true; - - } else if (p[i] == 1) { - /* - * attribute - * 1 bold (turn into highlight) - */ - _screen.sgr(p[i]); - result = true; - - } else if ((p[i] >= 30) && (p[i] <= 37)) { - /* - * color - * 30...37 text colors - * 40...47 background colors - */ - _screen.setaf(p[i] - 30); - return true; - - } else if ((p[i] == 39) && (p[!i] == 49)) - return (_screen.op(), true); - - } - return result; - } - case 'R': return (_screen.u6(p[0], p[1]), true); - default: return false; - } - } - - bool _handle_esc_seq_7() - { - /* - * All six-element escape sequences have the form - * \E[;; - */ - - if ((_escape_stack[0].value != '[') - || (_escape_stack[1].type != Escape_stack::Entry::NUMBER) - || (_escape_stack[2].value != ';') - || (_escape_stack[3].type != Escape_stack::Entry::NUMBER) - || (_escape_stack[4].value != ';') - || (_escape_stack[5].type != Escape_stack::Entry::NUMBER)) - return false; - - int const p1 = _escape_stack[1].value; - int const p2 = _escape_stack[2].value; - int const p3 = _escape_stack[3].value; - int const command = _escape_stack[6].value; - - switch (command) { - case 'm': - - /* - * Currently returning true w/o actually handling the - * sequence - */ - PDBG("Sequence '[%d;%d;%d%c' is not implemented", p1, p2, p3, command); - return true; - default: return false; - } - + PDBG("Sequence '[%d;%d;%d%c' is not implemented", p1, p2, p3, command); return true; + default: return false; } - public: + return true; + } - Decoder(Character_screen &screen) - : _state(STATE_IDLE), _screen(screen), _number(0) { } + public: - void insert(unsigned char c) - { - switch (_state) { + Decoder(Character_screen &screen) + : _state(STATE_IDLE), _screen(screen), _number(0) { } - case STATE_IDLE: + void insert(unsigned char c) + { + switch (_state) { - enum { ESC_PREFIX = 0x1b }; - if (c == ESC_PREFIX) { - _enter_state_esc_seq(); - break; - } - - /* handle special characters */ - - /* handle normal characters */ - _screen.output(c); + case STATE_IDLE: + enum { ESC_PREFIX = 0x1b }; + if (c == ESC_PREFIX) { + _enter_state_esc_seq(); break; + } - case STATE_ESC_SEQ: + /* handle special characters */ - /* - * We received the prefix character of an escape sequence, - * collect the escape-sequence elements until we detect the - * completion of the sequence. - */ + /* handle normal characters */ + _screen.output(c); - /* check for start of a number argument */ - if (is_digit(c) && !_number) - { - _enter_state_esc_number(); - _append_to_number(c); - break; - } + break; - /* non-number character of escape sequence */ - _escape_stack.push(Escape_stack::Code_entry(c)); + case STATE_ESC_SEQ: + + /* + * We received the prefix character of an escape sequence, + * collect the escape-sequence elements until we detect the + * completion of the sequence. + */ + + /* check for start of a number argument */ + if (is_digit(c) && !_number) + { + _enter_state_esc_number(); + _append_to_number(c); break; + } - case STATE_ESC_NUMBER: + /* non-number character of escape sequence */ + _escape_stack.push(Escape_stack::Code_entry(c)); + break; - /* - * We got the first character belonging to a number - * argument of an escape sequence. Keep reading digits. - */ - if (is_digit(c)) { - _append_to_number(c); - break; - } - - /* - * End of number is reached. - */ - - /* push the complete number to the escape stack */ - _escape_stack.push(Escape_stack::Number_entry(_number)); - _number = 0; - - /* push non-number character as commend entry */ - _escape_stack.push(Escape_stack::Code_entry(c)); + case STATE_ESC_NUMBER: + /* + * We got the first character belonging to a number + * argument of an escape sequence. Keep reading digits. + */ + if (is_digit(c)) { + _append_to_number(c); break; } /* - * Check for the completeness of an escape sequence. + * End of number is reached. */ - if (((_escape_stack.num_elem() == 1) && _handle_esc_seq_1()) - || ((_escape_stack.num_elem() == 2) && _handle_esc_seq_2()) - || ((_escape_stack.num_elem() == 3) && _handle_esc_seq_3()) - || ((_escape_stack.num_elem() == 4) && _handle_esc_seq_4()) - || ((_escape_stack.num_elem() == 5) && _handle_esc_seq_5()) - || ((_escape_stack.num_elem() == 7) && _handle_esc_seq_7())) - _enter_state_idle(); - }; - }; -} + + /* push the complete number to the escape stack */ + _escape_stack.push(Escape_stack::Number_entry(_number)); + _number = 0; + + /* push non-number character as commend entry */ + _escape_stack.push(Escape_stack::Code_entry(c)); + + break; + } + + /* + * Check for the completeness of an escape sequence. + */ + if (((_escape_stack.num_elem() == 1) && _handle_esc_seq_1()) + || ((_escape_stack.num_elem() == 2) && _handle_esc_seq_2()) + || ((_escape_stack.num_elem() == 3) && _handle_esc_seq_3()) + || ((_escape_stack.num_elem() == 4) && _handle_esc_seq_4()) + || ((_escape_stack.num_elem() == 5) && _handle_esc_seq_5()) + || ((_escape_stack.num_elem() == 7) && _handle_esc_seq_7())) + _enter_state_idle(); + }; +}; #endif /* _TERMINAL__DECODER_H_ */ diff --git a/repos/os/include/terminal/types.h b/repos/os/include/terminal/types.h index 29ff52816..0f4ef642d 100644 --- a/repos/os/include/terminal/types.h +++ b/repos/os/include/terminal/types.h @@ -16,112 +16,120 @@ namespace Terminal { - /* - * The character definition is wrapped in a compound data structure to make - * the implementation easily changeable to unicode later. - */ - struct Character - { - unsigned char c; - - Character() : c(0) { } - Character(unsigned char c) : c(c) { } - - bool is_valid() const { return c != 0; } - - unsigned char ascii() const { return c; } - }; - - - struct Boundary - { - int const width, height; - Boundary(int width, int height) : width(width), height(height) { } - }; - - - struct Offset - { - int const x, y; - - Offset(int x, int y) : x(x), y(y) { } - }; - - - struct Position - { - int x, y; - - Position() : x(0), y(0) { } - Position(int x, int y) : x(x), y(y) { } - - Position operator + (Offset const &offset) { - return Position(x + offset.x, y + offset.y); } - - bool operator == (Position const &pos) const { - return (pos.x == x) && (pos.y == y); } - - bool operator != (Position const &pos) const { - return (pos.x != x) || (pos.y != y); } - - /** - * Return true if position lies within the specified boundaries - */ - bool lies_within(Boundary const &boundary) const - { - return x >= 0 && x < boundary.width - && y >= 0 && y < boundary.height; - } - }; - - - struct Character_array - { - /** - * Assign character to specified position - */ - virtual void set(Position const &pos, Character c) = 0; - - /** - * Request character at specified position - */ - virtual Character get(Position const &pos) const = 0; - - /** - * Return array boundary - */ - virtual Boundary boundary() const = 0; - }; - - - template - class Static_character_array : public Character_array - { - private: - - Character _array[HEIGHT][WIDTH]; - Boundary const _boundary; - - public: - - Static_character_array() : _boundary(WIDTH, HEIGHT) { } - - void set(Position const &pos, Character c) - { - if (pos.lies_within(_boundary)) - _array[pos.y][pos.x] = c; - } - - Character get(Position const &pos) const - { - if (pos.lies_within(_boundary)) - return _array[pos.y][pos.x]; - else - return Character(); - } - - Boundary boundary() const { return _boundary; } - }; + struct Character; + struct Boundary; + struct Offset; + struct Position; + struct Character_array; + template class Static_character_array; } + +/* + * The character definition is wrapped in a compound data structure to make + * the implementation easily changeable to unicode later. + */ +struct Terminal::Character +{ + unsigned char c; + + Character() : c(0) { } + Character(unsigned char c) : c(c) { } + + bool is_valid() const { return c != 0; } + + unsigned char ascii() const { return c; } +}; + + +struct Terminal::Boundary +{ + int const width, height; + Boundary(int width, int height) : width(width), height(height) { } +}; + + +struct Terminal::Offset +{ + int const x, y; + + Offset(int x, int y) : x(x), y(y) { } +}; + + +struct Terminal::Position +{ + int x, y; + + Position() : x(0), y(0) { } + Position(int x, int y) : x(x), y(y) { } + + Position operator + (Offset const &offset) { + return Position(x + offset.x, y + offset.y); } + + bool operator == (Position const &pos) const { + return (pos.x == x) && (pos.y == y); } + + bool operator != (Position const &pos) const { + return (pos.x != x) || (pos.y != y); } + + /** + * Return true if position lies within the specified boundaries + */ + bool lies_within(Boundary const &boundary) const + { + return x >= 0 && x < boundary.width + && y >= 0 && y < boundary.height; + } +}; + + +struct Terminal::Character_array +{ + /** + * Assign character to specified position + */ + virtual void set(Position const &pos, Character c) = 0; + + /** + * Request character at specified position + */ + virtual Character get(Position const &pos) const = 0; + + /** + * Return array boundary + */ + virtual Boundary boundary() const = 0; +}; + + +template +class Terminal::Static_character_array : public Character_array +{ + private: + + Character _array[HEIGHT][WIDTH]; + Boundary const _boundary; + + public: + + Static_character_array() : _boundary(WIDTH, HEIGHT) { } + + void set(Position const &pos, Character c) + { + if (pos.lies_within(_boundary)) + _array[pos.y][pos.x] = c; + } + + Character get(Position const &pos) const + { + if (pos.lies_within(_boundary)) + return _array[pos.y][pos.x]; + else + return Character(); + } + + Boundary boundary() const { return _boundary; } +}; + #endif /* _TERMINAL__TYPES_H_ */ diff --git a/repos/os/include/terminal_session/connection.h b/repos/os/include/terminal_session/connection.h index 727d33695..037236240 100644 --- a/repos/os/include/terminal_session/connection.h +++ b/repos/os/include/terminal_session/connection.h @@ -17,39 +17,39 @@ #include #include -namespace Terminal { +namespace Terminal { struct Connection; } - struct Connection : Genode::Connection, Session_client + +struct Terminal::Connection : Genode::Connection, Session_client +{ + /** + * Wait for connection-established signal + */ + static void wait_for_connection(Genode::Capability cap) { - /** - * Wait for connection-established signal - */ - static void wait_for_connection(Genode::Capability cap) - { - using namespace Genode; + using namespace Genode; - /* create signal receiver, just for the single signal */ - Signal_context sig_ctx; - Signal_receiver sig_rec; - Signal_context_capability sig_cap = sig_rec.manage(&sig_ctx); + /* create signal receiver, just for the single signal */ + Signal_context sig_ctx; + Signal_receiver sig_rec; + Signal_context_capability sig_cap = sig_rec.manage(&sig_ctx); - /* register signal handler */ - cap.call(sig_cap); + /* register signal handler */ + cap.call(sig_cap); - /* wati for signal */ - sig_rec.wait_for_signal(); - sig_rec.dissolve(&sig_ctx); - } + /* wati for signal */ + sig_rec.wait_for_signal(); + sig_rec.dissolve(&sig_ctx); + } - Connection(char const *label = "") - : - Genode::Connection(session("ram_quota=%zd, label=\"%s\"", - 2*4096, label)), - Session_client(cap()) - { - wait_for_connection(cap()); - } - }; -} + Connection(char const *label = "") + : + Genode::Connection(session("ram_quota=%zd, label=\"%s\"", + 2*4096, label)), + Session_client(cap()) + { + wait_for_connection(cap()); + } +}; #endif /* _INCLUDE__TERMINAL_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/terminal_session/terminal_session.h b/repos/os/include/terminal_session/terminal_session.h index 8e04dd5fa..cf20b8b82 100644 --- a/repos/os/include/terminal_session/terminal_session.h +++ b/repos/os/include/terminal_session/terminal_session.h @@ -19,86 +19,86 @@ #include #include -namespace Terminal { +namespace Terminal { struct Session; } - struct Session : Genode::Session + +struct Terminal::Session : Genode::Session +{ + static const char *service_name() { return "Terminal"; } + + class Size { - static const char *service_name() { return "Terminal"; } + private: - class Size - { - private: + unsigned _columns, _lines; - unsigned _columns, _lines; + public: - public: + Size() : _columns(0), _lines(0) { } - Size() : _columns(0), _lines(0) { } + Size(unsigned columns, unsigned lines) + : _columns(columns), _lines(lines) { } - Size(unsigned columns, unsigned lines) - : _columns(columns), _lines(lines) { } - - unsigned columns() const { return _columns; } - unsigned lines() const { return _lines; } - }; - - /** - * Return terminal size - */ - virtual Size size() = 0; - - /** - * Return true of one or more characters are available for reading - */ - virtual bool avail() = 0; - - /** - * Read characters from terminal - */ - virtual Genode::size_t read(void *buf, Genode::size_t buf_size) = 0; - - /** - * Write characters to terminal - */ - virtual Genode::size_t write(void const *buf, Genode::size_t num_bytes) = 0; - - /** - * Register signal handler to be informed about the established connection - * - * This function is used for a simple startup protocol of terminal - * sessions. At session-creation time, the terminal session may not - * be ready to use. For example, a TCP terminal session needs an - * established TCP connection first. However, we do not want to let the - * session-creation block on the server side because this would render - * the servers entrypoint unavailable for all other clients until the - * TCP connection is ready. Instead, we deliver a 'connected' signal - * to the client emitted when the session becomes ready to use. The - * Terminal::Connection waits for this signal at construction time. - */ - virtual void connected_sigh(Genode::Signal_context_capability cap) = 0; - - /** - * Register signal handler to be informed about ready-to-read characters - */ - virtual void read_avail_sigh(Genode::Signal_context_capability cap) = 0; - - - /******************* - ** RPC interface ** - *******************/ - - GENODE_RPC(Rpc_size, Size, size); - GENODE_RPC(Rpc_avail, bool, avail); - GENODE_RPC(Rpc_read, Genode::size_t, _read, Genode::size_t); - GENODE_RPC(Rpc_write, void, _write, Genode::size_t); - GENODE_RPC(Rpc_connected_sigh, void, connected_sigh, Genode::Signal_context_capability); - GENODE_RPC(Rpc_read_avail_sigh, void, read_avail_sigh, Genode::Signal_context_capability); - GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, _dataspace); - - GENODE_RPC_INTERFACE(Rpc_size, Rpc_avail, Rpc_read, Rpc_write, - Rpc_connected_sigh, Rpc_read_avail_sigh, - Rpc_dataspace); + unsigned columns() const { return _columns; } + unsigned lines() const { return _lines; } }; -} + + /** + * Return terminal size + */ + virtual Size size() = 0; + + /** + * Return true of one or more characters are available for reading + */ + virtual bool avail() = 0; + + /** + * Read characters from terminal + */ + virtual Genode::size_t read(void *buf, Genode::size_t buf_size) = 0; + + /** + * Write characters to terminal + */ + virtual Genode::size_t write(void const *buf, Genode::size_t num_bytes) = 0; + + /** + * Register signal handler to be informed about the established connection + * + * This function is used for a simple startup protocol of terminal + * sessions. At session-creation time, the terminal session may not + * be ready to use. For example, a TCP terminal session needs an + * established TCP connection first. However, we do not want to let the + * session-creation block on the server side because this would render + * the servers entrypoint unavailable for all other clients until the + * TCP connection is ready. Instead, we deliver a 'connected' signal + * to the client emitted when the session becomes ready to use. The + * Terminal::Connection waits for this signal at construction time. + */ + virtual void connected_sigh(Genode::Signal_context_capability cap) = 0; + + /** + * Register signal handler to be informed about ready-to-read characters + */ + virtual void read_avail_sigh(Genode::Signal_context_capability cap) = 0; + + + /******************* + ** RPC interface ** + *******************/ + + GENODE_RPC(Rpc_size, Size, size); + GENODE_RPC(Rpc_avail, bool, avail); + GENODE_RPC(Rpc_read, Genode::size_t, _read, Genode::size_t); + GENODE_RPC(Rpc_write, void, _write, Genode::size_t); + GENODE_RPC(Rpc_connected_sigh, void, connected_sigh, Genode::Signal_context_capability); + GENODE_RPC(Rpc_read_avail_sigh, void, read_avail_sigh, Genode::Signal_context_capability); + GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, _dataspace); + + GENODE_RPC_INTERFACE(Rpc_size, Rpc_avail, Rpc_read, Rpc_write, + Rpc_connected_sigh, Rpc_read_avail_sigh, + Rpc_dataspace); +}; #endif /* _INCLUDE__TERMINAL_SESSION__TERMINAL_SESSION_H_ */ diff --git a/repos/os/include/timer_session/client.h b/repos/os/include/timer_session/client.h index 2e80c96ff..3dc00f59c 100644 --- a/repos/os/include/timer_session/client.h +++ b/repos/os/include/timer_session/client.h @@ -19,21 +19,21 @@ #include #include -namespace Timer { +namespace Timer { struct Session_client; } - struct Session_client : Genode::Rpc_client - { - explicit Session_client(Session_capability session) - : Genode::Rpc_client(session) { } - void trigger_once(unsigned us) { call(us); } +struct Timer::Session_client : Genode::Rpc_client +{ + explicit Session_client(Session_capability session) + : Genode::Rpc_client(session) { } - void trigger_periodic(unsigned us) { call(us); } + void trigger_once(unsigned us) override { call(us); } - void sigh(Signal_context_capability sigh) { call(sigh); } + void trigger_periodic(unsigned us) override { call(us); } - unsigned long elapsed_ms() const { return call(); } - }; -} + void sigh(Signal_context_capability sigh) override { call(sigh); } + + unsigned long elapsed_ms() const override { return call(); } +}; #endif /* _INCLUDE__TIMER_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/timer_session/connection.h b/repos/os/include/timer_session/connection.h index 52888a8f5..2f63881f3 100644 --- a/repos/os/include/timer_session/connection.h +++ b/repos/os/include/timer_session/connection.h @@ -17,64 +17,64 @@ #include #include -namespace Timer { +namespace Timer { class Connection; } - class Connection : public Genode::Connection, public Session_client - { - private: - Lock _lock; - Signal_receiver _sig_rec; - Signal_context _default_sigh_ctx; - Signal_context_capability _default_sigh_cap; - Signal_context_capability _custom_sigh_cap; +class Timer::Connection : public Genode::Connection, public Session_client +{ + private: - public: + Genode::Lock _lock; + Genode::Signal_receiver _sig_rec; + Genode::Signal_context _default_sigh_ctx; + Genode::Signal_context_capability _default_sigh_cap; + Genode::Signal_context_capability _custom_sigh_cap; - Connection() - : - Genode::Connection(session("ram_quota=8K")), - Session_client(cap()), - _default_sigh_cap(_sig_rec.manage(&_default_sigh_ctx)) - { - /* register default signal handler */ + public: + + Connection() + : + Genode::Connection(session("ram_quota=8K")), + Session_client(cap()), + _default_sigh_cap(_sig_rec.manage(&_default_sigh_ctx)) + { + /* register default signal handler */ + Session_client::sigh(_default_sigh_cap); + } + + ~Connection() { _sig_rec.dissolve(&_default_sigh_ctx); } + + /* + * Intercept 'sigh' to keep track of customized signal handlers + */ + void sigh(Signal_context_capability sigh) + { + _custom_sigh_cap = sigh; + Session_client::sigh(_custom_sigh_cap); + } + + void usleep(unsigned us) + { + /* serialize sleep calls issued by different threads */ + Genode::Lock::Guard guard(_lock); + + /* temporarily install to the default signal handler */ + if (_custom_sigh_cap.valid()) Session_client::sigh(_default_sigh_cap); - } - ~Connection() { _sig_rec.dissolve(&_default_sigh_ctx); } + /* trigger timeout at default signal handler */ + trigger_once(us); + _sig_rec.wait_for_signal(); - /* - * Intercept 'sigh' to keep track of customized signal handlers - */ - void sigh(Signal_context_capability sigh) - { - _custom_sigh_cap = sigh; + /* revert custom signal handler if registered */ + if (_custom_sigh_cap.valid()) Session_client::sigh(_custom_sigh_cap); - } + } - void usleep(unsigned us) - { - /* serialize sleep calls issued by different threads */ - Lock::Guard guard(_lock); - - /* temporarily install to the default signal handler */ - if (_custom_sigh_cap.valid()) - Session_client::sigh(_default_sigh_cap); - - /* trigger timeout at default signal handler */ - trigger_once(us); - _sig_rec.wait_for_signal(); - - /* revert custom signal handler if registered */ - if (_custom_sigh_cap.valid()) - Session_client::sigh(_custom_sigh_cap); - } - - void msleep(unsigned ms) - { - usleep(1000*ms); - } - }; -} + void msleep(unsigned ms) + { + usleep(1000*ms); + } +}; #endif /* _INCLUDE__TIMER_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/timer_session/timer_session.h b/repos/os/include/timer_session/timer_session.h index 1a396d057..0ef913153 100644 --- a/repos/os/include/timer_session/timer_session.h +++ b/repos/os/include/timer_session/timer_session.h @@ -19,64 +19,64 @@ #include #include -namespace Timer { - - using namespace Genode; - - struct Session : Genode::Session - { - static const char *service_name() { return "Timer"; } - - virtual ~Session() { } - - /** - * Program single timeout (relative from now in microseconds) - */ - virtual void trigger_once(unsigned us) = 0; - - /** - * Program periodic timeout (in microseconds) - * - * The first period will be triggered after 'us' at the latest, - * but it might be triggered earlier as well. - */ - virtual void trigger_periodic(unsigned us) = 0; - - /** - * Register timeout signal handler - */ - virtual void sigh(Signal_context_capability sigh) = 0; - - /** - * Return number of elapsed milliseconds since session creation - */ - virtual unsigned long elapsed_ms() const = 0; - - /** - * Client-side convenience function for sleeping the specified number - * of milliseconds - */ - virtual void msleep(unsigned ms) = 0; - - /** - * Client-side convenience function for sleeping the specified number - * of microseconds - */ - virtual void usleep(unsigned us) = 0; +namespace Timer { struct Session; } - /********************* - ** RPC declaration ** - *********************/ +struct Timer::Session : Genode::Session +{ + typedef Genode::Signal_context_capability Signal_context_capability; - GENODE_RPC(Rpc_trigger_once, void, trigger_once, unsigned); - GENODE_RPC(Rpc_trigger_periodic, void, trigger_periodic, unsigned); - GENODE_RPC(Rpc_sigh, void, sigh, Genode::Signal_context_capability); - GENODE_RPC(Rpc_elapsed_ms, unsigned long, elapsed_ms); + static const char *service_name() { return "Timer"; } - GENODE_RPC_INTERFACE(Rpc_trigger_once, Rpc_trigger_periodic, - Rpc_sigh, Rpc_elapsed_ms); - }; -} + virtual ~Session() { } + + /** + * Program single timeout (relative from now in microseconds) + */ + virtual void trigger_once(unsigned us) = 0; + + /** + * Program periodic timeout (in microseconds) + * + * The first period will be triggered after 'us' at the latest, + * but it might be triggered earlier as well. + */ + virtual void trigger_periodic(unsigned us) = 0; + + /** + * Register timeout signal handler + */ + virtual void sigh(Genode::Signal_context_capability sigh) = 0; + + /** + * Return number of elapsed milliseconds since session creation + */ + virtual unsigned long elapsed_ms() const = 0; + + /** + * Client-side convenience function for sleeping the specified number + * of milliseconds + */ + virtual void msleep(unsigned ms) = 0; + + /** + * Client-side convenience function for sleeping the specified number + * of microseconds + */ + virtual void usleep(unsigned us) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_trigger_once, void, trigger_once, unsigned); + GENODE_RPC(Rpc_trigger_periodic, void, trigger_periodic, unsigned); + GENODE_RPC(Rpc_sigh, void, sigh, Genode::Signal_context_capability); + GENODE_RPC(Rpc_elapsed_ms, unsigned long, elapsed_ms); + + GENODE_RPC_INTERFACE(Rpc_trigger_once, Rpc_trigger_periodic, + Rpc_sigh, Rpc_elapsed_ms); +}; #endif /* _INCLUDE__TIMER_SESSION__TIMER_SESSION_H_ */ diff --git a/repos/os/include/uart_session/client.h b/repos/os/include/uart_session/client.h index 6b786ddad..1a41f3ccf 100644 --- a/repos/os/include/uart_session/client.h +++ b/repos/os/include/uart_session/client.h @@ -18,65 +18,65 @@ #include #include -namespace Uart { - - class Session_client : public Genode::Rpc_client - { - private: - - Terminal::Session_client _terminal; - - public: - - Session_client(Genode::Capability cap) - : - Genode::Rpc_client(cap), _terminal(cap) - { } +namespace Uart { class Session_client; } - /******************** - ** UART interface ** - ********************/ +class Uart::Session_client : public Genode::Rpc_client +{ + private: - void baud_rate(Genode::size_t bits_per_second) - { - call(bits_per_second); - } + Terminal::Session_client _terminal; + + public: + + Session_client(Genode::Capability cap) + : + Genode::Rpc_client(cap), _terminal(cap) + { } - /************************ - ** Terminal interface ** - ************************/ + /******************** + ** UART interface ** + ********************/ - Size size() { return _terminal.size(); } + void baud_rate(Genode::size_t bits_per_second) + { + call(bits_per_second); + } - bool avail() { return _terminal.avail(); } - Genode::size_t read(void *buf, Genode::size_t buf_size) - { - return _terminal.read(buf, buf_size); - } + /************************ + ** Terminal interface ** + ************************/ - Genode::size_t write(void const *buf, Genode::size_t num_bytes) - { - return _terminal.write(buf, num_bytes); - } + Size size() { return _terminal.size(); } - void connected_sigh(Genode::Signal_context_capability cap) - { - _terminal.connected_sigh(cap); - } + bool avail() { return _terminal.avail(); } - void read_avail_sigh(Genode::Signal_context_capability cap) - { - _terminal.read_avail_sigh(cap); - } + Genode::size_t read(void *buf, Genode::size_t buf_size) + { + return _terminal.read(buf, buf_size); + } - Genode::size_t io_buffer_size() const - { - return _terminal.io_buffer_size(); - } - }; -} + Genode::size_t write(void const *buf, Genode::size_t num_bytes) + { + return _terminal.write(buf, num_bytes); + } + + void connected_sigh(Genode::Signal_context_capability cap) + { + _terminal.connected_sigh(cap); + } + + void read_avail_sigh(Genode::Signal_context_capability cap) + { + _terminal.read_avail_sigh(cap); + } + + Genode::size_t io_buffer_size() const + { + return _terminal.io_buffer_size(); + } +}; #endif /* _INCLUDE__UART_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/uart_session/connection.h b/repos/os/include/uart_session/connection.h index 02fe59eb2..5ddb8207a 100644 --- a/repos/os/include/uart_session/connection.h +++ b/repos/os/include/uart_session/connection.h @@ -17,18 +17,18 @@ #include #include -namespace Uart { +namespace Uart { struct Connection; } - struct Connection : Genode::Connection, Session_client + +struct Uart::Connection : Genode::Connection, Session_client +{ + Connection() + : + Genode::Connection(session("ram_quota=%zd", 2*4096)), + Session_client(cap()) { - Connection() - : - Genode::Connection(session("ram_quota=%zd", 2*4096)), - Session_client(cap()) - { - Terminal::Connection::wait_for_connection(cap()); - } - }; -} + Terminal::Connection::wait_for_connection(cap()); + } +}; #endif /* _INCLUDE__UART_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/uart_session/uart_session.h b/repos/os/include/uart_session/uart_session.h index 7420fae4e..6f0bde183 100644 --- a/repos/os/include/uart_session/uart_session.h +++ b/repos/os/include/uart_session/uart_session.h @@ -23,23 +23,26 @@ namespace Uart { using namespace Terminal; - struct Session : Terminal::Session - { - static const char *service_name() { return "Uart"; } - - /** - * Set baud rate - */ - virtual void baud_rate(Genode::size_t bits_per_second) = 0; - - - /******************* - ** RPC interface ** - *******************/ - - GENODE_RPC(Rpc_baud_rate, void, baud_rate, Genode::size_t); - GENODE_RPC_INTERFACE_INHERIT(Terminal::Session, Rpc_baud_rate); - }; + struct Session; } + +struct Uart::Session : Terminal::Session +{ + static const char *service_name() { return "Uart"; } + + /** + * Set baud rate + */ + virtual void baud_rate(Genode::size_t bits_per_second) = 0; + + + /******************* + ** RPC interface ** + *******************/ + + GENODE_RPC(Rpc_baud_rate, void, baud_rate, Genode::size_t); + GENODE_RPC_INTERFACE_INHERIT(Terminal::Session, Rpc_baud_rate); +}; + #endif /* _INCLUDE__UART_SESSION__UART_SESSION_H_ */ diff --git a/repos/os/include/usb/packet_handler.h b/repos/os/include/usb/packet_handler.h index e3d719f7e..f739f0886 100644 --- a/repos/os/include/usb/packet_handler.h +++ b/repos/os/include/usb/packet_handler.h @@ -16,9 +16,8 @@ #include #include -namespace Usb { - class Packet_handler; -} +namespace Usb { class Packet_handler; } + class Usb::Packet_handler { diff --git a/repos/os/include/usb_session/client.h b/repos/os/include/usb_session/client.h index 2f919d56a..3126321a6 100644 --- a/repos/os/include/usb_session/client.h +++ b/repos/os/include/usb_session/client.h @@ -24,6 +24,7 @@ namespace Usb { class Interface_client; } + class Usb::Session_client : public Genode::Rpc_client { private: diff --git a/repos/os/include/usb_session/connection.h b/repos/os/include/usb_session/connection.h index fdfbd7117..997695bf7 100644 --- a/repos/os/include/usb_session/connection.h +++ b/repos/os/include/usb_session/connection.h @@ -17,9 +17,8 @@ #include #include -namespace Usb { - struct Connection; -} +namespace Usb { struct Connection; } + struct Usb::Connection : Genode::Connection, Session_client { diff --git a/repos/os/include/usb_session/rpc_object.h b/repos/os/include/usb_session/rpc_object.h index 4ded3151d..cb764d8ac 100644 --- a/repos/os/include/usb_session/rpc_object.h +++ b/repos/os/include/usb_session/rpc_object.h @@ -17,9 +17,8 @@ #include #include -namespace Usb { - class Session_rpc_object; -} +namespace Usb { class Session_rpc_object; } + class Usb::Session_rpc_object : public Genode::Rpc_object { diff --git a/repos/os/include/util/xml_node.h b/repos/os/include/util/xml_node.h index 4449cc522..08d8702be 100644 --- a/repos/os/include/util/xml_node.h +++ b/repos/os/include/util/xml_node.h @@ -17,752 +17,752 @@ #include #include -namespace Genode { +namespace Genode { class Xml_node; } + + +/** + * Representation of an XML node + */ +class Genode::Xml_node +{ + /** + * Scanner policy that accepts hyphens in identifiers + */ + struct Scanner_policy_xml_identifier { + static bool identifier_char(char c, unsigned i) { + return is_letter(c) || c == '_' || c == ':' + || (i && (c == '-' || c == '.' || is_digit(c))); } }; /** - * Representation of an XML node + * Define tokenizer that matches XML tags (with hyphens) as identifiers */ - class Xml_node - { - /** - * Scanner policy that accepts hyphens in identifiers - */ - struct Scanner_policy_xml_identifier { - static bool identifier_char(char c, unsigned i) { - return is_letter(c) || c == '_' || c == ':' - || (i && (c == '-' || c == '.' || is_digit(c))); } }; + typedef ::Genode::Token Token; + + /** + * Forward declaration needed for befriending Tag with Attribut + */ + class Tag; + + public: + + /********************* + ** Exception types ** + *********************/ + + class Exception : public ::Genode::Exception { }; + class Invalid_syntax : public Exception { }; + class Nonexistent_sub_node : public Exception { }; + class Nonexistent_attribute : public Exception { }; + /** - * Define tokenizer that matches XML tags (with hyphens) as identifiers + * Representation of an XML-node attribute + * + * An attribute has the form 'name="value"'. */ - typedef ::Genode::Token Token; + class Attribute + { + private: - /** - * Forward declaration needed for befriending Tag with Attribut - */ - class Tag; + Token _name; + Token _value; - public: + friend class Xml_node; - /********************* - ** Exception types ** - *********************/ + /* + * Even though 'Tag' is part of 'Xml_node', the friendship + * to 'Xml_node' does not apply for 'Tag' when compiling + * the code with 'gcc-3.4'. Hence, we need to add an + * explicit friendship to 'Tag'. + */ + friend class Tag; - class Exception : public ::Genode::Exception { }; - class Invalid_syntax : public Exception { }; - class Nonexistent_sub_node : public Exception { }; - class Nonexistent_attribute : public Exception { }; + /** + * Constructor + * + * This constructor is meant to be used as implicitly to + * construct an 'Xml_attribute' from a token sequence via an + * assignment from the leading 'Token'. + */ + Attribute(Token t) : + _name(t.eat_whitespace()), _value(_name.next().next()) + { + if (_name.type() != Token::IDENT) + throw Nonexistent_attribute(); + if (_name.next()[0] != '=' || _value.type() != Token::STRING) + throw Invalid_syntax(); + } - /** - * Representation of an XML-node attribute - * - * An attribute has the form 'name="value"'. - */ - class Attribute - { - private: + /** + * Return token following the attribute declaration + */ + Token _next() const { return _name.next().next().next(); } - Token _name; - Token _value; + public: - friend class Xml_node; + /** + * Return attribute type as null-terminated string + */ + void type(char *dst, size_t max_len) const + { + /* + * Limit number of characters by token length, take + * null-termination into account. + */ + max_len = min(max_len, _name.len() + 1); + strncpy(dst, _name.start(), max_len); + } + + /** + * Return true if attribute has specified type + */ + bool has_type(const char *type) { + return strlen(type) == _name.len() && + strcmp(type, _name.start(), _name.len()) == 0; } + + /** + * Return size of value + */ + size_t value_size() const { return _value.len() - 2; } + char const *value_base() const { return _value.start() + 1; } + + /** + * Return attribute value as null-terminated string + * + * \return true on success, or + * false if attribute is invalid + */ + bool value(char *dst, size_t max_len) const + { + /* + * The value of 'max_len' denotes the maximum number of + * characters to be written to 'dst' including the null + * termination. From the quoted value string, we strip + * both quote characters and add a null-termination + * character. + */ + max_len = min(max_len, _value.len() - 2 + 1); + strncpy(dst, _value.start() + 1, max_len); + return true; + } + + /** + * Return true if attribute has the specified value + */ + bool has_value(const char *value) const { + return strlen(value) == (_value.len() - 2) && + !strcmp(value, _value.start() + 1, _value.len() - 2); } + + /** + * Return attribute value as typed value + * + * \param T type of value to read + * \return true on success, or + * false if attribute is invalid or value + * conversion failed + */ + template + bool value(T *out) const + { + /* + * The '_value' token starts with a quote, which we + * need to skip to access the string. For validating + * the length, we have to consider both the starting + * and the trailing quote character. + */ + return ascii_to(_value.start() + 1, out) == _value.len() - 2; + } + + /** + * Return next attribute in attribute list + */ + Attribute next() const { return Attribute(_next()); } + }; + + private: + + class Tag + { + public: + + enum Type { START, END, EMPTY, INVALID }; + + private: + + Token _token; + Token _name; + Type _type; + + public: + + /** + * Constructor + * + * \param start first token of the tag + * + * At construction time, the validity of the tag is checked and + * the tag type is determined. A valid tag consists of: + * # Leading '<' tag delimiter + * # '/' for marking an end tag + * # Tag name + * # Optional attribute sequence (if tag is no end tag) + * # '/' for marking an empty-element tag (if tag is no end tag) + * # Closing '>' tag delimiter + */ + Tag(Token start) : _token(start), _type(INVALID) + { + Type supposed_type = START; + + if (_token[0] != '<') + return; + + if (_token.next()[0] == '/') + supposed_type = END; + + if (_token.next().type() != Token::IDENT && _token.next()[0] != '/') + return; + + _name = _token.next()[0] == '/' ? _token.next().next() : _token.next(); + if (_name.type() != Token::IDENT) + return; + + /* skip attributes to find tag delimiter */ + Token delimiter = _name.next(); + if (supposed_type != END) + try { + for (Attribute a = _name.next(); ; a = a._next()) + delimiter = a._next(); + } catch (Nonexistent_attribute) { } + + delimiter = delimiter.eat_whitespace(); /* - * Even though 'Tag' is part of 'Xml_node', the friendship - * to 'Xml_node' does not apply for 'Tag' when compiling - * the code with 'gcc-3.4'. Hence, we need to add an - * explicit friendship to 'Tag'. + * Now we expect the '>' delimiter. For empty-element tags, + * the delimiter is prefixed with a '/'. */ - friend class Tag; + if (delimiter[0] == '/') { - /** - * Constructor - * - * This constructor is meant to be used as implicitly to - * construct an 'Xml_attribute' from a token sequence via an - * assignment from the leading 'Token'. - */ - Attribute(Token t) : - _name(t.eat_whitespace()), _value(_name.next().next()) - { - if (_name.type() != Token::IDENT) - throw Nonexistent_attribute(); - - if (_name.next()[0] != '=' || _value.type() != Token::STRING) - throw Invalid_syntax(); - } - - /** - * Return token following the attribute declaration - */ - Token _next() const { return _name.next().next().next(); } - - public: - - /** - * Return attribute type as null-terminated string - */ - void type(char *dst, size_t max_len) const - { - /* - * Limit number of characters by token length, take - * null-termination into account. - */ - max_len = min(max_len, _name.len() + 1); - strncpy(dst, _name.start(), max_len); - } - - /** - * Return true if attribute has specified type - */ - bool has_type(const char *type) { - return strlen(type) == _name.len() && - strcmp(type, _name.start(), _name.len()) == 0; } - - /** - * Return size of value - */ - size_t value_size() const { return _value.len() - 2; } - char const *value_base() const { return _value.start() + 1; } - - /** - * Return attribute value as null-terminated string - * - * \return true on success, or - * false if attribute is invalid - */ - bool value(char *dst, size_t max_len) const - { - /* - * The value of 'max_len' denotes the maximum number of - * characters to be written to 'dst' including the null - * termination. From the quoted value string, we strip - * both quote characters and add a null-termination - * character. - */ - max_len = min(max_len, _value.len() - 2 + 1); - strncpy(dst, _value.start() + 1, max_len); - return true; - } - - /** - * Return true if attribute has the specified value - */ - bool has_value(const char *value) const { - return strlen(value) == (_value.len() - 2) && - !strcmp(value, _value.start() + 1, _value.len() - 2); } - - /** - * Return attribute value as typed value - * - * \param T type of value to read - * \return true on success, or - * false if attribute is invalid or value - * conversion failed - */ - template - bool value(T *out) const - { - /* - * The '_value' token starts with a quote, which we - * need to skip to access the string. For validating - * the length, we have to consider both the starting - * and the trailing quote character. - */ - return ascii_to(_value.start() + 1, out) == _value.len() - 2; - } - - /** - * Return next attribute in attribute list - */ - Attribute next() const { return Attribute(_next()); } - }; - - private: - - class Tag - { - public: - - enum Type { START, END, EMPTY, INVALID }; - - private: - - Token _token; - Token _name; - Type _type; - - public: - - /** - * Constructor - * - * \param start first token of the tag - * - * At construction time, the validity of the tag is checked and - * the tag type is determined. A valid tag consists of: - * # Leading '<' tag delimiter - * # '/' for marking an end tag - * # Tag name - * # Optional attribute sequence (if tag is no end tag) - * # '/' for marking an empty-element tag (if tag is no end tag) - * # Closing '>' tag delimiter - */ - Tag(Token start) : _token(start), _type(INVALID) - { - Type supposed_type = START; - - if (_token[0] != '<') + /* if a '/' was already at the start, the tag is invalid */ + if (supposed_type == END) return; - if (_token.next()[0] == '/') - supposed_type = END; + supposed_type = EMPTY; - if (_token.next().type() != Token::IDENT && _token.next()[0] != '/') - return; - - _name = _token.next()[0] == '/' ? _token.next().next() : _token.next(); - if (_name.type() != Token::IDENT) - return; - - /* skip attributes to find tag delimiter */ - Token delimiter = _name.next(); - if (supposed_type != END) - try { - for (Attribute a = _name.next(); ; a = a._next()) - delimiter = a._next(); - } catch (Nonexistent_attribute) { } - - delimiter = delimiter.eat_whitespace(); - - /* - * Now we expect the '>' delimiter. For empty-element tags, - * the delimiter is prefixed with a '/'. - */ - if (delimiter[0] == '/') { - - /* if a '/' was already at the start, the tag is invalid */ - if (supposed_type == END) - return; - - supposed_type = EMPTY; - - /* skip '/' */ - delimiter = delimiter.next(); - } - - if (delimiter[0] != '>') return; - - _type = supposed_type; + /* skip '/' */ + delimiter = delimiter.next(); } - /** - * Default constructor produces invalid Tag - */ - Tag() : _type(INVALID) { } + if (delimiter[0] != '>') return; - /** - * Return type of tag - */ - Type type() const { return _type; } + _type = supposed_type; + } - /** - * Return true if tag is the start of a valid XML node - */ - bool is_node() const { return _type == START || _type == EMPTY; } - - /** - * Return first token of tag - */ - Token token() const { return _token; } - - /** - * Return name of tag - */ - Token name() const { return _name; } - - /** - * Return token after the closing tag delimiter - */ - Token next_token() const - { - /* - * Search for next closing delimiter, skip potential - * attributes and '/' delimiter prefix of empty-element - * tags. - */ - Token t = _name; - for (; t && t[0] != '>'; t = t.next()); - - /* if 't' is invalid, 't.next()' is invalid too */ - return t.next(); - } - - /** - * Return first attribute of tag - */ - Attribute attribute() const { return Attribute(_name.next()); } - }; - - class Comment - { - private: - - Token _next; /* token following the comment */ - bool _valid; /* true if comment is well formed */ - - /** - * Check if token sequence matches specified character sequence - * - * \param t start of token sequence - * \param s null-terminated character sequence - */ - static bool _match(Token t, const char *s) - { - for (int i = 0; s[i]; t = t.next(), i++) - if (t[0] != s[i]) - return false; - return true; - } - - public: - - /** - * Constructor - * - * \param start first token of the comment tag - */ - Comment(Token t) : _valid(false) - { - /* check for comment-start tag */ - if (!_match(t, ""); t = t.next()); - - if (t.type() == Token::END) - return; - - _next = t.next().next().next(); - _valid = true; - } - - /** - * Default constructor produces invalid Comment - */ - Comment() : _valid(false) { } - - /** - * Return true if comment is valid - */ - bool valid() const { return _valid; } - - /** - * Return token after the closing comment delimiter - */ - Token next_token() const { return _next; } - }; - - const char *_addr; /* first character of XML data */ - size_t _max_len; /* length of XML data in characters */ - int _num_sub_nodes; /* number of immediate sub nodes */ - Tag _start_tag; - Tag _end_tag; - - /** - * Search for end tag of XML node and initialize '_num_sub_nodes' - * - * \return end tag or invalid tag - * - * The function searches for a end tag that matches the same - * depth level and the same name as the start tag of the XML - * node. If the XML structure is invalid, the search results - * is an invalid Tag. - * - * During the search, the function also counts the number of - * immediate sub nodes. - */ - Tag _init_end_tag() - { - /* - * If the start tag is invalid or an empty-element tag, - * we use the same tag as end tag. + /** + * Default constructor produces invalid Tag */ - if (_start_tag.type() != Tag::START) - return _start_tag; + Tag() : _type(INVALID) { } - int depth = 1; - Token curr_token = _start_tag.next_token(); + /** + * Return type of tag + */ + Type type() const { return _type; } - while (curr_token.type() != Token::END) { + /** + * Return true if tag is the start of a valid XML node + */ + bool is_node() const { return _type == START || _type == EMPTY; } - /* eat XML comment */ - Comment curr_comment(curr_token); - if (curr_comment.valid()) { - curr_token = curr_comment.next_token(); - continue; - } + /** + * Return first token of tag + */ + Token token() const { return _token; } - /* skip all tokens that are no tags */ - Tag curr_tag(curr_token); - if (curr_tag.type() == Tag::INVALID) { - curr_token = curr_token.next(); - continue; - } + /** + * Return name of tag + */ + Token name() const { return _name; } - /* count sub nodes at depth 1 */ - if (depth == 1 && curr_tag.is_node()) - _num_sub_nodes++; + /** + * Return token after the closing tag delimiter + */ + Token next_token() const + { + /* + * Search for next closing delimiter, skip potential + * attributes and '/' delimiter prefix of empty-element + * tags. + */ + Token t = _name; + for (; t && t[0] != '>'; t = t.next()); - /* keep track of the current depth */ - depth += (curr_tag.type() == Tag::START); - depth -= (curr_tag.type() == Tag::END); - - /* within sub nodes, continue after current token */ - if (depth > 0) { - - /* continue search with token after current tag */ - curr_token = curr_tag.next_token(); - continue; - } - - /* reaching the same depth as the start tag */ - const char *start_name = _start_tag.name().start(); - size_t start_len = _start_tag.name().len(); - const char *curr_name = curr_tag.name().start(); - size_t curr_len = curr_tag.name().len(); - - /* on mismatch of start tag and end tag, return invalid tag */ - if (start_len != curr_len - || strcmp(start_name, curr_name, curr_len)) - return Tag(); - - /* end tag corresponds to start tag */ - return curr_tag; + /* if 't' is invalid, 't.next()' is invalid too */ + return t.next(); } - return Tag(); + + /** + * Return first attribute of tag + */ + Attribute attribute() const { return Attribute(_name.next()); } + }; + + class Comment + { + private: + + Token _next; /* token following the comment */ + bool _valid; /* true if comment is well formed */ + + /** + * Check if token sequence matches specified character sequence + * + * \param t start of token sequence + * \param s null-terminated character sequence + */ + static bool _match(Token t, const char *s) + { + for (int i = 0; s[i]; t = t.next(), i++) + if (t[0] != s[i]) + return false; + return true; + } + + public: + + /** + * Constructor + * + * \param start first token of the comment tag + */ + Comment(Token t) : _valid(false) + { + /* check for comment-start tag */ + if (!_match(t, ""); t = t.next()); + + if (t.type() == Token::END) + return; + + _next = t.next().next().next(); + _valid = true; + } + + /** + * Default constructor produces invalid Comment + */ + Comment() : _valid(false) { } + + /** + * Return true if comment is valid + */ + bool valid() const { return _valid; } + + /** + * Return token after the closing comment delimiter + */ + Token next_token() const { return _next; } + }; + + const char *_addr; /* first character of XML data */ + size_t _max_len; /* length of XML data in characters */ + int _num_sub_nodes; /* number of immediate sub nodes */ + Tag _start_tag; + Tag _end_tag; + + /** + * Search for end tag of XML node and initialize '_num_sub_nodes' + * + * \return end tag or invalid tag + * + * The function searches for a end tag that matches the same + * depth level and the same name as the start tag of the XML + * node. If the XML structure is invalid, the search results + * is an invalid Tag. + * + * During the search, the function also counts the number of + * immediate sub nodes. + */ + Tag _init_end_tag() + { + /* + * If the start tag is invalid or an empty-element tag, + * we use the same tag as end tag. + */ + if (_start_tag.type() != Tag::START) + return _start_tag; + + int depth = 1; + Token curr_token = _start_tag.next_token(); + + while (curr_token.type() != Token::END) { + + /* eat XML comment */ + Comment curr_comment(curr_token); + if (curr_comment.valid()) { + curr_token = curr_comment.next_token(); + continue; + } + + /* skip all tokens that are no tags */ + Tag curr_tag(curr_token); + if (curr_tag.type() == Tag::INVALID) { + curr_token = curr_token.next(); + continue; + } + + /* count sub nodes at depth 1 */ + if (depth == 1 && curr_tag.is_node()) + _num_sub_nodes++; + + /* keep track of the current depth */ + depth += (curr_tag.type() == Tag::START); + depth -= (curr_tag.type() == Tag::END); + + /* within sub nodes, continue after current token */ + if (depth > 0) { + + /* continue search with token after current tag */ + curr_token = curr_tag.next_token(); + continue; + } + + /* reaching the same depth as the start tag */ + const char *start_name = _start_tag.name().start(); + size_t start_len = _start_tag.name().len(); + const char *curr_name = curr_tag.name().start(); + size_t curr_len = curr_tag.name().len(); + + /* on mismatch of start tag and end tag, return invalid tag */ + if (start_len != curr_len + || strcmp(start_name, curr_name, curr_len)) + return Tag(); + + /* end tag corresponds to start tag */ + return curr_tag; + } + return Tag(); + } + + /** + * Find next non-whitespace and non-comment token + */ + static Token eat_whitespaces_and_comments(Token t) + { + while (true) { + + t = t.eat_whitespace(); + + /* eat comment */ + Comment comment(t); + if (comment.valid()) { + t = comment.next_token(); + continue; + } + + break; + } + return t; + } + + /** + * Create sub node from XML node + * + * \throw Nonexistent_sub_node + * \throw Invalid_syntax + */ + Xml_node _sub_node(const char *at) const + { + if (at < addr() || (size_t)(at - addr()) >= _max_len) + throw Nonexistent_sub_node(); + + return Xml_node(at, _max_len - (at - addr())); + } + + public: + + /** + * Constructor + * + * The constructor validates if the start tag has a + * matching end tag of the same depth and counts + * the number of immediate sub nodes. + */ + Xml_node(const char *addr, size_t max_len = ~0UL) : + _addr(addr), + _max_len(max_len), + _num_sub_nodes(0), + _start_tag(eat_whitespaces_and_comments(Token(addr, max_len))), + _end_tag(_init_end_tag()) + { + /* check validity of XML node */ + if (_start_tag.type() == Tag::EMPTY) return; + if (_start_tag.type() == Tag::START && _end_tag.type() == Tag::END) return; + + throw Invalid_syntax(); + } + + /** + * Request type name of XML node as null-terminated string + */ + void type_name(char *dst, size_t max_len) const { + _start_tag.name().string(dst, max_len); } + + /** + * Return true if tag is of specified type + */ + bool has_type(const char *type) const { + return (!strcmp(type, _start_tag.name().start(), + _start_tag.name().len()) + && strlen(type) == _start_tag.name().len()); } + + /** + * Request content of XML node as null-terminated string + */ + void value(char *dst, size_t max_len) const { + max_len = min(content_size() + 1, min(max_len, _max_len)); + strncpy(dst, content_addr(), max_len); } + + /** + * Read content as typed value from XML node + * + * \param T type of value to read from XML node + * \param out resulting value + * \return true on success + */ + template + bool value(T *out) const { + return ascii_to(content_addr(), out) == content_size(); } + + /** + * Return begin of node including the start tag + */ + const char *addr() const { return _addr; } + + /** + * Return size of node including start and end tags + */ + size_t size() const { return _end_tag.next_token().start() - addr(); } + + /** + * Return begin of node content as an opaque string + * + * Note that the returned string is not null-terminated as it + * points directly into a sub range of the unmodified Xml_node + * address range. + * + * XXX This function is deprecated. Use 'content_base()' instead. + */ + char *content_addr() const { return _start_tag.next_token().start(); } + + /** + * Return pointer to start of content + */ + char const *content_base() const { return content_addr(); } + + /** + * Return size of node content + */ + size_t content_size() const + { + if (_start_tag.type() == Tag::EMPTY) + return 0; + + return _end_tag.token().start() - content_addr(); + } + + /** + * Return the number of the XML node's immediate sub nodes + */ + size_t num_sub_nodes() const { return _num_sub_nodes; } + + /** + * Return XML node following the current one + * + * \throw Nonexistent_sub_node sub sequent node does not exist + */ + Xml_node next() const + { + Token after_node = _end_tag.next_token(); + after_node = eat_whitespaces_and_comments(after_node); + try { return _sub_node(after_node.start()); } + catch (Invalid_syntax) { throw Nonexistent_sub_node(); } + } + + /** + * Return next XML node of specified type + * + * \param type type of XML node, or + * 0 for matching any type + */ + Xml_node next(const char *type) const + { + Xml_node node = next(); + for (; type && !node.has_type(type); node = node.next()); + return node; + } + + /** + * Return true if node is the last of a node sequence + */ + bool is_last(const char *type = 0) const + { + try { next(type); return false; } + catch (Nonexistent_sub_node) { return true; } + } + + /** + * Return sub node with specified index + * + * \param idx index of sub node, + * default is the first node + * \throw Nonexistent_sub_node no such sub node exists + */ + Xml_node sub_node(unsigned idx = 0U) const + { + if (_num_sub_nodes > 0) { + + /* look up node at specified index */ + try { + Xml_node curr_node = _sub_node(content_addr()); + for (; idx > 0; idx--) + curr_node = curr_node.next(); + return curr_node; + } catch (Invalid_syntax) { } } - /** - * Find next non-whitespace and non-comment token - */ - static Token eat_whitespaces_and_comments(Token t) - { - while (true) { + throw Nonexistent_sub_node(); + } - t = t.eat_whitespace(); + /** + * Return first sub node that matches the specified type + * + * \throw Nonexistent_sub_node no such sub_node exists + */ + Xml_node sub_node(const char *type) const + { + if (_num_sub_nodes > 0) { - /* eat comment */ - Comment comment(t); - if (comment.valid()) { - t = comment.next_token(); - continue; - } + /* search for sub node of specified type */ + try { + Xml_node curr_node = _sub_node(content_addr()); + for ( ; true; curr_node = curr_node.next()) + if (curr_node.has_type(type)) + return curr_node; + } catch (...) { } + } + throw Nonexistent_sub_node(); + } + + /** + * Execute functor 'fn' for each sub node of specified type + */ + template + void for_each_sub_node(char const *type, FN const &fn) + { + if (_num_sub_nodes == 0) + return; + + Xml_node node = sub_node(); + for (int i = 0; ; node = node.next()) { + + if (!type || node.has_type(type)) + fn(node); + + if (++i == _num_sub_nodes) break; - } - return t; } + } - /** - * Create sub node from XML node - * - * \throw Nonexistent_sub_node - * \throw Invalid_syntax - */ - Xml_node _sub_node(const char *at) const - { - if (at < addr() || (size_t)(at - addr()) >= _max_len) - throw Nonexistent_sub_node(); + /** + * Execute functor 'fn' for each sub node + */ + template + void for_each_sub_node(FN const &fn) + { + for_each_sub_node(nullptr, fn); + } - return Xml_node(at, _max_len - (at - addr())); - } + /** + * Return Nth attribute of XML node + * + * \param idx attribute index, + * first attribute has index 0 + * \throw Nonexistent_attribute no such attribute exists + * \return XML attribute + */ + Attribute attribute(unsigned idx) const + { + /* get first attribute of the node */ + Attribute a = _start_tag.attribute(); - public: + /* skip attributes until we reach the target index */ + for (; idx > 0; idx--) + a = a._next(); - /** - * Constructor - * - * The constructor validates if the start tag has a - * matching end tag of the same depth and counts - * the number of immediate sub nodes. - */ - Xml_node(const char *addr, size_t max_len = ~0UL) : - _addr(addr), - _max_len(max_len), - _num_sub_nodes(0), - _start_tag(eat_whitespaces_and_comments(Token(addr, max_len))), - _end_tag(_init_end_tag()) - { - /* check validity of XML node */ - if (_start_tag.type() == Tag::EMPTY) return; - if (_start_tag.type() == Tag::START && _end_tag.type() == Tag::END) return; + return a; + } - throw Invalid_syntax(); - } + /** + * Return attribute of specified type + * + * \param type name of attribute type + * \throw Nonexistent_attribute no such attribute exists + * \return XML attribute + */ + Attribute attribute(const char *type) const + { + /* iterate, beginning with the first attribute of the node */ + for (Attribute a = _start_tag.attribute(); ; a = a.next()) + if (a.has_type(type)) + return a; + } - /** - * Request type name of XML node as null-terminated string - */ - void type_name(char *dst, size_t max_len) const { - _start_tag.name().string(dst, max_len); } + /** + * Shortcut for reading an attribute value from XML node + * + * \param type attribute name + * \param default_value value returned if no attribute with the + * name 'type' is present. + * \return attribute value or specified default value + * + * Without this shortcut, attribute values can be obtained by + * 'node.attribute(...).value(...)' only. Because the attribute + * lookup may throw a 'Nonexistent_attribute' exception, code that + * reads optional attributes (those with default values) has to + * handle the exception accordingly. Such code tends to become + * clumsy, in particular when many attributes are processed in a + * subsequent fashion. This function template relieves the XML node + * user from implementing the exception handling manually. + */ + template + inline T attribute_value(char const *type, T default_value) const + { + T result = default_value; + try { attribute(type).value(&result); } catch (...) { } + return result; + } - /** - * Return true if tag is of specified type - */ - bool has_type(const char *type) const { - return (!strcmp(type, _start_tag.name().start(), - _start_tag.name().len()) - && strlen(type) == _start_tag.name().len()); } + /** + * Return true if attribute of specified type exists + */ + inline bool has_attribute(char const *type) const + { + try { attribute(type); return true; } catch (...) { } + return false; + } - /** - * Request content of XML node as null-terminated string - */ - void value(char *dst, size_t max_len) const { - max_len = min(content_size() + 1, min(max_len, _max_len)); - strncpy(dst, content_addr(), max_len); } - - /** - * Read content as typed value from XML node - * - * \param T type of value to read from XML node - * \param out resulting value - * \return true on success - */ - template - bool value(T *out) const { - return ascii_to(content_addr(), out) == content_size(); } - - /** - * Return begin of node including the start tag - */ - const char *addr() const { return _addr; } - - /** - * Return size of node including start and end tags - */ - size_t size() const { return _end_tag.next_token().start() - addr(); } - - /** - * Return begin of node content as an opaque string - * - * Note that the returned string is not null-terminated as it - * points directly into a sub range of the unmodified Xml_node - * address range. - * - * XXX This function is deprecated. Use 'content_base()' instead. - */ - char *content_addr() const { return _start_tag.next_token().start(); } - - /** - * Return pointer to start of content - */ - char const *content_base() const { return content_addr(); } - - /** - * Return size of node content - */ - size_t content_size() const - { - if (_start_tag.type() == Tag::EMPTY) - return 0; - - return _end_tag.token().start() - content_addr(); - } - - /** - * Return the number of the XML node's immediate sub nodes - */ - size_t num_sub_nodes() const { return _num_sub_nodes; } - - /** - * Return XML node following the current one - * - * \throw Nonexistent_sub_node sub sequent node does not exist - */ - Xml_node next() const - { - Token after_node = _end_tag.next_token(); - after_node = eat_whitespaces_and_comments(after_node); - try { return _sub_node(after_node.start()); } - catch (Invalid_syntax) { throw Nonexistent_sub_node(); } - } - - /** - * Return next XML node of specified type - * - * \param type type of XML node, or - * 0 for matching any type - */ - Xml_node next(const char *type) const - { - Xml_node node = next(); - for (; type && !node.has_type(type); node = node.next()); - return node; - } - - /** - * Return true if node is the last of a node sequence - */ - bool is_last(const char *type = 0) const - { - try { next(type); return false; } - catch (Nonexistent_sub_node) { return true; } - } - - /** - * Return sub node with specified index - * - * \param idx index of sub node, - * default is the first node - * \throw Nonexistent_sub_node no such sub node exists - */ - Xml_node sub_node(unsigned idx = 0U) const - { - if (_num_sub_nodes > 0) { - - /* look up node at specified index */ - try { - Xml_node curr_node = _sub_node(content_addr()); - for (; idx > 0; idx--) - curr_node = curr_node.next(); - return curr_node; - } catch (Invalid_syntax) { } - } - - throw Nonexistent_sub_node(); - } - - /** - * Return first sub node that matches the specified type - * - * \throw Nonexistent_sub_node no such sub_node exists - */ - Xml_node sub_node(const char *type) const - { - if (_num_sub_nodes > 0) { - - /* search for sub node of specified type */ - try { - Xml_node curr_node = _sub_node(content_addr()); - for ( ; true; curr_node = curr_node.next()) - if (curr_node.has_type(type)) - return curr_node; - } catch (...) { } - } - - throw Nonexistent_sub_node(); - } - - /** - * Execute functor 'fn' for each sub node of specified type - */ - template - void for_each_sub_node(char const *type, FN const &fn) - { - if (_num_sub_nodes == 0) - return; - - Xml_node node = sub_node(); - for (int i = 0; ; node = node.next()) { - - if (!type || node.has_type(type)) - fn(node); - - if (++i == _num_sub_nodes) - break; - } - } - - /** - * Execute functor 'fn' for each sub node - */ - template - void for_each_sub_node(FN const &fn) - { - for_each_sub_node(nullptr, fn); - } - - /** - * Return Nth attribute of XML node - * - * \param idx attribute index, - * first attribute has index 0 - * \throw Nonexistent_attribute no such attribute exists - * \return XML attribute - */ - Attribute attribute(unsigned idx) const - { - /* get first attribute of the node */ - Attribute a = _start_tag.attribute(); - - /* skip attributes until we reach the target index */ - for (; idx > 0; idx--) - a = a._next(); - - return a; - } - - /** - * Return attribute of specified type - * - * \param type name of attribute type - * \throw Nonexistent_attribute no such attribute exists - * \return XML attribute - */ - Attribute attribute(const char *type) const - { - /* iterate, beginning with the first attribute of the node */ - for (Attribute a = _start_tag.attribute(); ; a = a.next()) - if (a.has_type(type)) - return a; - } - - /** - * Shortcut for reading an attribute value from XML node - * - * \param type attribute name - * \param default_value value returned if no attribute with the - * name 'type' is present. - * \return attribute value or specified default value - * - * Without this shortcut, attribute values can be obtained by - * 'node.attribute(...).value(...)' only. Because the attribute - * lookup may throw a 'Nonexistent_attribute' exception, code that - * reads optional attributes (those with default values) has to - * handle the exception accordingly. Such code tends to become - * clumsy, in particular when many attributes are processed in a - * subsequent fashion. This function template relieves the XML node - * user from implementing the exception handling manually. - */ - template - inline T attribute_value(char const *type, T default_value) const - { - T result = default_value; - try { attribute(type).value(&result); } catch (...) { } - return result; - } - - /** - * Return true if attribute of specified type exists - */ - inline bool has_attribute(char const *type) const - { - try { attribute(type); return true; } catch (...) { } - return false; - } - - /** - * Return true if sub node of specified type exists - */ - inline bool has_sub_node(char const *type) const - { - try { sub_node(type); return true; } catch (...) { } - return false; - } - }; -} + /** + * Return true if sub node of specified type exists + */ + inline bool has_sub_node(char const *type) const + { + try { sub_node(type); return true; } catch (...) { } + return false; + } +}; #endif /* _INCLUDE__UTIL__XML_NODE_H_ */ diff --git a/repos/os/src/drivers/timer/include/timer_root.h b/repos/os/src/drivers/timer/include/timer_root.h index 29f5f0fb8..afc4c1fd0 100644 --- a/repos/os/src/drivers/timer/include/timer_root.h +++ b/repos/os/src/drivers/timer/include/timer_root.h @@ -23,46 +23,46 @@ #include "timer_session_component.h" -namespace Timer { +namespace Timer { class Root_component; } - class Root_component : public Genode::Root_component - { - private: - Platform_timer _platform_timer; - Timeout_scheduler _timeout_scheduler; +class Timer::Root_component : public Genode::Root_component +{ + private: - protected: + Platform_timer _platform_timer; + Timeout_scheduler _timeout_scheduler; - Session_component *_create_session(const char *args) - { - Genode::size_t ram_quota = Genode::Arg_string::find_arg(args, "ram_quota").ulong_value(0); + protected: - if (ram_quota < sizeof(Session_component)) { - PWRN("Insufficient donated ram_quota (%zd bytes), require %zd bytes", - ram_quota, sizeof(Session_component)); - } + Session_component *_create_session(const char *args) + { + Genode::size_t ram_quota = Genode::Arg_string::find_arg(args, "ram_quota").ulong_value(0); - return new (md_alloc()) - Session_component(_timeout_scheduler); + if (ram_quota < sizeof(Session_component)) { + PWRN("Insufficient donated ram_quota (%zd bytes), require %zd bytes", + ram_quota, sizeof(Session_component)); } - public: + return new (md_alloc()) + Session_component(_timeout_scheduler); + } - /** - * Constructor - * - * The 'cap' argument is not used by the single-threaded server - * variant. - */ - Root_component(Genode::Rpc_entrypoint *session_ep, - Genode::Allocator *md_alloc, - Genode::Cap_session *cap) - : - Genode::Root_component(session_ep, md_alloc), - _timeout_scheduler(&_platform_timer, session_ep) - { } - }; -} + public: + + /** + * Constructor + * + * The 'cap' argument is not used by the single-threaded server + * variant. + */ + Root_component(Genode::Rpc_entrypoint *session_ep, + Genode::Allocator *md_alloc, + Genode::Cap_session *cap) + : + Genode::Root_component(session_ep, md_alloc), + _timeout_scheduler(&_platform_timer, session_ep) + { } +}; #endif diff --git a/repos/os/src/drivers/timer/include/timer_session_component.h b/repos/os/src/drivers/timer/include/timer_session_component.h index 563efdd66..c4cd09b6a 100644 --- a/repos/os/src/drivers/timer/include/timer_session_component.h +++ b/repos/os/src/drivers/timer/include/timer_session_component.h @@ -30,246 +30,253 @@ namespace Timer { enum { STACK_SIZE = 32*1024 }; - - struct Irq_dispatcher { - GENODE_RPC(Rpc_do_dispatch, void, do_dispatch); - GENODE_RPC_INTERFACE(Rpc_do_dispatch); - }; - - - /** - * Timer interrupt handler - * - * This class represents a RPC object that gets locally called for each - * timer interrupt. It is managed by the same entrypoint as all timer - * client components. Because the 'do_dispatch' function is executed in - * the same thread context as the dispatch functions of client requests, - * we are able to answer those requests from here (by calling the - * 'handle()' function of the alarm scheduler). - */ - class Irq_dispatcher_component : public Rpc_object - { - private: - - Genode::Alarm_scheduler *_alarm_scheduler; - Platform_timer *_platform_timer; - - public: - - /** - * Constructor - */ - Irq_dispatcher_component(Genode::Alarm_scheduler *as, - Platform_timer *pt) - : _alarm_scheduler(as), _platform_timer(pt) { } - - - /****************************** - ** Irq_dispatcher interface ** - ******************************/ - - void do_dispatch() - { - using namespace Genode; - - Alarm::Time now = _platform_timer->curr_time(); - Alarm::Time sleep_time; - - /* trigger timeout alarms */ - _alarm_scheduler->handle(now); - - /* determine duration for next one-shot timer event */ - Alarm::Time deadline; - if (_alarm_scheduler->next_deadline(&deadline)) - sleep_time = deadline - now; - else - sleep_time = _platform_timer->max_timeout(); - - if (sleep_time == 0) - sleep_time = 1; - - _platform_timer->schedule_timeout(sleep_time); - } - }; - - - /** - * Alarm for answering an oneshot timeout request - */ - class Wake_up_alarm : public Genode::Alarm - { - private: - - Signal_context_capability _sigh; - bool _periodic; - - public: - - Wake_up_alarm() : _periodic(false) { } - - void sigh(Signal_context_capability sigh) { _sigh = sigh; } - void periodic(bool periodic) { _periodic = periodic; } - bool periodic() { return _periodic; } - - - /********************* - ** Alarm interface ** - *********************/ - - /** - * Dispatch a wakeup alarm - * - * This function gets called by the 'Alarm_scheduler' thread. - */ - bool on_alarm (unsigned cnt) override - { - Signal_transmitter(_sigh).submit(cnt); - - return _periodic; - } - }; - - - class Timeout_scheduler : public Genode::Alarm_scheduler, - Genode::Thread - { - private: - - typedef Genode::Capability - Irq_dispatcher_capability; - - Platform_timer *_platform_timer; - Irq_dispatcher_component _irq_dispatcher_component; - Irq_dispatcher_capability _irq_dispatcher_cap; - - /** - * Timer-interrupt thread - * - * This thread blocks for the timer interrupt. For each occuring - * interrupt, it performs an local RPC call to the server - * activation, which, in turn, processes the scheduled timeouts and - * reprograms the platform timer. - */ - void entry() - { - while (true) { - - _platform_timer->wait_for_timeout(this); - - /* - * Call timer irq handler to trigger timeout alarms and - * reprogram the platform timer. - */ - _irq_dispatcher_cap.call(); - } - } - - public: - - /** - * Constructor - */ - Timeout_scheduler(Platform_timer *pt, Genode::Rpc_entrypoint *ep) - : - Thread("timeout_scheduler"), - _platform_timer(pt), - _irq_dispatcher_component(this, pt), - _irq_dispatcher_cap(ep->manage(&_irq_dispatcher_component)) - { - _platform_timer->schedule_timeout(0); - start(); - } - - /** - * Called from the '_trigger' function executed by the server activation - */ - void schedule_timeout(Wake_up_alarm *alarm, Genode::Alarm::Time timeout) - { - Alarm::Time now = _platform_timer->curr_time(); - if (alarm->periodic()) { - handle(now); /* update '_now' in 'Alarm_scheduler' */ - schedule(alarm, timeout); - } else schedule_absolute(alarm, now + timeout); - - /* interrupt current 'wait_for_timeout' */ - if (head_timeout(alarm)) - _platform_timer->schedule_timeout(0); - } - - unsigned long curr_time() const - { - return _platform_timer->curr_time(); - } - }; - - - /** - * Timer session - */ - class Session_component : public Rpc_object, - public List::Element - { - private: - - Timeout_scheduler &_timeout_scheduler; - Wake_up_alarm _wake_up_alarm; - unsigned long const _initial_time; - - void _trigger(unsigned us, bool periodic) - { - _wake_up_alarm.periodic(periodic); - _timeout_scheduler.schedule_timeout(&_wake_up_alarm, us); - } - - public: - - /** - * Constructor - */ - Session_component(Timeout_scheduler &ts) - : - _timeout_scheduler(ts), - _initial_time(_timeout_scheduler.curr_time()) - { } - - /** - * Destructor - */ - ~Session_component() - { - _timeout_scheduler.discard(&_wake_up_alarm); - } - - - /***************************** - ** Timer session interface ** - *****************************/ - - void trigger_once(unsigned us) - { - _trigger(us, false); - } - - void trigger_periodic(unsigned us) - { - _trigger(us, true); - } - - void sigh(Signal_context_capability sigh) - { - _wake_up_alarm.sigh(sigh); - } - - unsigned long elapsed_ms() const - { - unsigned long const now = _timeout_scheduler.curr_time(); - return (now - _initial_time) / 1000; - } - - void msleep(unsigned) { /* never called at the server side */ } - void usleep(unsigned) { /* never called at the server side */ } - }; + struct Irq_dispatcher; + class Irq_dispatcher_component; + class Wake_up_alarm; + class Timeout_scheduler; + class Session_component; } + +struct Timer::Irq_dispatcher +{ + GENODE_RPC(Rpc_do_dispatch, void, do_dispatch); + GENODE_RPC_INTERFACE(Rpc_do_dispatch); +}; + + +/** + * Timer interrupt handler + * + * This class represents a RPC object that gets locally called for each + * timer interrupt. It is managed by the same entrypoint as all timer + * client components. Because the 'do_dispatch' function is executed in + * the same thread context as the dispatch functions of client requests, + * we are able to answer those requests from here (by calling the + * 'handle()' function of the alarm scheduler). + */ +class Timer::Irq_dispatcher_component : public Genode::Rpc_object +{ + private: + + Genode::Alarm_scheduler *_alarm_scheduler; + Platform_timer *_platform_timer; + + public: + + /** + * Constructor + */ + Irq_dispatcher_component(Genode::Alarm_scheduler *as, + Platform_timer *pt) + : _alarm_scheduler(as), _platform_timer(pt) { } + + + /****************************** + ** Irq_dispatcher interface ** + ******************************/ + + void do_dispatch() + { + using namespace Genode; + + Alarm::Time now = _platform_timer->curr_time(); + Alarm::Time sleep_time; + + /* trigger timeout alarms */ + _alarm_scheduler->handle(now); + + /* determine duration for next one-shot timer event */ + Alarm::Time deadline; + if (_alarm_scheduler->next_deadline(&deadline)) + sleep_time = deadline - now; + else + sleep_time = _platform_timer->max_timeout(); + + if (sleep_time == 0) + sleep_time = 1; + + _platform_timer->schedule_timeout(sleep_time); + } +}; + + +/** + * Alarm for answering an oneshot timeout request + */ +class Timer::Wake_up_alarm : public Genode::Alarm +{ + private: + + Genode::Signal_context_capability _sigh; + bool _periodic; + + public: + + Wake_up_alarm() : _periodic(false) { } + + void sigh(Genode::Signal_context_capability sigh) { _sigh = sigh; } + void periodic(bool periodic) { _periodic = periodic; } + bool periodic() { return _periodic; } + + + /********************* + ** Alarm interface ** + *********************/ + + /** + * Dispatch a wakeup alarm + * + * This function gets called by the 'Alarm_scheduler' thread. + */ + bool on_alarm (unsigned cnt) override + { + Genode::Signal_transmitter(_sigh).submit(cnt); + + return _periodic; + } +}; + + +class Timer::Timeout_scheduler : public Genode::Alarm_scheduler, + Genode::Thread +{ + private: + + typedef Genode::Capability + Irq_dispatcher_capability; + + Platform_timer *_platform_timer; + Irq_dispatcher_component _irq_dispatcher_component; + Irq_dispatcher_capability _irq_dispatcher_cap; + + /** + * Timer-interrupt thread + * + * This thread blocks for the timer interrupt. For each occuring + * interrupt, it performs an local RPC call to the server + * activation, which, in turn, processes the scheduled timeouts and + * reprograms the platform timer. + */ + void entry() + { + while (true) { + + _platform_timer->wait_for_timeout(this); + + /* + * Call timer irq handler to trigger timeout alarms and + * reprogram the platform timer. + */ + _irq_dispatcher_cap.call(); + } + } + + public: + + /** + * Constructor + */ + Timeout_scheduler(Platform_timer *pt, Genode::Rpc_entrypoint *ep) + : + Thread("timeout_scheduler"), + _platform_timer(pt), + _irq_dispatcher_component(this, pt), + _irq_dispatcher_cap(ep->manage(&_irq_dispatcher_component)) + { + _platform_timer->schedule_timeout(0); + start(); + } + + /** + * Called from the '_trigger' function executed by the server activation + */ + void schedule_timeout(Wake_up_alarm *alarm, Genode::Alarm::Time timeout) + { + Genode::Alarm::Time now = _platform_timer->curr_time(); + if (alarm->periodic()) { + handle(now); /* update '_now' in 'Alarm_scheduler' */ + schedule(alarm, timeout); + } else schedule_absolute(alarm, now + timeout); + + /* interrupt current 'wait_for_timeout' */ + if (head_timeout(alarm)) + _platform_timer->schedule_timeout(0); + } + + unsigned long curr_time() const + { + return _platform_timer->curr_time(); + } +}; + + +/** + * Timer session + */ +class Timer::Session_component : public Genode::Rpc_object, + public Genode::List::Element +{ + private: + + Timeout_scheduler &_timeout_scheduler; + Wake_up_alarm _wake_up_alarm; + unsigned long const _initial_time; + + void _trigger(unsigned us, bool periodic) + { + _wake_up_alarm.periodic(periodic); + _timeout_scheduler.schedule_timeout(&_wake_up_alarm, us); + } + + public: + + /** + * Constructor + */ + Session_component(Timeout_scheduler &ts) + : + _timeout_scheduler(ts), + _initial_time(_timeout_scheduler.curr_time()) + { } + + /** + * Destructor + */ + ~Session_component() + { + _timeout_scheduler.discard(&_wake_up_alarm); + } + + + /***************************** + ** Timer session interface ** + *****************************/ + + void trigger_once(unsigned us) + { + _trigger(us, false); + } + + void trigger_periodic(unsigned us) + { + _trigger(us, true); + } + + void sigh(Signal_context_capability sigh) + { + _wake_up_alarm.sigh(sigh); + } + + unsigned long elapsed_ms() const + { + unsigned long const now = _timeout_scheduler.curr_time(); + return (now - _initial_time) / 1000; + } + + void msleep(unsigned) { /* never called at the server side */ } + void usleep(unsigned) { /* never called at the server side */ } +}; + #endif