eo - class table - move to mmaped memory if possible and alloc chunks

so memory for class id -> ptrs is mallocs. this means it likely will
be next to other memory malloced. which means overrunning memory
someone mallocs could walk into the class table and corrupt it. we put
eo ids in mmaped regions to avoid this if possible in case of buggy
code. let's do it for classes too.

this also now allocs in larger chunks. for mmap its in page chunks
(which can hold either 1024 or 512 classes depending on 32 or 64bit).
reallocs still work if mmap is not there and we do them in chunks of
128 classes (it seems that we start at about 70 or so classes atm when
elm_test starts and it grows to ~100 or let's do 128 as that's pretty
much our base as a power of 2 and we now dont realloc much).
This commit is contained in:
Carsten Haitzler 2016-04-24 12:00:37 +09:00
parent bbcde33f93
commit 09cdd364f9
1 changed files with 61 additions and 17 deletions

View File

@ -23,8 +23,9 @@ EAPI Eina_Spinlock _eo_class_creation_lock;
EAPI unsigned int _eo_init_generation = 1;
int _eo_log_dom = -1;
static _Eo_Class **_eo_classes;
static Eo_Id _eo_classes_last_id;
static _Eo_Class **_eo_classes = NULL;
static Eo_Id _eo_classes_last_id = 0;
static Eo_Id _eo_classes_alloc = 0;
static int _eo_init_count = 0;
static Eo_Op _eo_ops_last_id = 0;
static Eina_Hash *_ops_storage = NULL;
@ -961,6 +962,57 @@ _eo_class_isa_func(Eo *eo_id EINA_UNUSED, void *class_data EINA_UNUSED, va_list
/* Do nonthing. */
}
static inline void
_eo_classes_release(void)
{
#ifdef HAVE_MMAP
size_t size;
size = _eo_classes_alloc * sizeof(_Eo_Class *);
if (_eo_classes) munmap(_eo_classes, size);
#else
free(_eo_classes);
#endif
_eo_classes = NULL;
_eo_classes_last_id = 0;
_eo_classes_alloc = 0;
}
static inline void
_eo_classes_expand(void)
{
unsigned char *ptr;
size_t newsize, psize;
_eo_classes_last_id++;
if (_eo_classes_last_id <= _eo_classes_alloc) return;
psize = _eo_classes_alloc * sizeof(_Eo_Class *);
#ifdef HAVE_MMAP
_eo_classes_alloc += (MEM_PAGE_SIZE / sizeof(_Eo_Class *));
newsize = _eo_classes_alloc * sizeof(_Eo_Class *);
ptr = mmap(NULL, newsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED)
{
ERR("mmap of eo class table region failed!");
abort();
}
if (psize > 0) memcpy(ptr, _eo_classes, psize);
if (_eo_classes) munmap(_eo_classes, psize);
#else
_eo_classes_alloc += 128;
newsize = _eo_classes_alloc * sizeof(_Eo_Class *);
ptr = realloc(_eo_classes, newsize);
if (!ptr)
{
ERR("realloc of eo class table region faile!!");
abort();
}
#endif
memset(ptr + psize, 0, newsize - psize);
_eo_classes = (_Eo_Class **)ptr;
}
EAPI const Eo_Class *
eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...)
{
@ -1220,21 +1272,12 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...)
}
{
Eo_Id new_id = ++_eo_classes_last_id | MASK_CLASS_TAG;
Eo_Id new_id;
eina_spinlock_take(&_eo_class_creation_lock);
/* FIXME: Handle errors. */
size_t arrsize = _eo_classes_last_id * sizeof(*_eo_classes);
_Eo_Class **tmp;
tmp = realloc(_eo_classes, arrsize);
/* If it's the first allocation, memset. */
if (!_eo_classes)
memset(tmp, 0, arrsize);
_eo_classes = tmp;
new_id = (_eo_classes_last_id + 1) | MASK_CLASS_TAG;
_eo_classes_expand();
_eo_classes[_UNMASK_ID(new_id) - 1] = klass;
eina_spinlock_release(&_eo_class_creation_lock);
klass->header.id = new_id;
@ -1645,8 +1688,9 @@ eo_shutdown(void)
eo_class_free(*cls_itr);
}
if (_eo_classes)
free(_eo_classes);
eina_spinlock_take(&_eo_class_creation_lock);
_eo_classes_release();
eina_spinlock_release(&_eo_class_creation_lock);
eina_hash_free(_ops_storage);