anv/stream_alloc: Properly manage valgrind NOACCESS and UNDEFINED status

When I first did the valgrindifying for stream allocators, I misunderstood
some things about valgrind's expectations for NOACCESS and UNDEFINED.
First off, valgrind expects things to be marked NOACCESS before you
allocate out of them.  Since our blocks came from a pool backed by a
mmapped memfd, they came in as UNDEFINED; we needed to mark them as
NOACCESS.  Also, I didn't realize that VALGRIND_MEMPOOL_CHANGE only updated
the mempool allocation state and didn't actually change definedness; we had
to add a VALGRIND_MAKE_MEM_UNDEFINED to get rid of the NOACCESS on the
newly allocated portion.
This commit is contained in:
Jason Ekstrand
2015-12-30 10:33:09 -08:00
parent 91d93f7908
commit a0b2829f20
+19 -3
View File
@@ -682,6 +682,14 @@ struct stream_block {
void *current_map;
#ifdef HAVE_VALGRIND
/* The pointer pointing to the beginning of the user portion of the
* block. More specifically, this value is:
*
* current_map + ALIGN(sizeof(stream_block), first_chunk_alignment)
*
* where first_chunk_alignment is the alignment of the first chunk
* allocated out of this particular block.
*/
void *_vg_ptr;
#endif
};
@@ -733,9 +741,13 @@ anv_state_stream_alloc(struct anv_state_stream *stream,
block = anv_block_pool_alloc(stream->block_pool);
void *current_map = stream->block_pool->map;
sb = current_map + block;
VG_NOACCESS_WRITE(&sb->current_map, current_map);
VG_NOACCESS_WRITE(&sb->next, stream->current_block);
VG(VG_NOACCESS_WRITE(&sb->_vg_ptr, 0));
sb->current_map = current_map;
sb->next = stream->current_block;
VG(sb->_vg_ptr = NULL);
/* Blocks come in from the block_pool as UNDEFINED */
VG(VALGRIND_MAKE_MEM_NOACCESS(sb, stream->block_pool->block_size));
stream->current_block = block;
stream->next = block + sizeof(*sb);
stream->end = block + stream->block_pool->block_size;
@@ -759,8 +771,12 @@ anv_state_stream_alloc(struct anv_state_stream *stream,
ptrdiff_t vg_offset = vg_ptr - current_map;
assert(vg_offset >= stream->current_block &&
vg_offset < stream->end);
/* This only updates the mempool. The newly allocated chunk is still
* marked as NOACCESS. */
VALGRIND_MEMPOOL_CHANGE(stream, vg_ptr, vg_ptr,
(state.offset + size) - vg_offset);
/* Mark the newly allocated chunk as undefined */
VALGRIND_MAKE_MEM_UNDEFINED(state.map, state.alloc_size);
}
#endif