#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>
};
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)
{}
_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);
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;
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.
*
*/
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); }
: 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;
}
void release()
{
_active_instance = Invalid_inst;
+ pthread_mutex_unlock(&_mtx);
}
/*
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);
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);
}
* 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;
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'.