diff options
Diffstat (limited to 'web/server/h2o/libh2o/lib/common/memory.c')
-rw-r--r-- | web/server/h2o/libh2o/lib/common/memory.c | 400 |
1 files changed, 0 insertions, 400 deletions
diff --git a/web/server/h2o/libh2o/lib/common/memory.c b/web/server/h2o/libh2o/lib/common/memory.c deleted file mode 100644 index ba9f2dba2..000000000 --- a/web/server/h2o/libh2o/lib/common/memory.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (c) 2014 DeNA Co., Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include <assert.h> -#include <errno.h> -#include <fcntl.h> -#include <stddef.h> -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> -#include <unistd.h> -#include "h2o/memory.h" - -#if defined(__linux__) -#define USE_POSIX_FALLOCATE 1 -#elif __FreeBSD__ >= 9 -#define USE_POSIX_FALLOCATE 1 -#elif __NetBSD__ >= 7 -#define USE_POSIX_FALLOCATE 1 -#else -#define USE_POSIX_FALLOCATE 0 -#endif - -struct st_h2o_mem_recycle_chunk_t { - struct st_h2o_mem_recycle_chunk_t *next; -}; - -struct st_h2o_mem_pool_chunk_t { - struct st_h2o_mem_pool_chunk_t *next; - size_t _dummy; /* align to 2*sizeof(void*) */ - char bytes[4096 - sizeof(void *) * 2]; -}; - -struct st_h2o_mem_pool_direct_t { - struct st_h2o_mem_pool_direct_t *next; - size_t _dummy; /* align to 2*sizeof(void*) */ - char bytes[1]; -}; - -struct st_h2o_mem_pool_shared_ref_t { - struct st_h2o_mem_pool_shared_ref_t *next; - struct st_h2o_mem_pool_shared_entry_t *entry; -}; - -void *(*h2o_mem__set_secure)(void *, int, size_t) = memset; - -static __thread h2o_mem_recycle_t mempool_allocator = {16}; - -void h2o__fatal(const char *msg) -{ - fprintf(stderr, "fatal:%s\n", msg); - abort(); -} - -void *h2o_mem_alloc_recycle(h2o_mem_recycle_t *allocator, size_t sz) -{ - struct st_h2o_mem_recycle_chunk_t *chunk; - if (allocator->cnt == 0) - return h2o_mem_alloc(sz); - /* detach and return the pooled pointer */ - chunk = allocator->_link; - assert(chunk != NULL); - allocator->_link = chunk->next; - --allocator->cnt; - return chunk; -} - -void h2o_mem_free_recycle(h2o_mem_recycle_t *allocator, void *p) -{ - struct st_h2o_mem_recycle_chunk_t *chunk; - if (allocator->cnt == allocator->max) { - free(p); - return; - } - /* register the pointer to the pool */ - chunk = p; - chunk->next = allocator->_link; - allocator->_link = chunk; - ++allocator->cnt; -} - -void h2o_mem_init_pool(h2o_mem_pool_t *pool) -{ - pool->chunks = NULL; - pool->chunk_offset = sizeof(pool->chunks->bytes); - pool->directs = NULL; - pool->shared_refs = NULL; -} - -void h2o_mem_clear_pool(h2o_mem_pool_t *pool) -{ - /* release the refcounted chunks */ - if (pool->shared_refs != NULL) { - struct st_h2o_mem_pool_shared_ref_t *ref = pool->shared_refs; - do { - h2o_mem_release_shared(ref->entry->bytes); - } while ((ref = ref->next) != NULL); - pool->shared_refs = NULL; - } - /* release the direct chunks */ - if (pool->directs != NULL) { - struct st_h2o_mem_pool_direct_t *direct = pool->directs, *next; - do { - next = direct->next; - free(direct); - } while ((direct = next) != NULL); - pool->directs = NULL; - } - /* free chunks, and reset the first chunk */ - while (pool->chunks != NULL) { - struct st_h2o_mem_pool_chunk_t *next = pool->chunks->next; - h2o_mem_free_recycle(&mempool_allocator, pool->chunks); - pool->chunks = next; - } - pool->chunk_offset = sizeof(pool->chunks->bytes); -} - -void *h2o_mem_alloc_pool(h2o_mem_pool_t *pool, size_t sz) -{ - void *ret; - - if (sz >= sizeof(pool->chunks->bytes) / 4) { - /* allocate large requests directly */ - struct st_h2o_mem_pool_direct_t *newp = h2o_mem_alloc(offsetof(struct st_h2o_mem_pool_direct_t, bytes) + sz); - newp->next = pool->directs; - pool->directs = newp; - return newp->bytes; - } - - /* return a valid pointer even for 0 sized allocs */ - if (sz == 0) - sz = 1; - - /* 16-bytes rounding */ - sz = (sz + 15) & ~15; - if (sizeof(pool->chunks->bytes) - pool->chunk_offset < sz) { - /* allocate new chunk */ - struct st_h2o_mem_pool_chunk_t *newp = h2o_mem_alloc_recycle(&mempool_allocator, sizeof(*newp)); - newp->next = pool->chunks; - pool->chunks = newp; - pool->chunk_offset = 0; - } - - ret = pool->chunks->bytes + pool->chunk_offset; - pool->chunk_offset += sz; - return ret; -} - -static void link_shared(h2o_mem_pool_t *pool, struct st_h2o_mem_pool_shared_entry_t *entry) -{ - struct st_h2o_mem_pool_shared_ref_t *ref = h2o_mem_alloc_pool(pool, sizeof(struct st_h2o_mem_pool_shared_ref_t)); - ref->entry = entry; - ref->next = pool->shared_refs; - pool->shared_refs = ref; -} - -void *h2o_mem_alloc_shared(h2o_mem_pool_t *pool, size_t sz, void (*dispose)(void *)) -{ - struct st_h2o_mem_pool_shared_entry_t *entry = h2o_mem_alloc(offsetof(struct st_h2o_mem_pool_shared_entry_t, bytes) + sz); - entry->refcnt = 1; - entry->dispose = dispose; - if (pool != NULL) - link_shared(pool, entry); - return entry->bytes; -} - -void h2o_mem_link_shared(h2o_mem_pool_t *pool, void *p) -{ - h2o_mem_addref_shared(p); - link_shared(pool, H2O_STRUCT_FROM_MEMBER(struct st_h2o_mem_pool_shared_entry_t, bytes, p)); -} - -static size_t topagesize(size_t capacity) -{ - size_t pagesize = getpagesize(); - return (offsetof(h2o_buffer_t, _buf) + capacity + pagesize - 1) / pagesize * pagesize; -} - -void h2o_buffer__do_free(h2o_buffer_t *buffer) -{ - /* caller should assert that the buffer is not part of the prototype */ - if (buffer->capacity == buffer->_prototype->_initial_buf.capacity) { - h2o_mem_free_recycle(&buffer->_prototype->allocator, buffer); - } else if (buffer->_fd != -1) { - close(buffer->_fd); - munmap((void *)buffer, topagesize(buffer->capacity)); - } else { - free(buffer); - } -} - -h2o_iovec_t h2o_buffer_reserve(h2o_buffer_t **_inbuf, size_t min_guarantee) -{ - h2o_buffer_t *inbuf = *_inbuf; - h2o_iovec_t ret; - - if (inbuf->bytes == NULL) { - h2o_buffer_prototype_t *prototype = H2O_STRUCT_FROM_MEMBER(h2o_buffer_prototype_t, _initial_buf, inbuf); - if (min_guarantee <= prototype->_initial_buf.capacity) { - min_guarantee = prototype->_initial_buf.capacity; - inbuf = h2o_mem_alloc_recycle(&prototype->allocator, offsetof(h2o_buffer_t, _buf) + min_guarantee); - } else { - inbuf = h2o_mem_alloc(offsetof(h2o_buffer_t, _buf) + min_guarantee); - } - *_inbuf = inbuf; - inbuf->size = 0; - inbuf->bytes = inbuf->_buf; - inbuf->capacity = min_guarantee; - inbuf->_prototype = prototype; - inbuf->_fd = -1; - } else { - if (min_guarantee <= inbuf->capacity - inbuf->size - (inbuf->bytes - inbuf->_buf)) { - /* ok */ - } else if ((inbuf->size + min_guarantee) * 2 <= inbuf->capacity) { - /* the capacity should be less than or equal to 2 times of: size + guarantee */ - memmove(inbuf->_buf, inbuf->bytes, inbuf->size); - inbuf->bytes = inbuf->_buf; - } else { - size_t new_capacity = inbuf->capacity; - do { - new_capacity *= 2; - } while (new_capacity - inbuf->size < min_guarantee); - if (inbuf->_prototype->mmap_settings != NULL && inbuf->_prototype->mmap_settings->threshold <= new_capacity) { - size_t new_allocsize = topagesize(new_capacity); - int fd; - h2o_buffer_t *newp; - if (inbuf->_fd == -1) { - char *tmpfn = alloca(strlen(inbuf->_prototype->mmap_settings->fn_template) + 1); - strcpy(tmpfn, inbuf->_prototype->mmap_settings->fn_template); - if ((fd = mkstemp(tmpfn)) == -1) { - fprintf(stderr, "failed to create temporary file:%s:%s\n", tmpfn, strerror(errno)); - goto MapError; - } - unlink(tmpfn); - } else { - fd = inbuf->_fd; - } - int fallocate_ret; -#if USE_POSIX_FALLOCATE - fallocate_ret = posix_fallocate(fd, 0, new_allocsize); -#else - fallocate_ret = ftruncate(fd, new_allocsize); -#endif - if (fallocate_ret != 0) { - perror("failed to resize temporary file"); - goto MapError; - } - if ((newp = (void *)mmap(NULL, new_allocsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { - perror("mmap failed"); - goto MapError; - } - if (inbuf->_fd == -1) { - /* copy data (moving from malloc to mmap) */ - newp->size = inbuf->size; - newp->bytes = newp->_buf; - newp->capacity = new_capacity; - newp->_prototype = inbuf->_prototype; - newp->_fd = fd; - memcpy(newp->_buf, inbuf->bytes, inbuf->size); - h2o_buffer__do_free(inbuf); - *_inbuf = inbuf = newp; - } else { - /* munmap */ - size_t offset = inbuf->bytes - inbuf->_buf; - munmap((void *)inbuf, topagesize(inbuf->capacity)); - *_inbuf = inbuf = newp; - inbuf->capacity = new_capacity; - inbuf->bytes = newp->_buf + offset; - } - } else { - h2o_buffer_t *newp = h2o_mem_alloc(offsetof(h2o_buffer_t, _buf) + new_capacity); - newp->size = inbuf->size; - newp->bytes = newp->_buf; - newp->capacity = new_capacity; - newp->_prototype = inbuf->_prototype; - newp->_fd = -1; - memcpy(newp->_buf, inbuf->bytes, inbuf->size); - h2o_buffer__do_free(inbuf); - *_inbuf = inbuf = newp; - } - } - } - - ret.base = inbuf->bytes + inbuf->size; - ret.len = inbuf->_buf + inbuf->capacity - ret.base; - - return ret; - -MapError: - ret.base = NULL; - ret.len = 0; - return ret; -} - -void h2o_buffer_consume(h2o_buffer_t **_inbuf, size_t delta) -{ - h2o_buffer_t *inbuf = *_inbuf; - - if (delta != 0) { - assert(inbuf->bytes != NULL); - if (inbuf->size == delta) { - *_inbuf = &inbuf->_prototype->_initial_buf; - h2o_buffer__do_free(inbuf); - } else { - inbuf->size -= delta; - inbuf->bytes += delta; - } - } -} - -void h2o_buffer__dispose_linked(void *p) -{ - h2o_buffer_t **buf = p; - h2o_buffer_dispose(buf); -} - -void h2o_vector__expand(h2o_mem_pool_t *pool, h2o_vector_t *vector, size_t element_size, size_t new_capacity) -{ - void *new_entries; - assert(vector->capacity < new_capacity); - if (vector->capacity == 0) - vector->capacity = 4; - while (vector->capacity < new_capacity) - vector->capacity *= 2; - if (pool != NULL) { - new_entries = h2o_mem_alloc_pool(pool, element_size * vector->capacity); - h2o_memcpy(new_entries, vector->entries, element_size * vector->size); - } else { - new_entries = h2o_mem_realloc(vector->entries, element_size * vector->capacity); - } - vector->entries = new_entries; -} - -void h2o_mem_swap(void *_x, void *_y, size_t len) -{ - char *x = _x, *y = _y; - char buf[256]; - - while (len != 0) { - size_t blocksz = len < sizeof(buf) ? len : sizeof(buf); - memcpy(buf, x, blocksz); - memcpy(x, y, blocksz); - memcpy(y, buf, blocksz); - len -= blocksz; - x += blocksz; - y += blocksz; - } -} - -void h2o_dump_memory(FILE *fp, const char *buf, size_t len) -{ - size_t i, j; - - for (i = 0; i < len; i += 16) { - fprintf(fp, "%08zx", i); - for (j = 0; j != 16; ++j) { - if (i + j < len) - fprintf(fp, " %02x", (int)(unsigned char)buf[i + j]); - else - fprintf(fp, " "); - } - fprintf(fp, " "); - for (j = 0; j != 16 && i + j < len; ++j) { - int ch = buf[i + j]; - fputc(' ' <= ch && ch < 0x7f ? ch : '.', fp); - } - fprintf(fp, "\n"); - } -} - -void h2o_append_to_null_terminated_list(void ***list, void *element) -{ - size_t cnt; - - for (cnt = 0; (*list)[cnt] != NULL; ++cnt) - ; - *list = h2o_mem_realloc(*list, (cnt + 2) * sizeof(void *)); - (*list)[cnt++] = element; - (*list)[cnt] = NULL; -} |