]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/plr/server/src/memory
update
[l4.git] / l4 / pkg / plr / server / src / memory
index 07d282a9fbe1e77aebc42d8b3359d01d68a6ee56..c592fda762b110a2008edf029d245f37297f6543 100644 (file)
@@ -28,6 +28,7 @@
 #include <l4/re/util/region_mapping>
 #include <l4/re/util/dataspace_svr>
 #include <l4/util/bitops.h>
+#include <l4/util/rdtsc.h>
 
 #include <l4/sys/kdebug.h>
 
@@ -146,23 +147,26 @@ namespace Romain
                        };
 
                private:
-                       l4_cap_idx_t             _cap;       // capability of the underlying dataspace
+                       l4_cap_idx_t             _cap;        // capability of the underlying dataspace
                        Romain::Region            _local_regions[Romain::MAX_REPLICAS]; // replicated regions (writable regions exist in
                                                                                            // multiple instances)
-                       l4_addr_t                _offs;      // offset in DS
+                       l4_addr_t                _offs;       // offset in DS
                        DS                       _mem[Romain::MAX_REPLICAS]; // DS capabilities of underlying dataspaces
-                       unsigned char            _flags;     // region flags
-                       RegionWritableType       _row;       // rw state
-                       bool                     _shared;    // is DS shared across all replicas
-                                                            // (true for internal determinism's lock info page)
-                       l4_umword_t              _alignment; // alignment of this DS within master
+                       unsigned char            _flags;      // region flags
+                       RegionWritableType       _row;        // rw state
+                       bool                     _shared;     // is DS shared across all replicas
+                                                             // (true for internal determinism's lock info page)
+                       l4_umword_t              _alignment;  // alignment of this DS within master
+                       l4_umword_t              _align_diff; // diff between alignment and real start address
+                                                             // (see Region_map::attach_locally() for an explanation)
+                       l4_umword_t              _numpf;      // page faults seen on this region
 
                public:
 
                        Region_handler_template()
                                : _cap(L4_INVALID_CAP),  _offs(0), _flags(),
                              _row(Romain::Region_handler_template<DS, OPS>::Read_only),
-                             _shared(false), _alignment(L4_PAGESHIFT)
+                             _shared(false), _alignment(L4_PAGESHIFT), _align_diff(0), _numpf(0)
                        {}
 
 
@@ -172,7 +176,9 @@ namespace Romain
                                  _flags(o.flags()),
                                  _row(o.writable()),
                                  _shared(o.shared()),
-                                 _alignment(o.alignment())
+                                 _alignment(o.alignment()),
+                                 _align_diff(o.align_diff()),
+                                 _numpf(o.numpf())
                        {
                                for (unsigned i = 0; i < o.local_region_count(); ++i) {
                                        _local_regions[i] = o.local_region(i);
@@ -182,7 +188,8 @@ namespace Romain
 
                        Region_handler_template(DSCAP cap, l4_cap_idx_t client_cap = L4_INVALID_CAP, l4_addr_t offset = 0,
                                                unsigned flags = 0, Romain::Region local_reg = Romain::Region(0,0))
-                               : _cap(client_cap), _offs(offset), _flags(flags), _shared(false), _alignment(L4_PAGESHIFT)
+                               : _cap(client_cap), _offs(offset), _flags(flags), _shared(false),
+                                 _alignment(L4_PAGESHIFT), _align_diff(0), _numpf(0)
                        {
                                _local_regions[0] = local_reg;
                                _mem[0]           = cap;
@@ -229,7 +236,10 @@ namespace Romain
 
                        bool         shared() const throw()                 { return _shared; }
                        void         shared(bool yn) { _shared = yn; }
-                       l4_umword_t  alignment() const throw()                          { return _alignment; }
+                       l4_addr_t    alignment() const throw()                          { return _alignment; }
+                       l4_addr_t    align_diff() const throw()             { return _align_diff; }
+                       l4_umword_t  numpf() const throw()                  { return _numpf; }
+                       void         count_pf() throw()                     { _numpf++; }
 
                        /* Compute the target alignment for attaching locally.
                         *
@@ -240,19 +250,36 @@ namespace Romain
                         */
                        void alignToAddressAndSize(l4_addr_t address, l4_size_t size)
                        {
-                               _alignment = l4util_bsf(address);
-                               DEBUG() << std::hex << address << " --> target alignment: "
-                                       << _alignment;
-                               if (_alignment > L4_SUPERPAGESHIFT) {
-                                       _alignment = L4_SUPERPAGESHIFT;
+                               enum {
+                                       MIN_ALIGNMENT = 
+                                       //12, /* 4 kB -> minimum! */
+                                       //16, /* 64 kB */
+                                           //19, /* 512 kB */
+                                       22, /* 4 MB */
+                               };
+
+                               DEBUG() << "alignToAddressAndSize(" << std::hex << address
+                                       << ", " << size << ")";
+
+                               l4_addr_t min_align = MIN_ALIGNMENT;
+                               if (size < (1 << MIN_ALIGNMENT)) {
+                                       min_align = l4util_bsr(size);
                                }
-                               DEBUG() << std::hex << address << " --> [max: super page] alignment: "
-                                       << _alignment;
-                               if (_alignment > l4util_bsr(size)) {
-                                       _alignment = l4util_bsr(size);
+                               DEBUG() << "Minimum alignment: " << std::hex << min_align;
+
+                               if (min_align > L4_SUPERPAGESHIFT) {
+                                       min_align = L4_SUPERPAGESHIFT;
                                }
-                               DEBUG() << std::hex << address << " --> [max: size " << size
-                                       << "] alignment: " << _alignment;
+                               DEBUG() << std::hex << address
+                                       << " --> [max: super page] alignment: "
+                                       << min_align;
+
+                               _alignment             = min_align;
+                               l4_umword_t align_mask = (1 << _alignment) - 1;
+                               _align_diff            = address & align_mask;
+                               DEBUG() << std::hex << address << " --> align diff =  "
+                                       << align_diff();
+
                        }
 
                        void         take() const                           { Ops::take(this); }
@@ -306,12 +333,14 @@ namespace Romain
                : public L4Re::Util::Region_map<Romain::Region_handler,
                                                Romain::Allocator>
        {
+               pthread_mutex_t _mtx;
                public:
                        typedef L4Re::Util::Region_map<Romain::Region_handler, Romain::Allocator> Base;
                        enum { Invalid_inst = ~0U };
 
                        void activate(unsigned inst)
                        {
+                               pthread_mutex_lock(&_mtx);
                                _check(_active_instance != Invalid_inst, "rm already used, lock!!!");
                                _active_instance = inst;
                        }
@@ -319,6 +348,7 @@ namespace Romain
                        void release()
                        {
                                _active_instance = Invalid_inst;
+                               pthread_mutex_unlock(&_mtx);
                        }
 
                        /*
@@ -343,20 +373,31 @@ namespace Romain
 
                        bool copy_existing_mapping(Romain::Region_handler& r,
                                                   unsigned orig_id,
-                                                  unsigned inst_id) const
+                                                  unsigned inst_id,
+                                                  bool writepf = false) const
                        {
                                if (orig_id == inst_id) return true;
 
                                L4::Cap<L4Re::Dataspace> mem;
                                unsigned long size = r.local_region(orig_id).size();
 
-                               l4_addr_t a = Romain::Region_map::allocate_and_attach(&mem, size, 0, r.alignment());
+                               DEBUG() << "copy existing: " << std::hex << r.alignment()
+                                       << " diff " << r.align_diff();
+                               l4_addr_t a = Romain::Region_map::allocate_and_attach(&mem, size,
+                                                                                 0,  0,
+                                                                                 r.alignment(),
+                                                                                 r.align_diff());
                                _check(a == 0, "DS allocation failed");
 
+#if 0
+                               DEBUG() << "COPY: DS " << std::hex << mem.cap() << " SIZE " << size
+                                       << " attached @ " << a;
+                               DEBUG() << "memcpy(" << (void*)a << ", "
+                                       << (void*)r.local_region(orig_id).start()
+                                       << ", " << size << ")";
+#endif
                                memcpy((void*)a, (void*)r.local_region(orig_id).start(), size);
 
-                               //DEBUG() << "COPY: DS " << std::hex << mem.cap() << " SIZE " << size
-                               //      << " attached @ " << a;
                                r.set_local_region(inst_id, Romain::Region(a, a+size-1));
                                r.memory(inst_id, mem);
 
@@ -370,28 +411,66 @@ namespace Romain
                        static void
                        allocate_ds(L4::Cap<L4Re::Dataspace> *cap, unsigned size)
                        {
+                               unsigned long flags = 0;
+                               if (size >= L4_SUPERPAGESIZE) {
+                                       flags |= L4Re::Mem_alloc::Super_pages;
+                                       flags |= L4Re::Mem_alloc::Continuous;
+                               }
+                               
                                *cap = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
                                _check(!cap->is_valid(), "error allocating DS capability");
 
-                               int error = L4Re::Env::env()->mem_alloc()->alloc(size, *cap);
+                               int error = L4Re::Env::env()->mem_alloc()->alloc(size, *cap, flags);
                                _check(error != 0, "error allocating memory");
                        }
 
 
+                       static l4_addr_t
+                       attach_aligned(L4::Cap<L4Re::Dataspace> const * ds, unsigned size,
+                                      unsigned offs = 0, unsigned flags = 0,
+                                      unsigned align = L4_PAGESHIFT, unsigned aligndiff = 0)
+                       {
+                               l4_addr_t a           = 0;
+                               l4_addr_t search_size = size + aligndiff;
+
+                               l4_umword_t r = L4Re::Env::env()->rm()->reserve_area(&a, search_size,
+                                                                                    L4Re::Rm::Search_addr | flags,
+                                                                                    align);
+                               _check(r != 0, "reserve area failed");
+                               DEBUG() << std::hex << "Reserved area at " << a << " and will attach to "
+                                       << a + aligndiff;
+
+                               a += aligndiff;
+                               l4_addr_t tmp_a = a;
+
+                               r = L4Re::Env::env()->rm()->attach(&a, size, L4Re::Rm::In_area | L4Re::Rm::Eager_map | flags,
+                                                                  *ds, offs);
+                               _check(r != 0, "attach error");
+                               _check(a != tmp_a, "did not attach to correct location");
+
+                               DEBUG() << "att: " << (void*)a;
+
+                               r = L4Re::Env::env()->rm()->free_area(a);
+                               _check(r != 0, "free area failed");
+
+                               return a;
+                       }
+
+
                        /*
                         * Allocate and attach a master-local dataspace object.
                         */
                        static l4_addr_t
                        allocate_and_attach(L4::Cap<L4Re::Dataspace> *cap, unsigned size,
-                                               unsigned offs = 0, unsigned align = L4_PAGESHIFT)
+                                               unsigned offs = 0, unsigned flags = 0,
+                                               unsigned align = L4_PAGESHIFT,
+                                               unsigned aligndiff = 0)
                        {
                                Romain::Region_map::allocate_ds(cap, size);
 
-                               l4_addr_t a = 0;
-                               int error = L4Re::Env::env()->rm()->attach(&a, size, L4Re::Rm::Search_addr, *cap, offs, align);
-                               _check(error != 0, "attach failed");
-
-                               return a;
+                               return Romain::Region_map::attach_aligned(cap, size, offs,
+                                                                         flags, align,
+                                                                         aligndiff);
                        }
 
 
@@ -399,7 +478,7 @@ namespace Romain
                         * Check if a node already has a mapping to one of the replicas. If so,
                         * take a shortcut mapping to the next one (determined by inst parameter).
                         */
-                       bool lazy_map_region(Romain::Region_map::Base::Node &n, unsigned inst);
+                       bool lazy_map_region(Romain::Region_map::Base::Node &n, unsigned inst, bool writepf=false);
 
                private:
                        unsigned _active_instance;
@@ -430,6 +509,9 @@ namespace Romain
                        void *attach(void* addr, unsigned long size, Romain::Region_handler const &hdlr,
                                     unsigned flags = None, unsigned char align=L4_PAGESHIFT, bool shared = false);
 
+                       int detach(void* addr, unsigned long size, unsigned flags,
+                       L4Re::Util::Region* reg, Romain::Region_handler* h);
+
                        /*
                         * Copy the content of all writable regions of instance 'from' to
                         * the respective regions of instance 'to'.