main_poll_table_obsolete = 0;
}
-int
+void
main_loop(void)
{
DBG("MAIN: Entering main_loop");
DBG("MAIN: Timer %p expired at %Ld", tm, (long long) tm->expires);
tm->handler(tm);
}
+ int hook_min = HOOK_RETRY;
+ int hook_max = HOOK_SHUTDOWN;
CLIST_WALK_DELSAFE(ho, main_hook_list, tmp)
{
DBG("MAIN: Hook %p", ho);
- if (ho->handler(ho))
- wake = 0;
+ int ret = ho->handler(ho);
+ hook_min = MIN(hook_min, ret);
+ hook_max = MAX(hook_max, ret);
}
+ if (hook_min == HOOK_SHUTDOWN ||
+ hook_min == HOOK_DONE && hook_max == HOOK_DONE ||
+ main_shutdown)
+ {
+ DBG("MAIN: Shut down by %s", main_shutdown ? "main_shutdown" : "a hook");
+ return;
+ }
+ if (hook_max == HOOK_RETRY)
+ wake = 0;
if (main_poll_table_obsolete)
main_rebuild_poll_table();
if (!clist_empty(&main_process_list))
wake = 0;
}
}
- if (clist_empty(&main_file_list) &&
- clist_empty(&main_timer_list) &&
- clist_empty(&main_hook_list) &&
- clist_empty(&main_process_list))
- {
- DBG("MAIN: Nothing to do, exiting");
- return 0;
- }
- if (main_shutdown)
- {
- DBG("MAIN: Shutdown");
- return 1;
- }
/* FIXME: Here is a small race window where SIGCHLD can come unnoticed. */
if ((tm = clist_head(&main_timer_list)) && tm->expires < wake)
wake = tm->expires;
struct main_hook {
cnode n;
- int (*handler)(struct main_hook *ho); /* [*] Hook function; returns 1 if should be called again */
+ int (*handler)(struct main_hook *ho); /* [*] Hook function; returns HOOK_xxx */
void *data; /* [*] For use by the handler */
};
+enum main_hook_return {
+ HOOK_IDLE, /* Call again when the main loop becomes idle again */
+ HOOK_RETRY, /* Call again as soon as possible */
+ HOOK_DONE = -1, /* Shut down the main loop if all hooks return this value */
+ HOOK_SHUTDOWN = -2 /* Shut down the main loop immediately */
+};
+
void hook_add(struct main_hook *ho);
void hook_del(struct main_hook *ho);
/* The main loop */
void main_init(void);
-int main_loop(void);
+void main_loop(void);
void main_debug(void);
#endif