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:
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);