diff --git a/repos/dde_bsd/recipes/pkg/bsd_audio_drv/runtime b/repos/dde_bsd/recipes/pkg/bsd_audio_drv/runtime index fbdd563946..685270c0c9 100644 --- a/repos/dde_bsd/recipes/pkg/bsd_audio_drv/runtime +++ b/repos/dde_bsd/recipes/pkg/bsd_audio_drv/runtime @@ -1,4 +1,4 @@ - + diff --git a/repos/dde_bsd/run/audio_in.run b/repos/dde_bsd/run/audio_in.run index 3b0fa1714c..182948f62d 100644 --- a/repos/dde_bsd/run/audio_in.run +++ b/repos/dde_bsd/run/audio_in.run @@ -113,7 +113,7 @@ append config { - + diff --git a/repos/dde_bsd/run/audio_out.run b/repos/dde_bsd/run/audio_out.run index 1118b9bccf..def5a1f68d 100644 --- a/repos/dde_bsd/run/audio_out.run +++ b/repos/dde_bsd/run/audio_out.run @@ -99,9 +99,9 @@ install_config { - + - + diff --git a/repos/dde_bsd/src/lib/audio/mem.cc b/repos/dde_bsd/src/lib/audio/mem.cc index 7de10427fc..27859e59a6 100644 --- a/repos/dde_bsd/src/lib/audio/mem.cc +++ b/repos/dde_bsd/src/lib/audio/mem.cc @@ -14,6 +14,7 @@ /* Genode includes */ #include #include +#include #include #include #include @@ -28,330 +29,32 @@ static bool const verbose = false; -namespace Bsd { - typedef Genode::addr_t addr_t; - - class Slab_backend_alloc; - class Slab_alloc; - class Malloc; -} +static Genode::Allocator *_malloc; -/** - * Back-end allocator for Genode's slab allocator - */ -class Bsd::Slab_backend_alloc : public Genode::Allocator, - public Genode::Rm_connection, - public Genode::Region_map_client +void Bsd::mem_init(Genode::Env &env, Genode::Allocator &) { - private: + /* + * The total amount of memory is small (around 140 KiB) and + * static throughout the drivers life-time. Although a mix + * of very small (4B) and some larger (32 KiB) allocations + * is performed, the heap is good enough. + */ + static Genode::Heap m(env.ram(), env.rm()); - enum { - VM_SIZE = 8 * 1024 * 1024, /* size of VM region to reserve */ - BLOCK_SIZE = 1024 * 1024, /* 1 MiB */ - ELEMENTS = VM_SIZE / BLOCK_SIZE, /* MAX number of dataspaces in VM */ - }; - - addr_t _base; /* virt. base address */ - Genode::Ram_dataspace_capability _ds_cap[ELEMENTS]; /* dataspaces to put in VM */ - addr_t _ds_phys[ELEMENTS]; /* physical bases of dataspaces */ - int _index; /* current index in ds_cap */ - Genode::Allocator_avl _range; /* manage allocations */ - Genode::Ram_allocator &_ram; /* allocator to allocate ds from */ - - struct Extend_ok { }; - using Extend_result = Genode::Attempt; - - Extend_result _extend_one_block() - { - using namespace Genode; - - if (_index == ELEMENTS) { - error("Slab-backend exhausted!"); - return Alloc_error::DENIED; - } - - return _ram.try_alloc(BLOCK_SIZE).convert( - - [&] (Ram_dataspace_capability ds) -> Extend_result { - - _ds_cap[_index] = ds; - - Alloc_error alloc_error = Alloc_error::DENIED; - - try { - Region_map_client::attach_at(_ds_cap[_index], - _index * BLOCK_SIZE, - BLOCK_SIZE, 0); - - /* return base + offset in VM area */ - addr_t block_base = _base + (_index * BLOCK_SIZE); - ++_index; - - _range.add_range(block_base, BLOCK_SIZE); - - return Extend_ok(); - } - catch (Out_of_ram) { alloc_error = Alloc_error::OUT_OF_RAM; } - catch (Out_of_caps) { alloc_error = Alloc_error::OUT_OF_CAPS; } - catch (...) { alloc_error = Alloc_error::DENIED; } - - error("Slab_backend_alloc: local attach_at failed"); - - _ram.free(ds); - _ds_cap[_index] = { }; - - return alloc_error; - }, - [&] (Alloc_error e) -> Extend_result { return e; }); - } - - public: - - Slab_backend_alloc(Genode::Env &env, Genode::Ram_allocator &ram, - Genode::Region_map &rm, Genode::Allocator &md_alloc) - : - Rm_connection(env), - Region_map_client(Rm_connection::create(VM_SIZE)), - _index(0), _range(&md_alloc), _ram(ram) - { - /* reserver attach us, anywere */ - _base = rm.attach(dataspace()); - } - - addr_t start() const { return _base; } - addr_t end() const { return _base + VM_SIZE - 1; } - - - /************************* - ** Allocator interface ** - *************************/ - - Alloc_result try_alloc(Genode::size_t size) override - { - Alloc_result result = _range.try_alloc(size); - if (result.ok()) - return result; - - return _extend_one_block().convert( - [&] (Extend_ok) { - return _range.try_alloc(size); }, - - [&] (Alloc_error e) { - Genode::error("Backend allocator exhausted\n"); - return e; }); - } - - void free(void *addr, Genode::size_t size) { _range.free(addr, size); } - Genode::size_t overhead(Genode::size_t size) const { return 0; } - bool need_size_for_free() const override { return false; } -}; - - -/** - * Slab allocator using our back-end allocator - */ -class Bsd::Slab_alloc : public Genode::Slab -{ - private: - - Genode::size_t const _object_size; - - static Genode::size_t _calculate_block_size(Genode::size_t object_size) - { - Genode::size_t const block_size = 8*object_size; - return Genode::align_addr(block_size, 12); - } - - public: - - Slab_alloc(Genode::size_t object_size, Slab_backend_alloc &allocator) - : - Slab(object_size, _calculate_block_size(object_size), 0, &allocator), - _object_size(object_size) - { } - - Genode::addr_t alloc() - { - return Slab::try_alloc(_object_size).convert( - [&] (void *ptr) { return (Genode::addr_t)ptr; }, - [&] (Alloc_error) -> Genode::addr_t { return 0; }); - } - - void free(void *ptr) { Slab::free(ptr, _object_size); } -}; - - -/** - * Memory interface - */ -class Bsd::Malloc -{ - private: - - enum { - SLAB_START_LOG2 = 5, /* 32 B */ - SLAB_STOP_LOG2 = 17, /* 128 KiB */ - NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1, - }; - - typedef Genode::addr_t addr_t; - typedef Bsd::Slab_alloc Slab_alloc; - typedef Bsd::Slab_backend_alloc Slab_backend_alloc; - - Slab_backend_alloc &_back_allocator; - Slab_alloc *_allocator[NUM_SLABS]; - addr_t _start; - addr_t _end; - - /** - * Set 'value' at 'addr' - */ - void _set_at(addr_t addr, addr_t value) { *((addr_t *)addr) = value; } - - /** - * Retrieve slab index belonging to given address - */ - unsigned _slab_index(Genode::addr_t **addr) - { - using namespace Genode; - /* get index */ - addr_t index = *(*addr - 1); - - /* - * If index large, we use aligned memory, retrieve beginning of slab entry - * and read index from there - */ - if (index > 32) { - *addr = (addr_t *)*(*addr - 1); - index = *(*addr - 1); - } - - return index; - } - - /** - * Get the originally requested size of the allocation - */ - Genode::size_t _get_orig_size(Genode::addr_t **addr) - { - using namespace Genode; - - addr_t index = *(*addr - 1); - if (index > 32) { - *addr = (addr_t *) * (*addr - 1); - } - - return *(*addr - 2); - } - - public: - - Malloc(Slab_backend_alloc &alloc, Genode::Allocator &md_alloc) - : - _back_allocator(alloc), _start(alloc.start()), - _end(alloc.end()) - { - /* init slab allocators */ - for (unsigned i = SLAB_START_LOG2; i <= SLAB_STOP_LOG2; i++) { - _allocator[i - SLAB_START_LOG2] = - new (&md_alloc) Slab_alloc(1U << i, _back_allocator); - } - } - - /** - * Alloc in slabs - */ - void *alloc(Genode::size_t size, int align = 0) - { - using namespace Genode; - - /* save requested size */ - Genode::size_t orig_size = size; - size += sizeof(addr_t); - - /* += slab index + aligment size */ - size += sizeof(addr_t) + (align > 2 ? (1 << align) : 0); - - int msb = Genode::log2(size); - - if (size > (1U << msb)) - msb++; - - if (size < (1U << SLAB_START_LOG2)) - msb = SLAB_STOP_LOG2; - - if (msb > SLAB_STOP_LOG2) { - Genode::error("Slab too large ", 1U << msb, " reqested ", size); - return 0; - } - - addr_t addr = _allocator[msb - SLAB_START_LOG2]->alloc(); - if (!addr) { - Genode::error("Failed to get slab for ", 1U << msb); - return 0; - } - - _set_at(addr, orig_size); - addr += sizeof(addr_t); - - _set_at(addr, msb - SLAB_START_LOG2); - addr += sizeof(addr_t); - - if (align > 2) { - /* save */ - addr_t ptr = addr; - addr_t align_val = (1U << align); - addr_t align_mask = align_val - 1; - /* align */ - addr = (addr + align_val) & ~align_mask; - /* write start address before aligned address */ - _set_at(addr - sizeof(addr_t), ptr); - } - - return (addr_t *)addr; - } - - void free(void const *a) - { - using namespace Genode; - addr_t *addr = (addr_t *)a; - - unsigned nr = _slab_index(&addr); - /* we need to decrease addr by 2, orig_size and index come first */ - _allocator[nr]->free((void *)(addr - 2)); - } - - Genode::size_t size(void const *a) - { - using namespace Genode; - addr_t *addr = (addr_t *)a; - - return _get_orig_size(&addr); - } - - bool inside(addr_t const addr) const { return (addr > _start) && (addr <= _end); } -}; - - -static Bsd::Malloc *_malloc; - - -void Bsd::mem_init(Genode::Env &env, Genode::Allocator &alloc) -{ - static Bsd::Slab_backend_alloc sb(env, env.ram(), env.rm(), alloc); - static Bsd::Malloc m(sb, alloc); _malloc = &m; } -static Bsd::Malloc& malloc_backend() { return *_malloc; } +static Genode::Allocator &malloc_backend() { return *_malloc; } /********************** ** Memory allocation * **********************/ +static size_t _mallocarray_dummy; + extern "C" void *malloc(size_t size, int type, int flags) { void *addr = malloc_backend().alloc(size); @@ -368,6 +71,15 @@ extern "C" void *mallocarray(size_t nmemb, size_t size, int type, int flags) if (size != 0 && nmemb > (~0UL / size)) return 0; + /* + * The azalia codec code might call mallocarray with + * nmemb == 0 as 'nopin' etc. can be 0. The allocation + * will not be used, so simple return a dummy as NULL + * will be treated as ENOMEM. + */ + if (nmemb == 0 || size == 0) + return &_mallocarray_dummy; + return malloc(nmemb * size, type, flags); } @@ -376,22 +88,10 @@ extern "C" void free(void *addr, int type, size_t size) { if (!addr) return; - if (!malloc_backend().inside((Genode::addr_t)addr)) { - Genode::error("cannot free unknown memory at ", __builtin_return_address(0), - " called from ", addr); + if (addr == &_mallocarray_dummy) return; - } - if (size) { - size_t ssize = malloc_backend().size(addr); - - if (ssize != size) { - Genode::warning("size: ", size, "for ", addr, - " does not match stored size: ", ssize); - } - } - - malloc_backend().free(addr); + malloc_backend().free(addr, size); } diff --git a/repos/dde_bsd/src/lib/audio/pci.cc b/repos/dde_bsd/src/lib/audio/pci.cc index e7cb960b9b..075269e83d 100644 --- a/repos/dde_bsd/src/lib/audio/pci.cc +++ b/repos/dde_bsd/src/lib/audio/pci.cc @@ -42,7 +42,7 @@ class Pci_driver { private: - enum { DMA_SIZE = 1024 * 1024 }; + enum { DMA_SIZE = 256 * 1024 }; Genode::Env & _env; Platform::Connection _pci { _env };