Skip to content

Commit

Permalink
perf: use linux list
Browse files Browse the repository at this point in the history
Signed-off-by: Jianhui Zhao <zhaojh329@gmail.com>
  • Loading branch information
zhaojh329 committed Aug 25, 2021
1 parent 73da5b1 commit a0fa330
Show file tree
Hide file tree
Showing 8 changed files with 307 additions and 115 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ install(
uhttpd.h
log/log.h
utils.h
list.h
buffer/buffer.h
http-parser/http_parser.h
${CMAKE_CURRENT_BINARY_DIR}/config.h
Expand Down
32 changes: 13 additions & 19 deletions src/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,31 +510,31 @@ static bool match_path(struct uh_str *path, const char *needle, int needlelen, u
}
}

static bool set_path_handler(struct uh_connection_internal *conn, struct uh_path_handler *h,
static bool set_path_handler(struct uh_connection_internal *conn, struct list_head *head,
struct uh_str *path, bool wildcard)
{
while (h) {
struct uh_path_handler *h;

list_for_each_entry(h, head, list) {
if (match_path(path, h->path, h->len, h->flags, wildcard)) {
conn->handler = h->handler;
return true;
}

h = h->next;
}

return false;
}

static bool set_plugin_handler(struct uh_connection_internal *conn, struct uh_plugin *p,
static bool set_plugin_handler(struct uh_connection_internal *conn, struct list_head *head,
struct uh_str *path, bool wildcard)
{
while (p) {
struct uh_plugin *p;

list_for_each_entry(p, head, list) {
if (match_path(path, p->path, p->len, p->flags, wildcard)) {
conn->handler = p->h->handler;
return true;
}

p = p->next;
}

return false;
Expand Down Expand Up @@ -562,19 +562,19 @@ static int on_headers_complete(struct http_parser *parser)
addr_str, (saddr2str(sa, addr_str, sizeof(addr_str), &port) ? port : 0));

/* match non wildcard path handler */
if (set_path_handler(conn, srv->handlers, &path, false))
if (set_path_handler(conn, &srv->handlers, &path, false))
goto done;

/* match wildcard path handler */
if (set_path_handler(conn, srv->handlers, &path, true))
if (set_path_handler(conn, &srv->handlers, &path, true))
goto done;

/* match non wildcard plugin */
if (set_plugin_handler(conn, srv->plugins, &path, false))
if (set_plugin_handler(conn, &srv->plugins, &path, false))
goto done;

/* match wildcard plugin */
set_plugin_handler(conn, srv->plugins, &path, true);
set_plugin_handler(conn, &srv->plugins, &path, true);

done:
if (!conn->handler)
Expand Down Expand Up @@ -684,13 +684,7 @@ void conn_free(struct uh_connection_internal *conn)
if (conn->file.fd > 0)
close(conn->file.fd);

if (conn->prev)
conn->prev->next = conn->next;
else
conn->srv->conns = conn->next;

if (conn->next)
conn->next->prev = conn->prev;
list_del(&conn->list);

#ifdef SSL_SUPPORT
ssl_session_free(conn->ssl);
Expand Down
4 changes: 2 additions & 2 deletions src/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include "buffer.h"
#include "uhttpd.h"
#include "list.h"

#define UHTTPD_CONNECTION_TIMEOUT 30.0
#define UHTTPD_MAX_HEADER_NUM 50
Expand Down Expand Up @@ -68,6 +69,7 @@ struct uh_request {

struct uh_connection_internal {
struct uh_connection com;
struct list_head list;
int sock;
void *ssl;
uint8_t flags;
Expand All @@ -91,8 +93,6 @@ struct uh_connection_internal {
} addr; /* peer address */
struct http_parser parser;
struct http_parser_url url_parser;
struct uh_connection_internal *prev;
struct uh_connection_internal *next;
void (*handler)(struct uh_connection *conn, int event);
};

Expand Down
210 changes: 210 additions & 0 deletions src/list.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/*
* MIT License
*
* Copyright (c) 2021 Jianhui Zhao <zhaojh329@gmail.com>
*
* 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.
*
* Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org>
* Copyright (c) 2010 Isilon Systems, Inc.
* Copyright (c) 2010 iX Systems, Inc.
* Copyright (c) 2010 Panasas, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LINUX_LIST_H_
#define _LINUX_LIST_H_

#include <stddef.h>

#ifndef container_of
#define container_of(ptr, type, member) \
({ \
const __typeof__(((type *) NULL)->member) *__mptr = (ptr); \
(type *) ((char *) __mptr - offsetof(type, member)); \
})
#endif

struct list_head {
struct list_head *next;
struct list_head *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)

static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list->prev = list;
}

static inline bool list_empty(const struct list_head *head)
{
return (head->next == head);
}

static inline bool list_is_first(const struct list_head *list,
const struct list_head *head)
{
return list->prev == head;
}

static inline bool list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}

static inline void _list_del(struct list_head *entry)
{
entry->next->prev = entry->prev;
entry->prev->next = entry->next;
}

static inline void list_del(struct list_head *entry)
{
_list_del(entry);
entry->next = entry->prev = NULL;
}

static inline void _list_add(struct list_head *_new, struct list_head *prev,
struct list_head *next)
{

next->prev = _new;
_new->next = next;
_new->prev = prev;
prev->next = _new;
}

static inline void list_del_init(struct list_head *entry)
{
_list_del(entry);
INIT_LIST_HEAD(entry);
}

#define list_entry(ptr, type, field) container_of(ptr, type, field)
#define list_first_entry(ptr, type, field) list_entry((ptr)->next, type, field)
#define list_last_entry(ptr, type, field) list_entry((ptr)->prev, type, field)

#define list_for_each(p, head) \
for (p = (head)->next; p != (head); p = p->next)

#define list_for_each_safe(p, n, head) \
for (p = (head)->next, n = p->next; p != (head); p = n, n = p->next)

#define list_for_each_entry(p, h, field) \
for (p = list_first_entry(h, __typeof__(*p), field); &p->field != (h); \
p = list_entry(p->field.next, __typeof__(*p), field))

#define list_for_each_entry_safe(p, n, h, field) \
for (p = list_first_entry(h, __typeof__(*p), field), \
n = list_entry(p->field.next, __typeof__(*p), field); &p->field != (h);\
p = n, n = list_entry(n->field.next, __typeof__(*n), field))

#define list_for_each_entry_reverse(p, h, field) \
for (p = list_last_entry(h, __typeof__(*p), field); &p->field != (h); \
p = list_entry(p->field.prev, __typeof__(*p), field))

#define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = p->prev)
#define list_for_each_prev_safe(p, n, h) for (p = (h)->prev, n = p->prev; p != (h); p = n, n = p->prev)

static inline void list_add(struct list_head *_new, struct list_head *head)
{
_list_add(_new, head, head->next);
}

static inline void list_add_tail(struct list_head *_new, struct list_head *head)
{
_list_add(_new, head->prev, head);
}

static inline void list_move(struct list_head *list, struct list_head *head)
{
_list_del(list);
list_add(list, head);
}

static inline void list_move_tail(struct list_head *entry, struct list_head *head)
{
_list_del(entry);
list_add_tail(entry, head);
}

static inline void _list_splice(const struct list_head *list, struct list_head *prev,
struct list_head *next)
{
struct list_head *first;
struct list_head *last;

if (list_empty(list))
return;

first = list->next;
last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}

static inline void list_splice(const struct list_head *list, struct list_head *head)
{
_list_splice(list, head, head->next);
}

static inline void list_splice_tail(struct list_head *list, struct list_head *head)
{
_list_splice(list, head->prev, head);
}

static inline void list_splice_init(struct list_head *list, struct list_head *head)
{
_list_splice(list, head, head->next);
INIT_LIST_HEAD(list);
}

static inline void list_splice_tail_init(struct list_head *list, struct list_head *head)
{
_list_splice(list, head->prev, head);
INIT_LIST_HEAD(list);
}

#endif /* _LINUX_LIST_H_ */
Loading

0 comments on commit a0fa330

Please sign in to comment.