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 »