make fakebank use epoll() on platforms where it is available

This commit is contained in:
Christian Grothoff 2018-08-19 11:20:35 +02:00
parent 7ba7a46f24
commit 7fb43dd2ae
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
3 changed files with 195 additions and 3 deletions

View File

@ -88,6 +88,38 @@ AC_MSG_RESULT($enable_expensive)
AM_CONDITIONAL([HAVE_EXPENSIVE_TESTS], [test "x$enable_expensive" = "xyes"]) AM_CONDITIONAL([HAVE_EXPENSIVE_TESTS], [test "x$enable_expensive" = "xyes"])
AC_ARG_ENABLE([[epoll]],
[AS_HELP_STRING([[--enable-epoll[=ARG]]], [enable epoll support (yes, no, auto) [auto]])],
[enable_epoll=${enableval}],
[enable_epoll='auto']
)
AS_IF([test "$enable_epoll" != "no"],
[AX_HAVE_EPOLL
AS_IF([test "${ax_cv_have_epoll}" = "yes"],
[AC_DEFINE([[EPOLL_SUPPORT]],[[1]],[Define to 1 to enable epoll support])
enable_epoll='yes'],
[AS_IF([test "$enable_epoll" = "yes"],
AC_MSG_ERROR([[Support for epoll was explicitly requested but cannot be enabled on this platform.]]))
enable_epoll='no'])])
AM_CONDITIONAL([MHD_HAVE_EPOLL], [[test "x$enable_epoll" = xyes]])
AS_IF([test "x$enable_epoll" = "xyes"],
AC_CACHE_CHECK([for epoll_create1()],
[mhd_cv_have_epoll_create1], [
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
#include <sys/epoll.h>
]], [[
int fd;
fd = epoll_create1(EPOLL_CLOEXEC);]])],
[mhd_cv_have_epoll_create1=yes],
[mhd_cv_have_epoll_create1=no])])
AS_IF([test "x$mhd_cv_have_epoll_create1" = "xyes"],[
AC_DEFINE([[HAVE_EPOLL_CREATE1]], [[1]], [Define if you have epoll_create1 function.])]))
if test "$wallet_only" != yes if test "$wallet_only" != yes
then then

104
m4/ax_have_epoll.m4 Normal file
View File

@ -0,0 +1,104 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_have_epoll.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_HAVE_EPOLL([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# AX_HAVE_EPOLL_PWAIT([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
#
# DESCRIPTION
#
# This macro determines whether the system supports the epoll I/O event
# interface. A neat usage example would be:
#
# AX_HAVE_EPOLL(
# [AX_CONFIG_FEATURE_ENABLE(epoll)],
# [AX_CONFIG_FEATURE_DISABLE(epoll)])
# AX_CONFIG_FEATURE(
# [epoll], [This platform supports epoll(7)],
# [HAVE_EPOLL], [This platform supports epoll(7).])
#
# The epoll interface was added to the Linux kernel in version 2.5.45, and
# the macro verifies that a kernel newer than this is installed. This
# check is somewhat unreliable if <linux/version.h> doesn't match the
# running kernel, but it is necessary regardless, because glibc comes with
# stubs for the epoll_create(), epoll_wait(), etc. that allow programs to
# compile and link even if the kernel is too old; the problem would then
# be detected only at runtime.
#
# Linux kernel version 2.6.19 adds the epoll_pwait() call in addition to
# epoll_wait(). The availability of that function can be tested with the
# second macro. Generally speaking, it is safe to assume that
# AX_HAVE_EPOLL would succeed if AX_HAVE_EPOLL_PWAIT has, but not the
# other way round.
#
# LICENSE
#
# Copyright (c) 2008 Peter Simons <simons@cryp.to>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 11
AC_DEFUN([AX_HAVE_EPOLL], [dnl
ax_have_epoll_cppflags="${CPPFLAGS}"
AC_CHECK_HEADER([linux/version.h], [CPPFLAGS="${CPPFLAGS} -DHAVE_LINUX_VERSION_H"])
AC_MSG_CHECKING([for Linux epoll(7) interface])
AC_CACHE_VAL([ax_cv_have_epoll], [dnl
AC_LINK_IFELSE([dnl
AC_LANG_PROGRAM([dnl
#include <sys/epoll.h>
#ifdef HAVE_LINUX_VERSION_H
# include <linux/version.h>
# if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45)
# error linux kernel version is too old to have epoll
# endif
#endif
], [dnl
int fd, rc;
struct epoll_event ev;
fd = epoll_create(128);
rc = epoll_wait(fd, &ev, 1, 0);])],
[ax_cv_have_epoll=yes],
[ax_cv_have_epoll=no])])
CPPFLAGS="${ax_have_epoll_cppflags}"
AS_IF([test "${ax_cv_have_epoll}" = "yes"],
[AC_MSG_RESULT([yes])
$1],[AC_MSG_RESULT([no])
$2])
])dnl
AC_DEFUN([AX_HAVE_EPOLL_PWAIT], [dnl
ax_have_epoll_cppflags="${CPPFLAGS}"
AC_CHECK_HEADER([linux/version.h],
[CPPFLAGS="${CPPFLAGS} -DHAVE_LINUX_VERSION_H"])
AC_MSG_CHECKING([for Linux epoll(7) interface with signals extension])
AC_CACHE_VAL([ax_cv_have_epoll_pwait], [dnl
AC_LINK_IFELSE([dnl
AC_LANG_PROGRAM([dnl
#ifdef HAVE_LINUX_VERSION_H
# include <linux/version.h>
# if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
# error linux kernel version is too old to have epoll_pwait
# endif
#endif
#include <sys/epoll.h>
#include <signal.h>
], [dnl
int fd, rc;
struct epoll_event ev;
fd = epoll_create(128);
rc = epoll_wait(fd, &ev, 1, 0);
rc = epoll_pwait(fd, &ev, 1, 0, (sigset_t const *)(0));])],
[ax_cv_have_epoll_pwait=yes],
[ax_cv_have_epoll_pwait=no])])
CPPFLAGS="${ax_have_epoll_cppflags}"
AS_IF([test "${ax_cv_have_epoll_pwait}" = "yes"],
[AC_MSG_RESULT([yes])
$1],[AC_MSG_RESULT([no])
$2])
])dnl

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
(C) 2016, 2017 Inria and GNUnet e.V. (C) 2016, 2017, 2018 Inria and GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software terms of the GNU General Public License as published by the Free Software
@ -19,7 +19,6 @@
* @brief library that fakes being a Taler bank for testcases * @brief library that fakes being a Taler bank for testcases
* @author Christian Grothoff <christian@grothoff.org> * @author Christian Grothoff <christian@grothoff.org>
*/ */
#include "platform.h" #include "platform.h"
#include "taler_fakebank_lib.h" #include "taler_fakebank_lib.h"
#include "taler_bank_service.h" #include "taler_bank_service.h"
@ -125,6 +124,18 @@ struct TALER_FAKEBANK_Handle
* Number of transactions. * Number of transactions.
*/ */
uint64_t serial_counter; uint64_t serial_counter;
#if EPOLL_SUPPORT
/**
* Boxed @e mhd_fd.
*/
struct GNUNET_NETWORK_Handle *mhd_rfd;
/**
* File descriptor to use to wait for MHD.
*/
int mhd_fd;
#endif
}; };
@ -328,6 +339,9 @@ TALER_FAKEBANK_stop (struct TALER_FAKEBANK_Handle *h)
GNUNET_SCHEDULER_cancel (h->mhd_task); GNUNET_SCHEDULER_cancel (h->mhd_task);
h->mhd_task = NULL; h->mhd_task = NULL;
} }
#if EPOLL_SUPPORT
GNUNET_NETWORK_socket_free_memory_only_ (h->mhd_rfd);
#endif
if (NULL != h->mhd_bank) if (NULL != h->mhd_bank)
{ {
MHD_stop_daemon (h->mhd_bank); MHD_stop_daemon (h->mhd_bank);
@ -976,10 +990,42 @@ static void
run_mhd (void *cls); run_mhd (void *cls);
#if EPOLL_SUPPORT
/** /**
* Schedule MHD. This function should be called initially when an * Schedule MHD. This function should be called initially when an
* MHD is first getting its client socket, and will then automatically * MHD is first getting its client socket, and will then automatically
* always be called later whenever there is work to be done. * always be called later whenever there is work to be done.
*
* @param h fakebank handle to schedule MHD for
*/
static void
schedule_httpd (struct TALER_FAKEBANK_Handle *h)
{
int haveto;
MHD_UNSIGNED_LONG_LONG timeout;
struct GNUNET_TIME_Relative tv;
haveto = MHD_get_timeout (h->mhd_bank,
&timeout);
if (MHD_YES == haveto)
tv.rel_value_us = (uint64_t) timeout * 1000LL;
else
tv = GNUNET_TIME_UNIT_FOREVER_REL;
if (NULL != h->mhd_task)
GNUNET_SCHEDULER_cancel (h->mhd_task);
h->mhd_task =
GNUNET_SCHEDULER_add_read_net (tv,
h->mhd_rfd,
&run_mhd,
h);
}
#else
/**
* Schedule MHD. This function should be called initially when an
* MHD is first getting its client socket, and will then automatically
* always be called later whenever there is work to be done.
*
* @param h fakebank handle to schedule MHD for
*/ */
static void static void
schedule_httpd (struct TALER_FAKEBANK_Handle *h) schedule_httpd (struct TALER_FAKEBANK_Handle *h)
@ -1033,6 +1079,7 @@ schedule_httpd (struct TALER_FAKEBANK_Handle *h)
if (NULL != wws) if (NULL != wws)
GNUNET_NETWORK_fdset_destroy (wws); GNUNET_NETWORK_fdset_destroy (wws);
} }
#endif
/** /**
@ -1063,7 +1110,11 @@ TALER_FAKEBANK_start (uint16_t port)
struct TALER_FAKEBANK_Handle *h; struct TALER_FAKEBANK_Handle *h;
h = GNUNET_new (struct TALER_FAKEBANK_Handle); h = GNUNET_new (struct TALER_FAKEBANK_Handle);
h->mhd_bank = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_DUAL_STACK, h->mhd_bank = MHD_start_daemon (MHD_USE_DEBUG
#if EPOLL_SUPPORT
| MHD_USE_EPOLL
#endif
| MHD_USE_DUAL_STACK,
port, port,
NULL, NULL, NULL, NULL,
&handle_mhd_request, h, &handle_mhd_request, h,
@ -1075,6 +1126,11 @@ TALER_FAKEBANK_start (uint16_t port)
GNUNET_free (h); GNUNET_free (h);
return NULL; return NULL;
} }
#if EPOLL_SUPPORT
h->mhd_fd = MHD_get_daemon_info (h->mhd_bank,
MHD_DAEMON_INFO_EPOLL_FD)->epoll_fd;
h->mhd_rfd = GNUNET_NETWORK_socket_box_native (h->mhd_fd);
#endif
schedule_httpd (h); schedule_httpd (h);
return h; return h;
} }