lmdb: refines Valgrind usage.

Change-Id: I5f30a609b9053bbf8a693b7ca64dc57dc176f6e9
This commit is contained in:
Leo Yuriev 2015-01-18 00:29:31 +03:00
parent b6b2609f9e
commit ddbda992c7

110
mdb.c
View File

@ -271,18 +271,19 @@ union semun {
#endif /* !_WIN32 */ #endif /* !_WIN32 */
#ifdef USE_VALGRIND #ifdef USE_VALGRIND
#include <valgrind/memcheck.h> # include <valgrind/memcheck.h>
#define VGMEMP_CREATE(h,r,z) VALGRIND_CREATE_MEMPOOL(h,r,z)
#define VGMEMP_ALLOC(h,a,s) VALGRIND_MEMPOOL_ALLOC(h,a,s)
#define VGMEMP_FREE(h,a) VALGRIND_MEMPOOL_FREE(h,a)
#define VGMEMP_DESTROY(h) VALGRIND_DESTROY_MEMPOOL(h)
#define VGMEMP_DEFINED(a,s) VALGRIND_MAKE_MEM_DEFINED(a,s)
#else #else
#define VGMEMP_CREATE(h,r,z) # define VALGRIND_CREATE_MEMPOOL(h,r,z)
#define VGMEMP_ALLOC(h,a,s) # define VALGRIND_DESTROY_MEMPOOL(h)
#define VGMEMP_FREE(h,a) # define VALGRIND_MEMPOOL_TRIM(h,a,s)
#define VGMEMP_DESTROY(h) # define VALGRIND_MEMPOOL_ALLOC(h,a,s)
#define VGMEMP_DEFINED(a,s) # define VALGRIND_MEMPOOL_FREE(h,a)
# define VALGRIND_MEMPOOL_CHANGE(h,a,b,s)
# define VALGRIND_MAKE_MEM_NOACCESS(a,s)
# define VALGRIND_MAKE_MEM_DEFINED(a,s)
# define VALGRIND_MAKE_MEM_UNDEFINED(a,s)
# define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s)
# define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s)
#endif #endif
#ifndef BYTE_ORDER #ifndef BYTE_ORDER
@ -1380,6 +1381,9 @@ struct MDB_env {
size_t me_sync_size; /**< Tracking file size at last sync to decide when fsync() is needed */ size_t me_sync_size; /**< Tracking file size at last sync to decide when fsync() is needed */
#endif /* FDATASYNC_MAYBE_BROKEN */ #endif /* FDATASYNC_MAYBE_BROKEN */
MDB_oom_func *me_oom_func; /**< Callback for kicking laggard readers */ MDB_oom_func *me_oom_func; /**< Callback for kicking laggard readers */
#ifdef USE_VALGRIND
int me_valgrind_handle;
#endif
}; };
/** Nested transaction */ /** Nested transaction */
@ -1794,36 +1798,40 @@ static MDB_page *
mdb_page_malloc(MDB_txn *txn, unsigned num) mdb_page_malloc(MDB_txn *txn, unsigned num)
{ {
MDB_env *env = txn->mt_env; MDB_env *env = txn->mt_env;
MDB_page *ret = env->me_dpages; size_t size = env->me_psize;
size_t psize = env->me_psize, sz = psize, off; MDB_page *np = env->me_dpages;
/* For ! #MDB_NOMEMINIT, psize counts how much to init. if (num == 1 && np) {
* For a single page alloc, we init everything after the page header. VALGRIND_MEMPOOL_ALLOC(env, np, size);
VALGRIND_MAKE_MEM_DEFINED(&np->mp_next, sizeof(np->mp_next));
env->me_dpages = np->mp_next;
} else {
size *= num;
np = malloc(size);
if (! np) {
txn->mt_flags |= MDB_TXN_ERROR;
return np;
}
VALGRIND_MEMPOOL_ALLOC(env, np, size);
}
#ifdef LDAP_MEMORY_DEBUG
memset(np, 42, size);
#else
if ((env->me_flags & MDB_NOMEMINIT) == 0) {
/* For a single page alloc, we init everything after the page header.
* For multi-page, we init the final page; if the caller needed that * For multi-page, we init the final page; if the caller needed that
* many pages they will be filling in at least up to the last page. * many pages they will be filling in at least up to the last page.
*/ */
if (num == 1) { size_t skip = PAGEHDRSZ;
if (ret) { if (num > 1)
VGMEMP_ALLOC(env, ret, sz); skip += (num - 1) * env->me_psize;
VGMEMP_DEFINED(ret, sizeof(ret->mp_next)); memset((char *) np + skip, 0, size - skip);
env->me_dpages = ret->mp_next;
return ret;
} }
psize -= off = PAGEHDRSZ; #endif
} else { VALGRIND_MAKE_MEM_UNDEFINED(np, size);
sz *= num; return np;
off = sz - psize;
}
if ((ret = malloc(sz)) != NULL) {
VGMEMP_ALLOC(env, ret, sz);
if (!(env->me_flags & MDB_NOMEMINIT)) {
memset((char *)ret + off, 0, psize);
ret->mp_pad = 0;
}
} else {
txn->mt_flags |= MDB_TXN_ERROR;
}
return ret;
} }
/** Free a single page. /** Free a single page.
* Saves single pages to a list, for future reuse. * Saves single pages to a list, for future reuse.
* (This is not used for multi-page overflow pages.) * (This is not used for multi-page overflow pages.)
@ -1832,7 +1840,7 @@ static void
mdb_page_free(MDB_env *env, MDB_page *mp) mdb_page_free(MDB_env *env, MDB_page *mp)
{ {
mp->mp_next = env->me_dpages; mp->mp_next = env->me_dpages;
VGMEMP_FREE(env, mp); VALGRIND_MEMPOOL_FREE(env, mp);
env->me_dpages = mp; env->me_dpages = mp;
} }
@ -1844,7 +1852,7 @@ mdb_dpage_free(MDB_env *env, MDB_page *dp)
mdb_page_free(env, dp); mdb_page_free(env, dp);
} else { } else {
/* large pages just get freed directly */ /* large pages just get freed directly */
VGMEMP_FREE(env, dp); VALGRIND_MEMPOOL_FREE(env, dp);
free(dp); free(dp);
} }
} }
@ -2497,7 +2505,14 @@ search_done:
} else { } else {
txn->mt_next_pgno = pgno + num; txn->mt_next_pgno = pgno + num;
} }
#ifdef LDAP_MEMORY_DEBUG
memset(np, 111, env->me_psize * num);
#endif
VALGRIND_MAKE_MEM_UNDEFINED(np, env->me_psize * num);
np->mp_pgno = pgno; np->mp_pgno = pgno;
np->mp_pad = 0;
mdb_page_dirty(txn, np); mdb_page_dirty(txn, np);
*mp = np; *mp = np;
@ -4355,7 +4370,7 @@ mdb_env_create(MDB_env **env)
#endif #endif
e->me_pid = getpid(); e->me_pid = getpid();
GET_PAGESIZE(e->me_os_psize); GET_PAGESIZE(e->me_os_psize);
VGMEMP_CREATE(e,0,0); VALGRIND_CREATE_MEMPOOL(e,0,0);
*env = e; *env = e;
return MDB_SUCCESS; return MDB_SUCCESS;
} }
@ -4451,6 +4466,11 @@ mdb_env_map(MDB_env *env, void *addr)
return ErrCode(); return ErrCode();
#endif /* _WIN32 */ #endif /* _WIN32 */
#ifdef USE_VALGRIND
env->me_valgrind_handle = VALGRIND_CREATE_BLOCK(
env->me_map, env->me_mapsize, "lmdb");
#endif
return MDB_SUCCESS; return MDB_SUCCESS;
} }
@ -4476,6 +4496,10 @@ mdb_env_set_mapsize(MDB_env *env, size_t size)
size = minsize; size = minsize;
} }
munmap(env->me_map, env->me_mapsize); munmap(env->me_map, env->me_mapsize);
#ifdef USE_VALGRIND
VALGRIND_DISCARD(env->me_valgrind_handle);
env->me_valgrind_handle = -1;
#endif
env->me_mapsize = size; env->me_mapsize = size;
old = (env->me_flags & MDB_FIXEDMAP) ? env->me_map : NULL; old = (env->me_flags & MDB_FIXEDMAP) ? env->me_map : NULL;
rc = mdb_env_map(env, old); rc = mdb_env_map(env, old);
@ -5364,6 +5388,10 @@ mdb_env_close0(MDB_env *env, int excl)
if (env->me_map) { if (env->me_map) {
munmap(env->me_map, env->me_mapsize); munmap(env->me_map, env->me_mapsize);
#ifdef USE_VALGRIND
VALGRIND_DISCARD(env->me_valgrind_handle);
env->me_valgrind_handle = -1;
#endif
} }
if (env->me_mfd != env->me_fd && env->me_mfd != INVALID_HANDLE_VALUE) if (env->me_mfd != env->me_fd && env->me_mfd != INVALID_HANDLE_VALUE)
(void) close(env->me_mfd); (void) close(env->me_mfd);
@ -5426,9 +5454,9 @@ mdb_env_close(MDB_env *env)
if (env == NULL) if (env == NULL)
return; return;
VGMEMP_DESTROY(env); VALGRIND_DESTROY_MEMPOOL(env);
while ((dp = env->me_dpages) != NULL) { while ((dp = env->me_dpages) != NULL) {
VGMEMP_DEFINED(&dp->mp_next, sizeof(dp->mp_next)); VALGRIND_MAKE_MEM_DEFINED(&dp->mp_next, sizeof(dp->mp_next));
env->me_dpages = dp->mp_next; env->me_dpages = dp->mp_next;
free(dp); free(dp);
} }