Malloc / free ansd rump_fs ->Slab-backend exhausted

w_schmidt at ...181... w_schmidt at ...181...
Mon Aug 18 20:09:04 CEST 2014


Hi,

>> this seems to be happen only if rump_fs has a larger quota – the file
>> can be larger if rump_fs has a smaller quota. (memory tests of the
>> system have shown no errors so RAM should be okay)

>this is indeed very strange. I hope you have a Genode version where
>there is no Slab-Backend allocator, have a look at
'>include/util/allocator_fap.h" in the dde_rump repository, there should
>only be a PERR message with the slab warning left.

The file looks like below,

Best regards,
wOlfgang

/**
* \brief  Fast allocator for porting
* \author Sebastian Sumpf
* \date   2013-06-12
*/

/*
* Copyright (C) 2013-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 _INCLUDE__UTIL__ALLOCATOR_FAP_H_
#define _INCLUDE__UTIL__ALLOCATOR_FAP_H_

#include <base/allocator_avl.h>
#include <dataspace/client.h>
#include <rm_session/connection.h>


namespace Allocator {
    template <unsigned VM_SIZE, typename POLICY> class Backend_alloc;
    template <unsigned VM_SIZE, typename POLICY> class Fap;
}


namespace Allocator {

    using namespace Genode;

    struct Default_allocator_policy
    {
        static int  block()      { return 0; }
        static void unblock(int) { }
    };

    template <typename POLICY>
    struct Policy_guard
    {
        int val;
        Policy_guard()  { val = POLICY::block(); }
        ~Policy_guard() { POLICY::unblock(val); }
    };

    /**
     * Back-end allocator for Genode's slab allocator
     */
    template <unsigned VM_SIZE, typename POLICY = Default_allocator_policy>
    class Backend_alloc : public Genode::Allocator,
                          public Genode::Rm_connection
    {
        private:

            enum {
                BLOCK_SIZE = 1024  * 1024,         /* 1 MB */
                ELEMENTS   = VM_SIZE / BLOCK_SIZE, /* MAX number of 
dataspaces in VM */
            };

            typedef Genode::addr_t addr_t;
            typedef Genode::Ram_dataspace_capability 
Ram_dataspace_capability;
            typedef Genode::Allocator_avl Allocator_avl;

            addr_t                   _base;              /* virt. base 
address */
            Cache_attribute          _cached;            /* non-/cached RAM 
*/
            Ram_dataspace_capability _ds_cap[ELEMENTS];  /* dataspaces to 
put in VM */
            addr_t                   _ds_phys[ELEMENTS]; /* physical bases 
of dataspaces */
            int                      _index = 0;         /* current index in 
ds_cap */
            Allocator_avl            _range;             /* manage 
allocations */
            bool                     _quota_exceeded = false;

            bool _alloc_block()
            {
                if (_quota_exceeded)
                    return false;

                if (_index == ELEMENTS) {
                    PERR("Slab-backend exhausted!");
                    return false;
                }

                Policy_guard<POLICY> guard;

                try {
                    _ds_cap[_index] = 
Genode::env()->ram_session()->alloc(BLOCK_SIZE, _cached);
                    /* attach at index * BLOCK_SIZE */
                    Rm_connection::attach_at(_ds_cap[_index], _index * 
BLOCK_SIZE, BLOCK_SIZE, 0);
                    /* lookup phys. address */
                    _ds_phys[_index] = 
Genode::Dataspace_client(_ds_cap[_index]).phys_addr();
                } catch (Genode::Ram_session::Quota_exceeded) {
                    PWRN("Backend allocator exhausted");
                    _quota_exceeded = true;
                    return false;
                } catch (Genode::Rm_session::Attach_failed) {
                    PWRN("Backend VM region exhausted");
                    _quota_exceeded = true;
                    return false;
                }

                /* return base + offset in VM area */
                addr_t block_base = _base + (_index * BLOCK_SIZE);
                ++_index;

                _range.add_range(block_base, BLOCK_SIZE);
                return true;
            }

        public:

            Backend_alloc(Cache_attribute cached)
            : Rm_connection(0, VM_SIZE), _cached(cached),
              _range(Genode::env()->heap())
            {
                /* reserver attach us, anywere */
                _base = Genode::env()->rm_session()->attach(dataspace());
            }

            /**
             * Allocate
             */
            bool alloc(size_t size, void **out_addr)
            {
                bool done = _range.alloc(size, out_addr);

                if (done)
                    return done;

                done = _alloc_block();
                if (!done)
                    return false;

                return _range.alloc(size, out_addr);
            }

            void *alloc_aligned(size_t size, int align = 0)
            {
                void *addr;

                if (!_range.alloc_aligned(size, &addr, align).is_error())
                    return addr;

                if (!_alloc_block())
                    return 0;

                if (_range.alloc_aligned(size, &addr, align).is_error()) {
                    PERR("Backend allocator: Unable to allocate memory 
(size: %zu align: %d:)",
                         size, align);
                    return 0;
                }

                return addr;
            }

            void   free(void *addr, size_t size) { _range.free(addr, 
size); }
            size_t overhead(size_t size) { return  0; }
            bool need_size_for_free() const override { return false; }

            /**
             * Return phys address for given virtual addr.
             */
            addr_t phys_addr(addr_t addr)
            {
                if (addr < _base || addr >= (_base + VM_SIZE))
                    return ~0UL;

                int index = (addr - _base) / BLOCK_SIZE;

                /* physical base of dataspace */
                addr_t phys = _ds_phys[index];

                if (!phys)
                    return ~0UL;

                /* add offset */
                phys += (addr - _base - (index * BLOCK_SIZE));
                return phys;
            }

            bool inside(addr_t addr) const { return (addr >= _base) && (addr 
< (_base + VM_SIZE)); }
    };


    /**
     * Interface
     */
    template <unsigned VM_SIZE, typename POLICY = Default_allocator_policy>
    class Fap
    {
        private:

            typedef Allocator::Backend_alloc<VM_SIZE, POLICY> Backend_alloc;

            Backend_alloc  _back_allocator;

        public:

            Fap(bool cached)
            : _back_allocator(cached ? CACHED : UNCACHED) { }

            void *alloc(size_t size, int align = 0)
            {
                return _back_allocator.alloc_aligned(size, align);
            }

            void free(void *addr, size_t size)
            {
                _back_allocator.free(addr, size);
            }

            addr_t phys_addr(void *addr)
            {
                return _back_allocator.phys_addr((addr_t)addr);
            }
    };
} /* namespace Allocator */

#endif /* _INCLUDE__UTIL__ALLOCATOR_FAP_H_ */ 





More information about the users mailing list