Skip to content

Commit c18051d

Browse files
committed
Initial support for valgrind
See #3
1 parent d04a5c6 commit c18051d

File tree

7 files changed

+7526
-11
lines changed

7 files changed

+7526
-11
lines changed

CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ endif()
1515
# Enable GNU glibc extentions.
1616
add_definitions("-D_GNU_SOURCE")
1717

18+
# Valgrind
19+
include_directories(third_party)
20+
1821
set(lib_headers
1922
small/ibuf.h
2023
small/lf_lifo.h
@@ -54,6 +57,13 @@ if(DEFINED SMALL_EMBEDDED)
5457
return()
5558
endif()
5659

60+
option(ENABLE_VALGRIND "Enable integration with valgrind, a memory analyzing tool" OFF)
61+
if (NOT ENABLE_VALGRIND)
62+
add_definitions(-DNVALGRIND=1)
63+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-value")
64+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-value")
65+
endif()
66+
5767
add_library(${PROJECT_NAME}_shared SHARED ${lib_sources})
5868
set_target_properties(${PROJECT_NAME}_shared PROPERTIES VERSION 1.0 SOVERSION 1)
5969
set_target_properties(${PROJECT_NAME}_shared PROPERTIES OUTPUT_NAME ${PROJECT_NAME})

small/mempool.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
#include "mempool.h"
3232
#include <stdlib.h>
3333
#include <string.h>
34+
#include <valgrind/valgrind.h>
35+
#include <valgrind/memcheck.h>
36+
3437
#include "slab_cache.h"
3538

3639
/* slab fragmentation must reach 1/8 before it's recycled */
@@ -90,6 +93,8 @@ mslab_free(struct mempool *pool, struct mslab *slab, void *ptr)
9093
/* put object to garbage list */
9194
*(void **)ptr = slab->free_list;
9295
slab->free_list = ptr;
96+
VALGRIND_FREELIKE_BLOCK(ptr, 0);
97+
VALGRIND_MAKE_MEM_DEFINED(ptr, sizeof(void *));
9398

9499
slab->nfree++;
95100

@@ -195,7 +200,10 @@ mempool_alloc(struct mempool *pool)
195200
pool->first_hot_slab = slab;
196201
}
197202
pool->slabs.stats.used += pool->objsize;
198-
return mslab_alloc(pool, slab);
203+
void *ptr = mslab_alloc(pool, slab);
204+
assert(ptr != NULL);
205+
VALGRIND_MALLOCLIKE_BLOCK(ptr, pool->objsize, 0, 0);
206+
return ptr;
199207
}
200208

201209
void

small/region.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
*/
3131
#include "region.h"
3232
#include <sys/types.h> /* ssize_t */
33+
#include <valgrind/valgrind.h>
34+
#include <valgrind/memcheck.h>
3335

3436
void *
3537
region_reserve_slow(struct region *region, size_t size)
@@ -48,6 +50,7 @@ region_reserve_slow(struct region *region, size_t size)
4850
* region_truncate() won't work.
4951
*/
5052
slab_list_add(&region->slabs, &slab->slab, next_in_list);
53+
VALGRIND_MALLOCLIKE_BLOCK(rslab_data(slab), rslab_unused(slab), 0, 0);
5154
return rslab_data(slab);
5255
}
5356

small/slab_arena.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
#include <assert.h>
3939
#include <limits.h>
4040
#include "pmatomic.h"
41+
#include <valgrind/valgrind.h>
42+
#include <valgrind/memcheck.h>
4143

4244
#if !defined(MAP_ANONYMOUS)
4345
#define MAP_ANONYMOUS MAP_ANON
@@ -127,6 +129,8 @@ slab_arena_create(struct slab_arena *arena, struct quota *quota,
127129
{
128130
assert(flags & (MAP_PRIVATE | MAP_SHARED));
129131
lf_lifo_init(&arena->cache);
132+
VALGRIND_MAKE_MEM_DEFINED(&arena->cache, sizeof(struct lf_lifo));
133+
130134
/*
131135
* Round up the user supplied data - it can come in
132136
* directly from the configuration file. Allow
@@ -178,32 +182,42 @@ void *
178182
slab_map(struct slab_arena *arena)
179183
{
180184
void *ptr;
181-
if ((ptr = lf_lifo_pop(&arena->cache)))
185+
if ((ptr = lf_lifo_pop(&arena->cache))) {
186+
VALGRIND_MAKE_MEM_UNDEFINED(ptr, arena->slab_size);
182187
return ptr;
188+
}
183189

184190
if (quota_use(arena->quota, arena->slab_size) < 0)
185191
return NULL;
186192

187193
/** Need to allocate a new slab. */
188194
size_t used = pm_atomic_fetch_add(&arena->used, arena->slab_size);
189195
used += arena->slab_size;
190-
if (used <= arena->prealloc)
191-
return arena->arena + used - arena->slab_size;
196+
if (used <= arena->prealloc) {
197+
ptr = arena->arena + used - arena->slab_size;
198+
VALGRIND_MAKE_MEM_UNDEFINED(ptr, arena->slab_size);
199+
return ptr;
200+
}
192201

193202
ptr = mmap_checked(arena->slab_size, arena->slab_size,
194203
arena->flags);
195204
if (!ptr) {
196205
__sync_sub_and_fetch(&arena->used, arena->slab_size);
197206
quota_release(arena->quota, arena->slab_size);
198207
}
208+
VALGRIND_MAKE_MEM_UNDEFINED(ptr, arena->slab_size);
199209
return ptr;
200210
}
201211

202212
void
203213
slab_unmap(struct slab_arena *arena, void *ptr)
204214
{
205-
if (ptr)
206-
lf_lifo_push(&arena->cache, ptr);
215+
if (ptr == NULL)
216+
return;
217+
218+
lf_lifo_push(&arena->cache, ptr);
219+
VALGRIND_MAKE_MEM_NOACCESS(ptr, arena->slab_size);
220+
VALGRIND_MAKE_MEM_DEFINED(lf_lifo(ptr), sizeof(struct lf_lifo));
207221
}
208222

209223
void

small/slab_cache.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#include <stdio.h>
3737
#include <stdbool.h>
3838
#include <unistd.h>
39+
#include <valgrind/valgrind.h>
40+
#include <valgrind/memcheck.h>
3941

4042
const uint32_t slab_magic = 0xeec0ffee;
4143

@@ -73,6 +75,7 @@ slab_set_free(struct slab_cache *cache, struct slab *slab)
7375
cache->allocated.stats.used -= slab->size;
7476
cache->orders[slab->order].stats.used -= slab->size;
7577
slab->in_use = 0;
78+
VALGRIND_MEMPOOL_FREE(cache, slab_data(slab));
7679
}
7780

7881
static inline void
@@ -82,6 +85,7 @@ slab_set_used(struct slab_cache *cache, struct slab *slab)
8285
cache->orders[slab->order].stats.used += slab->size;
8386
/* Not a boolean to have an extra assert. */
8487
slab->in_use = 1 + slab->order;
88+
VALGRIND_MEMPOOL_ALLOC(cache, slab_data(slab), slab_capacity(slab));
8589
}
8690

8791
static inline bool
@@ -95,10 +99,11 @@ slab_poison(struct slab *slab)
9599
{
96100
(void)slab;
97101
#ifndef NDEBUG
102+
VALGRIND_MAKE_MEM_UNDEFINED(slab_data(slab), slab_capacity(slab));
98103
const char poison_char = 'P';
99-
memset((char *) slab + slab_sizeof(), poison_char,
100-
slab->size - slab_sizeof());
104+
memset(slab_data(slab), poison_char, slab_capacity(slab));
101105
#endif
106+
VALGRIND_MAKE_MEM_NOACCESS(slab_data(slab), slab_capacity(slab));
102107
}
103108

104109
static inline void
@@ -130,9 +135,12 @@ slab_split(struct slab_cache *cache, struct slab *slab)
130135
size_t new_size = slab_order_size(cache, new_order);
131136

132137
slab_create(slab, new_order, new_size);
138+
133139
struct slab *buddy = slab_buddy(cache, slab);
140+
VALGRIND_MAKE_MEM_UNDEFINED(buddy, sizeof(*buddy));
134141
slab_create(buddy, new_order, new_size);
135142
slab_list_add(&cache->orders[buddy->order], buddy, next_in_list);
143+
136144
return slab;
137145
}
138146

@@ -171,6 +179,8 @@ slab_cache_create(struct slab_cache *cache, struct slab_arena *arena)
171179
for (i = 0; i <= cache->order_max; i++)
172180
slab_list_create(&cache->orders[i]);
173181
slab_cache_set_thread(cache);
182+
VALGRIND_CREATE_MEMPOOL_EXT(cache, 0, 0, VALGRIND_MEMPOOL_METAPOOL |
183+
VALGRIND_MEMPOOL_AUTO_FREE);
174184
}
175185

176186
void
@@ -184,11 +194,14 @@ slab_cache_destroy(struct slab_cache *cache)
184194
*/
185195
struct slab *slab, *tmp;
186196
rlist_foreach_entry_safe(slab, slabs, next_in_cache, tmp) {
187-
if (slab->order == cache->order_max + 1)
197+
if (slab->order == cache->order_max + 1) {
198+
VALGRIND_MEMPOOL_FREE(cache, slab_data(slab));
188199
free(slab);
189-
else
200+
} else {
190201
slab_unmap(cache->arena, slab);
202+
}
191203
}
204+
VALGRIND_DESTROY_MEMPOOL(cache);
192205
}
193206

194207
struct slab *
@@ -260,6 +273,8 @@ slab_get(struct slab_cache *cache, size_t size)
260273
slab_create(slab, order, size);
261274
slab_list_add(&cache->allocated, slab, next_in_cache);
262275
cache->allocated.stats.used += size;
276+
VALGRIND_MEMPOOL_ALLOC(cache, slab_data(slab),
277+
slab_capacity(slab));
263278
return slab;
264279
}
265280
return slab_get_with_order(cache, order);
@@ -275,8 +290,11 @@ slab_put(struct slab_cache *cache, struct slab *slab)
275290
* Free a huge slab right away, we have no
276291
* further business to do with it.
277292
*/
293+
uint32_t slab_size = slab->size;
278294
slab_list_del(&cache->allocated, slab, next_in_cache);
279-
cache->allocated.stats.used -= slab->size;
295+
cache->allocated.stats.used -= slab_size;
296+
slab_poison(slab);
297+
VALGRIND_MEMPOOL_FREE(cache, slab_data(slab));
280298
free(slab);
281299
return;
282300
}

0 commit comments

Comments
 (0)