Beispiel #1
0
APR_DECLARE_NONSTD(void *) apr_bucket_alloc(apr_size_t in_size,
                                            apr_bucket_alloc_t *list)
{
    node_header_t *node;
    apr_memnode_t *active = list->blocks;
    char *endp;
    apr_size_t size;

    size = in_size + SIZEOF_NODE_HEADER_T;
    if (size <= SMALL_NODE_SIZE) {
        if (list->freelist) {
            node = list->freelist;
            list->freelist = node->next;
            APR_VALGRIND_UNDEFINED((char *)node + SIZEOF_NODE_HEADER_T,
                                   SMALL_NODE_SIZE - SIZEOF_NODE_HEADER_T);
        }
        else {
            endp = active->first_avail + SMALL_NODE_SIZE;
            if (endp >= active->endp) {
                list->blocks = apr_allocator_alloc(list->allocator, ALLOC_AMT);
                if (!list->blocks) {
                    list->blocks = active;
                    return NULL;
                }
                list->blocks->next = active;
                active = list->blocks;
                endp = active->first_avail + SMALL_NODE_SIZE;
                APR_VALGRIND_NOACCESS(active->first_avail,
                                      active->endp - active->first_avail);
            }
            node = (node_header_t *)active->first_avail;
            APR_VALGRIND_UNDEFINED(node, SMALL_NODE_SIZE);
            node->alloc = list;
            node->memnode = active;
            node->size = SMALL_NODE_SIZE;
            active->first_avail = endp;
        }
    }
    else {
        apr_memnode_t *memnode = apr_allocator_alloc(list->allocator, size);
        if (!memnode) {
            return NULL;
        }
        node = (node_header_t *)memnode->first_avail;
        node->alloc = list;
        node->memnode = memnode;
        node->size = size;
    }
    return ((char *)node) + SIZEOF_NODE_HEADER_T;
}
Beispiel #2
0
heap_t *heap_make(apr_pool_t *pool)
{
	apr_memnode_t *node;
	heap_t *hp = apr_palloc(pool, sizeof(*hp));
	hp->allocator = apr_pool_allocator_get(pool);
	
	node = apr_allocator_alloc(hp->allocator, HEAP_INIT_SIZE);
	if (node == NULL)
		return NULL;
	node->next = node;
	node->ref = &node->next;

	hp->active = node;
	
	//hp->htop = node->first_avail;
	hp->hend = node->first_avail;

	hp->alloc_size = 0;

	// gc never run, on the first run active node will be cleansed
	hp->gc_last = NULL;
	hp->gc_spot = NULL;

	// make sure the memory is freed when the pool
	// is cleared/destroyed
	apr_pool_cleanup_register(pool, hp, heap_destroy, 0);

	return hp;
}
Beispiel #3
0
buffer_t *buffer_make(apr_pool_t *pool, int max)
{
	buffer_t *buf = apr_palloc(pool, sizeof(*buf));
	buf->allocator = apr_pool_allocator_get(pool);
	buf->node = apr_allocator_alloc(buf->allocator, max);
	buf->offset = 0;
	return buf;
}
Beispiel #4
0
/*  	=================================================================================
	本函数的逻辑就是:
	if (size <= SMALL_NODE_SIZE){
		if(list中还有节点){
			从list中取走一个node返回
		}
		else{
			取当前node的剩余空间,或新分配一个node返回
		}
	}
	else {
		从allocator分配一个node返回
	}

	算法不好的地方就是,只要list中还有空node,就不会利用好当前节点剩余空间,
	直接使用新的node
 ====================================================================================*/
APU_DECLARE_NONSTD(void *) apr_bucket_alloc(apr_size_t size, 
                                            apr_bucket_alloc_t *list)
{
    node_header_t *node;
    apr_memnode_t *active = list->blocks;
    char *endp;

    size += SIZEOF_NODE_HEADER_T;
    if (size <= SMALL_NODE_SIZE) {
		//如果list还有剩余节点,则分配第一个节点出去,list去除已分配出去的那个节点
        if (list->freelist) {
            node = list->freelist;
            list->freelist = node->next;
        }
        else {
            endp = active->first_avail + SMALL_NODE_SIZE;
            if (endp >= active->endp) {
                list->blocks = apr_allocator_alloc(list->allocator, ALLOC_AMT);
                if (!list->blocks) {
                    list->blocks = active;
                    return NULL;
                }
                list->blocks->next = active;
                active = list->blocks;
                endp = active->first_avail + SMALL_NODE_SIZE;
            }
            node = (node_header_t *)active->first_avail;
            node->alloc = list;
            node->memnode = active;
            node->size = SMALL_NODE_SIZE;
            active->first_avail = endp;
        }
    }
    else {
        apr_memnode_t *memnode = apr_allocator_alloc(list->allocator, size);
        if (!memnode) {
            return NULL;
        }
        node = (node_header_t *)memnode->first_avail;
        node->alloc = list;
        node->memnode = memnode;
        node->size = size;
    }
    return ((char *)node) + SIZEOF_NODE_HEADER_T;
}
Beispiel #5
0
void buffer_resize(buffer_t *self, int avail)
{
	int size, new_size;
	apr_memnode_t *new_node;

	if (buffer_available(self) >= avail)
		return;
	size = buffer_len(self);
	new_size = size + avail;
	new_node = apr_allocator_alloc(self->allocator, new_size);
	memcpy((char *)new_node + APR_MEMNODE_T_SIZE, buffer_ptr(self), size);
	apr_allocator_free(self->allocator, self->node);
	self->node = new_node;
	self->offset = 0;
}
Beispiel #6
0
void heap_secure_space(heap_t *hp, int size)
{
	apr_memnode_t *active = hp->active;

	if (hp->hend + size > active->endp)
	{
		int anticipated_size = hp->hend - heap_htop(hp);
		active = apr_allocator_alloc(hp->allocator, anticipated_size + size);
		list_insert(active, hp->active);
		hp->active = active;

		//hp->htop = active->first_avail;
		hp->hend = heap_htop(hp) + anticipated_size;
	}

	hp->hend += size;
}
Beispiel #7
0
APU_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create_ex(
                                             apr_allocator_t *allocator)
{
    apr_bucket_alloc_t *list;
    apr_memnode_t *block;

    block = apr_allocator_alloc(allocator, ALLOC_AMT);
    if (!block) {
        return NULL;
    }
    list = (apr_bucket_alloc_t *)block->first_avail;
    list->pool = NULL;
    list->allocator = allocator;
    list->freelist = NULL;
    list->blocks = block;
    block->first_avail += APR_ALIGN_DEFAULT(sizeof(*list));

    return list;
}
Beispiel #8
0
apr_status_t heap_gc(heap_t *hp, term_t *roots[], int root_sizes[], int nroots)
{
	apr_memnode_t *saved_active;
	apr_memnode_t *gc_node, *copy_node;
	int node_size;
	int i, j;

	if (hp->gc_last == NULL)	// gc never run
		gc_node = hp->active;
	else
		gc_node = hp->gc_last->next;

	node_size = node_alloc_size(gc_node);

	// if gc_last node has enough space then use it for
	// live term copies, otherwise, create a new node
	// NB: gc_last may point to gc_node

	if (hp->gc_last != NULL && hp->gc_last != gc_node && node_free_space(hp->gc_last) >= node_size)
		copy_node = hp->gc_last;
	else
		copy_node = apr_allocator_alloc(hp->allocator, node_size);

	// temporarily make copy_node active; restore later
	saved_active = hp->active;
	hp->active = copy_node;
	hp->hend = heap_htop(hp);

	// save gc_node reference for seek_alive;
	// non-NULL gc_spot means gc in progress
	hp->gc_spot = gc_node;

	for (i = 0; i < nroots; i++)
		for (j = 0; j < root_sizes[i]; j++)
			seek_live(&roots[i][j], saved_active, hp);

	assert(hp->active == copy_node); // no overflow

	hp->gc_spot = NULL;

	// restore active node
	if (saved_active != gc_node)
		hp->active = saved_active;

	// insert copy_node into the ring:
	// if gc_node is the last node left
	// if copy_node is non-empty and was just created;
	// free copy_node if it was just created
	// and not put on the list

	if (gc_node->next == gc_node ||
		(node_alloc_size(copy_node) > 0 && copy_node != hp->gc_last))
	{
		list_insert(copy_node, gc_node);
		hp->gc_last = copy_node;
	}
	else if (copy_node != hp->gc_last)
	{
		if (hp->active == copy_node)
			hp->active = gc_node->next;
		apr_allocator_free(hp->allocator, copy_node);
	}

	hp->alloc_size -= node_alloc_size(gc_node);

	// reclaim memory
	list_remove(gc_node);
	gc_node->next = NULL;
	apr_allocator_free(hp->allocator, gc_node);

	// after gc is run, anticipated need is zero
	hp->hend = heap_htop(hp);

	return APR_SUCCESS;
}