summaryrefslogtreecommitdiff
path: root/legacy/ecore/src/lib/ecore/ecore_main.c
diff options
context:
space:
mode:
authorMike McCormack <mj.mccormack@samsung.com>2011-07-06 10:54:11 +0000
committerMike McCormack <mikem@ring3k.org>2011-07-06 10:54:11 +0000
commit0ddf5b9cabbdb0d43316217c7b1615067eb28515 (patch)
treeef53a8eb2a12aba9753c7f7a5ec174a733971943 /legacy/ecore/src/lib/ecore/ecore_main.c
parentf1b0e8d0754ccf93cefb27d07b1b7dcb4267138e (diff)
ecore: Use timerfd with g_main_loop
glib only allows millisecond resolution in g_main_loop. To avoid this limitation, use timerfd to wake up the main loop. Signed-off-by: Mike McCormack <mj.mccormack@samsung.com> SVN revision: 61079
Diffstat (limited to '')
-rw-r--r--legacy/ecore/src/lib/ecore/ecore_main.c99
1 files changed, 95 insertions, 4 deletions
diff --git a/legacy/ecore/src/lib/ecore/ecore_main.c b/legacy/ecore/src/lib/ecore/ecore_main.c
index ff67821b6f..4bf77b4894 100644
--- a/legacy/ecore/src/lib/ecore/ecore_main.c
+++ b/legacy/ecore/src/lib/ecore/ecore_main.c
@@ -63,10 +63,16 @@
63# include <sys/epoll.h> 63# include <sys/epoll.h>
64#endif 64#endif
65 65
66#ifdef HAVE_SYS_TIMERFD_H
67#include <sys/timerfd.h>
68#endif
69
66#ifdef USE_G_MAIN_LOOP 70#ifdef USE_G_MAIN_LOOP
67# include <glib.h> 71# include <glib.h>
68#endif 72#endif
69 73
74#define NS_PER_SEC (1000.0 * 1000.0 * 1000.0)
75
70struct _Ecore_Fd_Handler 76struct _Ecore_Fd_Handler
71{ 77{
72 EINA_INLIST; 78 EINA_INLIST;
@@ -157,6 +163,9 @@ static double t1 = 0.0;
157static double t2 = 0.0; 163static double t2 = 0.0;
158#endif 164#endif
159 165
166#ifdef HAVE_TIMERFD_CREATE
167static int timer_fd = -1;
168#endif
160#ifdef HAVE_EPOLL 169#ifdef HAVE_EPOLL
161static int epoll_fd = -1; 170static int epoll_fd = -1;
162static pid_t epoll_pid; 171static pid_t epoll_pid;
@@ -166,6 +175,9 @@ static pid_t epoll_pid;
166#ifdef HAVE_EPOLL 175#ifdef HAVE_EPOLL
167static GPollFD ecore_epoll_fd; 176static GPollFD ecore_epoll_fd;
168#endif 177#endif
178#ifdef HAVE_TIMERFD_CREATE
179static GPollFD ecore_timer_fd;
180#endif
169static GSource *ecore_glib_source; 181static GSource *ecore_glib_source;
170static guint ecore_glib_source_id; 182static guint ecore_glib_source_id;
171static GMainLoop* ecore_main_loop; 183static GMainLoop* ecore_main_loop;
@@ -462,8 +474,37 @@ _ecore_main_gsource_prepare(GSource *source __UNUSED__, gint *next_time)
462 { 474 {
463 if (_ecore_timers_exists()) 475 if (_ecore_timers_exists())
464 { 476 {
477 int r = -1;
465 double t = _ecore_timer_next_get(); 478 double t = _ecore_timer_next_get();
466 *next_time = ceil(t * 1000.0); 479#ifdef HAVE_TIMERFD_CREATE
480 if (timer_fd >= 0)
481 {
482 struct itimerspec ts;
483
484 ts.it_interval.tv_sec = 0;
485 ts.it_interval.tv_nsec = 0;
486 ts.it_value.tv_sec = t;
487 ts.it_value.tv_nsec = fmod(t*NS_PER_SEC, NS_PER_SEC);
488
489 /* timerfd cannot sleep for 0 time */
490 if (ts.it_value.tv_sec && ts.it_value.tv_nsec)
491 {
492 r = timerfd_settime(timer_fd, 0, &ts, NULL);
493 if (r < 0)
494 {
495 ERR("timer set returned %d (errno=%d)", r, errno);
496 close(timer_fd);
497 timer_fd = -1;
498 }
499 else
500 INF("sleeping for %ld s %06ldus",
501 ts.it_value.tv_sec,
502 ts.it_value.tv_nsec/1000);
503 }
504 }
505#endif
506 if (r == -1)
507 *next_time = ceil(t * 1000.0);
467 } 508 }
468 else 509 else
469 *next_time = -1; 510 *next_time = -1;
@@ -492,11 +533,27 @@ _ecore_main_gsource_check(GSource *source __UNUSED__)
492 /* check if old timers expired */ 533 /* check if old timers expired */
493 if (ecore_idling && !_ecore_idler_exist()) 534 if (ecore_idling && !_ecore_idler_exist())
494 { 535 {
495 if (_ecore_timers_exists()) 536#ifdef HAVE_TIMERFD_CREATE
537 if (timer_fd >= 0)
496 { 538 {
497 double next_time = _ecore_timer_next_get(); 539 uint64_t count = 0;
498 ret = _ecore_timers_exists() && (0.0 >= next_time); 540 int r = read(timer_fd, &count, sizeof count);
541 if (r == -1 && errno == EAGAIN)
542 INF("timer not ready");
543 else if (r == sizeof count)
544 {
545 INF("woke %d times", (int)count);
546 ret = TRUE;
547 }
548 else
549 {
550 /* unexpected things happened... fail back to old way */
551 ERR("timer read returned %d (errno=%d)", r, errno);
552 close(timer_fd);
553 timer_fd = -1;
554 }
499 } 555 }
556#endif
500 } 557 }
501 else 558 else
502 ret = TRUE; 559 ret = TRUE;
@@ -505,11 +562,20 @@ _ecore_main_gsource_check(GSource *source __UNUSED__)
505 ecore_fds_ready = (_ecore_main_fdh_poll_mark_active() > 0); 562 ecore_fds_ready = (_ecore_main_fdh_poll_mark_active() > 0);
506 _ecore_main_fd_handlers_cleanup(); 563 _ecore_main_fd_handlers_cleanup();
507 564
565 /* check timers after updating loop time */
508 _ecore_time_loop_time = ecore_time_get(); 566 _ecore_time_loop_time = ecore_time_get();
567 if (!ret && _ecore_timers_exists())
568 {
569 double next_time = _ecore_timer_next_get();
570 ret = _ecore_timers_exists() && (0.0 >= next_time);
571 }
509 _ecore_timer_enable_new(); 572 _ecore_timer_enable_new();
510 573
511 in_main_loop--; 574 in_main_loop--;
512 575
576 if (!(ret || ecore_fds_ready))
577 INF("nothing was ready");
578
513 return ret || ecore_fds_ready; 579 return ret || ecore_fds_ready;
514} 580}
515 581
@@ -609,18 +675,35 @@ _ecore_main_loop_init(void)
609 675
610#endif 676#endif
611 677
678 /* setup for the g_main_loop only integration */
612#ifdef USE_G_MAIN_LOOP 679#ifdef USE_G_MAIN_LOOP
613 ecore_glib_source = g_source_new(&ecore_gsource_funcs, sizeof (GSource)); 680 ecore_glib_source = g_source_new(&ecore_gsource_funcs, sizeof (GSource));
614 if (!ecore_glib_source) 681 if (!ecore_glib_source)
615 CRIT("Failed to create glib source for epoll!"); 682 CRIT("Failed to create glib source for epoll!");
616 else 683 else
617 { 684 {
685 /* epoll multiplexes fds into the g_main_loop */
618#ifdef HAVE_EPOLL 686#ifdef HAVE_EPOLL
619 ecore_epoll_fd.fd = epoll_fd; 687 ecore_epoll_fd.fd = epoll_fd;
620 ecore_epoll_fd.events = G_IO_IN; 688 ecore_epoll_fd.events = G_IO_IN;
621 ecore_epoll_fd.revents = 0; 689 ecore_epoll_fd.revents = 0;
622 g_source_add_poll(ecore_glib_source, &ecore_epoll_fd); 690 g_source_add_poll(ecore_glib_source, &ecore_epoll_fd);
623#endif 691#endif
692
693 /* timerfd gives us better than millisecond accuracy in g_main_loop */
694#ifdef HAVE_TIMERFD_CREATE
695 timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
696 if (timer_fd < 0)
697 ERR("failed to create timer fd!");
698 else
699 {
700 ecore_timer_fd.fd = timer_fd;
701 ecore_timer_fd.events = G_IO_IN;
702 ecore_timer_fd.revents = 0;
703 g_source_add_poll(ecore_glib_source, &ecore_timer_fd);
704 }
705#endif
706
624 ecore_glib_source_id = g_source_attach(ecore_glib_source, NULL); 707 ecore_glib_source_id = g_source_attach(ecore_glib_source, NULL);
625 if (ecore_glib_source_id <= 0) 708 if (ecore_glib_source_id <= 0)
626 CRIT("Failed to attach glib source to default context"); 709 CRIT("Failed to attach glib source to default context");
@@ -648,6 +731,14 @@ _ecore_main_loop_shutdown(void)
648 731
649 epoll_pid = 0; 732 epoll_pid = 0;
650#endif 733#endif
734
735#ifdef HAVE_TIMERFD_CREATE
736 if (timer_fd >= 0)
737 {
738 close(timer_fd);
739 timer_fd = -1;
740 }
741#endif
651} 742}
652 743
653/** 744/**