efl mem - every mmap anon - allow envv ar to turn it off to be malloc

helps with memory debug to use libc mallocs/callocs etc.
set EFL_NO_MMAP_ANON env var to anything to stop anon mmaps
This commit is contained in:
Carsten Haitzler 2021-09-06 10:03:22 +01:00
parent ab02b4fa46
commit 14946e9cf4
7 changed files with 168 additions and 70 deletions

View File

@ -54,6 +54,8 @@ static int chunk2_num = 0;
static int chunk3_size = 0; static int chunk3_size = 0;
static int chunk3_num = 0; static int chunk3_num = 0;
static int no_anon = -1;
// get a new chunk of "anonymous mmaped memory" // get a new chunk of "anonymous mmaped memory"
static void * static void *
_eina_debug_chunk_need(int size) _eina_debug_chunk_need(int size)
@ -65,9 +67,18 @@ _eina_debug_chunk_need(int size)
else else
#endif #endif
{ {
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, if (no_anon == -1)
MAP_PRIVATE | MAP_ANON, -1, 0); {
if (ptr == MAP_FAILED) return NULL; if (getenv("EFL_NO_MMAP_ANON")) no_anon = 1;
else no_anon = 0;
}
if (no_anon == 1) ptr = malloc(size);
else
{
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED) return NULL;
}
} }
return ptr; return ptr;
} }
@ -80,7 +91,10 @@ _eina_debug_chunk_noneed(void *ptr, int size)
if (RUNNING_ON_VALGRIND) free(ptr); if (RUNNING_ON_VALGRIND) free(ptr);
else else
#endif #endif
munmap(ptr, size); {
if (no_anon == 1) free(ptr);
else munmap(ptr, size);
}
} }
// push a new bit of mem on our growing stack of mem - given our workload, // push a new bit of mem on our growing stack of mem - given our workload,

View File

@ -94,6 +94,8 @@ get_time(void)
#endif #endif
} }
static int no_anon = -1;
static void static void
alloc_buf(Eina_Evlog_Buf *b, unsigned int size) alloc_buf(Eina_Evlog_Buf *b, unsigned int size)
{ {
@ -106,9 +108,18 @@ alloc_buf(Eina_Evlog_Buf *b, unsigned int size)
else else
# endif # endif
{ {
b->buf = mmap(NULL, size, PROT_READ | PROT_WRITE, if (no_anon == -1)
MAP_PRIVATE | MAP_ANON, -1, 0); {
if (b->buf == MAP_FAILED) b->buf = NULL; if (getenv("EFL_NO_MMAP_ANON")) no_anon = 1;
else no_anon = 0;
}
if (no_anon == 1) b->buf = malloc(size);
else
{
b->buf = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (b->buf == MAP_FAILED) b->buf = NULL;
}
} }
#else #else
b->buf = malloc(size); b->buf = malloc(size);
@ -125,7 +136,10 @@ free_buf(Eina_Evlog_Buf *b)
if (RUNNING_ON_VALGRIND) free(b->buf); if (RUNNING_ON_VALGRIND) free(b->buf);
else else
# endif # endif
munmap(b->buf, b->size); {
if (no_anon == 1) free(b->buf);
else munmap(b->buf, b->size);
}
#else #else
free(b->buf); free(b->buf);
#endif #endif

View File

@ -72,6 +72,8 @@ static Eina_Spinlock sl;
#define MEM_PAGE_SIZE 4096 #define MEM_PAGE_SIZE 4096
#define SAFEPOINTER_MAGIC 0x7DEADC03 #define SAFEPOINTER_MAGIC 0x7DEADC03
static int no_anon = -1;
static void * static void *
_eina_safepointer_calloc(int number, size_t size) _eina_safepointer_calloc(int number, size_t size)
{ {
@ -89,12 +91,21 @@ _eina_safepointer_calloc(int number, size_t size)
(size % MEM_PAGE_SIZE ? 1 : 0)) (size % MEM_PAGE_SIZE ? 1 : 0))
* MEM_PAGE_SIZE; * MEM_PAGE_SIZE;
header = mmap(NULL, newsize, PROT_READ | PROT_WRITE, if (no_anon == -1)
MAP_PRIVATE | MAP_ANON, -1, 0);
if (header == MAP_FAILED)
{ {
ERR("mmap of Eina_Safepointer table region failed."); if (getenv("EFL_NO_MMAP_ANON")) no_anon = 1;
return NULL; else no_anon = 0;
}
if (no_anon == 1) header = calloc(number, size);
else
{
header = mmap(NULL, newsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (header == MAP_FAILED)
{
ERR("mmap of Eina_Safepointer table region failed.");
return NULL;
}
} }
header->size = newsize; header->size = newsize;
@ -120,12 +131,15 @@ _eina_safepointer_free(void *pointer)
if (!pointer) return; if (!pointer) return;
header = (Eina_Memory_Header*)(pointer) - 1; if (no_anon == 1) free((void *)((uintptr_t) pointer & ~0x3));
if (!EINA_MAGIC_CHECK(header, SAFEPOINTER_MAGIC)) else
EINA_MAGIC_FAIL(header, SAFEPOINTER_MAGIC); {
header = (Eina_Memory_Header*)(pointer) - 1;
EINA_MAGIC_SET(header, 0); if (!EINA_MAGIC_CHECK(header, SAFEPOINTER_MAGIC))
munmap(header, header->size); EINA_MAGIC_FAIL(header, SAFEPOINTER_MAGIC);
EINA_MAGIC_SET(header, 0);
munmap(header, header->size);
}
} }
#else #else
free((void *)((uintptr_t) pointer & ~0x3)); free((void *)((uintptr_t) pointer & ~0x3));

View File

@ -1488,6 +1488,8 @@ eo_class_free(_Efl_Class *klass)
eina_freeq_ptr_main_add(klass, free, 0); eina_freeq_ptr_main_add(klass, free, 0);
} }
int _eo_no_anon = -1;
static inline void static inline void
_eo_classes_release(void) _eo_classes_release(void)
{ {
@ -1497,10 +1499,14 @@ _eo_classes_release(void)
else else
# endif # endif
{ {
size_t size; if (_eo_no_anon == 1) free(_eo_classes);
else
{
size_t size;
size = _eo_classes_alloc * sizeof(_Efl_Class *); size = _eo_classes_alloc * sizeof(_Efl_Class *);
if (_eo_classes) munmap(_eo_classes, size); if (_eo_classes) munmap(_eo_classes, size);
}
} }
#else #else
free(_eo_classes); free(_eo_classes);
@ -1535,17 +1541,36 @@ _eo_classes_expand(void)
else else
# endif # endif
{ {
_eo_classes_alloc += (MEM_PAGE_SIZE / sizeof(_Efl_Class *)); if (_eo_no_anon == -1)
newsize = _eo_classes_alloc * sizeof(_Efl_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!"); if (getenv("EFL_NO_MMAP_ANON")) _eo_no_anon = 1;
abort(); else _eo_no_anon = 0;
}
if (_eo_no_anon == 1)
{
_eo_classes_alloc += 128;
newsize = _eo_classes_alloc * sizeof(_Efl_Class *);
ptr = realloc(_eo_classes, newsize);
if (!ptr)
{
ERR("realloc of eo class table region faile!!");
abort();
}
}
else
{
_eo_classes_alloc += (MEM_PAGE_SIZE / sizeof(_Efl_Class *));
newsize = _eo_classes_alloc * sizeof(_Efl_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);
} }
if (psize > 0) memcpy(ptr, _eo_classes, psize);
if (_eo_classes) munmap(_eo_classes, psize);
} }
#else #else
_eo_classes_alloc += 128; _eo_classes_alloc += 128;

View File

@ -42,20 +42,29 @@ _eo_call_stack_mem_alloc(size_t size)
else else
# endif # endif
{ {
// allocate eo call stack via mmped anon segment if on linux - more if (_eo_no_anon == -1)
// secure and safe. also gives page aligned memory allowing madvise
void *ptr;
size_t newsize;
newsize = MEM_PAGE_SIZE * ((size + MEM_PAGE_SIZE - 1) /
MEM_PAGE_SIZE);
ptr = mmap(NULL, newsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED)
{ {
ERR("eo call stack mmap failed."); if (getenv("EFL_NO_MMAP_ANON")) _eo_no_anon = 1;
return NULL; else _eo_no_anon = 0;
}
if (_eo_no_anon == 1) return calloc(1, size);
else
{
// allocate eo call stack via mmped anon segment if on linux - more
// secure and safe. also gives page aligned memory allowing madvise
void *ptr;
size_t newsize;
newsize = MEM_PAGE_SIZE * ((size + MEM_PAGE_SIZE - 1) /
MEM_PAGE_SIZE);
ptr = mmap(NULL, newsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED)
{
ERR("eo call stack mmap failed.");
return NULL;
}
return ptr;
} }
return ptr;
} }
#else #else
//in regular cases just use malloc //in regular cases just use malloc
@ -71,7 +80,10 @@ _eo_call_stack_mem_free(void *ptr, size_t size)
if (RUNNING_ON_VALGRIND) free(ptr); if (RUNNING_ON_VALGRIND) free(ptr);
else else
# endif # endif
munmap(ptr, size); {
if (_eo_no_anon == 1) free(ptr);
else munmap(ptr, size);
}
#else #else
(void) size; (void) size;
free(ptr); free(ptr);

View File

@ -153,6 +153,8 @@ typedef struct _Mem_Header
size_t magic; size_t magic;
} Mem_Header; } Mem_Header;
extern int _eo_no_anon;
static void * static void *
_eo_id_mem_alloc(size_t size) _eo_id_mem_alloc(size_t size)
{ {
@ -162,23 +164,32 @@ _eo_id_mem_alloc(size_t size)
else else
# endif # endif
{ {
void *ptr; if (_eo_no_anon == -1)
Mem_Header *hdr;
size_t newsize;
newsize = MEM_PAGE_SIZE * ((size + MEM_HEADER_SIZE + MEM_PAGE_SIZE - 1) /
MEM_PAGE_SIZE);
ptr = mmap(NULL, newsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED)
{ {
ERR("mmap of eo id table region failed!"); if (getenv("EFL_NO_MMAP_ANON")) _eo_no_anon = 1;
return NULL; else _eo_no_anon = 0;
}
if (_eo_no_anon == 1) return malloc(size);
else
{
void *ptr;
Mem_Header *hdr;
size_t newsize;
newsize = MEM_PAGE_SIZE * ((size + MEM_HEADER_SIZE + MEM_PAGE_SIZE - 1) /
MEM_PAGE_SIZE);
ptr = mmap(NULL, newsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED)
{
ERR("mmap of eo id table region failed!");
return NULL;
}
hdr = ptr;
hdr->size = newsize;
hdr->magic = MEM_MAGIC;
/* DBG("asked:%lu allocated:%lu wasted:%lu bytes", size, newsize, (newsize - size)); */
return (void *)(((unsigned char *)ptr) + MEM_HEADER_SIZE);
} }
hdr = ptr;
hdr->size = newsize;
hdr->magic = MEM_MAGIC;
/* DBG("asked:%lu allocated:%lu wasted:%lu bytes", size, newsize, (newsize - size)); */
return (void *)(((unsigned char *)ptr) + MEM_HEADER_SIZE);
} }
#else #else
return malloc(size); return malloc(size);
@ -203,15 +214,19 @@ _eo_id_mem_free(void *ptr)
else else
# endif # endif
{ {
Mem_Header *hdr; if (_eo_no_anon == 1) free(ptr);
if (!ptr) return; else
hdr = (Mem_Header *)(((unsigned char *)ptr) - MEM_HEADER_SIZE);
if (hdr->magic != MEM_MAGIC)
{ {
ERR("unmap of eo table region has bad magic!"); Mem_Header *hdr;
return; if (!ptr) return;
hdr = (Mem_Header *)(((unsigned char *)ptr) - MEM_HEADER_SIZE);
if (hdr->magic != MEM_MAGIC)
{
ERR("unmap of eo table region has bad magic!");
return;
}
munmap(hdr, hdr->size);
} }
munmap(hdr, hdr->size);
} }
#else #else
free(ptr); free(ptr);

View File

@ -103,10 +103,14 @@ _evas_common_rgba_image_surface_size(unsigned int w, unsigned int h,
if (EINA_UNLIKELY(evas_image_no_mmap == -1)) if (EINA_UNLIKELY(evas_image_no_mmap == -1))
{ {
const char *s = getenv("EVAS_IMAGE_NO_MMAP"); if (getenv("EFL_NO_MMAP_ANON")) evas_image_no_mmap = 1;
evas_image_no_mmap = s && (atoi(s)); else
if (evas_image_no_mmap) {
WRN("EVAS_IMAGE_NO_MMAP is set, use this only for debugging!"); const char *s = getenv("EVAS_IMAGE_NO_MMAP");
evas_image_no_mmap = s && (atoi(s));
if (evas_image_no_mmap)
WRN("EVAS_IMAGE_NO_MMAP is set, use this only for debugging!");
}
} }
switch (cspace) switch (cspace)