Feature #8788 » tt_efd_v2.patch
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();
|
- « Previous
- 1
- 2
- 3
- Next »