Add fixed size memory pools and use them throughout Kore.

This commit is contained in:
Joris Vink 2013-07-15 10:13:36 +02:00
parent f54e7ace83
commit 29fa49ba83
11 changed files with 206 additions and 33 deletions

View File

@ -4,8 +4,8 @@ CC=gcc
BIN=kore
S_SRC+= src/kore.c src/accesslog.c src/buf.c src/config.c src/connection.c \
src/domain.c src/http.c src/mem.c src/module.c src/net.c src/spdy.c \
src/utils.c src/worker.c src/zlib_dict.c
src/domain.c src/http.c src/mem.c src/module.c src/net.c src/pool.c \
src/spdy.c src/utils.c src/worker.c src/zlib_dict.c
S_OBJS= $(S_SRC:.c=.o)
CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes

View File

@ -50,9 +50,13 @@
#define KORE_PIDFILE_DEFAULT "/var/run/kore.pid"
#define KORE_DEFAULT_CIPHER_LIST "HIGH:!aNULL:!MD5;"
#if defined(KORE_DEBUG)
#define kore_debug(fmt, ...) \
if (kore_debug) \
kore_debug_internal(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#else
#define kore_debug(fmt, ...)
#endif
#define NETBUF_RECV 0
#define NETBUF_SEND 1
@ -176,6 +180,29 @@ struct buf_vec {
u_int32_t length;
};
struct kore_pool_region {
void *start;
LIST_ENTRY(kore_pool_region) list;
} __attribute__((__packed__));
struct kore_pool_entry {
u_int8_t state;
struct kore_pool_region *region;
LIST_ENTRY(kore_pool_entry) list;
} __attribute__((__packed__));
struct kore_pool {
u_int32_t elen;
u_int32_t slen;
u_int32_t elms;
u_int32_t inuse;
char *name;
LIST_HEAD(, kore_pool_region) regions;
LIST_HEAD(, kore_pool_entry) freelist;
} __attribute__((__packed__));
extern pid_t kore_pid;
extern int kore_debug;
extern int server_port;
@ -200,6 +227,7 @@ extern struct kore_worker *worker;
extern struct kore_domain_h domains;
extern struct kore_domain *primary_dom;
extern struct passwd *pw;
extern struct kore_pool nb_pool;
void kore_signal(int);
void kore_worker_wait(int);
@ -227,6 +255,7 @@ void kore_worker_entry(struct kore_worker *);
int kore_ssl_sni_cb(SSL *, int *, void *);
int kore_ssl_npn_cb(SSL *, const u_char **, unsigned int *, void *);
void kore_connection_init(void);
int kore_connection_nonblock(int);
int kore_connection_handle(struct connection *);
void kore_connection_remove(struct connection *);
@ -246,6 +275,11 @@ void *kore_realloc(void *, size_t);
void kore_mem_free(void *);
void kore_mem_init(void);
void *kore_pool_get(struct kore_pool *);
void kore_pool_put(struct kore_pool *, void *);
void kore_pool_init(struct kore_pool *, char *,
u_int32_t, u_int32_t);
time_t kore_date_to_time(char *);
char *kore_time_to_date(time_t);
char *kore_strdup(const char *);
@ -275,6 +309,7 @@ u_int16_t net_read16(u_int8_t *);
u_int32_t net_read32(u_int8_t *);
void net_write16(u_int8_t *, u_int16_t);
void net_write32(u_int8_t *, u_int32_t);
void net_init(void);
int net_recv(struct connection *);
int net_send(struct connection *);
int net_send_flush(struct connection *);

View File

@ -22,6 +22,15 @@
#include "kore.h"
#include "http.h"
struct kore_pool connection_pool;
void
kore_connection_init(void)
{
kore_pool_init(&connection_pool, "connection_pool",
sizeof(struct connection), worker_max_connections);
}
int
kore_connection_accept(struct listener *l, struct connection **out)
{
@ -33,16 +42,16 @@ kore_connection_accept(struct listener *l, struct connection **out)
*out = NULL;
len = sizeof(struct sockaddr_in);
c = kore_malloc(sizeof(*c));
c = kore_pool_get(&connection_pool);
if ((c->fd = accept(l->fd, (struct sockaddr *)&(c->sin), &len)) == -1) {
kore_mem_free(c);
kore_pool_put(&connection_pool, c);
kore_debug("accept(): %s", errno_s);
return (KORE_RESULT_ERROR);
}
if (!kore_connection_nonblock(c->fd)) {
close(c->fd);
kore_mem_free(c);
kore_pool_put(&connection_pool, c);
return (KORE_RESULT_ERROR);
}
@ -191,14 +200,14 @@ kore_connection_remove(struct connection *c)
TAILQ_REMOVE(&(c->send_queue), nb, list);
if (nb->buf != NULL)
kore_mem_free(nb->buf);
kore_mem_free(nb);
kore_pool_put(&nb_pool, nb);
}
for (nb = TAILQ_FIRST(&(c->recv_queue)); nb != NULL; nb = next) {
next = TAILQ_NEXT(nb, list);
TAILQ_REMOVE(&(c->recv_queue), nb, list);
kore_mem_free(nb->buf);
kore_mem_free(nb);
kore_pool_put(&nb_pool, nb);
}
for (s = TAILQ_FIRST(&(c->spdy_streams)); s != NULL; s = snext) {
@ -215,7 +224,7 @@ kore_connection_remove(struct connection *c)
}
kore_worker_connection_remove(c);
kore_mem_free(c);
kore_pool_put(&connection_pool, c);
}
void

View File

@ -24,6 +24,8 @@ static int http_post_data_recv(struct netbuf *);
static int http_send_done(struct netbuf *);
static TAILQ_HEAD(, http_request) http_requests;
static struct kore_pool http_request_pool;
static struct kore_pool http_header_pool;
int http_request_count;
@ -32,6 +34,12 @@ http_init(void)
{
http_request_count = 0;
TAILQ_INIT(&http_requests);
kore_pool_init(&http_request_pool, "http_request_pool",
sizeof(struct http_request), worker_max_connections);
kore_pool_init(&http_header_pool, "http_header_pool",
sizeof(struct http_header),
worker_max_connections * HTTP_REQ_HEADER_MAX);
}
int
@ -48,7 +56,7 @@ http_request_new(struct connection *c, struct spdy_stream *s, char *host,
if (strlen(path) >= HTTP_URI_LEN - 1)
return (KORE_RESULT_ERROR);
req = kore_malloc(sizeof(*req));
req = kore_pool_get(&http_request_pool);
req->end = 0;
req->start = 0;
req->flags = 0;
@ -152,7 +160,7 @@ http_response_header_add(struct http_request *req, char *header, char *value)
kore_debug("http_response_header_add(%p, %s, %s)", req, header, value);
hdr = kore_malloc(sizeof(*hdr));
hdr = kore_pool_get(&http_header_pool);
hdr->header = kore_strdup(header);
hdr->value = kore_strdup(value);
TAILQ_INSERT_TAIL(&(req->resp_headers), hdr, list);
@ -170,7 +178,7 @@ http_request_free(struct http_request *req)
TAILQ_REMOVE(&(req->resp_headers), hdr, list);
kore_mem_free(hdr->header);
kore_mem_free(hdr->value);
kore_mem_free(hdr);
kore_pool_put(&http_header_pool, hdr);
}
for (hdr = TAILQ_FIRST(&(req->req_headers)); hdr != NULL; hdr = next) {
@ -179,7 +187,7 @@ http_request_free(struct http_request *req)
TAILQ_REMOVE(&(req->req_headers), hdr, list);
kore_mem_free(hdr->header);
kore_mem_free(hdr->value);
kore_mem_free(hdr);
kore_pool_put(&http_header_pool, hdr);
}
for (q = TAILQ_FIRST(&(req->arguments)); q != NULL; q = qnext) {
@ -194,7 +202,8 @@ http_request_free(struct http_request *req)
if (req->agent != NULL)
kore_mem_free(req->agent);
kore_mem_free(req);
kore_pool_put(&http_request_pool, req);
}
int
@ -387,7 +396,7 @@ http_header_recv(struct netbuf *nb)
*(p++) = '\0';
if (*p == ' ')
p++;
hdr = kore_malloc(sizeof(*hdr));
hdr = kore_pool_get(&http_header_pool);
hdr->header = kore_strdup(headers[i]);
hdr->value = kore_strdup(p);
TAILQ_INSERT_TAIL(&(req->req_headers), hdr, list);

View File

@ -63,7 +63,11 @@ main(int argc, char *argv[])
config_file = optarg;
break;
case 'd':
#if defined(KORE_DEBUG)
kore_debug = 1;
#else
printf("kore not compiled with debug support\n");
#endif
break;
default:
usage();
@ -75,12 +79,12 @@ main(int argc, char *argv[])
kore_pid = getpid();
kore_log_init();
kore_mem_init();
kore_domain_init();
kore_server_sslstart();
kore_parse_config();
kore_log_init();
kore_platform_init();
kore_accesslog_init();

View File

@ -93,7 +93,9 @@ kore_platform_event_wait(void)
}
if (*fd == server.fd) {
while (worker->accepted < worker->accept_treshold) {
while ((worker->accepted < worker->accept_treshold) &&
(worker_active_connections <
worker_max_connections)) {
kore_connection_accept(&server, &c);
if (c == NULL)
break;

View File

@ -27,7 +27,7 @@
struct meminfo {
u_int16_t magic;
TAILQ_ENTRY(meminfo) list;
};
} __attribute__((__packed__));
u_int32_t meminuse;
TAILQ_HEAD(, meminfo) memused;

View File

@ -16,15 +16,21 @@
#include "kore.h"
struct kore_pool nb_pool;
void
net_init(void)
{
kore_pool_init(&nb_pool, "nb_pool", sizeof(struct netbuf), 1000);
}
void
net_send_queue(struct connection *c, u_int8_t *data, size_t len, int flags,
struct netbuf **out, int (*cb)(struct netbuf *))
{
struct netbuf *nb;
//kore_debug("net_send_queue(%p, %p, %d, %p)", c, data, len, cb);
nb = kore_malloc(sizeof(*nb));
nb = kore_pool_get(&nb_pool);
nb->cb = cb;
nb->len = len;
nb->owner = c;
@ -50,9 +56,7 @@ net_recv_queue(struct connection *c, size_t len, int flags,
{
struct netbuf *nb;
//kore_debug("net_recv_queue(%p, %d, %p)", c, len, cb);
nb = kore_malloc(sizeof(*nb));
nb = kore_pool_get(&nb_pool);
nb->cb = cb;
nb->len = len;
nb->owner = c;
@ -70,8 +74,6 @@ int
net_recv_expand(struct connection *c, struct netbuf *nb, size_t len,
int (*cb)(struct netbuf *))
{
//kore_debug("net_recv_expand(%p, %p, %d, %p)", c, nb, len, cb);
if (nb->type != NETBUF_RECV) {
kore_debug("net_recv_expand(): wrong netbuf type");
return (KORE_RESULT_ERROR);
@ -131,7 +133,7 @@ net_send(struct connection *c)
if (nb->offset == nb->len) {
if (nb->buf != NULL)
kore_mem_free(nb->buf);
kore_mem_free(nb);
kore_pool_put(&nb_pool, nb);
}
if (r != KORE_RESULT_OK)
@ -202,7 +204,7 @@ handle:
TAILQ_REMOVE(&(c->recv_queue), nb, list);
kore_mem_free(nb->buf);
kore_mem_free(nb);
kore_pool_put(&nb_pool, nb);
}
if (r != KORE_RESULT_OK)

110
src/pool.c Normal file
View File

@ -0,0 +1,110 @@
/*
* Copyright (c) 2013 Joris Vink <joris@coders.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/queue.h>
#include "kore.h"
#define POOL_ELEMENT_BUSY 0
#define POOL_ELEMENT_FREE 1
static void pool_region_create(struct kore_pool *, u_int32_t);
void
kore_pool_init(struct kore_pool *pool, char *name, u_int32_t len, u_int32_t elm)
{
kore_debug("kore_pool_init(%p, %s, %d, %d)", pool, name, len, elm);
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));
LIST_INIT(&(pool->freelist));
pool_region_create(pool, elm);
}
void *
kore_pool_get(struct kore_pool *pool)
{
u_int8_t *ptr;
struct kore_pool_entry *entry;
if (LIST_EMPTY(&(pool->freelist))) {
kore_log(LOG_NOTICE, "pool %s is exhausted (%d/%d)",
pool->name, pool->inuse, pool->elms);
pool_region_create(pool, pool->elms);
}
entry = LIST_FIRST(&(pool->freelist));
LIST_REMOVE(entry, list);
entry->state = POOL_ELEMENT_BUSY;
ptr = (u_int8_t *)entry + sizeof(struct kore_pool_entry);
pool->inuse++;
return (ptr);
}
void
kore_pool_put(struct kore_pool *pool, void *ptr)
{
struct kore_pool_entry *entry;
entry = (struct kore_pool_entry *)
((u_int8_t *)ptr - sizeof(struct kore_pool_entry));
if (entry->state != POOL_ELEMENT_BUSY)
fatal("%s: element %p was not busy", pool->name, ptr);
entry->state = POOL_ELEMENT_FREE;
LIST_INSERT_HEAD(&(pool->freelist), entry, list);
pool->inuse--;
}
static void
pool_region_create(struct kore_pool *pool, u_int32_t elms)
{
u_int32_t i;
u_int8_t *p;
struct kore_pool_region *reg;
struct kore_pool_entry *entry;
kore_debug("pool_region_create(%p, %d)", pool, elms);
reg = kore_malloc(sizeof(struct kore_pool_region));
LIST_INSERT_HEAD(&(pool->regions), reg, list);
reg->start = kore_malloc(elms * pool->slen);
p = (u_int8_t *)reg->start;
for (i = 0; i < elms; i++) {
entry = (struct kore_pool_entry *)p;
entry->region = reg;
entry->state = POOL_ELEMENT_FREE;
LIST_INSERT_HEAD(&(pool->freelist), entry, list);
p = p + pool->slen;
}
pool->elms += elms;
}

View File

@ -461,7 +461,7 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb)
static int
spdy_ctrl_frame_settings(struct netbuf *nb)
{
u_int8_t *buf, flags;
u_int8_t *buf;
u_int32_t ecount, i, id, val, length;
struct connection *c = (struct connection *)nb->owner;
@ -478,7 +478,6 @@ spdy_ctrl_frame_settings(struct netbuf *nb)
buf = nb->buf + SPDY_FRAME_SIZE + 4;
for (i = 0; i < ecount; i++) {
flags = *(u_int8_t *)buf;
id = net_read32(buf) & 0xffffff;
val = net_read32(buf + 4);
@ -487,8 +486,7 @@ spdy_ctrl_frame_settings(struct netbuf *nb)
c->wsize_initial = val;
break;
default:
kore_debug("no handling for setting %d:%d (%d)",
id, val, flags);
kore_debug("no handling for setting %d:%d", id, val);
break;
}

View File

@ -192,7 +192,9 @@ kore_worker_entry(struct kore_worker *kw)
signal(SIGQUIT, kore_signal);
signal(SIGPIPE, SIG_IGN);
net_init();
http_init();
kore_connection_init();
TAILQ_INIT(&disconnected);
TAILQ_INIT(&worker_clients);
@ -213,12 +215,14 @@ kore_worker_entry(struct kore_worker *kw)
sig_recv = 0;
}
if (!worker->has_lock)
if (!worker->has_lock &&
(worker_active_connections < worker_max_connections))
kore_worker_acceptlock_obtain();
kore_platform_event_wait();
if (worker->accepted >= worker->accept_treshold &&
if (((worker->accepted >= worker->accept_treshold) ||
(worker_active_connections < worker_max_connections)) &&
worker->has_lock) {
worker->accepted = 0;
kore_worker_acceptlock_release();