From patchwork Tue May 13 00:35:48 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masashi Honma X-Patchwork-Id: 348193 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from maxx.maxx.shmoo.com (maxx.shmoo.com [205.134.188.171]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id B4B7D14007E for ; Tue, 13 May 2014 10:36:37 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 931BD9C127; Mon, 12 May 2014 20:36:33 -0400 (EDT) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id nrdjfJBv7na7; Mon, 12 May 2014 20:36:33 -0400 (EDT) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id D1BD49C186; Mon, 12 May 2014 20:36:27 -0400 (EDT) X-Original-To: mailman-post+hostap@maxx.shmoo.com Delivered-To: mailman-post+hostap@maxx.shmoo.com Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 97B649C186 for ; Mon, 12 May 2014 20:36:26 -0400 (EDT) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id TyPByiApi4BU for ; Mon, 12 May 2014 20:36:20 -0400 (EDT) Received: from mail-pb0-f43.google.com (mail-pb0-f43.google.com [209.85.160.43]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (not verified)) by maxx.maxx.shmoo.com (Postfix) with ESMTPS id 622939C127 for ; Mon, 12 May 2014 20:36:20 -0400 (EDT) Received: by mail-pb0-f43.google.com with SMTP id up15so278996pbc.30 for ; Mon, 12 May 2014 17:36:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ywE56+5di1rgSQyz0OKCBswi9UgfIatt6Gw5/yJt1KM=; b=MJS+rigNP015fgJb2oovj7iguDj+Mz/A7DcUFzc4eMIIgADuKmibaoeZauKmF07ZWm Ke6IY9dkjfcMZpaP04U2qv4N1HEaOp8f/Zw2tow5JGyI3xg0GLLqg/2yGIiWGMnasWfC gC073cqk2LPmxumQqlTQCscvzjZsJRbBytIARlVlo7oR8RzV4h1rytNij4ZKz0p8Inpx q2o6XSNTxSAmsz3Eq6t5iy7SDmSHvbD/6Unn1WSg/6yMXX4KnDWxG1LxGkSRIPPJpCi+ Z2+tvY5/H96RfxEd/nrLYy8ewOduVFPrmFbnQaC36WBNCCZ8QBaRo3LV7zDgOuquIirf SvMQ== X-Received: by 10.67.14.69 with SMTP id fe5mr60641491pad.120.1399941378302; Mon, 12 May 2014 17:36:18 -0700 (PDT) Received: from localhost.localdomain (pa8f0e6.kngwnt01.ap.so-net.ne.jp. [182.168.240.230]) by mx.google.com with ESMTPSA id ox3sm24934742pbb.88.2014.05.12.17.36.16 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 12 May 2014 17:36:17 -0700 (PDT) From: Masashi Honma To: hostap@lists.shmoo.com Subject: [PATCH] Add epoll option for better performance Date: Tue, 13 May 2014 09:35:48 +0900 Message-Id: <1399941348-3059-1-git-send-email-masashi.honma@gmail.com> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <20140512155708.GE15222@w1.fi> References: <20140512155708.GE15222@w1.fi> X-BeenThere: hostap@lists.shmoo.com X-Mailman-Version: 2.1.11 Precedence: list List-Id: HostAP Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: hostap-bounces@lists.shmoo.com Errors-To: hostap-bounces@lists.shmoo.com > On its own, this does not seem to be changing anything, so I'm not going to > apply it without some real justification showing how this is going to be > used with the following changes (epoll). This is the following patch. Signed-off-by: Masashi Honma --- src/utils/eloop.c | 175 ++++++++++++++++++++++++++++++++++++++---- wpa_supplicant/Android.mk | 4 + wpa_supplicant/Makefile | 3 + wpa_supplicant/android.config | 5 +- wpa_supplicant/defconfig | 5 +- 5 files changed, 174 insertions(+), 18 deletions(-) diff --git a/src/utils/eloop.c b/src/utils/eloop.c index a788260..68c3b8c 100644 --- a/src/utils/eloop.c +++ b/src/utils/eloop.c @@ -14,14 +14,21 @@ #include "list.h" #include "eloop.h" -#ifndef CONFIG_ELOOP_POLL +#if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_EPOLL) +#error Do not define both of poll and epoll +#endif + +#if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL) #define CONFIG_ELOOP_SELECT -#endif /* CONFIG_ELOOP_POLL */ +#endif #ifdef CONFIG_ELOOP_POLL #include #endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_EPOLL +#include +#endif /* CONFIG_ELOOP_EPOLL */ struct eloop_sock { int sock; @@ -54,7 +61,11 @@ struct eloop_signal { struct eloop_sock_table { int count; struct eloop_sock *table; +#ifdef CONFIG_ELOOP_EPOLL + eloop_event_type type; +#else /* CONFIG_ELOOP_EPOLL */ int changed; +#endif /* CONFIG_ELOOP_EPOLL */ }; struct eloop_data { @@ -67,6 +78,13 @@ struct eloop_data { struct pollfd *pollfds; struct pollfd **pollfds_map; #endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_EPOLL + int epollfd; + int epoll_max_event_num; + int epoll_max_fd; + struct eloop_sock *epoll_table; + struct epoll_event *epoll_events; +#endif /* CONFIG_ELOOP_EPOLL */ struct eloop_sock_table readers; struct eloop_sock_table writers; struct eloop_sock_table exceptions; @@ -79,7 +97,6 @@ struct eloop_data { int pending_terminate; int terminate; - int reader_table_changed; }; static struct eloop_data eloop; @@ -132,6 +149,17 @@ int eloop_init(void) { os_memset(&eloop, 0, sizeof(eloop)); dl_list_init(&eloop.timeout); +#ifdef CONFIG_ELOOP_EPOLL + eloop.epollfd = epoll_create1(0); + if (eloop.epollfd < 0) { + wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s\n", + __func__, strerror(errno)); + return -1; + } + eloop.readers.type = EVENT_TYPE_READ; + eloop.writers.type = EVENT_TYPE_WRITE; + eloop.exceptions.type = EVENT_TYPE_EXCEPTION; +#endif /* CONFIG_ELOOP_EPOLL */ #ifdef WPA_TRACE signal(SIGSEGV, eloop_sigsegv_handler); #endif /* WPA_TRACE */ @@ -143,6 +171,11 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, int sock, eloop_sock_handler handler, void *eloop_data, void *user_data) { +#ifdef CONFIG_ELOOP_EPOLL + struct eloop_sock *temp_table; + struct epoll_event ev, *temp_events; + int next; +#endif /* CONFIG_ELOOP_EPOLL */ struct eloop_sock *tmp; int new_max_sock; @@ -178,6 +211,33 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, eloop.pollfds = n; } #endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_EPOLL + if (new_max_sock >= eloop.epoll_max_fd) { + next = eloop.epoll_max_fd == 0 ? 16 : eloop.epoll_max_fd * 2; + temp_table = os_realloc_array(eloop.epoll_table, next, + sizeof(struct eloop_sock)); + if (temp_table == NULL) + return -1; + + eloop.epoll_max_fd = next; + eloop.epoll_table = temp_table; + } + + if (eloop.count + 1 > eloop.epoll_max_event_num) { + next = eloop.epoll_max_event_num == 0 ? 8 : + eloop.epoll_max_event_num * 2; + temp_events = os_realloc_array(eloop.epoll_events, next, + sizeof(struct epoll_event)); + if (temp_events == NULL) { + wpa_printf(MSG_ERROR, "%s: malloc for epoll failed. " + "%s\n", __func__, strerror(errno)); + return -1; + } + + eloop.epoll_max_event_num = next; + eloop.epoll_events = temp_events; + } +#endif /* CONFIG_ELOOP_EPOLL */ eloop_trace_sock_remove_ref(table); tmp = os_realloc_array(table->table, table->count + 1, @@ -194,9 +254,38 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, table->table = tmp; eloop.max_sock = new_max_sock; eloop.count++; +#ifndef CONFIG_ELOOP_EPOLL table->changed = 1; +#endif /* CONFIG_ELOOP_EPOLL */ eloop_trace_sock_add_ref(table); +#ifdef CONFIG_ELOOP_EPOLL + os_memset(&ev, 0, sizeof(ev)); + switch (table->type) { + case EVENT_TYPE_READ: + ev.events = EPOLLIN; + break; + case EVENT_TYPE_WRITE: + ev.events = EPOLLOUT; + break; + /* + * Exceptions are always checked when using epoll, but I suppose it's + * possible that someone registered a socket *only* for exception + * handling. + */ + case EVENT_TYPE_EXCEPTION: + ev.events = EPOLLERR | EPOLLHUP; + break; + } + ev.data.fd = sock; + if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) { + wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d " + "failed. %s\n", __func__, sock, strerror(errno)); + return -1; + } + os_memcpy(&eloop.epoll_table[sock], &table->table[table->count - 1], + sizeof(struct eloop_sock)); +#endif /* CONFIG_ELOOP_EPOLL */ return 0; } @@ -223,8 +312,18 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, } table->count--; eloop.count--; +#ifndef CONFIG_ELOOP_EPOLL table->changed = 1; +#endif /* CONFIG_ELOOP_EPOLL */ eloop_trace_sock_add_ref(table); +#ifdef CONFIG_ELOOP_EPOLL + if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) { + wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d " + "failed. %s\n", __func__, sock, strerror(errno)); + return; + } + os_memset(&eloop.epoll_table[sock], 0, sizeof(struct eloop_sock)); +#endif /* CONFIG_ELOOP_EPOLL */ } @@ -410,6 +509,23 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *table, #endif /* CONFIG_ELOOP_SELECT */ +#ifdef CONFIG_ELOOP_EPOLL +static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds) +{ + struct eloop_sock *table; + int i; + + for (i = 0; i < nfds; i++) { + table = &eloop.epoll_table[events[i].data.fd]; + if (table->handler == NULL) + continue; + table->handler(table->sock, table->eloop_data, + table->user_data); + } +} +#endif /* CONFIG_ELOOP_EPOLL */ + + static void eloop_sock_table_destroy(struct eloop_sock_table *table) { if (table) { @@ -787,6 +903,9 @@ void eloop_run(void) fd_set *rfds, *wfds, *efds; struct timeval _tv; #endif /* CONFIG_ELOOP_SELECT */ +#ifdef CONFIG_ELOOP_EPOLL + int timeout_ms = -1; +#endif /* CONFIG_ELOOP_EPOLL */ int res; struct os_reltime tv, now; @@ -810,9 +929,9 @@ void eloop_run(void) os_reltime_sub(&timeout->time, &now, &tv); else tv.sec = tv.usec = 0; -#ifdef CONFIG_ELOOP_POLL +#if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) timeout_ms = tv.sec * 1000 + tv.usec / 1000; -#endif /* CONFIG_ELOOP_POLL */ +#endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */ #ifdef CONFIG_ELOOP_SELECT _tv.tv_sec = tv.sec; _tv.tv_usec = tv.usec; @@ -826,12 +945,6 @@ void eloop_run(void) eloop.max_pollfd_map); res = poll(eloop.pollfds, num_poll_fds, timeout ? timeout_ms : -1); - - if (res < 0 && errno != EINTR && errno != 0) { - wpa_printf(MSG_INFO, "eloop: poll: %s", - strerror(errno)); - goto out; - } #endif /* CONFIG_ELOOP_POLL */ #ifdef CONFIG_ELOOP_SELECT eloop_sock_table_set_fds(&eloop.readers, rfds); @@ -839,12 +952,29 @@ void eloop_run(void) eloop_sock_table_set_fds(&eloop.exceptions, efds); res = select(eloop.max_sock + 1, rfds, wfds, efds, timeout ? &_tv : NULL); +#endif /* CONFIG_ELOOP_SELECT */ +#ifdef CONFIG_ELOOP_EPOLL + if (eloop.count == 0) { + res = 0; + } else { + res = epoll_wait(eloop.epollfd, eloop.epoll_events, + eloop.count, timeout_ms); + } +#endif /* CONFIG_ELOOP_EPOLL */ if (res < 0 && errno != EINTR && errno != 0) { - wpa_printf(MSG_INFO, "eloop: select: %s", - strerror(errno)); + wpa_printf(MSG_ERROR, "eloop: %s: %s", +#ifdef CONFIG_ELOOP_POLL + "poll" +#endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_SELECT + "select" +#endif /* CONFIG_ELOOP_SELECT */ +#ifdef CONFIG_ELOOP_EPOLL + "epoll" +#endif /* CONFIG_ELOOP_EPOLL */ + , strerror(errno)); goto out; } -#endif /* CONFIG_ELOOP_SELECT */ eloop_process_pending_signals(); /* check if some registered timeouts have occurred */ @@ -876,6 +1006,9 @@ void eloop_run(void) eloop_sock_table_dispatch(&eloop.writers, wfds); eloop_sock_table_dispatch(&eloop.exceptions, efds); #endif /* CONFIG_ELOOP_SELECT */ +#ifdef CONFIG_ELOOP_EPOLL + eloop_sock_table_dispatch(eloop.epoll_events, res); +#endif /* CONFIG_ELOOP_EPOLL */ } eloop.terminate = 0; @@ -928,6 +1061,11 @@ void eloop_destroy(void) os_free(eloop.pollfds); os_free(eloop.pollfds_map); #endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_EPOLL + os_free(eloop.epoll_table); + os_free(eloop.epoll_events); + close(eloop.epollfd); +#endif /* CONFIG_ELOOP_EPOLL */ } @@ -951,7 +1089,12 @@ void eloop_wait_for_read_sock(int sock) poll(&pfd, 1, -1); #endif /* CONFIG_ELOOP_POLL */ -#ifdef CONFIG_ELOOP_SELECT +#if defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) + /* + * We can use epoll() here. But epoll() requres 4 system calls. + * epoll_create1(), epoll_ctl() for ADD, epoll_wait, and close() for + * epoll fd. So select() is better for performance here. + */ fd_set rfds; if (sock < 0) @@ -960,7 +1103,7 @@ void eloop_wait_for_read_sock(int sock) FD_ZERO(&rfds); FD_SET(sock, &rfds); select(sock + 1, &rfds, NULL, NULL, NULL); -#endif /* CONFIG_ELOOP_SELECT */ +#endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */ } #ifdef CONFIG_ELOOP_SELECT diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index a60a26a..369119d 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -140,6 +140,10 @@ ifdef CONFIG_ELOOP_POLL L_CFLAGS += -DCONFIG_ELOOP_POLL endif +ifdef CONFIG_ELOOP_EPOLL +L_CFLAGS += -DCONFIG_ELOOP_EPOLL +endif + ifdef CONFIG_EAPOL_TEST L_CFLAGS += -Werror -DEAPOL_TEST endif diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 19dae70..9b46661 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -138,6 +138,9 @@ ifdef CONFIG_ELOOP_POLL CFLAGS += -DCONFIG_ELOOP_POLL endif +ifdef CONFIG_ELOOP_EPOLL +CFLAGS += -DCONFIG_ELOOP_EPOLL +endif ifdef CONFIG_EAPOL_TEST CFLAGS += -Werror -DEAPOL_TEST diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config index ffa2f01..3ed734d 100644 --- a/wpa_supplicant/android.config +++ b/wpa_supplicant/android.config @@ -237,7 +237,7 @@ CONFIG_BACKEND=file # main_none = Very basic example (development use only) #CONFIG_MAIN=main -# Select wrapper for operatins system and C library specific functions +# Select wrapper for operating system and C library specific functions # unix = UNIX/POSIX like systems (default) # win32 = Windows systems # none = Empty template @@ -251,6 +251,9 @@ CONFIG_ELOOP=eloop # Should we use poll instead of select? Select is used by default. #CONFIG_ELOOP_POLL=y +# Should we use epoll instead of select? Select is used by default. +#CONFIG_ELOOP_EPOLL=y + # Select layer 2 packet implementation # linux = Linux packet socket (default) # pcap = libpcap/libdnet/WinPcap diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index d194eb8..94c94b1 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -253,7 +253,7 @@ CONFIG_BACKEND=file # main_none = Very basic example (development use only) #CONFIG_MAIN=main -# Select wrapper for operatins system and C library specific functions +# Select wrapper for operating system and C library specific functions # unix = UNIX/POSIX like systems (default) # win32 = Windows systems # none = Empty template @@ -267,6 +267,9 @@ CONFIG_BACKEND=file # Should we use poll instead of select? Select is used by default. #CONFIG_ELOOP_POLL=y +# Should we use epoll instead of select? Select is used by default. +#CONFIG_ELOOP_EPOLL=y + # Select layer 2 packet implementation # linux = Linux packet socket (default) # pcap = libpcap/libdnet/WinPcap