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_num = 0;
static int no_anon = -1;
// get a new chunk of "anonymous mmaped memory"
static void *
_eina_debug_chunk_need(int size)
@ -65,9 +67,18 @@ _eina_debug_chunk_need(int size)
else
#endif
{
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED) return NULL;
if (no_anon == -1)
{
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;
}
@ -80,7 +91,10 @@ _eina_debug_chunk_noneed(void *ptr, int size)
if (RUNNING_ON_VALGRIND) free(ptr);
else
#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,

View File

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

View File

@ -72,6 +72,8 @@ static Eina_Spinlock sl;
#define MEM_PAGE_SIZE 4096
#define SAFEPOINTER_MAGIC 0x7DEADC03
static int no_anon = -1;
static void *
_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))
* MEM_PAGE_SIZE;
header = mmap(NULL, newsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (header == MAP_FAILED)
if (no_anon == -1)
{
ERR("mmap of Eina_Safepointer table region failed.");
return NULL;
if (getenv("EFL_NO_MMAP_ANON")) no_anon = 1;
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;
@ -120,12 +131,15 @@ _eina_safepointer_free(void *pointer)
if (!pointer) return;
header = (Eina_Memory_Header*)(pointer) - 1;
if (!EINA_MAGIC_CHECK(header, SAFEPOINTER_MAGIC))
EINA_MAGIC_FAIL(header, SAFEPOINTER_MAGIC);
EINA_MAGIC_SET(header, 0);
munmap(header, header->size);
if (no_anon == 1) free((void *)((uintptr_t) pointer & ~0x3));
else
{
header = (Eina_Memory_Header*)(pointer) - 1;
if (!EINA_MAGIC_CHECK(header, SAFEPOINTER_MAGIC))
EINA_MAGIC_FAIL(header, SAFEPOINTER_MAGIC);
EINA_MAGIC_SET(header, 0);
munmap(header, header->size);
}
}
#else
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);
}
int _eo_no_anon = -1;
static inline void
_eo_classes_release(void)
{
@ -1497,10 +1499,14 @@ _eo_classes_release(void)
else
# endif
{
size_t size;
if (_eo_no_anon == 1) free(_eo_classes);
else
{
size_t size;
size = _eo_classes_alloc * sizeof(_Efl_Class *);
if (_eo_classes) munmap(_eo_classes, size);
size = _eo_classes_alloc * sizeof(_Efl_Class *);
if (_eo_classes) munmap(_eo_classes, size);
}
}
#else
free(_eo_classes);
@ -1535,17 +1541,36 @@ _eo_classes_expand(void)
else
# endif
{
_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)
if (_eo_no_anon == -1)
{
ERR("mmap of eo class table region failed!");
abort();
if (getenv("EFL_NO_MMAP_ANON")) _eo_no_anon = 1;
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
_eo_classes_alloc += 128;

View File

@ -42,20 +42,29 @@ _eo_call_stack_mem_alloc(size_t size)
else
# endif
{
// 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)
if (_eo_no_anon == -1)
{
ERR("eo call stack mmap failed.");
return NULL;
if (getenv("EFL_NO_MMAP_ANON")) _eo_no_anon = 1;
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
//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);
else
# endif
munmap(ptr, size);
{
if (_eo_no_anon == 1) free(ptr);
else munmap(ptr, size);
}
#else
(void) size;
free(ptr);

View File

@ -153,6 +153,8 @@ typedef struct _Mem_Header
size_t magic;
} Mem_Header;
extern int _eo_no_anon;
static void *
_eo_id_mem_alloc(size_t size)
{
@ -162,23 +164,32 @@ _eo_id_mem_alloc(size_t size)
else
# endif
{
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)
if (_eo_no_anon == -1)
{
ERR("mmap of eo id table region failed!");
return NULL;
if (getenv("EFL_NO_MMAP_ANON")) _eo_no_anon = 1;
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
return malloc(size);
@ -203,15 +214,19 @@ _eo_id_mem_free(void *ptr)
else
# endif
{
Mem_Header *hdr;
if (!ptr) return;
hdr = (Mem_Header *)(((unsigned char *)ptr) - MEM_HEADER_SIZE);
if (hdr->magic != MEM_MAGIC)
if (_eo_no_anon == 1) free(ptr);
else
{
ERR("unmap of eo table region has bad magic!");
return;
Mem_Header *hdr;
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
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))
{
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!");
if (getenv("EFL_NO_MMAP_ANON")) evas_image_no_mmap = 1;
else
{
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)