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; }
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; }
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; }
/* ================================================================================= 本函数的逻辑就是: 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; }
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; }
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; }
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; }
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; }