mmap memory allocation - do not used when under valgrind

we can't sensibly use things like massif to track memory if we bypass
itr with mmaping -1 fd anonymous memory... so if built with valgrind
support and running under valgrind, use malloc/calloc and free so
these tools actually do something useful for these bits of memory.
This commit is contained in:
Carsten Haitzler 2018-01-12 02:59:34 +09:00
parent fb048e7312
commit f32f0d89f4
7 changed files with 217 additions and 99 deletions

View File

@ -24,6 +24,11 @@
# include "config.h"
# endif
#ifdef HAVE_VALGRIND
# include <valgrind.h>
# include <memcheck.h>
#endif
#ifdef HAVE_MMAP
# include <sys/mman.h>
@ -50,9 +55,15 @@ _eina_debug_chunk_need(int size)
{
void *ptr;
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED) return NULL;
#ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) ptr = malloc(size);
else
#endif
{
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED) return NULL;
}
return ptr;
}
@ -60,7 +71,11 @@ _eina_debug_chunk_need(int size)
static void
_eina_debug_chunk_noneed(void *ptr, int size)
{
munmap(ptr, size);
#ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) free(ptr);
else
#endif
munmap(ptr, size);
}
// push a new bit of mem on our growing stack of mem - given our workload,

View File

@ -20,6 +20,11 @@
# include "config.h"
#endif
#ifdef HAVE_VALGRIND
# include <valgrind.h>
# include <memcheck.h>
#endif
#include "Eina.h"
#include "eina_evlog.h"
#include "eina_debug.h"
@ -97,13 +102,19 @@ alloc_buf(Eina_Evlog_Buf *b, unsigned int size)
if (b->buf) return;
b->size = size;
b->top = 0;
# ifdef HAVE_MMAP
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);
#ifdef HAVE_MMAP
# ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) b->buf = malloc(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;
}
#else
b->buf = malloc(size);
#endif
b->overflow = 0;
}
@ -111,11 +122,15 @@ static void
free_buf(Eina_Evlog_Buf *b)
{
if (!b->buf) return;
# ifdef HAVE_MMAP
munmap(b->buf, b->size);
# else
free(b->buf);
#ifdef HAVE_MMAP
# ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) free(b->buf);
else
# endif
munmap(b->buf, b->size);
#else
free(b->buf);
#endif
b->buf = NULL;
b->size = 0;
b->top = 0;

View File

@ -2,6 +2,11 @@
# include "config.h"
#endif
#ifdef HAVE_VALGRIND
# include <valgrind.h>
# include <memcheck.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@ -66,26 +71,32 @@ static void *
_eina_safepointer_calloc(int number, size_t size)
{
#ifdef HAVE_MMAP
Eina_Memory_Header *header;
size_t newsize;
size = size * number + sizeof (Eina_Memory_Header);
newsize = ((size / MEM_PAGE_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)
# ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) return calloc(number, size);
else
# endif
{
ERR("mmap of Eina_Safepointer table region failed.");
return NULL;
Eina_Memory_Header *header;
size_t newsize;
size = size * number + sizeof (Eina_Memory_Header);
newsize = ((size / MEM_PAGE_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)
{
ERR("mmap of Eina_Safepointer table region failed.");
return NULL;
}
header->size = newsize;
EINA_MAGIC_SET(header, SAFEPOINTER_MAGIC);
return (void *)(header + 1);
}
header->size = newsize;
EINA_MAGIC_SET(header, SAFEPOINTER_MAGIC);
return (void*)(header + 1);
#else
return calloc(number, size);
#endif
@ -95,18 +106,24 @@ static void
_eina_safepointer_free(void *pointer)
{
#ifdef HAVE_MMAP
Eina_Memory_Header *header;
# ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) free((void *)((uintptr_t) pointer & ~0x3));
else
# endif
{
Eina_Memory_Header *header;
if (!pointer) return ;
if (!pointer) return;
header = (Eina_Memory_Header*)(pointer) - 1;
if (!EINA_MAGIC_CHECK(header, SAFEPOINTER_MAGIC))
EINA_MAGIC_FAIL(header, SAFEPOINTER_MAGIC);
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);
EINA_MAGIC_SET(header, 0);
munmap(header, header->size);
}
#else
free((void*) ((uintptr_t) pointer & ~0x3));
free((void *)((uintptr_t) pointer & ~0x3));
#endif
}
@ -115,15 +132,21 @@ static void
_eina_safepointer_protect(void *pointer, Eina_Bool may_not_write)
{
#ifdef HAVE_MMAP
Eina_Memory_Header *header;
# ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) { (void) pointer; }
else
# endif
{
Eina_Memory_Header *header;
if (!pointer) return ;
if (!pointer) return;
header = (Eina_Memory_Header*)(pointer) - 1;
if (!EINA_MAGIC_CHECK(header, SAFEPOINTER_MAGIC))
EINA_MAGIC_FAIL(header, SAFEPOINTER_MAGIC);
header = (Eina_Memory_Header*)(pointer) - 1;
if (!EINA_MAGIC_CHECK(header, SAFEPOINTER_MAGIC))
EINA_MAGIC_FAIL(header, SAFEPOINTER_MAGIC);
mprotect(header, header->size, PROT_READ | ( may_not_write ? 0 : PROT_WRITE));
mprotect(header, header->size, PROT_READ | ( may_not_write ? 0 : PROT_WRITE));
}
#else
(void) pointer;
#endif

View File

@ -1383,10 +1383,16 @@ static inline void
_eo_classes_release(void)
{
#ifdef HAVE_MMAP
size_t size;
# ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) free(_eo_classes);
else
# endif
{
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);
#endif
@ -1405,17 +1411,33 @@ _eo_classes_expand(void)
if (_eo_classes_last_id <= _eo_classes_alloc) return;
psize = _eo_classes_alloc * sizeof(_Efl_Class *);
#ifdef HAVE_MMAP
_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)
# ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND)
{
ERR("mmap of eo class table region failed!");
abort();
_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
# 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)
{
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;
newsize = _eo_classes_alloc * sizeof(_Efl_Class *);

View File

@ -2,6 +2,11 @@
# include <config.h>
#endif
#ifdef HAVE_VALGRIND
# include <valgrind.h>
# include <memcheck.h>
#endif
#if defined HAVE_DLADDR && ! defined _WIN32
# include <dlfcn.h>
#endif
@ -32,20 +37,26 @@ static void *
_eo_call_stack_mem_alloc(size_t size)
{
#ifdef HAVE_MMAP
// 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)
# ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) return calloc(1, size);
else
# endif
{
ERR("eo call stack mmap failed.");
return NULL;
// 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
return calloc(1, size);
@ -56,6 +67,10 @@ static void
_eo_call_stack_mem_free(void *ptr, size_t size)
{
#ifdef HAVE_MMAP
# ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) free(ptr);
else
# endif
munmap(ptr, size);
#else
(void) size;

View File

@ -6,6 +6,11 @@
#include <sys/mman.h>
#endif
#ifdef HAVE_VALGRIND
# include <valgrind.h>
# include <memcheck.h>
#endif
/* Start of pointer indirection:
*
* This feature is responsible of hiding from the developer the real pointer of
@ -149,23 +154,29 @@ static void *
_eo_id_mem_alloc(size_t size)
{
#ifdef HAVE_MMAP
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)
# ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) return malloc(size);
else
# endif
{
ERR("mmap of eo id table region failed!");
return NULL;
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);
#endif
@ -184,15 +195,21 @@ static void
_eo_id_mem_free(void *ptr)
{
#ifdef HAVE_MMAP
Mem_Header *hdr;
if (!ptr) return;
hdr = (Mem_Header *)(((unsigned char *)ptr) - MEM_HEADER_SIZE);
if (hdr->magic != MEM_MAGIC)
# ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) free(ptr);
else
# endif
{
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);
#endif
@ -203,15 +220,21 @@ static void
_eo_id_mem_protect(void *ptr, Eina_Bool may_not_write)
{
# ifdef HAVE_MMAP
Mem_Header *hdr;
if (!ptr) return;
hdr = (Mem_Header *)(((unsigned char *)ptr) - MEM_HEADER_SIZE);
if (hdr->magic != MEM_MAGIC)
# ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) { return; }
else
# endif
{
ERR("mprotect 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("mprotect of eo table region has bad magic!");
return;
}
mprotect(hdr, hdr->size, PROT_READ | ( may_not_write ? 0 : PROT_WRITE) );
}
mprotect(hdr, hdr->size, PROT_READ | ( may_not_write ? 0 : PROT_WRITE) );
# endif
}
# define PROTECT(_ptr_) _eo_id_mem_protect((_ptr_), EINA_TRUE)

View File

@ -17,6 +17,7 @@
//#include "evas_cs.h"
#ifdef HAVE_VALGRIND
# include <valgrind.h>
# include <memcheck.h>
#endif
@ -115,6 +116,10 @@ _evas_common_rgba_image_surface_size(unsigned int w, unsigned int h,
int siz, block_size = 8;
Eina_Bool reset_borders = EINA_TRUE;
#ifdef HAVE_VALGRIND
if (RUNNING_ON_VALGRIND) evas_image_no_mmap = 1;
#endif
if (EINA_UNLIKELY(evas_image_no_mmap == -1))
{
const char *s = getenv("EVAS_IMAGE_NO_MMAP");