mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-04 10:16:17 +01:00
gmain: use Linux eventfd() for main context wake up
The Linux eventfd() call is basically tailor made for the main loop wake up pipe - all we want is a threadsafe way to write to a file descriptor, and wake up the context on the other end; we don't care about the content at all. The eventfd manual page basically explains the benefits: Applications can use an eventfd file descriptor instead of a pipe (see pipe(2)) in all cases where a pipe is used simply to signal events. The kernel overhead of an eventfd file descriptor is much lower than that of a pipe, and only one file descriptor is required (versus the two required for a pipe). When writing my multithreaded spawn test case I actually hit the 1024 file descriptor limit quickly, because we used 2 fds per main context. This brings that down to 1. https://bugzilla.gnome.org/show_bug.cgi?id=653140
This commit is contained in:
parent
29bb7638a5
commit
3904c8761a
20
configure.ac
20
configure.ac
@ -2604,6 +2604,26 @@ main (void)
|
|||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([for eventfd(2) system call])
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
],[
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
eventfd (0, EFD_CLOEXEC);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
])],
|
||||||
|
[
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE(HAVE_EVENTFD, 1, [we have the eventfd(2) system call])
|
||||||
|
],
|
||||||
|
[
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
])
|
||||||
|
|
||||||
dnl ****************************************
|
dnl ****************************************
|
||||||
dnl *** GLib POLL* compatibility defines ***
|
dnl *** GLib POLL* compatibility defines ***
|
||||||
dnl ****************************************
|
dnl ****************************************
|
||||||
|
59
glib/gmain.c
59
glib/gmain.c
@ -49,6 +49,9 @@
|
|||||||
|
|
||||||
#ifdef G_OS_UNIX
|
#ifdef G_OS_UNIX
|
||||||
#include "glib-unix.h"
|
#include "glib-unix.h"
|
||||||
|
#ifdef HAVE_EVENTFD
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -397,6 +400,14 @@ static GSList *main_contexts_without_pipe = NULL;
|
|||||||
|
|
||||||
#ifndef G_OS_WIN32
|
#ifndef G_OS_WIN32
|
||||||
|
|
||||||
|
#ifdef HAVE_EVENTFD
|
||||||
|
typedef struct {
|
||||||
|
guint checked_eventfd : 1;
|
||||||
|
guint have_eventfd : 1;
|
||||||
|
} EventFdState;
|
||||||
|
EventFdState event_fd_state = { 0, 0 };
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The UNIX signal pipe contains a single byte specifying which
|
/* The UNIX signal pipe contains a single byte specifying which
|
||||||
* signal was received.
|
* signal was received.
|
||||||
*/
|
*/
|
||||||
@ -529,7 +540,9 @@ g_main_context_unref (GMainContext *context)
|
|||||||
if (g_thread_supported())
|
if (g_thread_supported())
|
||||||
{
|
{
|
||||||
#ifndef G_OS_WIN32
|
#ifndef G_OS_WIN32
|
||||||
|
if (context->wake_up_pipe[0] != -1)
|
||||||
close (context->wake_up_pipe[0]);
|
close (context->wake_up_pipe[0]);
|
||||||
|
if (context->wake_up_pipe[1] != -1)
|
||||||
close (context->wake_up_pipe[1]);
|
close (context->wake_up_pipe[1]);
|
||||||
#else
|
#else
|
||||||
CloseHandle (context->wake_up_semaphore);
|
CloseHandle (context->wake_up_semaphore);
|
||||||
@ -556,8 +569,32 @@ g_main_context_init_pipe (GMainContext *context)
|
|||||||
if (context->wake_up_pipe[0] != -1)
|
if (context->wake_up_pipe[0] != -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef HAVE_EVENTFD
|
||||||
|
if (!event_fd_state.checked_eventfd
|
||||||
|
|| event_fd_state.have_eventfd)
|
||||||
|
{
|
||||||
|
int efd;
|
||||||
|
|
||||||
|
event_fd_state.checked_eventfd = TRUE;
|
||||||
|
efd = eventfd (0, EFD_CLOEXEC);
|
||||||
|
if (efd == -1 && errno == ENOSYS)
|
||||||
|
{
|
||||||
|
event_fd_state.have_eventfd = FALSE;
|
||||||
if (!g_unix_open_pipe (context->wake_up_pipe, FD_CLOEXEC, &error))
|
if (!g_unix_open_pipe (context->wake_up_pipe, FD_CLOEXEC, &error))
|
||||||
g_error ("Cannot create pipe main loop wake-up: %s", error->message);
|
g_error ("Cannot create pipe main loop wake-up: %s", error->message);
|
||||||
|
}
|
||||||
|
else if (efd >= 0)
|
||||||
|
{
|
||||||
|
event_fd_state.have_eventfd = TRUE;
|
||||||
|
context->wake_up_pipe[0] = efd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_error ("Cannot create eventfd for main loop wake-up: %s", g_strerror (errno));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!g_unix_open_pipe (context->wake_up_pipe, FD_CLOEXEC, &error))
|
||||||
|
g_error ("Cannot create pipe main loop wake-up: %s", error->message);
|
||||||
|
#endif
|
||||||
|
|
||||||
context->wake_up_rec.fd = context->wake_up_pipe[0];
|
context->wake_up_rec.fd = context->wake_up_pipe[0];
|
||||||
context->wake_up_rec.events = G_IO_IN;
|
context->wake_up_rec.events = G_IO_IN;
|
||||||
@ -580,7 +617,9 @@ g_main_context_init_pipe (GMainContext *context)
|
|||||||
void
|
void
|
||||||
_g_main_thread_init (void)
|
_g_main_thread_init (void)
|
||||||
{
|
{
|
||||||
GSList *curr = main_contexts_without_pipe;
|
GSList *curr;
|
||||||
|
|
||||||
|
curr = main_contexts_without_pipe;
|
||||||
while (curr)
|
while (curr)
|
||||||
{
|
{
|
||||||
g_main_context_init_pipe ((GMainContext *)curr->data);
|
g_main_context_init_pipe ((GMainContext *)curr->data);
|
||||||
@ -2942,8 +2981,18 @@ g_main_context_check (GMainContext *context,
|
|||||||
if (!context->poll_waiting)
|
if (!context->poll_waiting)
|
||||||
{
|
{
|
||||||
#ifndef G_OS_WIN32
|
#ifndef G_OS_WIN32
|
||||||
|
#ifdef HAVE_EVENTFD
|
||||||
|
if (event_fd_state.have_eventfd)
|
||||||
|
{
|
||||||
|
guint64 buf;
|
||||||
|
read (context->wake_up_pipe[0], &buf, sizeof(guint64));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
gchar a;
|
gchar a;
|
||||||
read (context->wake_up_pipe[0], &a, 1);
|
read (context->wake_up_pipe[0], &a, 1);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3794,6 +3843,14 @@ g_main_context_wakeup_unlocked (GMainContext *context)
|
|||||||
{
|
{
|
||||||
context->poll_waiting = FALSE;
|
context->poll_waiting = FALSE;
|
||||||
#ifndef G_OS_WIN32
|
#ifndef G_OS_WIN32
|
||||||
|
#ifdef HAVE_EVENTFD
|
||||||
|
if (event_fd_state.have_eventfd)
|
||||||
|
{
|
||||||
|
guint64 buf = 1;
|
||||||
|
write (context->wake_up_pipe[0], &buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
write (context->wake_up_pipe[1], "A", 1);
|
write (context->wake_up_pipe[1], "A", 1);
|
||||||
#else
|
#else
|
||||||
ReleaseSemaphore (context->wake_up_semaphore, 1, NULL);
|
ReleaseSemaphore (context->wake_up_semaphore, 1, NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user