Project

General

Profile

Feature #8788 » tt_efd_v2.patch

normalperson (Eric Wong), 07/08/2014 10:38 PM

View differences:

configure.in
intrinsics.h \
langinfo.h \
locale.h \
sys/eventfd.h \
sys/sendfile.h \
time.h \
net/socket.h \
......
AC_CHECK_FUNCS(dup3)
AC_CHECK_FUNCS(eaccess)
AC_CHECK_FUNCS(endgrent)
AC_CHECK_FUNCS(eventfd)
AC_CHECK_FUNCS(fchmod)
AC_CHECK_FUNCS(fchown)
AC_CHECK_FUNCS(fcntl)
thread_pthread.c
#define TIME_QUANTUM_USEC (100 * 1000)
#if USE_SLEEPY_TIMER_THREAD
static ssize_t
tt_pipe_write(int fd)
{
return write(fd, "!", 1);
}
static ssize_t
tt_pipe_read(int fd)
{
#define CCP_READ_BUFF_SIZE 1024
/* buffer can be shared because no one refers to them. */
static char buff[CCP_READ_BUFF_SIZE];
return read(fd, buff, sizeof(buff));
}
struct tt_wakeup_impl {
ssize_t (*tt_write)(int fd);
ssize_t (*tt_read)(int fd);
};
struct tt_wakeup_impl *ttwup;
struct tt_wakeup_impl tt_pipe = { tt_pipe_write, tt_pipe_read };
static struct {
int normal[2];
int low[2];
......
/* already opened */
if (timer_thread_pipe.owner_process == getpid()) {
const char *buff = "!";
retry:
if ((result = write(fd, buff, 1)) <= 0) {
if ((result = ttwup->tt_write(fd)) <= 0) {
int e = errno;
switch (e) {
case EINTR: goto retry;
......
static void
consume_communication_pipe(int fd)
{
#define CCP_READ_BUFF_SIZE 1024
/* buffer can be shared because no one refers to them. */
static char buff[CCP_READ_BUFF_SIZE];
ssize_t result;
while (1) {
result = read(fd, buff, sizeof(buff));
result = ttwup->tt_read(fd);
if (result == 0) {
return;
}
......
if (close(pipes[0]) < 0) {
rb_bug_errno("native_stop_timer_thread - close(ttp[0])", errno);
}
if (close(pipes[1]) < 0) {
if ((pipes[0] != pipes[1]) && (close(pipes[1]) < 0)) {
rb_bug_errno("native_stop_timer_thread - close(ttp[1])", errno);
}
pipes[0] = pipes[1] = -1;
......
set_nonblock(pipes[1]);
}
#if defined(HAVE_EVENTFD) && defined(HAVE_SYS_EVENTFD_H)
# include <sys/eventfd.h>
static ssize_t tt_efd_write(int fd)
{
static const uint64_t buf = 1;
return write(fd, &buf, sizeof(buf));
}
static ssize_t tt_efd_read(int fd)
{
uint64_t buf;
return read(fd, &buf, sizeof(buf));
}
struct tt_wakeup_impl tt_efd = { tt_efd_write, tt_efd_read };
/*
* eventfd appeared in 2.6.22, but only gained EFD_CLOEXEC/NONBLOCK support
* in 2.6.27, so we must take care of systems having new headers but
* run on old kernels
*/
# if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
# define TT_EFD_FLAGS (EFD_CLOEXEC|EFD_NONBLOCK)
# else
# define TT_EFD_FLAGS (0)
# endif
static int
efd_pair(int fds[2])
{
static int efd_flags = TT_EFD_FLAGS;
int fd;
/* close eventfd of parent process */
if (fds[0] >= 0)
close_communication_pipe(fds);
fd = eventfd(0, efd_flags);
if (fd < 0) {
int err = errno;
if (err == EINVAL && efd_flags != 0) { /* Linux 2.6.22 - 2.6.26 */
efd_flags = 0; /* need manual fixup later */
fd = eventfd(0, efd_flags);
if (fd < 0)
return errno;
}
else {
return err; /* ENOSYS, EMFILE, ENFILE, ENODEV or ENOMEM */
}
}
rb_update_max_fd(fd);
if (efd_flags == 0) { /* fixup for old kernels */
set_nonblock(fd);
rb_maygvl_fd_fix_cloexec(fd);
}
fds[0] = fds[1] = fd;
return 0;
}
static int
efd_setup(void)
{
int err = efd_pair(timer_thread_pipe.normal);
if (err) return err;
err = efd_pair(timer_thread_pipe.low);
if (!err)
ttwup = &tt_efd; /* success! */
else
close_communication_pipe(timer_thread_pipe.normal);
return err;
}
# else /* !HAVE_EVENTFD */
static int
efd_setup(void)
{
return ENOSYS;
}
# endif /* !HAVE_EVENTFD */
/* communication pipe with timer thread and signal handler */
static void
setup_communication_pipe(void)
......
/* already set up. */
return;
}
setup_communication_pipe_internal(timer_thread_pipe.normal);
setup_communication_pipe_internal(timer_thread_pipe.low);
if (efd_setup() != 0) {
setup_communication_pipe_internal(timer_thread_pipe.normal);
setup_communication_pipe_internal(timer_thread_pipe.low);
ttwup = &tt_pipe;
}
/* validate pipe on this process */
timer_thread_pipe.owner_process = getpid();
(3-3/3)