1 /*
2     GSK - a library to write servers
3     Copyright (C) 2001-2004 Dave Benson
4 
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2 of the License, or (at your option) any later version.
9 
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14 
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
18 
19     Contact:
20         daveb@ffem.org <Dave Benson>
21 */
22 
23 #include <sys/wait.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <errno.h>
28 
29 #include "gskmainloop.h"
30 #include "gskmacros.h"
31 #include "gskrbtreemacros.h"
32 #include "config.h"
33 #include "gskghelpers.h"
34 #include "gskerrno.h"
35 #include "gskerror.h"
36 #include "gskinit.h"
37 #include "gskdebug.h"
38 #include "cycle.h"
39 #include "debug.h"
40 
41 /* --- prototypes --- */
42 static GObjectClass *parent_class = NULL;
43 
44 /* lifetime of a source;
45       - created
46       - run (maybe recursively) (maybe repeatedly)
47       - removed from list of sources / io changed
48       - user destroy function run
49       - memory for source free'd
50  */
51 
52 /* --- a main-loop source --- */
53 typedef enum
54 {
55   GSK_SOURCE_TYPE_IDLE,
56   GSK_SOURCE_TYPE_TIMER,
57   GSK_SOURCE_TYPE_IO,
58   GSK_SOURCE_TYPE_SIGNAL,
59   GSK_SOURCE_TYPE_PROCESS
60 } GskSourceType;
61 
62 struct _GskSource
63 {
64   GskSourceType          type;
65   /* are we calling the users' callback? */
66   guint                  run_count : 16;
67 
68   /* is the user's destroy function called? */
69   guint                  is_destroyed : 1;
70 
71   /* was this remove'd while running? */
72   guint                  must_remove : 1;
73 
74   /* are we allowed to recursively invoke this source? */
75   guint                  is_reentrant : 1;
76 
77   /* only for timers */
78   guint                  timer_adjusted_while_running : 1;
79   guint                  timer_is_red : 1;
80   guint                  timer_in_tree : 1;
81 
82   GskMainLoop           *main_loop;
83 
84   gpointer               user_data;
85   GDestroyNotify         destroy;
86 
87   union
88   {
89     struct
90     {
91       int                    fd;
92       GIOCondition           events;
93       GskMainLoopIOFunc      func;
94     } io;
95     struct
96     {
97       GTimeVal               expire_time;
98       gint64                 milli_period;
99       GskMainLoopTimeoutFunc func;
100       GskSource             *left, *right, *parent;
101     } timer;
102     struct
103     {
104       int                    process_id;
105       GskMainLoopWaitPidFunc func;
106       GskSource             *prev;
107       GskSource             *next;
108     } process;
109     struct
110     {
111       int                    number;
112       GskMainLoopSignalFunc  func;
113       GskSource             *prev;
114       GskSource             *next;
115     } signal;
116     struct
117     {
118       GskMainLoopIdleFunc    func;
119       GskSource             *prev;
120       GskSource             *next;
121     } idle;
122   } data;
123 };
124 
125 struct _GskMainLoopContextList
126 {
127   GMainContext *context;
128   guint num_fds_alloced;
129   GPollFD *poll_fds;
130   GskSource **sources;		/* one for each poll_fd */
131   guint num_fds_received;
132   gint priority;
133   GskMainLoopContextList *next;
134 };
135 
136 /* --- helper macros --- */
137 #define MAIN_LOOP_CLASS(main_loop) 	GSK_MAIN_LOOP_GET_CLASS(main_loop)
138 #define DEBUG_POLL(args)		\
139 		_GSK_DEBUG_PRINTF (GSK_DEBUG_MAIN_LOOP,args)
140 
141 /* gskrbtree of timers */
142 #define TIMER_GET_IS_RED(source)    ((source)->timer_is_red)
143 #define TIMER_SET_IS_RED(source, v) (source)->timer_is_red=v
144 #define TIMEVALS_COMPARE(a,b)                           \
145               (a).tv_sec < (b).tv_sec ? -1              \
146             : (a).tv_sec > (b).tv_sec ? +1              \
147             : (a).tv_usec < (b).tv_usec ? -1            \
148             : (a).tv_usec > (b).tv_usec ? +1            \
149             : 0
150 #define TIMER_COMPARE(a,b, rv) \
151   rv = TIMEVALS_COMPARE(a->data.timer.expire_time, b->data.timer.expire_time); \
152   if (rv == 0) { if (a < b) rv = -1; else if (a > b) rv = 1; }
153 #define GET_MAIN_LOOP_TIMER_TREE(main_loop) \
154   (main_loop)->timers, GskSource *, TIMER_GET_IS_RED, TIMER_SET_IS_RED,  \
155   data.timer.parent, data.timer.left, data.timer.right, TIMER_COMPARE
156 
157 
158 static inline GIOCondition
get_io_events(GskMainLoop * main_loop,guint fd)159 get_io_events (GskMainLoop *main_loop,
160 	       guint        fd)
161 {
162   return (main_loop->read_sources->pdata[fd] ? (G_IO_IN|G_IO_HUP)  : 0)
163        | (main_loop->write_sources->pdata[fd] ? (G_IO_OUT|G_IO_HUP) : 0);
164 }
165 
166 static inline void
gsk_main_loop_change_signal(GskMainLoop * main_loop,guint signal,gboolean add)167 gsk_main_loop_change_signal (GskMainLoop  *main_loop,
168 			     guint         signal,
169 			     gboolean      add)
170 {
171   GskMainLoopChange change;
172   change.type = GSK_MAIN_LOOP_EVENT_SIGNAL;
173   change.data.signal.number = signal;
174   change.data.signal.add = add;
175   (*MAIN_LOOP_CLASS (main_loop)->change) (main_loop, &change);
176   DEBUG_POLL (("gsk_main_loop_change_signal: %s watch on signal %d",
177 	      (add ? "adding" : "removing"), signal));
178 }
179 
180 static inline void
gsk_main_loop_change_io(GskMainLoop * main_loop,GIOCondition old_events,guint fd)181 gsk_main_loop_change_io (GskMainLoop  *main_loop,
182 			 GIOCondition  old_events,
183 			 guint         fd)
184 {
185   GskMainLoopChange change;
186   change.type = GSK_MAIN_LOOP_EVENT_IO;
187   change.data.io.fd = fd;
188   change.data.io.old_events = old_events;
189   change.data.io.events = get_io_events (main_loop, fd);
190 
191   (*MAIN_LOOP_CLASS (main_loop)->change) (main_loop, &change);
192 
193   DEBUG_POLL (("gsk_main_loop_change_io: fd=%d: old events:%s%s; "
194 	       "new events=%s%s",
195 	       fd,
196 	       (old_events & G_IO_IN) ? " in" : "",
197 	       (old_events & G_IO_OUT) ? " out" : "",
198 	       (change.data.io.events & G_IO_IN) ? " in" : "",
199 	       (change.data.io.events & G_IO_OUT) ? " out" : ""));
200 }
201 
202 static inline void
gsk_main_loop_change_process(GskMainLoop * main_loop,guint pid,gboolean did_exit,gboolean add)203 gsk_main_loop_change_process (GskMainLoop  *main_loop,
204 			      guint         pid,
205                               gboolean      did_exit,
206 			      gboolean      add)
207 {
208   GskMainLoopChange change;
209   if (did_exit)
210     g_assert (!add);
211   change.type = GSK_MAIN_LOOP_EVENT_PROCESS;
212   change.data.process.pid = pid;
213   change.data.process.add = add;
214   change.data.process.did_exit = did_exit;
215   (*MAIN_LOOP_CLASS (main_loop)->change) (main_loop, &change);
216   DEBUG_POLL (("gsk_main_loop_change_process: %s watch on %d",
217 	       (add ? "adding" : "removing"), pid));
218 }
219 
220 static guint
gsk_main_loop_run_io_sources(GskMainLoop * main_loop,guint fd,GIOCondition condition)221 gsk_main_loop_run_io_sources (GskMainLoop     *main_loop,
222 			      guint            fd,
223 			      GIOCondition     condition)
224 {
225   GskSource *read_source = NULL;
226   GskSource *write_source = NULL;
227   g_return_val_if_fail (main_loop->read_sources->len > fd, 0);
228   if (condition & G_IO_IN)
229     read_source = main_loop->read_sources->pdata[fd];
230   if (condition & G_IO_OUT)
231     write_source = main_loop->write_sources->pdata[fd];
232   if (read_source == NULL && write_source == NULL)
233     {
234       g_message ("WARNING: got event %u for unknown file-descriptor %d",
235                  (guint) condition, fd);
236       return 0;
237     }
238   if (read_source == write_source)
239     {
240       read_source->run_count++;
241       if (!(*read_source->data.io.func) (fd, G_IO_IN | G_IO_OUT,
242 			                 read_source->user_data))
243 	read_source->must_remove = 1;
244       read_source->run_count--;
245       if (read_source->run_count == 0 && read_source->must_remove)
246 	gsk_source_remove (read_source);
247       return 1;
248     }
249   else
250     {
251       if (read_source != NULL)
252 	{
253 	  read_source->run_count++;
254 	  if (!(*read_source->data.io.func) (fd, G_IO_IN,
255 				             read_source->user_data))
256 	    read_source->must_remove = 1;
257 	  read_source->run_count--;
258 	  if (read_source->run_count == 0 && read_source->must_remove)
259 	    gsk_source_remove (read_source);
260 	}
261       if (write_source != NULL)
262 	{
263 	  write_source->run_count++;
264 	  if (!(*write_source->data.io.func) (fd, G_IO_OUT,
265 				              write_source->user_data))
266 	    write_source->must_remove = 1;
267 	  write_source->run_count--;
268 	  if (write_source->run_count == 0 && write_source->must_remove)
269 	    gsk_source_remove (write_source);
270 	}
271       return (read_source && write_source) ? 2 : 1;
272     }
273 }
274 
275 static guint
gsk_main_loop_run_signal_sources(GskMainLoop * main_loop,guint signal)276 gsk_main_loop_run_signal_sources (GskMainLoop     *main_loop,
277 			          guint            signal)
278 {
279   GskSource *at;
280   guint rv = 0;
281   if (main_loop->signal_source_lists->len <= signal)
282     return rv;
283   at = main_loop->signal_source_lists->pdata[signal];
284   if (at != NULL)
285     at->run_count++;
286   while (at != NULL)
287     {
288       GskSource *next;
289       rv++;
290       if (!(*at->data.signal.func) (signal, at->user_data))
291 	at->must_remove = 1;
292       next = at->data.signal.next;
293       if (next != NULL)
294 	next->run_count++;
295       at->run_count--;
296       if (at->run_count == 0 && at->must_remove)
297 	gsk_source_remove (at);
298       at = next;
299     }
300   return rv;
301 }
302 
303 static guint
gsk_main_loop_run_process_sources(GskMainLoop * main_loop,GskMainLoopWaitInfo * wait_info)304 gsk_main_loop_run_process_sources (GskMainLoop     *main_loop,
305 			           GskMainLoopWaitInfo *wait_info)
306 {
307   GskSource *at;
308   guint rv = 0;
309 
310   g_hash_table_remove (main_loop->alive_pids, GUINT_TO_POINTER (wait_info->pid));
311   at = g_hash_table_lookup (main_loop->process_source_lists,
312 			  GUINT_TO_POINTER (wait_info->pid));
313   if (at != NULL)
314     at->run_count++;
315   while (at != NULL)
316     {
317       GskSource *next;
318       rv++;
319       (*at->data.process.func) (wait_info, at->user_data);
320       at->must_remove = 1;
321       next = at->data.process.next;
322       if (next != NULL)
323 	next->run_count++;
324       at->run_count--;
325       if (at->run_count == 0 && at->must_remove)
326 	gsk_source_remove (at);
327       at = next;
328     }
329   return rv;
330 }
331 
332 #define INITIAL_MAX_EVENTS		2048
333 
334 static inline void
g_time_val_add_millis(GTimeVal * in_out,guint64 millis)335 g_time_val_add_millis (GTimeVal  *in_out,
336 		       guint64    millis)
337 {
338   /* the two cases in this if() statement are
339      equivalent, if millis is really a 32-bit number.
340      but on x86 which lacks good 64-bit divides,
341      the first branch is much faster.
342 
343      1<<32 milliseconds is about 50 days,
344      so MOST timeouts are in the first case. */
345 
346   /* TODO: we should really decide at compile
347      time if we have fast 64-bit int support,
348      and if so, only use the second branch,
349      to save code space.  Of course, i have
350      no idea how to detect it, but it could be based
351      on "cpu".
352 
353      TODO: another nice thing would be support for
354      microsecond precision timers. */
355 #ifndef HAVE_FAST_64BIT_INT_SUPPORT     /* TODO: define this on non-x86 */
356   if (G_LIKELY ((millis>>32) == 0))
357     {
358       guint ms = (guint) millis;
359       in_out->tv_sec += ms / 1000;
360       in_out->tv_usec += (guint)(ms % 1000) * 1000;
361     }
362   else
363 #endif
364     {
365       in_out->tv_sec += millis / 1000;
366       in_out->tv_usec += (guint)(millis % 1000) * 1000;
367     }
368 
369   /* check for overflow of the microseconds column. */
370   if (in_out->tv_usec > 1000 * 1000)
371     {
372       in_out->tv_usec -= 1000 * 1000;
373       in_out->tv_sec++;
374     }
375 }
376 
377 #ifdef HAVE_TICK_COUNTER
378 static guint64 last_tick;
379 static GTimeVal last_tick_time;
380 typedef enum
381 {
382   TICK_STATE_INIT,
383   TICK_STATE_HAS_LAST_TICK,
384   TICK_STATE_HAS_TICK_RATE,
385   TICK_STATE_READY,
386   TICK_STATE_FALLBACK
387 } TickState;
388 
389 #if defined(TICKS_PER_USEC)
390 static guint usecs_per_tick = USECS_PER_TICK;
391 static guint usecs_per_tick_shift = USECS_PER_TICK_SHIFT;
392 static TickState tick_state = TICK_STATE_HAS_TICK_RATE;
393 static guint64 max_tick_delta = ((1000000ULL * TICKS_PER_USEC_b20) >> 20);
394 #else
395 static guint usecs_per_tick;
396 static guint usecs_per_tick_shift;
397 static TickState tick_state = TICK_STATE_INIT;
398 static guint64 max_tick_delta;
399 #endif
400 
401 #if GTIMEVAL_EQUALS_SYS_TIMEVAL
402 #define _gsk_g_get_current_time(tv) gettimeofday((struct timeval*)(tv), NULL)
403 #else
404 #define _gsk_g_get_current_time(tv) g_get_current_time(tv)
405 #endif
406 
407 void
gsk_get_current_time(GTimeVal * tv)408 gsk_get_current_time (GTimeVal *tv)
409 {
410   switch (tick_state)
411     {
412     case TICK_STATE_INIT:
413       _gsk_g_get_current_time (&last_tick_time);
414       last_tick = getticks ();
415       *tv = last_tick_time;
416       tick_state = TICK_STATE_HAS_LAST_TICK;
417       break;
418     case TICK_STATE_HAS_LAST_TICK:
419       _gsk_g_get_current_time (tv);
420       if (tv->tv_sec > last_tick_time.tv_sec + 3)
421         {
422           /* compute tick rate */
423           gdouble dusec = ((double)tv->tv_usec - last_tick_time.tv_usec)
424                         + 1e6 * ((double)tv->tv_sec - last_tick_time.tv_sec);
425           guint64 this_ticks = getticks ();
426           gint64 dticks = this_ticks - last_tick;
427           gdouble ticks_per_usec_d = (gdouble)dticks / dusec;
428           if (ticks_per_usec_d <= 1.0)
429             {
430               g_message ("ticking too slow... not using cpu timer");
431               tick_state = TICK_STATE_FALLBACK;
432               break;
433             }
434           usecs_per_tick_shift = 30;
435           usecs_per_tick = (double)(1 << usecs_per_tick_shift) / ticks_per_usec_d;
436           max_tick_delta = (guint64)(1000000ULL * ticks_per_usec_d);
437           tick_state = TICK_STATE_READY;
438           if (usecs_per_tick == 0)
439             {
440               g_message ("ticking miscalc");
441               tick_state = TICK_STATE_FALLBACK;
442               break;
443             }
444           last_tick = this_ticks;
445           last_tick_time = *tv;
446         }
447       break;
448     case TICK_STATE_HAS_TICK_RATE:
449       _gsk_g_get_current_time (&last_tick_time);
450       last_tick = getticks ();
451       *tv = last_tick_time;
452       tick_state = TICK_STATE_READY;
453       break;
454     case TICK_STATE_READY:
455       {
456         guint64 this_ticks = getticks ();
457         guint64 delta = this_ticks - last_tick;
458         if (delta > max_tick_delta)
459           {
460             last_tick = this_ticks;
461             _gsk_g_get_current_time (&last_tick_time);
462             *tv = last_tick_time;
463             //g_message ("resync: %u.%06u [ticks=%llu]",(guint)last_tick_time.tv_sec,(guint)last_tick_time.tv_usec,last_tick);
464           }
465         else
466           {
467             guint usecs = (guint)(((guint64)delta * usecs_per_tick) >> usecs_per_tick_shift);
468             //g_message ("delta=%llu; cached time: usecs=%u", delta,usecs);
469             *tv = last_tick_time;
470             tv->tv_usec += usecs;
471             while (tv->tv_usec >= 1000000)
472               {
473                 tv->tv_usec -= 1000000;
474                 tv->tv_sec += 1;
475               }
476           }
477         break;
478       }
479     case TICK_STATE_FALLBACK:
480       _gsk_g_get_current_time (tv);
481       break;
482 
483     default:
484       g_assert_not_reached ();
485     }
486 }
487 #else
488 void
gsk_get_current_time(GTimeVal * tv)489 gsk_get_current_time (GTimeVal *tv)
490 {
491   _gsk_g_get_current_time (tv);
492 }
493 #endif
494 
495 
496 /**
497  * gsk_main_loop_update_current_time:
498  * @main_loop: main loop whose notion of time should be updated.
499  *
500  * Update the main loop's cached time value by querying the
501  * system clock.
502  */
503 void
gsk_main_loop_update_current_time(GskMainLoop * main_loop)504 gsk_main_loop_update_current_time (GskMainLoop *main_loop)
505 {
506   gsk_get_current_time (&main_loop->current_time);
507 }
508 
509 /**
510  * gsk_main_loop_do_waitpid:
511  * @pid: the process id to wait for.
512  * @wait_info: place to collect termination status of the process.
513  *
514  * Do a waitpid system call on the process and munge the
515  * data into @wait_info for the caller to use.
516  *
517  * returns: whether the waitpid succeeded.
518  */
519 gboolean
gsk_main_loop_do_waitpid(int pid,GskMainLoopWaitInfo * wait_info)520 gsk_main_loop_do_waitpid (int                  pid,
521                           GskMainLoopWaitInfo *wait_info)
522 {
523   int status;
524 
525 retry:
526   pid = waitpid (pid, &status, WNOHANG);
527   if (pid < 0)
528     {
529       if (gsk_errno_is_ignorable (errno))
530         goto retry;
531 
532       /*gsk_log_errno ("error running waitpid");*/
533       return FALSE;
534     }
535   if (pid == 0)
536     return FALSE;
537   wait_info->pid = pid;
538   wait_info->exited = WIFEXITED (status);
539   if (wait_info->exited)
540     {
541       wait_info->d.exit_status = WEXITSTATUS (status);
542       wait_info->dumped_core = FALSE;
543     }
544   else
545     {
546       wait_info->d.signal = WTERMSIG (status);
547 #ifdef WCOREDUMP
548       wait_info->dumped_core = WCOREDUMP (status);
549 #else
550       wait_info->dumped_core = FALSE;
551 #endif
552     }
553   return TRUE;
554 }
555 
556 
557 static gboolean
handle_poll_fd_set(int fd,GIOCondition condition,gpointer data)558 handle_poll_fd_set (int          fd,
559 		    GIOCondition condition,
560 		    gpointer     data)
561 {
562   GPollFD *poll_fd = data;
563   g_assert (poll_fd->fd == fd);
564   poll_fd->revents = condition;
565   return TRUE;
566 }
567 
568 /**
569  * gsk_main_loop_run:
570  * @main_loop: the main loop to run.
571  * @timeout: the maximum number of milliseconds to run, or -1 for no maximum.
572  * @t_waited_out: the number of milliseconds out used, if non-NULL.
573  *
574  * Run the main loop once, for a specified number of milliseconds.
575  *
576  * returns: the number of sources processed.
577  */
578 guint
gsk_main_loop_run(GskMainLoop * main_loop,gint timeout,guint * t_waited_out)579 gsk_main_loop_run          (GskMainLoop       *main_loop,
580 			    gint               timeout,
581 			    guint             *t_waited_out)
582 {
583   GskMainLoopEvent *events;
584   GskMainLoopClass *class = MAIN_LOOP_CLASS (main_loop);
585   guint num_events;
586   guint rv = 0;
587   GTimeVal old_time;
588   GTimeVal *current_time;
589   guint i;
590   GskSource *at;
591   GskMainLoopContextList *list;
592   GskMainLoopContextList **plist;
593 
594   g_return_val_if_fail (!main_loop->is_running, 0);
595   main_loop->is_running = 1;
596 
597   gsk_main_loop_update_current_time (main_loop);
598   current_time = &main_loop->current_time;
599   old_time = *current_time;
600   if (main_loop->first_idle != NULL)
601     timeout = 0;
602   GSK_RBTREE_FIRST (GET_MAIN_LOOP_TIMER_TREE (main_loop), at);
603   if (at != NULL)
604     {
605       /* This rounds upward to the nearest millisecond */
606       GTimeVal *exp_time = &at->data.timer.expire_time;
607       if (exp_time->tv_sec < current_time->tv_sec
608        || (exp_time->tv_sec == current_time->tv_sec
609            && exp_time->tv_usec <= current_time->tv_usec))
610         timeout = 0;
611       else
612         {
613           guint ts = exp_time->tv_sec - current_time->tv_sec;
614           gint tus = exp_time->tv_usec - current_time->tv_usec;
615           gint t;
616           if (tus < 0)
617             {
618               tus += 1000000;
619               ts--;
620             }
621           t = ts * 1000 + (tus + 999) / 1000;
622           if (timeout < 0 || t < timeout)
623             timeout = t;
624         }
625     }
626 
627   /* TODO: this doesn't work for reentrant main-loops. */
628   events = main_loop->event_array_cache;
629 
630   for (plist = &main_loop->first_context; *plist != NULL; )
631     {
632       GskMainLoopContextList *list = *plist;
633       GMainContext *context = list->context;
634       gint c_timeout;
635 
636       /* XXX: how can we tell if g_main_loop_quit was called? */
637 #if 0
638       if (context->has_quit)
639 	{
640 	  *plist = list->next;
641 	  if (*plist == NULL && main_loop->first_context == NULL)
642 	    main_loop->last_context = NULL;
643 
644 	  g_free (list->poll_fds);
645 	  g_free (list->sources);
646 	  g_free (list);
647 	  continue;
648 	}
649 #endif
650 
651       if (!g_main_context_prepare (context, &list->priority))
652 	{
653 	  /* i think that TRUE means we can ditch calling 'query';
654 	   * but we always call query anyways.
655 	   */
656 	}
657 
658       /* hmm, is this allowed? */
659 retry_query:
660       list->num_fds_received = g_main_context_query (context, list->priority,
661 						     &c_timeout,
662 						     list->poll_fds,
663 						     list->num_fds_alloced);
664       /* if we filled the entire array, double its size */
665       if (list->num_fds_received == list->num_fds_alloced)
666 	{
667 	  guint new_count = list->num_fds_alloced * 2;
668 	  list->poll_fds = g_renew (GPollFD, list->poll_fds, new_count);
669 	  list->sources = g_renew (GskSource *, list->sources, new_count);
670 	  list->num_fds_alloced = new_count;
671 	  goto retry_query;
672 	}
673 
674       if (timeout < 0 || (c_timeout >= 0 && c_timeout < timeout))
675 	timeout = c_timeout;
676 
677       /* add indication of interest in fd_events/n_events */
678       for (i = 0; i < list->num_fds_received; i++)
679 	{
680 	  GPollFD *poll_fd = &list->poll_fds[i];
681 	  poll_fd->revents = 0;
682 	  list->sources[i] = gsk_main_loop_add_io (main_loop,
683 						   poll_fd->fd,
684 						   poll_fd->events,
685 						   handle_poll_fd_set,
686 						   poll_fd,
687 						   NULL);
688 	}
689       plist = &((*plist)->next);
690     }
691   num_events = (*class->poll) (main_loop, main_loop->max_events, events, timeout);
692   gsk_main_loop_update_current_time (main_loop);
693   /* run i/o, signal and process handlers */
694   for (i = 0; i < num_events; i++)
695     {
696       switch (events[i].type)
697 	{
698         case GSK_MAIN_LOOP_EVENT_IO:
699 	  rv += gsk_main_loop_run_io_sources (main_loop,
700 					      events[i].data.io.fd,
701 					      events[i].data.io.events);
702 	  break;
703         case GSK_MAIN_LOOP_EVENT_SIGNAL:
704 	  rv += gsk_main_loop_run_signal_sources (main_loop,
705 					          events[i].data.signal);
706 	  break;
707         case GSK_MAIN_LOOP_EVENT_PROCESS:
708 	  rv += gsk_main_loop_run_process_sources (main_loop,
709 					           &events[i].data.process_wait_info);
710 	  break;
711 	}
712     }
713 
714   /* deal with the glib-style main contexts */
715   for (list = main_loop->first_context; list != NULL; list = list->next)
716     {
717       GMainContext *context = list->context;
718       for (i = 0; i < list->num_fds_received; i++)
719 	gsk_source_remove (list->sources[i]);
720       g_main_context_check (context, list->priority, list->poll_fds, list->num_fds_received);
721       g_main_context_dispatch (context);
722     }
723 
724   /* run idle functions */
725   at = main_loop->first_idle;
726   if (at != NULL)
727     at->run_count++;
728   while (at != NULL)
729     {
730       GskSource *next;
731       if (!(*at->data.idle.func) (at->user_data))
732 	at->must_remove = 1;
733       rv++;
734       next = at->data.idle.next;
735       if (next)
736 	next->run_count++;
737       at->run_count--;
738       if (at->run_count == 0 && at->must_remove)
739 	gsk_source_remove (at);
740       at = next;
741     }
742 
743   /* expire timers */
744   for (;;)
745     {
746       GSK_RBTREE_FIRST (GET_MAIN_LOOP_TIMER_TREE (main_loop), at);
747       if (at == NULL)
748         break;
749       if (at->data.timer.expire_time.tv_sec > current_time->tv_sec
750        || (at->data.timer.expire_time.tv_sec == current_time->tv_sec
751         && at->data.timer.expire_time.tv_usec >= current_time->tv_usec))
752 	break;
753 
754       at->run_count++;
755       g_assert (at->timer_in_tree);
756       GSK_RBTREE_REMOVE (GET_MAIN_LOOP_TIMER_TREE (main_loop), at);
757       at->timer_in_tree = 0;
758       if (!(*at->data.timer.func) (at->user_data))
759 	at->must_remove = 1;
760       rv++;
761       at->run_count--;
762       if (at->run_count == 0 && at->must_remove)
763 	gsk_source_remove (at);
764       else
765 	{
766           if (at->timer_adjusted_while_running)
767 	    at->timer_adjusted_while_running = 0;
768 	  else
769 	    g_time_val_add_millis (&at->data.timer.expire_time,
770 				   at->data.timer.milli_period);
771           g_assert (!at->timer_in_tree);
772           {
773             GskSource *unused;
774             GSK_RBTREE_INSERT (GET_MAIN_LOOP_TIMER_TREE (main_loop),
775                                at, unused);
776             at->timer_in_tree = 1;
777           }
778 	}
779     }
780 
781   g_return_val_if_fail (main_loop->is_running, rv);
782   main_loop->is_running = 0;
783 
784   if (t_waited_out != NULL)
785     {
786       *t_waited_out = (main_loop->current_time.tv_sec - old_time.tv_sec) * 1000
787 	            + (main_loop->current_time.tv_usec - old_time.tv_usec) / 1000;
788     }
789 
790   if (main_loop->max_events == num_events)
791     {
792       /* If we are pushing the number-of-events threshold,
793 	 then double the size of our buffer. */
794       main_loop->max_events *= 2;
795       main_loop->event_array_cache
796 	= g_renew (GskMainLoopEvent,
797 		   main_loop->event_array_cache, main_loop->max_events);
798     }
799   return rv;
800 }
801 
802 static GMemChunk *gsk_source_chunk = NULL;
803 G_LOCK_DEFINE_STATIC (gsk_source_chunk);
804 
805 static inline GskSource  *
gsk_source_new(GskSourceType type,GskMainLoop * main_loop,gpointer user_data,GDestroyNotify destroy)806 gsk_source_new   (GskSourceType     type,
807 		  GskMainLoop      *main_loop,
808 		  gpointer          user_data,
809 		  GDestroyNotify    destroy)
810 {
811   GskSource *rv;
812   G_LOCK (gsk_source_chunk);
813   if (gsk_source_chunk == NULL)
814     gsk_source_chunk = g_mem_chunk_create (GskSource, 16, G_ALLOC_AND_FREE);
815   rv = g_mem_chunk_alloc (gsk_source_chunk);
816   G_UNLOCK (gsk_source_chunk);
817   rv->type = type;
818   rv->user_data = user_data;
819   rv->destroy = destroy;
820   rv->main_loop = main_loop;
821   rv->run_count = 0;
822   rv->must_remove = 0;
823   rv->is_destroyed = 0;
824   rv->is_reentrant = 0;
825   return rv;
826 }
827 static inline void
gsk_source_free(GskSource * gsk_source)828 gsk_source_free (GskSource *gsk_source)
829 {
830   G_LOCK (gsk_source_chunk);
831   g_mem_chunk_free (gsk_source_chunk, gsk_source);
832   G_UNLOCK (gsk_source_chunk);
833 }
834 
835 /**
836  * gsk_main_loop_add_idle:
837  * @main_loop: the loop to add the idle function to.
838  * @source_func: the function to call.
839  * @user_data: parameter to be passed to @source_func
840  * @destroy: to be called when the source is destroyed.
841  *
842  * This adds an idle function to the main loop.
843  * An idle function is a function which gets called every
844  * time the main loop is run.  Furthermore, while there are
845  * idle functions, the main loop will never block.
846  *
847  * One popular use of idle functions is to defer
848  * an operation, usually because either something is not
849  * in a good state to call immediately,
850  * or because there may be many requests that should
851  * be handled at one time.
852  *
853  * returns: a #GskSource which can be removed (or ignored).
854  */
855 GskSource *
gsk_main_loop_add_idle(GskMainLoop * main_loop,GskMainLoopIdleFunc source_func,gpointer user_data,GDestroyNotify destroy)856 gsk_main_loop_add_idle     (GskMainLoop       *main_loop,
857 			    GskMainLoopIdleFunc source_func,
858 			    gpointer           user_data,
859 			    GDestroyNotify     destroy)
860 {
861   GskSource *source = gsk_source_new (GSK_SOURCE_TYPE_IDLE, main_loop, user_data, destroy);
862   source->data.idle.func = source_func;
863   source->data.idle.prev = main_loop->last_idle;
864   source->data.idle.next = NULL;
865   if (main_loop->last_idle == NULL)
866     main_loop->first_idle = source;
867   else
868     main_loop->last_idle->data.idle.next = source;
869   main_loop->last_idle = source;
870   return source;
871 }
872 
873 /**
874  * gsk_main_loop_add_signal:
875  * @main_loop: the loop to add the unix signal handler function to.
876  * @signal_number: the number of the signal handler, like SIGINT.
877  * @signal_func: the function to run synchronously when a unix signal is raised.
878  * @user_data: data to be passed to @signal_func.
879  * @destroy: to be called when the source is destroyed.
880  *
881  * Add a signal handler to the main loop.
882  *
883  * Please note that unlike a normal unix signal handler (as provided by
884  * signal(2) or sigaction(2)), this handler will be run synchronously,
885  * so you can call non-reentrant methods.
886  *
887  * Also, because unix signal delivery is unreliable, if the signal is raised a
888  * few times in rapid succession, you may miss some callbacks.
889  *
890  * It is ok to connect multiple times to a single signal simulataneously.
891  *
892  * returns: a #GskSource which can be removed (or ignored).
893  */
894 GskSource *
gsk_main_loop_add_signal(GskMainLoop * main_loop,int signal_number,GskMainLoopSignalFunc signal_func,gpointer user_data,GDestroyNotify destroy)895 gsk_main_loop_add_signal   (GskMainLoop       *main_loop,
896 			    int                signal_number,
897 			    GskMainLoopSignalFunc signal_func,
898 			    gpointer           user_data,
899 			    GDestroyNotify     destroy)
900 {
901   GskSource *source;
902   GskSource *first;
903   GskSource *last;
904   //g_return_val_if_fail (signal_number != SIGCHLD, NULL);
905   source = gsk_source_new (GSK_SOURCE_TYPE_SIGNAL, main_loop, user_data, destroy);
906   if (main_loop->signal_source_lists->len <= (guint) signal_number)
907     g_ptr_array_set_size (main_loop->signal_source_lists, signal_number + 1);
908   first = main_loop->signal_source_lists->pdata[signal_number];
909   last = first;
910 
911   /* XXX: really need to save last elements!!! */
912   if (last != NULL)
913     while (last->data.signal.next != NULL)
914       last = last->data.signal.next;
915 
916   source->data.signal.number = signal_number;
917   source->data.signal.func = signal_func;
918   source->data.signal.prev = last;
919   source->data.signal.next = NULL;
920   if (last == NULL)
921     {
922       gsk_main_loop_change_signal (main_loop, signal_number, TRUE);
923       main_loop->signal_source_lists->pdata[signal_number] = source;
924     }
925   else
926     last->data.signal.next = source;
927   main_loop->num_sources++;
928   return source;
929 }
930 
931 /**
932  * gsk_main_loop_add_waitpid:
933  * @main_loop: the loop to add the child-process termination handler function to.
934  * @process_id: the child's process-id to wait for.
935  * @waitpid_func: function to call when the process terminates in some way or another.
936  * @user_data: data to be passed to @waitpid_func
937  * @destroy: to be called when the source is destroyed.
938  *
939  * Add a handler to trap process termination.
940  *
941  * Only one handler is allowed per child process.
942  *
943  * The handler will be invoked synchronously.
944  *
945  * returns: #GskSource which can be removed (or ignored).
946  */
947 GskSource *
gsk_main_loop_add_waitpid(GskMainLoop * main_loop,int process_id,GskMainLoopWaitPidFunc waitpid_func,gpointer user_data,GDestroyNotify destroy)948 gsk_main_loop_add_waitpid  (GskMainLoop       *main_loop,
949 			    int                process_id,
950 			    GskMainLoopWaitPidFunc waitpid_func,
951 			    gpointer           user_data,
952 			    GDestroyNotify     destroy)
953 {
954   GskSource *source = gsk_source_new (GSK_SOURCE_TYPE_PROCESS, main_loop, user_data, destroy);
955   GskSource *first;
956   GskSource *last;
957   first = g_hash_table_lookup (main_loop->process_source_lists,
958                                GUINT_TO_POINTER (process_id));
959   /* XXX: really need to save last elements!!! */
960   last = first;
961   if (last != NULL)
962     while (last->data.process.next != NULL)
963       last = last->data.process.next;
964   source->data.process.process_id = process_id;
965   source->data.process.prev = last;
966   source->data.process.next = NULL;
967   source->data.process.func = waitpid_func;
968   if (last == NULL)
969     {
970       gsk_main_loop_change_process (main_loop, process_id, FALSE, TRUE);
971       g_hash_table_insert (main_loop->process_source_lists,
972 			   GUINT_TO_POINTER (process_id),
973 			   source);
974     }
975   else
976     last->data.process.next = source;
977   main_loop->num_sources++;
978   return source;
979 }
980 
981 /**
982  * gsk_main_loop_add_io:
983  * @main_loop: the loop to add the i/o watch to.
984  * @fd: the file-descriptor to watch for events.
985  * @events: initial I/O events to watch for.
986  * @io_func: a function to call when the currently requested
987  * events occur.
988  * @user_data: data to be passed to @io_func
989  * @destroy: to be called when the source is destroyed.
990  *
991  * Add a handler to input or output on a file-descriptor (a socket or a pipe, usually).
992  *
993  * Only one handler trap is allowed per file-descriptor.
994  *
995  * The handler will be re-invoked until the event subsides.
996  * For example, if you read only part of the data when a input event is raised,
997  * the @io_func will be invoked again at every iteration of the main-loop
998  * until there is no data available.
999  *
1000  * returns: a #GskSource which can be removed or altered.
1001  */
1002 GskSource *
gsk_main_loop_add_io(GskMainLoop * main_loop,int fd,guint events,GskMainLoopIOFunc io_func,gpointer user_data,GDestroyNotify destroy)1003 gsk_main_loop_add_io       (GskMainLoop       *main_loop,
1004 			    int                fd,
1005 			    guint              events,
1006 			    GskMainLoopIOFunc  io_func,
1007 			    gpointer           user_data,
1008 			    GDestroyNotify     destroy)
1009 {
1010   GskSource *source;
1011   GIOCondition old_events;
1012   g_return_val_if_fail (fd >= 0, NULL);
1013   if ((guint) fd >= main_loop->read_sources->len)
1014     {
1015       g_ptr_array_set_size (main_loop->read_sources, fd + 1);
1016       g_ptr_array_set_size (main_loop->write_sources, fd + 1);
1017     }
1018   old_events = get_io_events (main_loop, fd);
1019   g_return_val_if_fail ((old_events & events & (G_IO_IN|G_IO_OUT)) == 0, NULL);
1020   source = gsk_source_new (GSK_SOURCE_TYPE_IO, main_loop, user_data, destroy);
1021   source->data.io.fd = fd;
1022   source->data.io.events = events;
1023   source->data.io.func = io_func;
1024   if ((events & G_IO_IN) == G_IO_IN)
1025     {
1026       g_return_val_if_fail (main_loop->read_sources->pdata[fd] == NULL, NULL);
1027       main_loop->read_sources->pdata[fd] = source;
1028     }
1029   if ((events & G_IO_OUT) == G_IO_OUT)
1030     {
1031       g_return_val_if_fail (main_loop->write_sources->pdata[fd] == NULL, NULL);
1032       main_loop->write_sources->pdata[fd] = source;
1033     }
1034   gsk_main_loop_change_io (main_loop, old_events, fd);
1035   main_loop->num_sources++;
1036   return source;
1037 }
1038 
1039 /**
1040  * gsk_source_adjust_io:
1041  * @source: the I/O source which now wants to watch different events.
1042  * @events: the new events to watch for the I/O source.
1043  *
1044  * This changes the types of events being watched by the main-loop.
1045  *
1046  * Note:  each new file-descriptor needs a new GskSource.
1047  * You must reuse this GskSource for a new file-descriptor
1048  * even if it happens to have the same numeric value
1049  * as a file-descriptor you closed.
1050  * (The reason why:  GSK automatically coagulates
1051  * multiple adjust_io calls.  This is fine with all main-loops.
1052  * However, kqueue(2) on BSD, and possibly others, automatically
1053  * unregister all interest in an event if the file-descriptor closes.
1054  * Hence, if the file-descriptor is re-opened and re-used with the
1055  * same GskSource, GSK will not be able to determine
1056  * that anything has changed, and will not issue a new #GskMainLoopChange.
1057  * This will break main-loops that are sensitive to exact which file-descriptor
1058  * (not just the number) was registered.)
1059  */
1060 void
gsk_source_adjust_io(GskSource * source,guint events)1061 gsk_source_adjust_io    (GskSource         *source,
1062 			 guint              events)
1063 {
1064   guint fd;
1065   GIOCondition old_events;
1066   GskMainLoop *main_loop = source->main_loop;
1067 
1068   g_return_if_fail (source != NULL);
1069   g_return_if_fail (source->type == GSK_SOURCE_TYPE_IO);
1070   g_return_if_fail (main_loop->read_sources->len > (guint) source->data.io.fd);
1071 
1072   fd = source->data.io.fd;
1073 
1074   if ((events & (G_IO_IN|G_IO_OUT)) == (source->data.io.events & (G_IO_IN|G_IO_OUT)))
1075     return;
1076   old_events = get_io_events (main_loop, fd);
1077   if ((events & G_IO_IN) == G_IO_IN)
1078     {
1079       GskSource *old = main_loop->read_sources->pdata[fd];
1080       g_return_if_fail (old == source || old == NULL);
1081       main_loop->read_sources->pdata[fd] = source;
1082     }
1083   else if (main_loop->read_sources->pdata[fd] == source)
1084     main_loop->read_sources->pdata[fd] = NULL;
1085 
1086   if ((events & G_IO_OUT) == G_IO_OUT)
1087     {
1088       GskSource *old = main_loop->write_sources->pdata[fd];
1089       g_return_if_fail (old == source || old == NULL);
1090       main_loop->write_sources->pdata[fd] = source;
1091     }
1092   else if (main_loop->write_sources->pdata[fd] == source)
1093     main_loop->write_sources->pdata[fd] = NULL;
1094   source->data.io.events = events;
1095   gsk_main_loop_change_io (main_loop, old_events, fd);
1096 }
1097 
1098 /**
1099  * gsk_source_add_io_events:
1100  * @source: the input/output source whose events-of-interest set
1101  * should be expanded.
1102  * @events: new events which should cause @source to wake-up.
1103  *
1104  * Cause this source to be notified if any of the events in
1105  * the @events parameter are set, in addition to the events which
1106  * already caused this source to be woken up.
1107  */
1108 void
gsk_source_add_io_events(GskSource * source,guint events)1109 gsk_source_add_io_events (GskSource *source,
1110 			  guint      events)
1111 {
1112   g_return_if_fail (source != NULL);
1113   g_return_if_fail (source->type == GSK_SOURCE_TYPE_IO);
1114   gsk_source_adjust_io (source, source->data.io.events | events);
1115 }
1116 
1117 /**
1118  * gsk_source_remove_io_events:
1119  * @source: the input/output source whose events-of-interest set
1120  * should be reduced.
1121  * @events: new events which should stop causing @source to wake-up.
1122  *
1123  * Cause this source to stop being notified if any of the events in
1124  * the @events parameter are set.
1125  */
1126 void
gsk_source_remove_io_events(GskSource * source,guint events)1127 gsk_source_remove_io_events (GskSource *source,
1128 			     guint      events)
1129 {
1130   g_return_if_fail (source != NULL);
1131   g_return_if_fail (source->type == GSK_SOURCE_TYPE_IO);
1132   gsk_source_adjust_io (source, source->data.io.events & (~events));
1133 }
1134 
1135 /**
1136  * gsk_main_loop_add_timer:
1137  * @main_loop: the main-loop which should keep track and run the timeout.
1138  * @timer_func: function to call when the requested amount of time elapses.
1139  * @timer_data: data to pass to @timer_func.
1140  * @timer_destroy: optional function to call to destroy the @timer_data.
1141  * @millis_expire: number of milliseconds to wait before running @timer_func.
1142  * @milli_period: period between subsequent invocation of the timeout.
1143  * This may be -1 to indicate that the timeout is a one-shot.
1144  *
1145  * Add a timeout function to the main-loop.
1146  * This is a function that will be called after
1147  * a fixed amount of time passes, and then may be called
1148  * at a regular interval thereafter.
1149  *
1150  * returns: #GskSource which can be removed or altered.
1151  */
1152 #undef gsk_main_loop_add_timer
1153 GskSource *
gsk_main_loop_add_timer64(GskMainLoop * main_loop,GskMainLoopTimeoutFunc timer_func,gpointer timer_data,GDestroyNotify timer_destroy,gint64 millis_expire,gint64 milli_period)1154 gsk_main_loop_add_timer64  (GskMainLoop       *main_loop,
1155 			    GskMainLoopTimeoutFunc timer_func,
1156 			    gpointer           timer_data,
1157 			    GDestroyNotify     timer_destroy,
1158 			    gint64             millis_expire,
1159 			    gint64             milli_period)
1160 {
1161   GskSource *source = gsk_source_new (GSK_SOURCE_TYPE_TIMER, main_loop, timer_data, timer_destroy);
1162   GskSource *unused;
1163   source->data.timer.expire_time = main_loop->current_time;
1164   g_time_val_add_millis (&source->data.timer.expire_time, millis_expire);
1165   source->data.timer.milli_period = milli_period;
1166   source->data.timer.func = timer_func;
1167   source->timer_adjusted_while_running = FALSE;
1168   GSK_RBTREE_INSERT (GET_MAIN_LOOP_TIMER_TREE (main_loop), source, unused);
1169   source->timer_in_tree = 1;
1170   main_loop->num_sources++;
1171   return source;
1172 }
1173 GskSource *
gsk_main_loop_add_timer(GskMainLoop * main_loop,GskMainLoopTimeoutFunc timer_func,gpointer timer_data,GDestroyNotify timer_destroy,gint millis_expire,gint milli_period)1174 gsk_main_loop_add_timer    (GskMainLoop       *main_loop,
1175 			    GskMainLoopTimeoutFunc timer_func,
1176 			    gpointer           timer_data,
1177 			    GDestroyNotify     timer_destroy,
1178 			    gint               millis_expire,
1179 			    gint               milli_period)
1180 {
1181   return gsk_main_loop_add_timer64 (main_loop,
1182                                     timer_func, timer_data, timer_destroy,
1183                                     millis_expire, milli_period);
1184 }
1185 
1186 /**
1187  * gsk_main_loop_add_timer_absolute:
1188  * @main_loop: the main-loop which should keep track and run the timeout.
1189  * @timer_func: function to call when the requested amount of time elapses.
1190  * @timer_data: data to pass to @timer_func.
1191  * @timer_destroy: optional function to call to destroy the @timer_data.
1192  * @unixtime: number of seconds since Jan 1, 1970 GMT that will have passed when the
1193  * timer should expire.
1194  * @unixtime_micro: fractional part of @unixtime, in microseconds.
1195  *
1196  * Add a timeout function to the main-loop.
1197  * The @timer_func will be called as soon as we detect that the specified time has passed.
1198  *
1199  * The time to wait until is (@unixtime + @unixtime_micro * 10^{-6}) seconds after
1200  * New Years, Jan 1, 1970 GMT.
1201  *
1202  * returns: a #GskSource which can be removed or altered.
1203  */
1204 GskSource *
gsk_main_loop_add_timer_absolute(GskMainLoop * main_loop,GskMainLoopTimeoutFunc timer_func,gpointer timer_data,GDestroyNotify timer_destroy,int unixtime,int unixtime_micro)1205 gsk_main_loop_add_timer_absolute (GskMainLoop       *main_loop,
1206 				  GskMainLoopTimeoutFunc timer_func,
1207 				  gpointer           timer_data,
1208 				  GDestroyNotify     timer_destroy,
1209 				  int                unixtime,
1210 				  int                unixtime_micro)
1211 {
1212   GskSource *source = gsk_source_new (GSK_SOURCE_TYPE_TIMER, main_loop, timer_data, timer_destroy);
1213   GskSource *unused;
1214   source->data.timer.expire_time.tv_sec = unixtime;
1215   source->data.timer.expire_time.tv_usec = unixtime_micro;
1216   source->data.timer.milli_period = -1;
1217   source->data.timer.func = timer_func;
1218   source->timer_adjusted_while_running = 0;
1219   GSK_RBTREE_INSERT (GET_MAIN_LOOP_TIMER_TREE (main_loop), source, unused);
1220   source->timer_in_tree = 1;
1221   main_loop->num_sources++;
1222   return source;
1223 }
1224 
1225 /**
1226  * gsk_source_adjust_timer:
1227  * @timer_source: the timeout source returned by gsk_main_loop_add_timer() or gsk_main_loop_add_timer_absolute().
1228  * @millis_expire: the number of milliseconds from now that the timer should run.
1229  * @milli_period: the period between subsequent runs of the timer, or -1 to indicate that
1230  * the timer is a one-shot.
1231  *
1232  * Adjust the timeout and period for an already existing timer source.
1233  * (You may only call this on timer sources.)
1234  */
1235 #undef gsk_source_adjust_timer                              /* compatibility hack */
1236 #define gsk_source_adjust_timer gsk_source_adjust_timer64   /* compatibility hack */
1237 void
gsk_source_adjust_timer(GskSource * timer_source,gint64 millis_expire,gint64 milli_period)1238 gsk_source_adjust_timer   (GskSource         *timer_source,
1239 			   gint64             millis_expire,
1240 			   gint64             milli_period)
1241 {
1242   GskMainLoop *main_loop = timer_source->main_loop;
1243   g_return_if_fail (timer_source->type == GSK_SOURCE_TYPE_TIMER);
1244   if (timer_source->timer_in_tree)
1245     {
1246       GSK_RBTREE_REMOVE (GET_MAIN_LOOP_TIMER_TREE (main_loop), timer_source);
1247       timer_source->timer_in_tree = 0;
1248     }
1249   timer_source->data.timer.expire_time = main_loop->current_time;
1250   g_time_val_add_millis (&timer_source->data.timer.expire_time, millis_expire);
1251   timer_source->data.timer.milli_period = milli_period;
1252   if (timer_source->run_count == 0)
1253     {
1254       if (!timer_source->timer_in_tree)
1255         {
1256           GskSource *unused;
1257           GSK_RBTREE_INSERT (GET_MAIN_LOOP_TIMER_TREE (main_loop),
1258                              timer_source,
1259                              unused);
1260           timer_source->timer_in_tree = 1;
1261         }
1262     }
1263   else
1264     timer_source->timer_adjusted_while_running = 1;
1265 }
1266 #undef gsk_source_adjust_timer                  /* compatibility hack */
1267 void                                            /* compatibility hack */
gsk_source_adjust_timer(GskSource * timer_source,gint millis_expire,gint milli_period)1268 gsk_source_adjust_timer   (GskSource         *timer_source,
1269 			   gint               millis_expire,
1270 			   gint               milli_period)
1271 {
1272   gsk_source_adjust_timer64 (timer_source, millis_expire, milli_period);
1273 }
1274 
1275 static inline void
gsk_main_loop_block_io(GskMainLoop * main_loop,GskSource * source)1276 gsk_main_loop_block_io (GskMainLoop *main_loop,
1277 			GskSource   *source)
1278 {
1279   switch (source->type)
1280     {
1281       case GSK_SOURCE_TYPE_IDLE:
1282 	if (source->data.idle.prev != NULL)
1283 	  source->data.idle.prev->data.idle.next = source->data.idle.next;
1284 	else
1285 	  main_loop->first_idle = source->data.idle.next;
1286 	if (source->data.idle.next != NULL)
1287 	  source->data.idle.next->data.idle.prev = source->data.idle.prev;
1288 	else
1289 	  main_loop->last_idle = source->data.idle.prev;
1290 	break;
1291 
1292       case GSK_SOURCE_TYPE_TIMER:
1293         if (source->timer_in_tree)
1294           {
1295             GSK_RBTREE_REMOVE (GET_MAIN_LOOP_TIMER_TREE (main_loop), source);
1296             source->timer_in_tree = 0;
1297           }
1298 	break;
1299 
1300       case GSK_SOURCE_TYPE_IO:
1301 	{
1302 	  int fd = source->data.io.fd;
1303 	  GIOCondition old_events = get_io_events (main_loop, fd);
1304 	  if ((source->data.io.events & G_IO_IN) == G_IO_IN)
1305 	    {
1306 	      g_return_if_fail (main_loop->read_sources->pdata[fd] == source);
1307 	      main_loop->read_sources->pdata[fd] = NULL;
1308 	    }
1309 	  if ((source->data.io.events & G_IO_OUT) == G_IO_OUT)
1310 	    {
1311 	      g_return_if_fail (main_loop->write_sources->pdata[fd] == source);
1312 	      main_loop->write_sources->pdata[fd] = NULL;
1313 	    }
1314 	  gsk_main_loop_change_io (main_loop, old_events, fd);
1315 	}
1316 	break;
1317 
1318       case GSK_SOURCE_TYPE_SIGNAL:
1319 	{
1320 	  int signo = source->data.signal.number;
1321 	  if (source->data.signal.prev != NULL)
1322 	    source->data.signal.prev->data.signal.next = source->data.signal.next;
1323 	  else
1324 	    {
1325 	      main_loop->signal_source_lists->pdata[signo]
1326 		= source->data.signal.next;
1327 	      if (main_loop->signal_source_lists->pdata[signo] == NULL)
1328 		gsk_main_loop_change_signal (main_loop, signo, FALSE);
1329 	    }
1330 	  if (source->data.signal.next != NULL)
1331 	    source->data.signal.next->data.signal.prev = source->data.signal.prev;
1332 	  break;
1333 	}
1334 
1335       case GSK_SOURCE_TYPE_PROCESS:
1336 	{
1337 	  guint pid = source->data.process.process_id;
1338 	  if (source->data.process.prev != NULL)
1339 	    source->data.process.prev->data.process.next
1340 	      = source->data.process.next;
1341 	  else
1342 	    {
1343 	      if (source->data.process.next == NULL)
1344 		{
1345 		  g_hash_table_remove (main_loop->process_source_lists,
1346 				       GUINT_TO_POINTER (pid));
1347                   if (g_hash_table_lookup (main_loop->alive_pids,
1348                                            GUINT_TO_POINTER (pid)))
1349                     {
1350 		      gsk_main_loop_change_process (main_loop, pid, FALSE, FALSE);
1351                       g_hash_table_remove (main_loop->alive_pids,
1352                                            GUINT_TO_POINTER (pid));
1353                     }
1354                   else
1355 		    gsk_main_loop_change_process (main_loop, pid, TRUE, FALSE);
1356 		}
1357 	      else
1358 		g_hash_table_insert (main_loop->process_source_lists,
1359 				     GUINT_TO_POINTER (pid),
1360 				     source->data.process.next);
1361 	    }
1362 	  if (source->data.process.next != NULL)
1363 	    source->data.process.next->data.process.prev
1364 	      = source->data.process.prev;
1365 	  break;
1366 	}
1367     }
1368 }
1369 
1370 /**
1371  * gsk_source_peek_main_loop:
1372  * @source: the source to query.
1373  *
1374  * Get the main-loop where the source was created.
1375  *
1376  * returns: the main-loop associated with the source.
1377  */
gsk_source_peek_main_loop(GskSource * source)1378 GskMainLoop *gsk_source_peek_main_loop (GskSource *source)
1379 {
1380   return source->main_loop;
1381 }
1382 
1383 /**
1384  * gsk_source_remove:
1385  * @source: the source to remove and destroy.
1386  *
1387  * Destroy a main loop's source.
1388  *
1389  * If the source is currently running,
1390  * it's destroy method will not be called until the
1391  * source's callback returns.  (This way, important data won't be
1392  * deleted unexpectedly in the middle of the user's callback.)
1393  */
1394 void
gsk_source_remove(GskSource * source)1395 gsk_source_remove (GskSource         *source)
1396 {
1397   GskMainLoop *main_loop = source->main_loop;
1398   if (source->run_count > 0)
1399     {
1400       /* Remove fd interest immediately, even if reenterring.
1401 
1402          This is important because the
1403          caller may be planning to close the file descriptor. */
1404       if (source->type == GSK_SOURCE_TYPE_IO)
1405         {
1406           int fd = source->data.io.fd;
1407 	  GIOCondition old_events = get_io_events (main_loop, fd);
1408           if (old_events)
1409             {
1410               if (source->data.io.events & G_IO_IN)
1411                 main_loop->read_sources->pdata[fd] = NULL;
1412               if (source->data.io.events & G_IO_OUT)
1413                 main_loop->write_sources->pdata[fd] = NULL;
1414               source->data.io.events = 0;
1415               gsk_main_loop_change_io (main_loop, old_events, fd);
1416             }
1417         }
1418       source->must_remove = 1;
1419       return;
1420     }
1421 
1422   if (!source->is_destroyed)
1423     {
1424       source->is_destroyed = 1;
1425       if (source->destroy != NULL)
1426 	(*source->destroy) (source->user_data);
1427     }
1428 
1429   /* remove from lists and change i/o handling */
1430   gsk_main_loop_block_io (main_loop, source);
1431   main_loop->num_sources--;
1432 
1433   gsk_source_free (source);
1434 }
1435 
1436 /**
1437  * gsk_main_loop_quit:
1438  * @main_loop: the main-loop which is being asked to quit.
1439  *
1440  * Set the main-loop flag that indicates that it should really stop running.
1441  *
1442  * If you are executing a GskMainLoop using gsk_main_loop_run(),
1443  * then you should probably check gsk_main_loop_should_continue() at every iteration
1444  * to ensure that you should not have quit by now.
1445  */
1446 void
gsk_main_loop_quit(GskMainLoop * main_loop)1447 gsk_main_loop_quit (GskMainLoop       *main_loop)
1448 {
1449   main_loop->quit = 1;
1450 }
1451 
1452 /**
1453  * gsk_main_loop_should_continue:
1454  * @main_loop: the main-loop to query.
1455  *
1456  * Query whether the main-loop should keep running or not.
1457  *
1458  * returns: whether to keep running this main-loop.
1459  */
1460 gboolean
gsk_main_loop_should_continue(GskMainLoop * main_loop)1461 gsk_main_loop_should_continue (GskMainLoop       *main_loop)
1462 {
1463 #if 0
1464   if (main_loop->quit)
1465     return FALSE;
1466   return main_loop->num_sources > 0 || main_loop->first_context != NULL;
1467 #else
1468   return !main_loop->quit;
1469 #endif
1470 }
1471 
1472 /* XXX: this kind of trick should be done constantly (whenever a source
1473         of the appropriate type is removed) */
1474 static void
check_if_all_handlers_clear(GskMainLoop * main_loop)1475 check_if_all_handlers_clear (GskMainLoop *main_loop)
1476 {
1477   guint max_len;
1478   guint i;
1479 
1480   /* if all signals are untrapped, reset the array */
1481   max_len = 0;
1482   for (i = 0; i < main_loop->signal_source_lists->len; i++)
1483     if (main_loop->signal_source_lists->pdata[i] != NULL)
1484       max_len = i + 1;
1485   g_ptr_array_set_size (main_loop->signal_source_lists, max_len);
1486 
1487   /* if all fds are untrapped, reset the array */
1488   max_len = 0;
1489   for (i = 0; i < main_loop->read_sources->len; i++)
1490     if (main_loop->read_sources->pdata[i] != NULL
1491      || main_loop->write_sources->pdata[i] != NULL)
1492       max_len = i + 1;
1493   g_ptr_array_set_size (main_loop->read_sources, max_len);
1494   g_ptr_array_set_size (main_loop->write_sources, max_len);
1495 }
1496 
1497 void
gsk_main_loop_destroy_all_sources(GskMainLoop * main_loop)1498 gsk_main_loop_destroy_all_sources (GskMainLoop *main_loop)
1499 {
1500   /* temporary variables */
1501   GskSource *at;
1502   GSList *list, *at_list;
1503   guint i;
1504 
1505   /* Destroy idle functions */
1506   at = main_loop->first_idle;
1507   while (at != NULL)
1508     {
1509       GskSource *next = at->data.idle.next;
1510       if (next != NULL)
1511 	next->run_count++;
1512       gsk_source_remove (at);
1513       if (next != NULL)
1514 	next->run_count--;
1515 
1516       at = next;     /* possibly must_remove is set, but it's ok */
1517     }
1518 
1519   /* Destroy timers */
1520   while (main_loop->timers)
1521     gsk_source_remove (main_loop->timers);
1522 
1523   /* Destroy i/o handlers */
1524   for (i = 0; i < main_loop->read_sources->len; i++)
1525     {
1526       at = main_loop->read_sources->pdata[i];
1527       if (at != NULL)
1528 	gsk_source_remove (at);
1529       at = main_loop->write_sources->pdata[i];
1530       if (at != NULL)
1531 	gsk_source_remove (at);
1532     }
1533 
1534   /* Destroy signal handlers */
1535   for (i = 0; i < main_loop->signal_source_lists->len; i++)
1536     {
1537       at = main_loop->signal_source_lists->pdata[i];
1538       while (at != NULL)
1539 	{
1540 	  GskSource *next = at->data.signal.next;
1541 	  if (next != NULL)
1542 	    next->run_count++;
1543 	  gsk_source_remove (at);
1544 	  if (next != NULL)
1545 	    next->run_count--;
1546 
1547 	  at = next;     /* possibly must_remove is set, but it's ok */
1548 	}
1549     }
1550 
1551 
1552   /* Destroy waitpid handlers */
1553   list = gsk_g_hash_table_key_slist (main_loop->process_source_lists);
1554   for (at_list = list; at_list != NULL; at_list = at_list->next)
1555     {
1556       at = g_hash_table_lookup (main_loop->process_source_lists, at_list->data);
1557       while (at != NULL)
1558 	{
1559 	  GskSource *next = at->data.idle.next;
1560 	  if (next != NULL)
1561 	    next->run_count++;
1562 	  gsk_source_remove (at);
1563 	  if (next != NULL)
1564 	    next->run_count--;
1565 
1566 	  at = next;     /* possibly must_remove is set, but it's ok */
1567 	}
1568     }
1569   g_slist_free (list);
1570 
1571   check_if_all_handlers_clear (main_loop);
1572 }
1573 
1574 #define CHECK_INVARIANTS(main_loop)				              \
1575   G_STMT_START{							              \
1576     g_assert (main_loop->write_sources->len == main_loop->read_sources->len); \
1577   }G_STMT_END
1578 
1579 static void
gsk_main_loop_finalize(GObject * object)1580 gsk_main_loop_finalize (GObject *object)
1581 {
1582   GskMainLoop *main_loop = GSK_MAIN_LOOP (object);
1583   gsk_main_loop_destroy_all_sources (main_loop);
1584 
1585   g_assert (main_loop->first_idle == NULL);
1586   g_assert (main_loop->last_idle == NULL);
1587   g_assert (main_loop->timers == NULL);
1588   g_assert (g_hash_table_size (main_loop->process_source_lists) == 0);
1589   g_assert (main_loop->running_source == NULL);
1590   CHECK_INVARIANTS (main_loop);
1591 
1592   g_hash_table_destroy (main_loop->process_source_lists);
1593   g_ptr_array_free (main_loop->read_sources, TRUE);
1594   g_ptr_array_free (main_loop->write_sources, TRUE);
1595   g_ptr_array_free (main_loop->signal_source_lists, TRUE);
1596   g_free (main_loop->event_array_cache);
1597 
1598   g_hash_table_destroy (main_loop->alive_pids);
1599 
1600   (*parent_class->finalize) (object);
1601 }
1602 
1603 /* --- functions --- */
1604 static void
gsk_main_loop_init(GskMainLoop * main_loop)1605 gsk_main_loop_init (GskMainLoop *main_loop)
1606 {
1607   main_loop->timers = NULL;
1608   main_loop->read_sources = g_ptr_array_new ();
1609   main_loop->write_sources = g_ptr_array_new ();
1610   main_loop->signal_source_lists = g_ptr_array_new ();
1611   main_loop->process_source_lists = g_hash_table_new (NULL, NULL);
1612   main_loop->alive_pids = g_hash_table_new (NULL, NULL);
1613   main_loop->max_events = INITIAL_MAX_EVENTS;
1614   main_loop->event_array_cache = g_new (GskMainLoopEvent, main_loop->max_events);
1615   gsk_main_loop_update_current_time (main_loop);
1616 }
1617 
1618 static void
gsk_main_loop_class_init(GskMainLoopClass * class)1619 gsk_main_loop_class_init (GskMainLoopClass *class)
1620 {
1621   GObjectClass *object_class = G_OBJECT_CLASS (class);
1622   parent_class = g_type_class_peek_parent (class);
1623   object_class->finalize = gsk_main_loop_finalize;
1624 }
1625 
gsk_main_loop_get_type()1626 GType gsk_main_loop_get_type()
1627 {
1628   static GType main_loop_type = 0;
1629   if (!main_loop_type)
1630     {
1631       static const GTypeInfo main_loop_info =
1632       {
1633 	sizeof(GskMainLoopClass),
1634 	(GBaseInitFunc) NULL,
1635 	(GBaseFinalizeFunc) NULL,
1636 	(GClassInitFunc) gsk_main_loop_class_init,
1637 	NULL,		/* class_finalize */
1638 	NULL,		/* class_data */
1639 	sizeof (GskMainLoop),
1640 	0,		/* n_preallocs */
1641 	(GInstanceInitFunc) gsk_main_loop_init,
1642 	NULL		/* value_table */
1643       };
1644       GType parent = G_TYPE_OBJECT;
1645       main_loop_type = g_type_register_static (parent,
1646                                                   "GskMainLoop",
1647 						  &main_loop_info, 0);
1648     }
1649   return main_loop_type;
1650 }
1651 
1652 /* --- GskMainLoopWaitInfo type registration --- */
1653 static GskMainLoopWaitInfo *
gsk_main_loop_wait_info_copy(const GskMainLoopWaitInfo * wait_info)1654 gsk_main_loop_wait_info_copy (const GskMainLoopWaitInfo *wait_info)
1655 {
1656   return g_memdup (wait_info, sizeof (GskMainLoopWaitInfo));
1657 }
1658 
gsk_main_loop_wait_info_get_type(void)1659 GType gsk_main_loop_wait_info_get_type(void)
1660 {
1661   static GType rv = 0;
1662   if (rv == 0)
1663     rv = g_boxed_type_register_static ("GskMainLoopWaitInfo",
1664                                        (GBoxedCopyFunc) gsk_main_loop_wait_info_copy,
1665                                        (GBoxedFreeFunc) g_free);
1666   return rv;
1667 }
1668 
1669 
1670 /* --- Default Construction --- */
1671 #include "main-loops/gskmainloopkqueue.h"
1672 #include "main-loops/gskmainloopdevpoll.h"
1673 #include "main-loops/gskmainloopepoll.h"
1674 #include "main-loops/gskmainlooppoll.h"
1675 #include "main-loops/gskmainloopselect.h"
1676 
1677 static struct
1678 {
1679   GType (*get_type_func) () G_GNUC_CONST;
1680   const char *env_value;
1681   gboolean supports_threads;
1682 } main_loop_types[] = {
1683 #if HAVE_EPOLL_SUPPORT
1684   { gsk_main_loop_epoll_get_type,    "epoll",   TRUE  },
1685 #endif
1686 #if HAVE_SYS_DEV_POLL
1687   { gsk_main_loop_dev_poll_get_type, "devpoll", TRUE  },
1688 #endif
1689 #if HAVE_KQUEUE
1690   { gsk_main_loop_kqueue_get_type,   "kqueue",  FALSE },
1691 #endif
1692 #if HAVE_POLL
1693   { gsk_main_loop_poll_get_type,     "poll",    TRUE  },
1694 #endif
1695 #if HAVE_SELECT
1696   { gsk_main_loop_select_get_type,   "select",  TRUE  },
1697 #endif
1698   { NULL, NULL, FALSE }
1699 };
1700 
1701 
1702 GskMainLoop *
gsk_main_loop_new(GskMainLoopCreateFlags create_flags)1703 gsk_main_loop_new (GskMainLoopCreateFlags create_flags)
1704 {
1705   gboolean threads = (create_flags & GSK_MAIN_LOOP_NEEDS_THREADS) != 0;
1706   GType type = 0;
1707   /* Try the GSK_MAIN_LOOP_TYPE environment variable */
1708   guint i = 0;
1709   const char *env_type = g_getenv ("GSK_MAIN_LOOP_TYPE");
1710 
1711   if (env_type != NULL)
1712     {
1713       GSK_SKIP_WHITESPACE (env_type);
1714       if (*env_type == '\0')
1715 	env_type = NULL;
1716     }
1717 
1718   if (env_type != NULL)
1719     {
1720       GskMainLoop *main_loop;
1721       while (main_loop_types[i].get_type_func != NULL)
1722 	{
1723 	  if (strcmp (env_type, main_loop_types[i].env_value) == 0
1724 	   && (!threads || main_loop_types[i].supports_threads))
1725 	    {
1726 	      type = (*main_loop_types[i].get_type_func) ();
1727 	      break;
1728 	    }
1729 	  i++;
1730 	}
1731       if (type == 0)
1732 	{
1733 	  if (strcmp (env_type, "kqueue") == 0)
1734 	    g_warning ("kqueue doesn't support threads; "
1735 		       "falling back to poll");
1736 	  else
1737 	    g_warning ("GSK_MAIN_LOOP_TYPE set to %s: unsupported", env_type);
1738 	}
1739       else
1740 	{
1741 	  GskMainLoopClass *class;
1742 	  main_loop = g_object_new (type, NULL);
1743 	  class = GSK_MAIN_LOOP_GET_CLASS (main_loop);
1744 	  if (class->setup == NULL || (*class->setup) (main_loop))
1745 	    return main_loop;
1746 	  else
1747 	    {
1748 	      g_warning ("could not setup main-loop of type %s", env_type);
1749 	    }
1750 	  g_object_unref (main_loop);
1751 	}
1752     }
1753 
1754   /* Try autoconf-detected defaults, in our preferred order. */
1755   for (i = 0; main_loop_types[i].get_type_func != NULL; i++)
1756     {
1757       if (!threads || main_loop_types[i].supports_threads)
1758 	{
1759 	  GskMainLoop *main_loop;
1760 	  GskMainLoopClass *class;
1761 	  type = (*main_loop_types[i].get_type_func) ();
1762 	  main_loop = g_object_new (type, NULL);
1763 	  class = GSK_MAIN_LOOP_GET_CLASS (main_loop);
1764 	  main_loop->is_setup = 1;
1765 	  if (class->setup != NULL && !((*class->setup) (main_loop)))
1766 	    {
1767 	      g_object_unref (main_loop);
1768 	      continue;
1769 	    }
1770 	  return main_loop;
1771 	}
1772       i++;
1773     }
1774 
1775   g_warning ("No type of GskMainLoop can be constructed");
1776   return NULL;
1777 }
1778 
1779 /* --- GMainLoop support --- */
1780 /**
1781  * gsk_main_loop_add_context:
1782  * @main_loop: main-loop which will take responsibility for @context.
1783  * @context: a GMainContext that should be handled by gsk_main_loop_run().
1784  *
1785  * Indicate that a particular #GskMainLoop will take care of
1786  * invoking the necessary methods of @context.
1787  */
1788 void
gsk_main_loop_add_context(GskMainLoop * main_loop,GMainContext * context)1789 gsk_main_loop_add_context (GskMainLoop  *main_loop,
1790 			   GMainContext *context)
1791 {
1792   GskMainLoopContextList *node = g_new (GskMainLoopContextList, 1);
1793   node->context = context;
1794   node->num_fds_alloced = 16;
1795   node->poll_fds = g_new (GPollFD, node->num_fds_alloced);
1796   node->sources = g_new (GskSource *, node->num_fds_alloced);
1797   node->num_fds_received = 0;
1798   node->priority = G_PRIORITY_DEFAULT;
1799 
1800   node->next = NULL;
1801   if (main_loop->last_context != NULL)
1802     main_loop->last_context->next = node;
1803   else
1804     main_loop->first_context = node;
1805   main_loop->last_context = node;
1806 }
1807 
1808 /* --- per-thread default main-loop --- */
1809 
1810 /* globals for non-threaded main-loops */
1811 static GskMainLoop *non_thread_main_loop = NULL;
1812 
1813 /* globals for per-thread main-loops */
1814 static GPrivate *private_main_loop_key;
1815 
1816 /**
1817  * gsk_main_loop_default:
1818  *
1819  * Get the main-loop which is associated with the current thread.
1820  *
1821  * returns: a pointer to the main-loop.  This function does not
1822  * increase the ref-count on the main-loop, so you do not need
1823  * to call g_object_unref() on the return value.
1824  */
1825 GskMainLoop *
gsk_main_loop_default()1826 gsk_main_loop_default ()
1827 {
1828   if (gsk_init_get_support_threads ())
1829     {
1830       GskMainLoop *main_loop = g_private_get (private_main_loop_key);
1831       if (main_loop != NULL)
1832 	return main_loop;
1833       main_loop = gsk_main_loop_new (GSK_MAIN_LOOP_NEEDS_THREADS);
1834       g_assert (main_loop != NULL);
1835       g_private_set (private_main_loop_key, main_loop);
1836       return main_loop;
1837     }
1838   else
1839     {
1840       if (non_thread_main_loop != NULL)
1841 	return non_thread_main_loop;
1842       non_thread_main_loop = gsk_main_loop_new (0);
1843       g_assert (non_thread_main_loop != NULL);
1844       return non_thread_main_loop;
1845     }
1846 }
1847 
1848 /* --- fork wrapper --- */
1849 void
_gsk_main_loop_fork_notify()1850 _gsk_main_loop_fork_notify ()
1851 {
1852   if (!gsk_init_get_support_threads ())
1853     {
1854       /* NOTE: we don't free the memory for the main-loop,
1855 	 but it should not amount to much.
1856 
1857 	 However, critical resources that may not be shared,
1858 	 like file-descriptors should probably be registered
1859 	 with the gsk_fork_* functions. */
1860 
1861       non_thread_main_loop = NULL;
1862     }
1863 }
1864 
1865 /* --- initialization --- */
1866 void
_gsk_main_loop_init(void)1867 _gsk_main_loop_init (void)
1868 {
1869   if (gsk_init_get_support_threads ())
1870     private_main_loop_key = g_private_new (g_object_unref);
1871 }
1872