forked from mirrors/kore
Add fixed size memory pools and use them throughout Kore.
This commit is contained in:
parent
f54e7ace83
commit
29fa49ba83
4
Makefile
4
Makefile
|
@ -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
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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
|
||||
|
|
21
src/http.c
21
src/http.c
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
struct meminfo {
|
||||
u_int16_t magic;
|
||||
TAILQ_ENTRY(meminfo) list;
|
||||
};
|
||||
} __attribute__((__packed__));
|
||||
|
||||
u_int32_t meminuse;
|
||||
TAILQ_HEAD(, meminfo) memused;
|
||||
|
|
22
src/net.c
22
src/net.c
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue