Backporting high cpu usage fix in wayland from upstream 72/2772/1 accepted/2.0alpha-wayland/20130227.211101 submit/2.0alpha-wayland/20130220.232504
authorJimmy Huang <jimmy.huang@intel.com>
Wed, 20 Feb 2013 23:20:39 +0000 (15:20 -0800)
committerJimmy Huang <jimmy.huang@intel.com>
Wed, 20 Feb 2013 23:20:39 +0000 (15:20 -0800)
Backporting 81360

ecore-wayland: (version 2)Fix monitoring ECORE_FD_WRITE

defaultly on wayland display fd lead to 100% cpu usage

In ecore_wl_init(), adding wayland display fd with ECORE_FD_WRITE
flag make CPU usage 100%. The proper way to monitor the ECORE_FD_WRITE
is when the wl_display_flush() return value < 0 and errno == EAGAIN.
And if wl_display_flush() return, we remove ECORE_FD_WRITE flag from
the display fd.

Change from v1:
Add idle enterer destroy code into _ecore_wl_shutdown() to avoid
using freed wl_display.

Signed-off-by: Jimmy Huang <jimmy.huang@intel.com>
src/lib/ecore_wayland/Ecore_Wayland.h
src/lib/ecore_wayland/ecore_wl.c

index eae1681..8f22be3 100644 (file)
@@ -92,6 +92,7 @@ struct _Ecore_Wl_Display
    unsigned int mask;
    unsigned int serial;
    Ecore_Fd_Handler *fd_hdl;
+   Ecore_Idle_Enterer *idle_enterer;
 
    struct wl_list inputs;
    struct wl_list outputs;
index 4c3a26d..02d1db2 100644 (file)
@@ -33,6 +33,7 @@ void *alloca (size_t);
 
 /* local function prototypes */
 static Eina_Bool _ecore_wl_shutdown(Eina_Bool close);
+static Eina_Bool _ecore_wl_cb_idle_enterer(void *data);
 static Eina_Bool _ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl);
 static void _ecore_wl_cb_handle_global(void *data, struct wl_registry *registry, unsigned int id, const char *interface, unsigned int version __UNUSED__);
 static Eina_Bool _ecore_wl_xkb_init(Ecore_Wl_Display *ewd);
@@ -162,12 +163,15 @@ ecore_wl_init(const char *name)
 
    _ecore_wl_disp->fd = wl_display_get_fd(_ecore_wl_disp->wl.display);
 
-   _ecore_wl_disp->fd_hdl = 
-     ecore_main_fd_handler_add(_ecore_wl_disp->fd, 
-                               ECORE_FD_READ | ECORE_FD_WRITE,
-                               _ecore_wl_cb_handle_data, _ecore_wl_disp, 
+   _ecore_wl_disp->fd_hdl =
+     ecore_main_fd_handler_add(_ecore_wl_disp->fd,
+                               ECORE_FD_READ,
+                               _ecore_wl_cb_handle_data, _ecore_wl_disp,
                                NULL, NULL);
 
+   _ecore_wl_disp->idle_enterer =
+     ecore_idle_enterer_add(_ecore_wl_cb_idle_enterer, _ecore_wl_disp);
+
    wl_list_init(&_ecore_wl_disp->inputs);
    wl_list_init(&_ecore_wl_disp->outputs);
 
@@ -382,6 +386,8 @@ _ecore_wl_shutdown(Eina_Bool close)
 
    if (_ecore_wl_disp->fd_hdl) 
      ecore_main_fd_handler_del(_ecore_wl_disp->fd_hdl);
+   if (_ecore_wl_disp->idle_enterer)
+      ecore_idle_enterer_del(_ecore_wl_disp->idle_enterer);
 
    if (close) 
      {
@@ -422,10 +428,33 @@ _ecore_wl_shutdown(Eina_Bool close)
    return _ecore_wl_init_count;
 }
 
-static Eina_Bool 
+static Eina_Bool
+_ecore_wl_cb_idle_enterer(void *data)
+{
+   Ecore_Wl_Display *ewd;
+   int ret;
+
+   if (!(ewd = data)) return ECORE_CALLBACK_RENEW;
+
+   ret = wl_display_flush(ewd->wl.display);
+   if ((ret < 0) && (errno == EAGAIN))
+     {
+        ecore_main_fd_handler_active_set(ewd->fd_hdl, 
+                                         (ECORE_FD_READ | ECORE_FD_WRITE));
+     }
+   else if (ret < 0)
+     {
+      /* FIXME: need do error processing? */
+     }
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
 _ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl)
 {
    Ecore_Wl_Display *ewd;
+   int ret;
 
    /* LOGFN(__FILE__, __LINE__, __FUNCTION__); */
 
@@ -438,7 +467,15 @@ _ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl)
    if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_READ))
      wl_display_dispatch(ewd->wl.display);
    else if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_WRITE))
-     wl_display_flush(ewd->wl.display);
+     {
+        ret = wl_display_flush(ewd->wl.display);
+        if (ret == 0)
+          ecore_main_fd_handler_active_set(hdl, ECORE_FD_READ);
+        else if ((ret == -1) && (errno != EAGAIN))
+          {
+            /* FIXME: need do error processing? */
+          }
+     }
 
    return ECORE_CALLBACK_RENEW;
 }