예제 #1
0
static Block* 
sec_block_create (size_t size,
                  const char *during_tag)
{
	Block *block;
	Cell *cell;

	ASSERT (during_tag);

	/* We can force all all memory to be malloced */
	if (getenv ("SECMEM_FORCE_FALLBACK"))
		return NULL;

	block = pool_alloc ();
	if (!block)
		return NULL;

	cell = pool_alloc ();
	if (!cell) {
		pool_free (block);
		return NULL;
	}

	/* The size above is a minimum, we're free to go bigger */
	if (size < DEFAULT_BLOCK_SIZE)
		size = DEFAULT_BLOCK_SIZE;
		
	block->words = sec_acquire_pages (&size, during_tag);
	block->n_words = size / sizeof (word_t);
	if (!block->words) {
		pool_free (block);
		pool_free (cell);
		return NULL;
	}
	
#ifdef WITH_VALGRIND
	VALGRIND_MAKE_MEM_DEFINED (block->words, size);
#endif
	
	/* The first cell to allocate from */
	cell->words = block->words;
	cell->n_words = block->n_words;
	cell->requested = 0;
	sec_write_guards (cell);
	sec_insert_cell_ring (&block->unused_cells, cell);

	block->next = all_blocks;
	all_blocks = block;
	
	return block;
}
예제 #2
0
static void*
sec_free (Block *block, void *memory)
{
	Cell *cell, *other;
	word_t *word;

	ASSERT (block);
	ASSERT (memory);

	word = memory;
	--word;

#ifdef WITH_VALGRIND
	VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
#endif

	/* Lookup the meta for this memory block (using guard pointer) */
	ASSERT (sec_is_valid_word (block, word));
	ASSERT (pool_valid (*word));
	cell = *word;

#ifdef WITH_VALGRIND
	VALGRIND_MAKE_MEM_DEFINED (cell->words, cell->n_words * sizeof (word_t));
#endif

	sec_check_guards (cell);
	sec_clear_memory (memory, 0, cell->allocated);

	sec_check_guards (cell);
	ASSERT (cell->next == NULL);
	ASSERT (cell->prev == NULL);
	ASSERT (cell->allocated > 0);

        /* Find previous unallocated neighbor, and merge if possible */
        other = sec_neighbor_before (block, cell);
        if (other && other->allocated == 0) {
        	ASSERT (other->next && other->prev);
        	other->n_words += cell->n_words;
        	sec_write_guards (other);
        	pool_free (cell);
        	cell = other;
        }

        /* Find next unallocated neighbor, and merge if possible */
        other = sec_neighbor_after (block, cell);
        if (other && other->allocated == 0) {
        	ASSERT (other->next && other->prev);
        	other->n_words += cell->n_words;
        	other->words = cell->words;
        	if (cell->next)
        		sec_remove_cell_ring (&block->unused, cell);
        	sec_write_guards (other);
        	pool_free (cell);
        	cell = other;
        }

        /* Add to the unused list if not already there */
        if (!cell->next)
        	sec_insert_cell_ring (&block->unused, cell);

        cell->allocated = 0;
        --block->used;
        return NULL;
}
예제 #3
0
static void*
sec_alloc (Block *block,
           const char *tag,
           size_t length)
{
	Cell *cell, *other;
	size_t n_words;
	void *memory;
	
	ASSERT (block);
	ASSERT (length);
	ASSERT (tag);

	if (!block->unused_cells)
		return NULL;

	/* 
	 * Each memory allocation is aligned to a pointer size, and 
	 * then, sandwidched between two pointers to its meta data.
	 * These pointers also act as guards.
	 *
	 * We allocate memory in units of sizeof (void*) 
	 */
	
	n_words = sec_size_to_words (length) + 2;
	
	/* Look for a cell of at least our required size */
	cell = block->unused_cells;
	while (cell->n_words < n_words) {
		cell = cell->next;
		if (cell == block->unused_cells) {
			cell = NULL;
			break;
		}
	}
	
	if (!cell)
		return NULL;

	ASSERT (cell->tag == NULL);
	ASSERT (cell->requested == 0);
	ASSERT (cell->prev);
	ASSERT (cell->words);
	sec_check_guards (cell);
	
	/* Steal from the cell if it's too long */
	if (cell->n_words > n_words + WASTE) {
		other = pool_alloc ();
		if (!other)
			return NULL;
		other->n_words = n_words;
		other->words = cell->words;
		cell->n_words -= n_words;
		cell->words += n_words;
		
		sec_write_guards (other);
		sec_write_guards (cell);
		
		cell = other;
	}
	
	if (cell->next)
		sec_remove_cell_ring (&block->unused_cells, cell);

	++block->n_used;
	cell->tag = tag;
	cell->requested = length;
	sec_insert_cell_ring (&block->used_cells, cell);
	memory = sec_cell_to_memory (cell);
	
#ifdef WITH_VALGRIND
	VALGRIND_MAKE_MEM_UNDEFINED (memory, length);
#endif
	
	return memset (memory, 0, length);
}