mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-11 13:35:27 +00:00
core: re-design memory allocator (fix #1091)
* Core_mem_allocator: implement Range_allocator interface * Core_mem_allocator: allocate with page-granularity only * Use slab allocators in core where meaningful (e.g. dataspace objects)
This commit is contained in:
parent
36bfb56e49
commit
0dece91973
@ -60,7 +60,7 @@ namespace Genode {
|
|||||||
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
|
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
|
||||||
Range_allocator *irq_alloc() { return &_irq_alloc; }
|
Range_allocator *irq_alloc() { return &_irq_alloc; }
|
||||||
Range_allocator *region_alloc() { return _core_mem_alloc.virt_alloc(); }
|
Range_allocator *region_alloc() { return _core_mem_alloc.virt_alloc(); }
|
||||||
Allocator *core_mem_alloc() { return &_core_mem_alloc; }
|
Range_allocator *core_mem_alloc() { return &_core_mem_alloc; }
|
||||||
addr_t vm_start() const { return _vm_base; }
|
addr_t vm_start() const { return _vm_base; }
|
||||||
size_t vm_size() const { return _vm_size; }
|
size_t vm_size() const { return _vm_size; }
|
||||||
Rom_fs *rom_fs() { return &_rom_fs; }
|
Rom_fs *rom_fs() { return &_rom_fs; }
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
inline size_t get_page_size_log2() { return 12; }
|
constexpr size_t get_page_size_log2() { return 12; }
|
||||||
inline size_t get_page_size() { return 1 << get_page_size_log2(); }
|
constexpr size_t get_page_size() { return 1 << get_page_size_log2(); }
|
||||||
inline addr_t get_page_mask() { return ~(get_page_size() - 1); }
|
constexpr addr_t get_page_mask() { return ~(get_page_size() - 1); }
|
||||||
inline addr_t trunc_page(addr_t addr) { return addr & get_page_mask(); }
|
inline addr_t trunc_page(addr_t addr) { return addr & get_page_mask(); }
|
||||||
inline addr_t round_page(addr_t addr) { return trunc_page(addr + get_page_size() - 1); }
|
inline addr_t round_page(addr_t addr) { return trunc_page(addr + get_page_size() - 1); }
|
||||||
|
|
||||||
|
@ -126,9 +126,15 @@ int Platform::_init_rom_fs()
|
|||||||
** Support for core memory management **
|
** Support for core memory management **
|
||||||
****************************************/
|
****************************************/
|
||||||
|
|
||||||
bool Core_mem_allocator::Mapped_mem_allocator::_map_local(addr_t virt_addr, addr_t phys_addr, unsigned size_log2)
|
bool Core_mem_allocator::_map_local(addr_t virt_addr, addr_t phys_addr, unsigned size)
|
||||||
{
|
{
|
||||||
return map_local(phys_addr, virt_addr, 1 << (size_log2 - get_page_size_log2()));
|
return map_local(phys_addr, virt_addr, size / get_page_size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Core_mem_allocator::_unmap_local(addr_t virt_addr, unsigned size)
|
||||||
|
{
|
||||||
|
return unmap_local(virt_addr, size / get_page_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ namespace Genode {
|
|||||||
** Generic platform interface **
|
** Generic platform interface **
|
||||||
********************************/
|
********************************/
|
||||||
|
|
||||||
Allocator *core_mem_alloc() { return &_ram_alloc; }
|
Range_allocator *core_mem_alloc() { return &_ram_alloc; }
|
||||||
Range_allocator *ram_alloc() { return &_ram_alloc; }
|
Range_allocator *ram_alloc() { return &_ram_alloc; }
|
||||||
Range_allocator *io_mem_alloc() { return &_io_mem_alloc; }
|
Range_allocator *io_mem_alloc() { return &_io_mem_alloc; }
|
||||||
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
|
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
|
||||||
|
@ -92,13 +92,10 @@ namespace Genode {
|
|||||||
return l4_round_superpage(addr);
|
return l4_round_superpage(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t get_page_size() { return L4_PAGESIZE; }
|
constexpr size_t get_page_size() { return L4_PAGESIZE; }
|
||||||
|
constexpr size_t get_page_size_log2() { return L4_LOG2_PAGESIZE; }
|
||||||
inline size_t get_page_size_log2() { return L4_LOG2_PAGESIZE; }
|
constexpr size_t get_super_page_size() { return L4_SUPERPAGESIZE; }
|
||||||
|
constexpr size_t get_super_page_size_log2() { return L4_LOG2_SUPERPAGESIZE; }
|
||||||
inline size_t get_super_page_size() { return L4_SUPERPAGESIZE; }
|
|
||||||
|
|
||||||
inline size_t get_super_page_size_log2() { return L4_LOG2_SUPERPAGESIZE; }
|
|
||||||
|
|
||||||
inline void print_page_fault(const char *msg, addr_t pf_addr, addr_t pf_ip,
|
inline void print_page_fault(const char *msg, addr_t pf_addr, addr_t pf_ip,
|
||||||
Rm_session::Fault_type pf_type,
|
Rm_session::Fault_type pf_type,
|
||||||
|
@ -149,7 +149,7 @@ namespace Genode {
|
|||||||
** Generic platform interface **
|
** Generic platform interface **
|
||||||
********************************/
|
********************************/
|
||||||
|
|
||||||
Allocator *core_mem_alloc() { return &_ram_alloc; }
|
Range_allocator *core_mem_alloc() { return &_ram_alloc; }
|
||||||
Range_allocator *ram_alloc() { return &_ram_alloc; }
|
Range_allocator *ram_alloc() { return &_ram_alloc; }
|
||||||
Range_allocator *io_mem_alloc() { return &_io_mem_alloc; }
|
Range_allocator *io_mem_alloc() { return &_io_mem_alloc; }
|
||||||
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
|
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
|
||||||
|
@ -91,13 +91,10 @@ namespace Genode {
|
|||||||
return (addr + L4_SUPERPAGESIZE-1) & L4_SUPERPAGEMASK;
|
return (addr + L4_SUPERPAGESIZE-1) & L4_SUPERPAGEMASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t get_page_size() { return L4_PAGESIZE; }
|
constexpr size_t get_page_size() { return L4_PAGESIZE; }
|
||||||
|
constexpr size_t get_page_size_log2() { return L4_LOG2_PAGESIZE; }
|
||||||
inline size_t get_page_size_log2() { return L4_LOG2_PAGESIZE; }
|
constexpr size_t get_super_page_size() { return L4_SUPERPAGESIZE; }
|
||||||
|
constexpr size_t get_super_page_size_log2() { return L4_LOG2_SUPERPAGESIZE; }
|
||||||
inline size_t get_super_page_size() { return L4_SUPERPAGESIZE; }
|
|
||||||
|
|
||||||
inline size_t get_super_page_size_log2() { return L4_LOG2_SUPERPAGESIZE; }
|
|
||||||
|
|
||||||
inline void print_page_fault(const char *msg, addr_t pf_addr, addr_t pf_ip,
|
inline void print_page_fault(const char *msg, addr_t pf_addr, addr_t pf_ip,
|
||||||
Rm_session::Fault_type pf_type,
|
Rm_session::Fault_type pf_type,
|
||||||
|
@ -38,7 +38,7 @@ namespace Genode {
|
|||||||
Range_allocator *io_port_alloc() { return 0; }
|
Range_allocator *io_port_alloc() { return 0; }
|
||||||
Range_allocator *irq_alloc() { return 0; }
|
Range_allocator *irq_alloc() { return 0; }
|
||||||
Range_allocator *region_alloc() { return 0; }
|
Range_allocator *region_alloc() { return 0; }
|
||||||
Allocator *core_mem_alloc() { return 0; }
|
Range_allocator *core_mem_alloc() { return 0; }
|
||||||
addr_t vm_start() const { return 0; }
|
addr_t vm_start() const { return 0; }
|
||||||
size_t vm_size() const { return 0; }
|
size_t vm_size() const { return 0; }
|
||||||
Rom_fs *rom_fs() { return 0; }
|
Rom_fs *rom_fs() { return 0; }
|
||||||
|
@ -20,9 +20,9 @@
|
|||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
inline size_t get_page_size_log2() { return 12; }
|
constexpr size_t get_page_size_log2() { return 12; }
|
||||||
inline size_t get_page_size() { return 1 << get_page_size_log2(); }
|
constexpr size_t get_page_size() { return 1 << get_page_size_log2(); }
|
||||||
inline addr_t get_page_mask() { return ~(get_page_size() - 1); }
|
constexpr addr_t get_page_mask() { return ~(get_page_size() - 1); }
|
||||||
inline addr_t trunc_page(addr_t addr) { return addr & get_page_mask(); }
|
inline addr_t trunc_page(addr_t addr) { return addr & get_page_mask(); }
|
||||||
inline addr_t round_page(addr_t addr) { return trunc_page(addr + get_page_size() - 1); }
|
inline addr_t round_page(addr_t addr) { return trunc_page(addr + get_page_size() - 1); }
|
||||||
|
|
||||||
|
@ -38,19 +38,19 @@ namespace Genode
|
|||||||
/**
|
/**
|
||||||
* Get the the minimal supported page-size log 2
|
* Get the the minimal supported page-size log 2
|
||||||
*/
|
*/
|
||||||
inline size_t get_page_size_log2() { return MIN_PAGE_SIZE_LOG2; }
|
constexpr size_t get_page_size_log2() { return MIN_PAGE_SIZE_LOG2; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the the minimal supported page-size
|
* Get the the minimal supported page-size
|
||||||
*/
|
*/
|
||||||
inline size_t get_page_size() { return 1 << get_page_size_log2(); }
|
constexpr size_t get_page_size() { return 1 << get_page_size_log2(); }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the base mask for the minimal supported page-size
|
* Get the base mask for the minimal supported page-size
|
||||||
*/
|
*/
|
||||||
inline addr_t get_page_mask() { return ~(get_page_size() - 1); }
|
constexpr addr_t get_page_mask() { return ~(get_page_size() - 1); }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
22
base-linux/src/core/include/util.h
Normal file
22
base-linux/src/core/include/util.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* \brief Core-internal utilities
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2014-03-10
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CORE__INCLUDE__UTIL_H_
|
||||||
|
#define _CORE__INCLUDE__UTIL_H_
|
||||||
|
|
||||||
|
namespace Genode {
|
||||||
|
constexpr size_t get_page_size_log2() { return 12; }
|
||||||
|
constexpr size_t get_page_size() { return 1 << get_page_size_log2(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _CORE__INCLUDE__UTIL_H_ */
|
@ -67,7 +67,7 @@ namespace Genode {
|
|||||||
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
|
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
|
||||||
Range_allocator *irq_alloc() { return &_irq_alloc; }
|
Range_allocator *irq_alloc() { return &_irq_alloc; }
|
||||||
Range_allocator *region_alloc() { return _core_mem_alloc.virt_alloc(); }
|
Range_allocator *region_alloc() { return _core_mem_alloc.virt_alloc(); }
|
||||||
Allocator *core_mem_alloc() { return &_core_mem_alloc; }
|
Range_allocator *core_mem_alloc() { return &_core_mem_alloc; }
|
||||||
addr_t vm_start() const { return _vm_base; }
|
addr_t vm_start() const { return _vm_base; }
|
||||||
size_t vm_size() const { return _vm_size; }
|
size_t vm_size() const { return _vm_size; }
|
||||||
Rom_fs *rom_fs() { return &_rom_fs; }
|
Rom_fs *rom_fs() { return &_rom_fs; }
|
||||||
|
@ -20,11 +20,11 @@
|
|||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
inline size_t get_page_size_log2() { return 12; }
|
constexpr size_t get_page_size_log2() { return 12; }
|
||||||
inline size_t get_page_size() { return 1 << get_page_size_log2(); }
|
constexpr size_t get_page_size() { return 1 << get_page_size_log2(); }
|
||||||
inline addr_t get_page_mask() { return ~(get_page_size() - 1); }
|
constexpr addr_t get_page_mask() { return ~(get_page_size() - 1); }
|
||||||
inline size_t get_super_page_size_log2() { return 22; }
|
constexpr size_t get_super_page_size_log2() { return 22; }
|
||||||
inline size_t get_super_page_size() { return 1 << get_super_page_size_log2(); }
|
constexpr size_t get_super_page_size() { return 1 << get_super_page_size_log2(); }
|
||||||
inline addr_t trunc_page(addr_t addr) { return addr & get_page_mask(); }
|
inline addr_t trunc_page(addr_t addr) { return addr & get_page_mask(); }
|
||||||
inline addr_t round_page(addr_t addr) { return trunc_page(addr + get_page_size() - 1); }
|
inline addr_t round_page(addr_t addr) { return trunc_page(addr + get_page_size() - 1); }
|
||||||
|
|
||||||
|
@ -327,6 +327,17 @@ Platform::Platform() :
|
|||||||
* Now that we can access the I/O ports for comport 0, printf works...
|
* Now that we can access the I/O ports for comport 0, printf works...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* remap main utcb to default utcb address
|
||||||
|
* we do this that early, because Core_mem_allocator uses
|
||||||
|
* the main_thread_utcb very early to establish mappings
|
||||||
|
*/
|
||||||
|
if (map_local(__main_thread_utcb, (addr_t)__main_thread_utcb,
|
||||||
|
(addr_t)main_thread_utcb(), 1, Rights(true, true, false))) {
|
||||||
|
PERR("could not remap utcb of main thread");
|
||||||
|
nova_die();
|
||||||
|
}
|
||||||
|
|
||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
if (hip->sel_exc + 3 > NUM_INITIAL_PT_RESERVED) {
|
if (hip->sel_exc + 3 > NUM_INITIAL_PT_RESERVED) {
|
||||||
printf("configuration error\n");
|
printf("configuration error\n");
|
||||||
@ -616,13 +627,6 @@ Platform::Platform() :
|
|||||||
_irq_alloc.add_range(0, hip->sel_gsi - 1);
|
_irq_alloc.add_range(0, hip->sel_gsi - 1);
|
||||||
_gsi_base_sel = (hip->mem_desc_offset - hip->cpu_desc_offset) / hip->cpu_desc_size;
|
_gsi_base_sel = (hip->mem_desc_offset - hip->cpu_desc_offset) / hip->cpu_desc_size;
|
||||||
|
|
||||||
/* remap main utcb to default utcb address */
|
|
||||||
if (map_local(__main_thread_utcb, (addr_t)__main_thread_utcb,
|
|
||||||
(addr_t)main_thread_utcb(), 1, Rights(true, true, false))) {
|
|
||||||
PERR("could not remap utcb of main thread");
|
|
||||||
nova_die();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose_boot_info) {
|
if (verbose_boot_info) {
|
||||||
printf(":virt_alloc: "); _core_mem_alloc.virt_alloc()->raw()->dump_addr_tree();
|
printf(":virt_alloc: "); _core_mem_alloc.virt_alloc()->raw()->dump_addr_tree();
|
||||||
printf(":phys_alloc: "); _core_mem_alloc.phys_alloc()->raw()->dump_addr_tree();
|
printf(":phys_alloc: "); _core_mem_alloc.phys_alloc()->raw()->dump_addr_tree();
|
||||||
@ -661,17 +665,24 @@ Platform::Platform() :
|
|||||||
** Support for core memory management **
|
** Support for core memory management **
|
||||||
****************************************/
|
****************************************/
|
||||||
|
|
||||||
bool Core_mem_allocator::Mapped_mem_allocator::_map_local(addr_t virt_addr,
|
bool Core_mem_allocator::_map_local(addr_t virt_addr, addr_t phys_addr,
|
||||||
addr_t phys_addr,
|
unsigned size)
|
||||||
unsigned size_log2)
|
|
||||||
{
|
{
|
||||||
map_local((Utcb *)Thread_base::myself()->utcb(), phys_addr,
|
map_local((Utcb *)Thread_base::myself()->utcb(), phys_addr,
|
||||||
virt_addr, 1 << (size_log2 - get_page_size_log2()),
|
virt_addr, size / get_page_size(),
|
||||||
Rights(true, true, true), true);
|
Rights(true, true, true), true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Core_mem_allocator::_unmap_local(addr_t virt_addr, unsigned size)
|
||||||
|
{
|
||||||
|
unmap_local((Utcb *)Thread_base::myself()->utcb(),
|
||||||
|
virt_addr, size / get_page_size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/********************************
|
/********************************
|
||||||
** Generic platform interface **
|
** Generic platform interface **
|
||||||
********************************/
|
********************************/
|
||||||
|
@ -35,7 +35,9 @@ namespace Genode {
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef Core_mem_allocator::Phys_allocator Phys_allocator;
|
using Phys_allocator = Core_mem_allocator::Phys_allocator;
|
||||||
|
using Rom_slab = Tslab<Rom_module, get_page_size()>;
|
||||||
|
using Thread_slab = Tslab<Platform_thread, get_page_size()>;
|
||||||
|
|
||||||
Platform_pd *_core_pd; /* core protection domain */
|
Platform_pd *_core_pd; /* core protection domain */
|
||||||
Platform_thread *_core_pager; /* pager for core threads */
|
Platform_thread *_core_pager; /* pager for core threads */
|
||||||
@ -43,7 +45,9 @@ namespace Genode {
|
|||||||
Phys_allocator _io_mem_alloc; /* MMIO allocator */
|
Phys_allocator _io_mem_alloc; /* MMIO allocator */
|
||||||
Phys_allocator _io_port_alloc; /* I/O port allocator */
|
Phys_allocator _io_port_alloc; /* I/O port allocator */
|
||||||
Phys_allocator _irq_alloc; /* IRQ allocator */
|
Phys_allocator _irq_alloc; /* IRQ allocator */
|
||||||
|
Rom_slab _rom_slab; /* Slab for rom modules */
|
||||||
Rom_fs _rom_fs; /* ROM file system */
|
Rom_fs _rom_fs; /* ROM file system */
|
||||||
|
Thread_slab _thread_slab; /* Slab for platform threads */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Virtual-memory range for non-core address spaces.
|
* Virtual-memory range for non-core address spaces.
|
||||||
@ -75,6 +79,10 @@ namespace Genode {
|
|||||||
*/
|
*/
|
||||||
Platform_thread *core_pager() { return _core_pager; }
|
Platform_thread *core_pager() { return _core_pager; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessor for platform thread object slab allocator
|
||||||
|
*/
|
||||||
|
Thread_slab *thread_slab() { return &_thread_slab; }
|
||||||
|
|
||||||
/**********************************************
|
/**********************************************
|
||||||
** Callbacks used for parsing the boot info **
|
** Callbacks used for parsing the boot info **
|
||||||
@ -113,7 +121,7 @@ namespace Genode {
|
|||||||
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
|
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
|
||||||
Range_allocator *irq_alloc() { return &_irq_alloc; }
|
Range_allocator *irq_alloc() { return &_irq_alloc; }
|
||||||
Range_allocator *region_alloc() { return _core_mem_alloc.virt_alloc(); }
|
Range_allocator *region_alloc() { return _core_mem_alloc.virt_alloc(); }
|
||||||
Allocator *core_mem_alloc() { return &_core_mem_alloc; }
|
Range_allocator *core_mem_alloc() { return &_core_mem_alloc; }
|
||||||
addr_t vm_start() const { return _vm_start; }
|
addr_t vm_start() const { return _vm_start; }
|
||||||
size_t vm_size() const { return _vm_size; }
|
size_t vm_size() const { return _vm_size; }
|
||||||
Rom_fs *rom_fs() { return &_rom_fs; }
|
Rom_fs *rom_fs() { return &_rom_fs; }
|
||||||
|
@ -61,9 +61,9 @@ namespace Genode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t get_page_size_log2() { return 12; }
|
constexpr size_t get_page_size_log2() { return 12; }
|
||||||
inline size_t get_page_size() { return 1 << get_page_size_log2(); }
|
constexpr size_t get_page_size() { return 1 << get_page_size_log2(); }
|
||||||
inline addr_t get_page_mask() { return ~(get_page_size() - 1); }
|
constexpr addr_t get_page_mask() { return ~(get_page_size() - 1); }
|
||||||
|
|
||||||
inline size_t get_super_page_size_log2()
|
inline size_t get_super_page_size_log2()
|
||||||
{
|
{
|
||||||
|
@ -53,12 +53,13 @@ static int num_boot_module_objects;
|
|||||||
** Support for core memory management **
|
** Support for core memory management **
|
||||||
****************************************/
|
****************************************/
|
||||||
|
|
||||||
bool Core_mem_allocator::Mapped_mem_allocator::_map_local(addr_t virt_addr,
|
bool Core_mem_allocator::_map_local(addr_t virt_addr, addr_t phys_addr,
|
||||||
addr_t phys_addr,
|
unsigned size) {
|
||||||
unsigned size_log2)
|
return map_local(phys_addr, virt_addr, size / get_page_size()); }
|
||||||
{
|
|
||||||
return map_local(phys_addr, virt_addr, 1 << (size_log2 - get_page_size_log2()));
|
|
||||||
}
|
bool Core_mem_allocator::_unmap_local(addr_t virt_addr, unsigned size) {
|
||||||
|
return unmap_local(virt_addr, size / get_page_size()); }
|
||||||
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
@ -185,9 +186,14 @@ Okl4::bi_name_t Platform::bi_new_ms(Okl4::bi_name_t owner,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char init_slab_block_rom[get_page_size()];
|
||||||
|
static char init_slab_block_thread[get_page_size()];
|
||||||
|
|
||||||
Platform::Platform() :
|
Platform::Platform() :
|
||||||
_io_mem_alloc(core_mem_alloc()), _io_port_alloc(core_mem_alloc()),
|
_io_mem_alloc(core_mem_alloc()), _io_port_alloc(core_mem_alloc()),
|
||||||
_irq_alloc(core_mem_alloc())
|
_irq_alloc(core_mem_alloc()),
|
||||||
|
_rom_slab(core_mem_alloc(), (Slab_block *)&init_slab_block_rom),
|
||||||
|
_thread_slab(core_mem_alloc(), (Slab_block *)&init_slab_block_thread)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We must be single-threaded at this stage and so this is safe.
|
* We must be single-threaded at this stage and so this is safe.
|
||||||
@ -247,7 +253,7 @@ Platform::Platform() :
|
|||||||
/* make gathered boot-module info known to '_rom_fs' */
|
/* make gathered boot-module info known to '_rom_fs' */
|
||||||
int num_boot_modules = min(num_boot_module_objects, num_boot_module_memsects);
|
int num_boot_modules = min(num_boot_module_objects, num_boot_module_memsects);
|
||||||
for (int i = 0; i < num_boot_modules; i++) {
|
for (int i = 0; i < num_boot_modules; i++) {
|
||||||
Rom_module *r = new (core_mem_alloc())
|
Rom_module *r = new (&_rom_slab)
|
||||||
Rom_module(boot_modules[i].base,
|
Rom_module(boot_modules[i].base,
|
||||||
boot_modules[i].size,
|
boot_modules[i].size,
|
||||||
boot_modules[i].name);
|
boot_modules[i].name);
|
||||||
@ -294,7 +300,7 @@ Platform::Platform() :
|
|||||||
* not destroy this task, it should be no problem.
|
* not destroy this task, it should be no problem.
|
||||||
*/
|
*/
|
||||||
Platform_thread *core_thread =
|
Platform_thread *core_thread =
|
||||||
new(core_mem_alloc()) Platform_thread("core.main");
|
new(&_thread_slab) Platform_thread("core.main");
|
||||||
|
|
||||||
core_thread->set_l4_thread_id(Okl4::L4_rootserver);
|
core_thread->set_l4_thread_id(Okl4::L4_rootserver);
|
||||||
|
|
||||||
|
@ -34,7 +34,8 @@ void Thread_base::_thread_start()
|
|||||||
void Thread_base::start()
|
void Thread_base::start()
|
||||||
{
|
{
|
||||||
/* create and start platform thread */
|
/* create and start platform thread */
|
||||||
_tid.pt = new(platform()->core_mem_alloc()) Platform_thread(_context->name);
|
_tid.pt = new(platform_specific()->thread_slab())
|
||||||
|
Platform_thread(_context->name);
|
||||||
|
|
||||||
platform_specific()->core_pd()->bind_thread(_tid.pt);
|
platform_specific()->core_pd()->bind_thread(_tid.pt);
|
||||||
|
|
||||||
@ -53,5 +54,5 @@ void Thread_base::cancel_blocking()
|
|||||||
void Thread_base::_deinit_platform_thread()
|
void Thread_base::_deinit_platform_thread()
|
||||||
{
|
{
|
||||||
/* destruct platform thread */
|
/* destruct platform thread */
|
||||||
destroy(platform()->core_mem_alloc(), _tid.pt);
|
destroy(platform_specific()->thread_slab(), _tid.pt);
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ namespace Genode {
|
|||||||
** Generic platform interface **
|
** Generic platform interface **
|
||||||
********************************/
|
********************************/
|
||||||
|
|
||||||
Allocator *core_mem_alloc() { return &_ram_alloc; }
|
Range_allocator *core_mem_alloc() { return &_ram_alloc; }
|
||||||
Range_allocator *ram_alloc() { return &_ram_alloc; }
|
Range_allocator *ram_alloc() { return &_ram_alloc; }
|
||||||
Range_allocator *io_mem_alloc() { return &_io_mem_alloc; }
|
Range_allocator *io_mem_alloc() { return &_io_mem_alloc; }
|
||||||
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
|
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
|
||||||
|
@ -78,9 +78,9 @@ namespace Genode {
|
|||||||
touch_read_write(bptr);
|
touch_read_write(bptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t get_page_size() { return Pistachio::get_page_size(); }
|
constexpr size_t get_page_size_log2() { return 12; }
|
||||||
inline size_t get_page_size_log2() { return Pistachio::get_page_size_log2(); }
|
constexpr size_t get_page_size() { return 1 << get_page_size_log2(); }
|
||||||
inline addr_t get_page_mask() { return Pistachio::get_page_mask(); }
|
constexpr addr_t get_page_mask() { return ~(get_page_size() - 1); }
|
||||||
|
|
||||||
inline size_t get_super_page_size_log2()
|
inline size_t get_super_page_size_log2()
|
||||||
{
|
{
|
||||||
|
@ -257,13 +257,11 @@ namespace Genode {
|
|||||||
*
|
*
|
||||||
* \param BMDT block meta-data type
|
* \param BMDT block meta-data type
|
||||||
*/
|
*/
|
||||||
template <typename BMDT>
|
template <typename BMDT, unsigned SLAB_BLOCK_SIZE = 256 * sizeof(addr_t)>
|
||||||
class Allocator_avl_tpl : public Allocator_avl_base
|
class Allocator_avl_tpl : public Allocator_avl_base
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum { SLAB_BLOCK_SIZE = 256 * sizeof(addr_t) };
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pump up the Block class with custom meta-data type
|
* Pump up the Block class with custom meta-data type
|
||||||
*/
|
*/
|
||||||
|
2
base/src/base/env/platform_env_common.h
vendored
2
base/src/base/env/platform_env_common.h
vendored
@ -117,7 +117,7 @@ struct Genode::Expanding_ram_session_client : Upgradeable_client<Genode::Ram_ses
|
|||||||
* Because the worst case almost never happens, we request
|
* Because the worst case almost never happens, we request
|
||||||
* a bit too much quota for the most time.
|
* a bit too much quota for the most time.
|
||||||
*/
|
*/
|
||||||
enum { ALLOC_OVERHEAD = 1024U };
|
enum { ALLOC_OVERHEAD = 4096U };
|
||||||
Genode::snprintf(buf, sizeof(buf), "ram_quota=%zu",
|
Genode::snprintf(buf, sizeof(buf), "ram_quota=%zu",
|
||||||
size + ALLOC_OVERHEAD);
|
size + ALLOC_OVERHEAD);
|
||||||
env()->parent()->resource_request(buf);
|
env()->parent()->resource_request(buf);
|
||||||
|
@ -124,8 +124,15 @@ class Context_area_rm_session : public Rm_session
|
|||||||
|
|
||||||
class Context_area_ram_session : public Ram_session
|
class Context_area_ram_session : public Ram_session
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
enum { verbose = false };
|
enum { verbose = false };
|
||||||
|
|
||||||
|
using Ds_slab = Synchronized_allocator<Tslab<Dataspace_component,
|
||||||
|
get_page_size()> >;
|
||||||
|
|
||||||
|
Ds_slab _ds_slab { platform()->core_mem_alloc() };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Ram_dataspace_capability alloc(size_t size, bool cached)
|
Ram_dataspace_capability alloc(size_t size, bool cached)
|
||||||
@ -153,7 +160,7 @@ class Context_area_ram_session : public Ram_session
|
|||||||
if (verbose)
|
if (verbose)
|
||||||
PDBG("phys_base = %p, size = 0x%zx", phys_base, size);
|
PDBG("phys_base = %p, size = 0x%zx", phys_base, size);
|
||||||
|
|
||||||
context_ds[i] = new (platform()->core_mem_alloc())
|
context_ds[i] = new (&_ds_slab)
|
||||||
Dataspace_component(size, 0, (addr_t)phys_base, false, true, 0);
|
Dataspace_component(size, 0, (addr_t)phys_base, false, true, 0);
|
||||||
|
|
||||||
Dataspace_capability cap = Dataspace_capability::local_cap(context_ds[i]);
|
Dataspace_capability cap = Dataspace_capability::local_cap(context_ds[i]);
|
||||||
@ -180,7 +187,7 @@ class Context_area_ram_session : public Ram_session
|
|||||||
if (verbose)
|
if (verbose)
|
||||||
PDBG("phys_addr = %p, size = 0x%zx", phys_addr, size);
|
PDBG("phys_addr = %p, size = 0x%zx", phys_addr, size);
|
||||||
|
|
||||||
destroy(platform()->core_mem_alloc(), dataspace_component);
|
destroy(&_ds_slab, dataspace_component);
|
||||||
platform_specific()->ram_alloc()->free(phys_addr, size);
|
platform_specific()->ram_alloc()->free(phys_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Allocator for core-local memory
|
* \brief Allocator for core-local memory
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2009-10-12
|
* \date 2009-10-12
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -16,48 +17,46 @@
|
|||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include <core_mem_alloc.h>
|
#include <core_mem_alloc.h>
|
||||||
#include <util.h>
|
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
static const bool verbose_core_mem_alloc = false;
|
static const bool verbose_core_mem_alloc = false;
|
||||||
|
|
||||||
|
|
||||||
bool Core_mem_allocator::Mapped_mem_allocator::alloc(size_t size, void **out_addr)
|
Range_allocator::Alloc_return
|
||||||
|
Core_mem_allocator::alloc_aligned(size_t size, void **out_addr, int align)
|
||||||
{
|
{
|
||||||
/* try to allocate block in cores already mapped virtual address ranges */
|
|
||||||
if (_alloc.alloc(size, out_addr))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
/* there is no sufficient space in core's mapped virtual memory, expansion needed */
|
|
||||||
size_t page_rounded_size = (size + get_page_size() - 1) & get_page_mask();
|
size_t page_rounded_size = (size + get_page_size() - 1) & get_page_mask();
|
||||||
void *phys_addr = 0, *virt_addr = 0;
|
void *phys_addr = 0;
|
||||||
|
align = max((size_t)align, get_page_size_log2());
|
||||||
|
|
||||||
/* allocate physical pages */
|
/* allocate physical pages */
|
||||||
if (!_phys_alloc->alloc(page_rounded_size, &phys_addr)) {
|
Alloc_return ret1 = _phys_alloc.raw()->alloc_aligned(page_rounded_size,
|
||||||
PERR("Could not allocate physical memory region of size %zu\n", page_rounded_size);
|
&phys_addr, align);
|
||||||
return false;
|
if (!ret1.is_ok()) {
|
||||||
|
PERR("Could not allocate physical memory region of size %zu\n",
|
||||||
|
page_rounded_size);
|
||||||
|
return ret1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate range in core's virtual address space */
|
/* allocate range in core's virtual address space */
|
||||||
if (!_virt_alloc->alloc(page_rounded_size, &virt_addr)) {
|
Alloc_return ret2 = _virt_alloc.raw()->alloc_aligned(page_rounded_size,
|
||||||
PERR("Could not allocate virtual address range in core of size %zu\n", page_rounded_size);
|
out_addr, align);
|
||||||
|
if (!ret2.is_ok()) {
|
||||||
|
PERR("Could not allocate virtual address range in core of size %zu\n",
|
||||||
|
page_rounded_size);
|
||||||
|
|
||||||
/* revert physical allocation */
|
/* revert physical allocation */
|
||||||
_phys_alloc->free(phys_addr);
|
_phys_alloc.raw()->free(phys_addr);
|
||||||
return false;
|
return ret2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose_core_mem_alloc)
|
if (verbose_core_mem_alloc)
|
||||||
printf("added core memory block of %zu bytes at virt=%p phys=%p\n",
|
printf("added core memory block of %zu bytes at virt=%p phys=%p\n",
|
||||||
page_rounded_size, virt_addr, phys_addr);
|
page_rounded_size, *out_addr, phys_addr);
|
||||||
|
|
||||||
/* make physical page accessible at the designated virtual address */
|
/* make physical page accessible at the designated virtual address */
|
||||||
_map_local((addr_t)virt_addr, (addr_t)phys_addr, get_page_size_log2());
|
_map_local((addr_t)*out_addr, (addr_t)phys_addr, page_rounded_size);
|
||||||
|
|
||||||
/* add new range to core's allocator for mapped virtual memory */
|
return Alloc_return::OK;
|
||||||
_alloc.add_range((addr_t)virt_addr, page_rounded_size);
|
|
||||||
|
|
||||||
/* now that we have added enough memory, try again... */
|
|
||||||
return _alloc.alloc(size, out_addr);
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Allocator infrastructure for core
|
* \brief Allocator infrastructure for core
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2009-10-12
|
* \date 2009-10-12
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -17,82 +18,27 @@
|
|||||||
#include <base/lock.h>
|
#include <base/lock.h>
|
||||||
#include <base/sync_allocator.h>
|
#include <base/sync_allocator.h>
|
||||||
#include <base/allocator_avl.h>
|
#include <base/allocator_avl.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
class Core_mem_allocator;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocators for physical memory, core's virtual address space,
|
* Allocators for physical memory, core's virtual address space,
|
||||||
* and core-local memory. The interface of this class is thread safe.
|
* and core-local memory. The interface of this class is thread safe.
|
||||||
|
* The class itself implements a ready-to-use memory allocator for
|
||||||
|
* core that allows to allocate memory at page granularity only.
|
||||||
*/
|
*/
|
||||||
class Core_mem_allocator : public Allocator
|
class Genode::Core_mem_allocator : public Genode::Range_allocator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef Synchronized_range_allocator<Allocator_avl> Phys_allocator;
|
using Page_allocator = Allocator_avl_tpl<Empty, get_page_size()>;
|
||||||
|
using Phys_allocator = Synchronized_range_allocator<Page_allocator>;
|
||||||
private:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsynchronized allocator for core-mapped memory
|
|
||||||
*
|
|
||||||
* This is an allocator of core-mapped memory. It is meant to be used as
|
|
||||||
* meta-data allocator for the other allocators and as back end for core's
|
|
||||||
* synchronized memory allocator.
|
|
||||||
*/
|
|
||||||
class Mapped_mem_allocator : public Allocator
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Allocator_avl _alloc;
|
|
||||||
Range_allocator *_phys_alloc;
|
|
||||||
Range_allocator *_virt_alloc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initial chunk to populate the core mem allocator
|
|
||||||
*
|
|
||||||
* This chunk is used at platform initialization time.
|
|
||||||
*/
|
|
||||||
char _initial_chunk[16*1024];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map physical page locally to specified virtual address
|
|
||||||
*
|
|
||||||
* \param virt_addr core-local address
|
|
||||||
* \param phys_addr physical memory address
|
|
||||||
* \param size_log2 size of memory block to map
|
|
||||||
* \return true on success
|
|
||||||
*/
|
|
||||||
bool _map_local(addr_t virt_addr, addr_t phys_addr, unsigned size_log2);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* \param phys_alloc allocator of physical memory
|
|
||||||
* \param virt_alloc allocator of core-local virtual memory ranges
|
|
||||||
*/
|
|
||||||
Mapped_mem_allocator(Range_allocator *phys_alloc,
|
|
||||||
Range_allocator *virt_alloc)
|
|
||||||
: _alloc(0), _phys_alloc(phys_alloc), _virt_alloc(virt_alloc)
|
|
||||||
{
|
|
||||||
_alloc.add_range((addr_t)_initial_chunk, sizeof(_initial_chunk));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************
|
|
||||||
** Allocator interface **
|
|
||||||
*************************/
|
|
||||||
|
|
||||||
bool alloc(size_t size, void **out_addr);
|
|
||||||
void free(void *addr, size_t size) { _alloc.free(addr, size); }
|
|
||||||
size_t consumed() { return _phys_alloc->consumed(); }
|
|
||||||
size_t overhead(size_t size) { return _phys_alloc->overhead(size); }
|
|
||||||
|
|
||||||
bool need_size_for_free() const override {
|
|
||||||
return _phys_alloc->need_size_for_free(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock used for synchronization of all operations on the
|
* Lock used for synchronization of all operations on the
|
||||||
@ -116,29 +62,17 @@ namespace Genode {
|
|||||||
*/
|
*/
|
||||||
Phys_allocator _virt_alloc;
|
Phys_allocator _virt_alloc;
|
||||||
|
|
||||||
/**
|
bool _map_local(addr_t virt_addr, addr_t phys_addr, unsigned size);
|
||||||
* Unsynchronized core-mapped memory allocator
|
bool _unmap_local(addr_t virt_addr, unsigned size);
|
||||||
*
|
|
||||||
* This allocator is internally used within this class for
|
|
||||||
* allocating meta data for the other allocators. It is not
|
|
||||||
* synchronized to avoid nested locking. The lock-guarded
|
|
||||||
* access to this allocator from the outer world is
|
|
||||||
* provided via the 'Allocator' interface implemented by
|
|
||||||
* 'Core_mem_allocator'. The allocator works at byte
|
|
||||||
* granularity.
|
|
||||||
*/
|
|
||||||
Mapped_mem_allocator _mem_alloc;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Core_mem_allocator() :
|
Core_mem_allocator()
|
||||||
_phys_alloc(&_lock, &_mem_alloc),
|
: _phys_alloc(&_lock, this),
|
||||||
_virt_alloc(&_lock, &_mem_alloc),
|
_virt_alloc(&_lock, this) { }
|
||||||
_mem_alloc(_phys_alloc.raw(), _virt_alloc.raw())
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access physical-memory allocator
|
* Access physical-memory allocator
|
||||||
@ -151,21 +85,29 @@ namespace Genode {
|
|||||||
Phys_allocator *virt_alloc() { return &_virt_alloc; }
|
Phys_allocator *virt_alloc() { return &_virt_alloc; }
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************
|
||||||
|
** Range allocator interface **
|
||||||
|
*******************************/
|
||||||
|
|
||||||
|
int add_range(addr_t base, size_t size) { return -1; }
|
||||||
|
int remove_range(addr_t base, size_t size) { return -1; }
|
||||||
|
Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0);
|
||||||
|
Alloc_return alloc_addr(size_t size, addr_t addr) {
|
||||||
|
return Alloc_return::RANGE_CONFLICT; }
|
||||||
|
void free(void *addr) {}
|
||||||
|
size_t avail() { return _phys_alloc.avail(); }
|
||||||
|
|
||||||
|
bool valid_addr(addr_t addr) { return _virt_alloc.valid_addr(addr); }
|
||||||
|
|
||||||
|
|
||||||
/*************************
|
/*************************
|
||||||
** Allocator interface **
|
** Allocator interface **
|
||||||
*************************/
|
*************************/
|
||||||
|
|
||||||
bool alloc(size_t size, void **out_addr)
|
bool alloc(size_t size, void **out_addr) {
|
||||||
{
|
return alloc_aligned(size, out_addr).is_ok(); }
|
||||||
Lock::Guard lock_guard(_lock);
|
|
||||||
return _mem_alloc.alloc(size, out_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void free(void *addr, size_t size)
|
void free(void *addr, size_t) { free(addr); }
|
||||||
{
|
|
||||||
Lock::Guard lock_guard(_lock);
|
|
||||||
_mem_alloc.free(addr, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t consumed() { return _phys_alloc.consumed(); }
|
size_t consumed() { return _phys_alloc.consumed(); }
|
||||||
size_t overhead(size_t size) { return _phys_alloc.overhead(size); }
|
size_t overhead(size_t size) { return _phys_alloc.overhead(size); }
|
||||||
@ -173,6 +115,5 @@ namespace Genode {
|
|||||||
bool need_size_for_free() const override {
|
bool need_size_for_free() const override {
|
||||||
return _phys_alloc.need_size_for_free(); }
|
return _phys_alloc.need_size_for_free(); }
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _CORE__INCLUDE__CORE_MEM_ALLOC_H_ */
|
#endif /* _CORE__INCLUDE__CORE_MEM_ALLOC_H_ */
|
||||||
|
@ -37,7 +37,7 @@ namespace Genode {
|
|||||||
/**
|
/**
|
||||||
* Allocator of core-local mapped virtual memory
|
* Allocator of core-local mapped virtual memory
|
||||||
*/
|
*/
|
||||||
virtual Allocator *core_mem_alloc() = 0;
|
virtual Range_allocator *core_mem_alloc() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocator of physical memory
|
* Allocator of physical memory
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <dataspace_component.h>
|
#include <dataspace_component.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
@ -37,9 +38,10 @@ namespace Genode {
|
|||||||
|
|
||||||
class Invalid_dataspace : public Exception { };
|
class Invalid_dataspace : public Exception { };
|
||||||
|
|
||||||
enum { SBS = 1024 }; /* slab block size */
|
static constexpr size_t SBS = get_page_size();
|
||||||
|
|
||||||
typedef Synchronized_allocator<Tslab<Dataspace_component, SBS> > Ds_slab;
|
using Ds_slab = Synchronized_allocator<Tslab<Dataspace_component,
|
||||||
|
SBS> >;
|
||||||
|
|
||||||
Rpc_entrypoint *_ds_ep;
|
Rpc_entrypoint *_ds_ep;
|
||||||
Rpc_entrypoint *_ram_session_ep;
|
Rpc_entrypoint *_ram_session_ep;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user