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"])
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
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
(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
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
* @author Christian Grothoff <christian@grothoff.org>
*/
#include "platform.h"
#include "taler_fakebank_lib.h"
#include "taler_bank_service.h"
@ -125,6 +124,18 @@ struct TALER_FAKEBANK_Handle
* Number of transactions.
*/
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);
h->mhd_task = NULL;
}
#if EPOLL_SUPPORT
GNUNET_NETWORK_socket_free_memory_only_ (h->mhd_rfd);
#endif
if (NULL != h->mhd_bank)
{
MHD_stop_daemon (h->mhd_bank);
@ -976,10 +990,42 @@ static void
run_mhd (void *cls);
#if EPOLL_SUPPORT
/**
* 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
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
schedule_httpd (struct TALER_FAKEBANK_Handle *h)
@ -1033,6 +1079,7 @@ schedule_httpd (struct TALER_FAKEBANK_Handle *h)
if (NULL != wws)
GNUNET_NETWORK_fdset_destroy (wws);
}
#endif
/**
@ -1063,7 +1110,11 @@ TALER_FAKEBANK_start (uint16_t port)
struct TALER_FAKEBANK_Handle *h;
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,
NULL, NULL,
&handle_mhd_request, h,
@ -1075,6 +1126,11 @@ TALER_FAKEBANK_start (uint16_t port)
GNUNET_free (h);
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);
return h;
}