kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit 4ad50caa29a8a4d4be3baf1754ca2c78e27afd51
parent d30921103bb172252e40cfefd9bdbb2a1852e713
Author: Joris Vink <joris@coders.se>
Date:   Tue, 12 Jul 2016 13:54:14 +0200

Large changes to the memory subsystem in kore.

- Change pools to use mmap() for allocating regions.
- Change kore_malloc() to use pools for commonly sized objects.
  (split into multiple of 2 buckets, starting at 8 bytes up to 8192).
- Rename kore_mem_free() to kore_free().

The preallocated pools will hold up to 128K of elements per block size.

In case a larger object is to be allocated kore_malloc() will use
malloc() instead.

Diffstat:
examples/generic/src/example.c | 12++++++------
examples/integers/src/check_integers.c | 2+-
examples/ktunnel/src/ktunnel.c | 2+-
examples/sse/src/sse.c | 2+-
examples/tasks/src/tasks.c | 2+-
examples/video_stream/src/stream.c | 16++++++++--------
includes/kore.h | 5+++--
src/auth.c | 6+++---
src/bsd.c | 2+-
src/buf.c | 10+++++-----
src/cli.c | 14+++++++-------
src/config.c | 12++++++------
src/connection.c | 6+++---
src/domain.c | 14+++++++-------
src/http.c | 32++++++++++++++++----------------
src/keymgr.c | 4++--
src/kore.c | 14+++++++-------
src/linux.c | 2+-
src/mem.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
src/module.c | 14+++++++-------
src/net.c | 4++--
src/pgsql.c | 16++++++++--------
src/pool.c | 27+++++++++++++++++++++------
src/timer.c | 4++--
src/utils.c | 6+++---
src/validator.c | 6+++---
src/websocket.c | 2+-
27 files changed, 200 insertions(+), 125 deletions(-)

diff --git a/examples/generic/src/example.c b/examples/generic/src/example.c @@ -130,7 +130,7 @@ serve_b64test(struct http_request *req) http_response_header(req, "content-type", "text/plain"); http_response(req, 200, data, len); - kore_mem_free(data); + kore_free(data); return (KORE_RESULT_OK); } @@ -176,7 +176,7 @@ serve_file_upload(struct http_request *req) http_response_header(req, "content-type", "text/html"); http_response(req, 200, d, len); - kore_mem_free(d); + kore_free(d); return (KORE_RESULT_OK); } @@ -201,10 +201,10 @@ test_base64(u_int8_t *src, u_int32_t slen, struct kore_buf *res) kore_buf_appendf(res, "decoded: "); kore_buf_append(res, out, len); kore_buf_appendf(res, "\n"); - kore_mem_free(out); + kore_free(out); } - kore_mem_free(in); + kore_free(in); } kore_buf_appendf(res, "\n"); @@ -278,7 +278,7 @@ serve_params_test(struct http_request *req) http_response_header(req, "content-type", "text/html"); d = kore_buf_release(b, &len); http_response(req, 200, d, len); - kore_mem_free(d); + kore_free(d); return (KORE_RESULT_OK); } @@ -297,7 +297,7 @@ serve_params_test(struct http_request *req) http_response_header(req, "content-type", "text/html"); d = kore_buf_release(b, &len); http_response(req, 200, d, len); - kore_mem_free(d); + kore_free(d); return (KORE_RESULT_OK); } diff --git a/examples/integers/src/check_integers.c b/examples/integers/src/check_integers.c @@ -42,7 +42,7 @@ page(struct http_request *req) data = kore_buf_release(buf, &len); http_response(req, 200, data, len); - kore_mem_free(data); + kore_free(data); return (KORE_RESULT_OK); } diff --git a/examples/ktunnel/src/ktunnel.c b/examples/ktunnel/src/ktunnel.c @@ -181,7 +181,7 @@ ktunnel_pipe_disconnect(struct connection *c) printf("ktunnel_pipe_disconnect(%p)->%p\n", c, cpipe); if (cpipe != NULL) { - /* Prevent Kore from calling kore_mem_free() on hdlr_extra. */ + /* Prevent Kore from calling kore_free() on hdlr_extra. */ c->hdlr_extra = NULL; kore_connection_disconnect(cpipe); } diff --git a/examples/sse/src/sse.c b/examples/sse/src/sse.c @@ -159,7 +159,7 @@ sse_disconnect(struct connection *c) /* Kill our timer and free/remove the state. */ kore_timer_remove(state->timer); - kore_mem_free(state); + kore_free(state); /* Prevent us to be called again. */ c->hdlr_extra = NULL; diff --git a/examples/tasks/src/tasks.c b/examples/tasks/src/tasks.c @@ -218,7 +218,7 @@ run_curl(struct kore_task *t) */ data = kore_buf_release(b, &len); kore_task_channel_write(t, data, len); - kore_mem_free(data); + kore_free(data); return (KORE_RESULT_OK); } diff --git a/examples/video_stream/src/stream.c b/examples/video_stream/src/stream.c @@ -186,8 +186,8 @@ video_open(struct http_request *req, struct video **out) close(v->fd); TAILQ_REMOVE(&videos, v, list); - kore_mem_free(v->path); - kore_mem_free(v); + kore_free(v->path); + kore_free(v); http_response(req, 500, NULL, 0); return (KORE_RESULT_ERROR); @@ -201,8 +201,8 @@ video_open(struct http_request *req, struct video **out) v->path = kore_strdup(fpath); if ((v->fd = open(fpath, O_RDONLY)) == -1) { - kore_mem_free(v->path); - kore_mem_free(v); + kore_free(v->path); + kore_free(v); if (errno == ENOENT) http_response(req, 404, NULL, 0); @@ -214,8 +214,8 @@ video_open(struct http_request *req, struct video **out) if (fstat(v->fd, &st) == -1) { close(v->fd); - kore_mem_free(v->path); - kore_mem_free(v); + kore_free(v->path); + kore_free(v); http_response(req, 500, NULL, 0); return (KORE_RESULT_ERROR); @@ -224,8 +224,8 @@ video_open(struct http_request *req, struct video **out) v->size = st.st_size; if (!video_mmap(req, v)) { close(v->fd); - kore_mem_free(v->path); - kore_mem_free(v); + kore_free(v->path); + kore_free(v); http_response(req, 500, NULL, 0); return (KORE_RESULT_ERROR); diff --git a/includes/kore.h b/includes/kore.h @@ -332,7 +332,8 @@ struct kore_buf { }; struct kore_pool_region { - void *start; + void *start; + size_t length; LIST_ENTRY(kore_pool_region) list; }; @@ -511,7 +512,7 @@ void *kore_malloc(size_t); void kore_parse_config(void); void *kore_calloc(size_t, size_t); void *kore_realloc(void *, size_t); -void kore_mem_free(void *); +void kore_free(void *); void kore_mem_init(void); void *kore_pool_get(struct kore_pool *); diff --git a/src/auth.c b/src/auth.c @@ -127,18 +127,18 @@ kore_auth_cookie(struct http_request *req, struct kore_auth *auth) } if (i == v) { - kore_mem_free(cookie); + kore_free(cookie); return (KORE_RESULT_ERROR); } c = cookies[i]; if ((value = strchr(c, '=')) == NULL) { - kore_mem_free(cookie); + kore_free(cookie); return (KORE_RESULT_ERROR); } i = kore_validator_check(req, auth->validator, ++value); - kore_mem_free(cookie); + kore_free(cookie); return (i); } diff --git a/src/bsd.c b/src/bsd.c @@ -103,7 +103,7 @@ kore_platform_event_cleanup(void) } if (events != NULL) { - kore_mem_free(events); + kore_free(events); events = NULL; } } diff --git a/src/buf.c b/src/buf.c @@ -57,7 +57,7 @@ kore_buf_appendb(struct kore_buf *buf, struct kore_buf *src) d = kore_buf_release(src, &len); kore_buf_append(buf, d, len); - kore_mem_free(d); + kore_free(d); } void @@ -114,7 +114,7 @@ kore_buf_release(struct kore_buf *buf, size_t *len) p = buf->data; *len = buf->offset; - kore_mem_free(buf); + kore_free(buf); return (p); } @@ -122,8 +122,8 @@ kore_buf_release(struct kore_buf *buf, size_t *len) void kore_buf_free(struct kore_buf *buf) { - kore_mem_free(buf->data); - kore_mem_free(buf); + kore_free(buf->data); + kore_free(buf); } void @@ -153,7 +153,7 @@ kore_buf_replace_string(struct kore_buf *b, char *src, void *dst, size_t len) memcpy((tmp + off), dst, len); memcpy((tmp + off + len), end, off2); - kore_mem_free(b->data); + kore_free(b->data); b->data = (u_int8_t *)tmp; b->offset = off + len + off2; b->length = nlen; diff --git a/src/cli.c b/src/cli.c @@ -806,7 +806,7 @@ cli_build_asset(char *fpath, struct dirent *dp) *ext = '_'; cli_add_source_file(name, cpath, opath, &st, BUILD_NOBUILD); - kore_mem_free(name); + kore_free(name); return; } @@ -865,7 +865,7 @@ cli_build_asset(char *fpath, struct dirent *dp) /* Register the .c file now (cpath is free'd later). */ cli_add_source_file(name, cpath, opath, &st, BUILD_C); - kore_mem_free(name); + kore_free(name); } static void @@ -1367,10 +1367,10 @@ cli_buildopt_cleanup(void) if (bopt->ldflags != NULL) kore_buf_free(bopt->ldflags); if (bopt->kore_source != NULL) - kore_mem_free(bopt->kore_source); + kore_free(bopt->kore_source); if (bopt->kore_flavor != NULL) - kore_mem_free(bopt->kore_flavor); - kore_mem_free(bopt); + kore_free(bopt->kore_flavor); + kore_free(bopt); } } @@ -1433,7 +1433,7 @@ cli_buildopt_kore_source(struct buildopt *bopt, const char *string) cli_fatal("kore_source only supported in global context"); if (bopt->kore_source != NULL) - kore_mem_free(bopt->kore_source); + kore_free(bopt->kore_source); bopt->kore_source = kore_strdup(string); } @@ -1447,7 +1447,7 @@ cli_buildopt_kore_flavor(struct buildopt *bopt, const char *string) cli_fatal("kore_flavor only supported in global context"); if (bopt->kore_flavor != NULL) - kore_mem_free(bopt->kore_flavor); + kore_free(bopt->kore_flavor); bopt->kore_flavor = kore_strdup(string); } diff --git a/src/config.c b/src/config.c @@ -621,7 +621,7 @@ static int configure_http_body_disk_path(char *path) { if (strcmp(http_body_disk_path, HTTP_BODY_DISK_PATH)) - kore_mem_free(http_body_disk_path); + kore_free(http_body_disk_path); http_body_disk_path = kore_strdup(path); return (KORE_RESULT_OK); @@ -848,7 +848,7 @@ configure_authentication_value(char *option) } if (current_auth->value != NULL) - kore_mem_free(current_auth->value); + kore_free(current_auth->value); current_auth->value = kore_strdup(option); return (KORE_RESULT_OK); @@ -883,7 +883,7 @@ configure_authentication_uri(char *uri) } if (current_auth->redirect != NULL) - kore_mem_free(current_auth->redirect); + kore_free(current_auth->redirect); current_auth->redirect = kore_strdup(uri); return (KORE_RESULT_OK); @@ -925,7 +925,7 @@ static int configure_chroot(char *path) { if (chroot_path != NULL) - kore_mem_free(chroot_path); + kore_free(chroot_path); chroot_path = kore_strdup(path); return (KORE_RESULT_OK); @@ -935,7 +935,7 @@ static int configure_runas(char *user) { if (runas_user != NULL) - kore_mem_free(runas_user); + kore_free(runas_user); runas_user = kore_strdup(user); return (KORE_RESULT_OK); @@ -959,7 +959,7 @@ static int configure_pidfile(char *path) { if (strcmp(kore_pidfile, KORE_PIDFILE_DEFAULT)) - kore_mem_free(kore_pidfile); + kore_free(kore_pidfile); kore_pidfile = kore_strdup(path); return (KORE_RESULT_OK); diff --git a/src/connection.c b/src/connection.c @@ -328,7 +328,7 @@ kore_connection_remove(struct connection *c) close(c->fd); if (c->hdlr_extra != NULL) - kore_mem_free(c->hdlr_extra); + kore_free(c->hdlr_extra); #if !defined(KORE_NO_HTTP) for (req = TAILQ_FIRST(&(c->http_requests)); req != NULL; req = rnext) { @@ -343,7 +343,7 @@ kore_connection_remove(struct connection *c) next = TAILQ_NEXT(nb, list); TAILQ_REMOVE(&(c->send_queue), nb, list); if (!(nb->flags & NETBUF_IS_STREAM)) { - kore_mem_free(nb->buf); + kore_free(nb->buf); } else if (nb->cb != NULL) { (void)nb->cb(nb); } @@ -351,7 +351,7 @@ kore_connection_remove(struct connection *c) } if (c->rnb != NULL) { - kore_mem_free(c->rnb->buf); + kore_free(c->rnb->buf); kore_pool_put(&nb_pool, c->rnb); } diff --git a/src/domain.c b/src/domain.c @@ -168,19 +168,19 @@ kore_domain_free(struct kore_domain *dom) TAILQ_REMOVE(&domains, dom, list); if (dom->domain != NULL) - kore_mem_free(dom->domain); + kore_free(dom->domain); #if !defined(KORE_NO_TLS) if (dom->ssl_ctx != NULL) SSL_CTX_free(dom->ssl_ctx); if (dom->cafile != NULL) - kore_mem_free(dom->cafile); + kore_free(dom->cafile); if (dom->certkey != NULL) - kore_mem_free(dom->certkey); + kore_free(dom->certkey); if (dom->certfile != NULL) - kore_mem_free(dom->certfile); + kore_free(dom->certfile); if (dom->crlfile != NULL) - kore_mem_free(dom->crlfile); + kore_free(dom->crlfile); #endif #if !defined(KORE_NO_HTTP) @@ -190,7 +190,7 @@ kore_domain_free(struct kore_domain *dom) kore_module_handler_free(hdlr); } #endif - kore_mem_free(dom); + kore_free(dom); } void @@ -330,7 +330,7 @@ kore_domain_sslstart(struct kore_domain *dom) SSL_CTX_set_info_callback(dom->ssl_ctx, kore_tls_info_callback); SSL_CTX_set_tlsext_servername_callback(dom->ssl_ctx, kore_tls_sni_cb); - kore_mem_free(dom->certfile); + kore_free(dom->certfile); dom->certfile = NULL; #endif } diff --git a/src/http.c b/src/http.c @@ -425,8 +425,8 @@ http_request_free(struct http_request *req) next = TAILQ_NEXT(hdr, list); TAILQ_REMOVE(&(req->resp_headers), hdr, list); - kore_mem_free(hdr->header); - kore_mem_free(hdr->value); + kore_free(hdr->header); + kore_free(hdr->value); kore_pool_put(&http_header_pool, hdr); } @@ -434,8 +434,8 @@ http_request_free(struct http_request *req) next = TAILQ_NEXT(hdr, list); TAILQ_REMOVE(&(req->req_headers), hdr, list); - kore_mem_free(hdr->header); - kore_mem_free(hdr->value); + kore_free(hdr->header); + kore_free(hdr->value); kore_pool_put(&http_header_pool, hdr); } @@ -443,19 +443,19 @@ http_request_free(struct http_request *req) qnext = TAILQ_NEXT(q, list); TAILQ_REMOVE(&(req->arguments), q, list); - kore_mem_free(q->name); + kore_free(q->name); if (q->s_value != NULL) - kore_mem_free(q->s_value); - kore_mem_free(q); + kore_free(q->s_value); + kore_free(q); } for (f = TAILQ_FIRST(&(req->files)); f != NULL; f = fnext) { fnext = TAILQ_NEXT(f, list); TAILQ_REMOVE(&(req->files), f, list); - kore_mem_free(f->filename); - kore_mem_free(f->name); - kore_mem_free(f); + kore_free(f->filename); + kore_free(f->name); + kore_free(f); } if (req->http_body != NULL) @@ -474,7 +474,7 @@ http_request_free(struct http_request *req) if (req->hdlr_extra != NULL && !(req->flags & HTTP_REQUEST_RETAIN_EXTRA)) - kore_mem_free(req->hdlr_extra); + kore_free(req->hdlr_extra); kore_pool_put(&http_request_pool, req); http_request_count--; @@ -958,7 +958,7 @@ http_populate_get(struct http_request *req) http_argument_add(req, val[0], val[1]); } - kore_mem_free(query); + kore_free(query); } void @@ -1202,7 +1202,7 @@ multipart_parse_headers(struct http_request *req, struct kore_buf *in, if (opt[2] == NULL) { multipart_add_field(req, in, name, boundary, blen); - kore_mem_free(name); + kore_free(name); continue; } @@ -1211,7 +1211,7 @@ multipart_parse_headers(struct http_request *req, struct kore_buf *in, if (!strncasecmp(d, "filename=", 9)) { if ((val = strchr(d, '=')) == NULL) { - kore_mem_free(name); + kore_free(name); continue; } @@ -1221,12 +1221,12 @@ multipart_parse_headers(struct http_request *req, struct kore_buf *in, multipart_file_add(req, in, name, fname, boundary, blen); } - kore_mem_free(fname); + kore_free(fname); } else { kore_debug("got unknown: %s", opt[2]); } - kore_mem_free(name); + kore_free(name); } return (KORE_RESULT_OK); diff --git a/src/keymgr.c b/src/keymgr.c @@ -107,7 +107,7 @@ kore_keymgr_cleanup(void) TAILQ_REMOVE(&keys, key, list); EVP_PKEY_free(key->pkey); - kore_mem_free(key); + kore_free(key); } } @@ -130,7 +130,7 @@ keymgr_load_privatekey(struct kore_domain *dom) fatal("PEM_read_PrivateKey: %s", ssl_errno_s); (void)fclose(fp); - kore_mem_free(dom->certkey); + kore_free(dom->certkey); dom->certkey = NULL; TAILQ_INSERT_TAIL(&keys, key, list); diff --git a/src/kore.c b/src/kore.c @@ -295,7 +295,7 @@ kore_server_bind(const char *ip, const char *port, const char *ccb) fatal("getaddrinfo(): unknown address family %d", l->addrtype); if ((l->fd = socket(results->ai_family, SOCK_STREAM, 0)) == -1) { - kore_mem_free(l); + kore_free(l); freeaddrinfo(results); kore_debug("socket(): %s", errno_s); printf("failed to create socket: %s\n", errno_s); @@ -303,7 +303,7 @@ kore_server_bind(const char *ip, const char *port, const char *ccb) } if (!kore_connection_nonblock(l->fd, 1)) { - kore_mem_free(l); + kore_free(l); freeaddrinfo(results); printf("failed to make socket non blocking: %s\n", errno_s); return (KORE_RESULT_ERROR); @@ -313,7 +313,7 @@ kore_server_bind(const char *ip, const char *port, const char *ccb) if (setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on)) == -1) { close(l->fd); - kore_mem_free(l); + kore_free(l); freeaddrinfo(results); kore_debug("setsockopt(): %s", errno_s); printf("failed to set SO_REUSEADDR: %s\n", errno_s); @@ -322,7 +322,7 @@ kore_server_bind(const char *ip, const char *port, const char *ccb) if (bind(l->fd, results->ai_addr, results->ai_addrlen) == -1) { close(l->fd); - kore_mem_free(l); + kore_free(l); freeaddrinfo(results); kore_debug("bind(): %s", errno_s); printf("failed to bind to %s port %s: %s\n", ip, port, errno_s); @@ -333,7 +333,7 @@ kore_server_bind(const char *ip, const char *port, const char *ccb) if (listen(l->fd, kore_socket_backlog) == -1) { close(l->fd); - kore_mem_free(l); + kore_free(l); kore_debug("listen(): %s", errno_s); printf("failed to listen on socket: %s\n", errno_s); return (KORE_RESULT_ERROR); @@ -344,7 +344,7 @@ kore_server_bind(const char *ip, const char *port, const char *ccb) if (l->connect == NULL) { printf("no such callback: '%s'\n", ccb); close(l->fd); - kore_mem_free(l); + kore_free(l); return (KORE_RESULT_ERROR); } } else { @@ -374,7 +374,7 @@ kore_listener_cleanup(void) l = LIST_FIRST(&listeners); LIST_REMOVE(l, list); close(l->fd); - kore_mem_free(l); + kore_free(l); } } diff --git a/src/linux.c b/src/linux.c @@ -80,7 +80,7 @@ kore_platform_event_cleanup(void) } if (events != NULL) { - kore_mem_free(events); + kore_free(events); events = NULL; } } diff --git a/src/mem.c b/src/mem.c @@ -21,9 +21,13 @@ #include "kore.h" +#define KORE_MEM_BLOCKS 11 +#define KORE_MEM_BLOCK_SIZE_MAX 8192 +#define KORE_MEM_BLOCK_PREALLOC 128 + #define KORE_MEM_MAGIC 0xd0d0 #define KORE_MEMSIZE(x) \ - (*(u_int32_t *)((u_int8_t *)x - sizeof(u_int32_t))) + (*(size_t *)((u_int8_t *)x - sizeof(size_t))) #define KORE_MEMINFO(x) \ (struct meminfo *)((u_int8_t *)x + KORE_MEMSIZE(x)) @@ -31,30 +35,59 @@ struct meminfo { u_int16_t magic; }; +struct memblock { + struct kore_pool pool; +}; + +static size_t memblock_index(size_t); + +static struct memblock blocks[KORE_MEM_BLOCKS]; + void kore_mem_init(void) { + int i, len; + char name[32]; + u_int32_t size, elm, mlen; + + size = 8; + + for (i = 0; i < KORE_MEM_BLOCKS; i++) { + len = snprintf(name, sizeof(name), "block-%u", size); + if (len == -1 || (size_t)len >= sizeof(name)) + fatal("kore_mem_init: snprintf"); + + elm = (KORE_MEM_BLOCK_PREALLOC * 1024) / size; + mlen = sizeof(size_t) + size + sizeof(struct meminfo); + kore_pool_init(&blocks[i].pool, name, mlen, elm); + + size = size << 1; + } } void * kore_malloc(size_t len) { - size_t mlen; void *ptr; struct meminfo *mem; u_int8_t *addr; - u_int32_t *plen; + size_t mlen, idx, *plen; if (len == 0) fatal("kore_malloc(): zero size"); - mlen = sizeof(u_int32_t) + len + sizeof(struct meminfo); - if ((ptr = calloc(1, mlen)) == NULL) - fatal("kore_malloc(%zd): %d", len, errno); + if (len <= KORE_MEM_BLOCK_SIZE_MAX) { + idx = memblock_index(len); + ptr = kore_pool_get(&blocks[idx].pool); + } else { + mlen = sizeof(size_t) + len + sizeof(struct meminfo); + if ((ptr = calloc(1, mlen)) == NULL) + fatal("kore_malloc(%zd): %d", len, errno); + } - plen = (u_int32_t *)ptr; + plen = (size_t *)ptr; *plen = len; - addr = (u_int8_t *)ptr + sizeof(u_int32_t); + addr = (u_int8_t *)ptr + sizeof(size_t); mem = KORE_MEMINFO(addr); mem->magic = KORE_MEM_MAGIC; @@ -80,7 +113,7 @@ kore_realloc(void *ptr, size_t len) nptr = kore_malloc(len); memcpy(nptr, ptr, MIN(len, KORE_MEMSIZE(ptr))); - kore_mem_free(ptr); + kore_free(ptr); } return (nptr); @@ -98,20 +131,28 @@ kore_calloc(size_t memb, size_t len) } void -kore_mem_free(void *ptr) +kore_free(void *ptr) { - u_int8_t *addr; - struct meminfo *mem; + u_int8_t *addr; + struct meminfo *mem; + size_t len, idx; if (ptr == NULL) return; mem = KORE_MEMINFO(ptr); if (mem->magic != KORE_MEM_MAGIC) - fatal("kore_mem_free(): magic boundary not found"); + fatal("kore_free(): magic boundary not found"); + + len = KORE_MEMSIZE(ptr); + addr = (u_int8_t *)ptr - sizeof(size_t); - addr = (u_int8_t *)ptr - sizeof(u_int32_t); - free(addr); + if (len <= KORE_MEM_BLOCK_SIZE_MAX) { + idx = memblock_index(len); + kore_pool_put(&blocks[idx].pool, addr); + } else { + free(addr); + } } char * @@ -126,3 +167,21 @@ kore_strdup(const char *str) return (nstr); } + +static size_t +memblock_index(size_t len) +{ + size_t mlen, idx; + + idx = 0; + mlen = 8; + while (mlen < len) { + idx++; + mlen = mlen << 1; + } + + if (idx > (KORE_MEM_BLOCKS - 1)) + fatal("kore_malloc: idx too high"); + + return (idx); +} diff --git a/src/module.c b/src/module.c @@ -37,9 +37,9 @@ kore_module_cleanup(void) next = TAILQ_NEXT(module, list); TAILQ_REMOVE(&modules, module, list); - kore_mem_free(module->path); + kore_free(module->path); (void)dlclose(module->handle); - kore_mem_free(module); + kore_free(module); } } @@ -232,9 +232,9 @@ kore_module_handler_free(struct kore_module_handle *hdlr) return; if (hdlr->func != NULL) - kore_mem_free(hdlr->func); + kore_free(hdlr->func); if (hdlr->path != NULL) - kore_mem_free(hdlr->path); + kore_free(hdlr->path); if (hdlr->type == HANDLER_TYPE_DYNAMIC) regfree(&(hdlr->rctx)); @@ -242,11 +242,11 @@ kore_module_handler_free(struct kore_module_handle *hdlr) while ((param = TAILQ_FIRST(&(hdlr->params))) != NULL) { TAILQ_REMOVE(&(hdlr->params), param, list); if (param->name != NULL) - kore_mem_free(param->name); - kore_mem_free(param); + kore_free(param->name); + kore_free(param); } - kore_mem_free(hdlr); + kore_free(hdlr); } struct kore_module_handle * diff --git a/src/net.c b/src/net.c @@ -131,7 +131,7 @@ net_recv_reset(struct connection *c, size_t len, int (*cb)(struct netbuf *)) c->rnb->m_len < (NETBUF_SEND_PAYLOAD_MAX / 2)) return; - kore_mem_free(c->rnb->buf); + kore_free(c->rnb->buf); c->rnb->m_len = len; c->rnb->buf = kore_malloc(c->rnb->m_len); } @@ -266,7 +266,7 @@ net_remove_netbuf(struct netbuf_head *list, struct netbuf *nb) } if (!(nb->flags & NETBUF_IS_STREAM)) { - kore_mem_free(nb->buf); + kore_free(nb->buf); } else if (nb->cb != NULL) { (void)nb->cb(nb); } diff --git a/src/pgsql.c b/src/pgsql.c @@ -205,9 +205,9 @@ kore_pgsql_v_query_params(struct kore_pgsql *pgsql, ret = KORE_RESULT_OK; cleanup: - kore_mem_free(values); - kore_mem_free(lengths); - kore_mem_free(formats); + kore_free(values); + kore_free(lengths); + kore_free(formats); return (ret); } @@ -285,7 +285,7 @@ kore_pgsql_continue(struct http_request *req, struct kore_pgsql *pgsql) req->owner, req, pgsql->state); if (pgsql->error) { - kore_mem_free(pgsql->error); + kore_free(pgsql->error); pgsql->error = NULL; } @@ -320,7 +320,7 @@ kore_pgsql_cleanup(struct kore_pgsql *pgsql) PQclear(pgsql->result); if (pgsql->error != NULL) - kore_mem_free(pgsql->error); + kore_free(pgsql->error); if (pgsql->conn != NULL) pgsql_conn_release(pgsql); @@ -417,7 +417,7 @@ static void pgsql_set_error(struct kore_pgsql *pgsql, const char *msg) { if (pgsql->error != NULL) - kore_mem_free(pgsql->error); + kore_free(pgsql->error); pgsql->error = kore_strdup(msg); pgsql->state = KORE_PGSQL_STATE_ERROR; @@ -555,8 +555,8 @@ pgsql_conn_cleanup(struct pgsql_conn *conn) PQfinish(conn->db); pgsql_conn_count--; - kore_mem_free(conn->name); - kore_mem_free(conn); + kore_free(conn->name); + kore_free(conn); } static void diff --git a/src/pool.c b/src/pool.c @@ -14,8 +14,11 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <sys/mman.h> #include <sys/queue.h> +#include <stdint.h> + #include "kore.h" #define POOL_ELEMENT_BUSY 0 @@ -30,10 +33,12 @@ kore_pool_init(struct kore_pool *pool, const char *name, { kore_debug("kore_pool_init(%p, %s, %d, %d)", pool, name, len, elm); + if ((pool->name = strdup(name)) == NULL) + fatal("kore_pool_init: strdup %s", errno_s); + pool->elms = 0; pool->inuse = 0; pool->elen = len; - pool->name = kore_strdup(name); pool->slen = pool->elen + sizeof(struct kore_pool_entry); LIST_INIT(&(pool->regions)); @@ -51,7 +56,7 @@ kore_pool_cleanup(struct kore_pool *pool) pool->slen = 0; if (pool->name != NULL) { - kore_mem_free(pool->name); + free(pool->name); pool->name = NULL; } @@ -111,10 +116,20 @@ pool_region_create(struct kore_pool *pool, u_int32_t elms) kore_debug("pool_region_create(%p, %d)", pool, elms); - reg = kore_malloc(sizeof(struct kore_pool_region)); + if ((reg = calloc(1, sizeof(struct kore_pool_region))) == NULL) + fatal("pool_region_create: calloc: %s", errno_s); + LIST_INSERT_HEAD(&(pool->regions), reg, list); - reg->start = kore_malloc(elms * pool->slen); + if (SIZE_MAX / elms < pool->slen) + fatal("pool_region_create: overflow"); + + reg->length = elms * pool->slen; + reg->start = mmap(NULL, reg->length, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (reg->start == NULL) + fatal("mmap: %s", errno_s); + p = (u_int8_t *)reg->start; for (i = 0; i < elms; i++) { @@ -140,8 +155,8 @@ pool_region_destroy(struct kore_pool *pool) while (!LIST_EMPTY(&pool->regions)) { reg = LIST_FIRST(&pool->regions); LIST_REMOVE(reg, list); - kore_mem_free(reg->start); - kore_mem_free(reg); + (void)munmap(reg->start, reg->length); + free(reg); } /* Freelist references into the regions memory allocations */ diff --git a/src/timer.c b/src/timer.c @@ -56,7 +56,7 @@ void kore_timer_remove(struct kore_timer *timer) { TAILQ_REMOVE(&kore_timers, timer, list); - kore_mem_free(timer); + kore_free(timer); } u_int64_t @@ -77,7 +77,7 @@ kore_timer_run(u_int64_t now) timer->cb(timer->arg, now); if (timer->flags & KORE_TIMER_ONESHOT) { - kore_mem_free(timer); + kore_free(timer); } else { timer->nextrun = now + timer->interval; TAILQ_FOREACH(t, &kore_timers, list) { diff --git a/src/utils.c b/src/utils.c @@ -341,7 +341,7 @@ kore_date_to_time(char *http_date) } out: - kore_mem_free(sdup); + kore_free(sdup); return (t); } @@ -430,7 +430,7 @@ kore_base64_encode(u_int8_t *data, size_t len, char **out) kore_buf_append(res, (u_int8_t *)"=", 1); if (pdata != data) - kore_mem_free(pdata); + kore_free(pdata); pdata = kore_buf_release(res, &plen); if ((plen + 1) < plen) @@ -438,7 +438,7 @@ kore_base64_encode(u_int8_t *data, size_t len, char **out) *out = kore_malloc(plen + 1); (void)kore_strlcpy(*out, (char *)pdata, plen + 1); - kore_mem_free(pdata); + kore_free(pdata); return (KORE_RESULT_OK); } diff --git a/src/validator.c b/src/validator.c @@ -35,7 +35,7 @@ kore_validator_add(const char *name, u_int8_t type, const char *arg) switch (val->type) { case KORE_VALIDATOR_TYPE_REGEX: if (regcomp(&(val->rctx), arg, REG_EXTENDED | REG_NOSUB)) { - kore_mem_free(val); + kore_free(val); kore_log(LOG_NOTICE, "validator %s has bad regex %s", name, arg); return (KORE_RESULT_ERROR); @@ -44,7 +44,7 @@ kore_validator_add(const char *name, u_int8_t type, const char *arg) case KORE_VALIDATOR_TYPE_FUNCTION: *(void **)(&val->func) = kore_module_getsym(arg); if (val->func == NULL) { - kore_mem_free(val); + kore_free(val); kore_log(LOG_NOTICE, "validator %s has undefined callback %s", name, arg); @@ -52,7 +52,7 @@ kore_validator_add(const char *name, u_int8_t type, const char *arg) } break; default: - kore_mem_free(val); + kore_free(val); return (KORE_RESULT_ERROR); } diff --git a/src/websocket.c b/src/websocket.c @@ -91,7 +91,7 @@ kore_websocket_handshake(struct http_request *req, struct kore_wscbs *wscbs) http_response_header(req, "upgrade", "websocket"); http_response_header(req, "connection", "upgrade"); http_response_header(req, "sec-websocket-accept", base64); - kore_mem_free(base64); + kore_free(base64); kore_debug("%p: new websocket connection", req->owner);