X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=ucw%2Fmainloop.c;h=b2b07c5082476bedbdc023e094f49f6feb02a28b;hb=6efdc514c193f18c9ef840096750c37e78a01bf6;hp=ca296bbd88541ea42e81ddfe20297c42b8ab17a2;hpb=e846601463c9b20b012cd4fdbd47b5b27cd2e16c;p=libucw.git diff --git a/ucw/mainloop.c b/ucw/mainloop.c index ca296bbd..b2b07c50 100644 --- a/ucw/mainloop.c +++ b/ucw/mainloop.c @@ -1,7 +1,7 @@ /* * UCW Library -- Main Loop * - * (c) 2004--2011 Martin Mares + * (c) 2004--2012 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -9,11 +9,13 @@ #undef LOCAL_DEBUG -#include "ucw/lib.h" -#include "ucw/heap.h" -#include "ucw/mainloop.h" -#include "ucw/threads.h" -#include "ucw/gary.h" +#include +#include +#include +#include +#include +#include +#include #include #include @@ -49,10 +51,7 @@ static void signal_del_ctx(struct main_context *m, struct main_signal *ms); static void main_get_time_ctx(struct main_context *m) { - struct timeval tv; - gettimeofday(&tv, NULL); - m->now_seconds = tv.tv_sec; - m->now = (timestamp_t)tv.tv_sec * 1000 + tv.tv_usec / 1000; + m->now = get_timestamp(); } static struct main_context * @@ -100,7 +99,7 @@ main_new(void) m->epoll_fd = epoll_create(64); if (m->epoll_fd < 0) die("epoll_create() failed: %m"); - m->epoll_events = xmalloc(EPOLL_BUF_SIZE * sizeof(struct epoll_event *)); + m->epoll_events = xmalloc(EPOLL_BUF_SIZE * sizeof(struct epoll_event)); clist_init(&m->file_recalc_list); #else m->poll_table_obsolete = 1; @@ -306,9 +305,9 @@ file_want_events(struct main_file *fi) { uns events = 0; if (fi->read_handler) - events |= POLLIN | POLLHUP | POLLERR; + events |= POLLIN; if (fi->write_handler) - events |= POLLOUT | POLLERR; + events |= POLLOUT; return events; } @@ -318,7 +317,7 @@ file_add(struct main_file *fi) struct main_context *m = main_current(); DBG("MAIN: Adding file %p (fd=%d)", fi, fi->fd); - ASSERT(!clist_is_linked(&fi->n)); + ASSERT(!file_is_active(fi)); clist_add_tail(&m->file_list, &fi->n); m->file_cnt++; #ifdef CONFIG_UCW_EPOLL @@ -355,7 +354,8 @@ file_del_ctx(struct main_context *m, struct main_file *fi) // XXX: Can be called on a non-current context DBG("MAIN: Deleting file %p (fd=%d)", fi, fi->fd); - ASSERT(clist_is_linked(&fi->n)); + if (!file_is_active(fi)) + return; clist_unlink(&fi->n); m->file_cnt--; #ifdef CONFIG_UCW_EPOLL @@ -378,7 +378,8 @@ hook_add(struct main_hook *ho) struct main_context *m = main_current(); DBG("MAIN: Adding hook %p", ho); - ASSERT(!clist_is_linked(&ho->n)); + if (hook_is_active(ho)) + clist_unlink(&ho->n); clist_add_tail(&m->hook_list, &ho->n); } @@ -386,8 +387,8 @@ void hook_del(struct main_hook *ho) { DBG("MAIN: Deleting hook %p", ho); - ASSERT(clist_is_linked(&ho->n)); - clist_unlink(&ho->n); + if (hook_is_active(ho)) + clist_unlink(&ho->n); } static void @@ -419,7 +420,7 @@ process_add(struct main_process *mp) struct main_context *m = main_current(); DBG("MAIN: Adding process %p (pid=%d)", mp, mp->pid); - ASSERT(!clist_is_linked(&mp->n)); + ASSERT(!process_is_active(mp)); ASSERT(mp->handler); clist_add_tail(&m->process_list, &mp->n); if (!m->sigchld_handler) @@ -436,8 +437,8 @@ void process_del(struct main_process *mp) { DBG("MAIN: Deleting process %p (pid=%d)", mp, mp->pid); - ASSERT(clist_is_linked(&mp->n)); - clist_unlink(&mp->n); + if (process_is_active(mp)) + clist_unlink(&mp->n); } int @@ -543,7 +544,7 @@ signal_add(struct main_signal *ms) DBG("MAIN: Adding signal %p (sig=%d)", ms, ms->signum); - ASSERT(!clist_is_linked(&ms->n)); + ASSERT(!signal_is_active(ms)); // Adding at the head of the list is better if we are in the middle of walking the list. clist_add_head(&m->signal_list, &ms->n); if (m->sig_pipe_recv < 0) @@ -568,7 +569,8 @@ signal_del_ctx(struct main_context *m, struct main_signal *ms) // XXX: Can be called on a non-current context DBG("MAIN: Deleting signal %p (sig=%d)", ms, ms->signum); - ASSERT(clist_is_linked(&ms->n)); + if (!signal_is_active(ms)) + return; clist_unlink(&ms->n); int another = 0; @@ -594,7 +596,7 @@ signal_del(struct main_signal *ms) signal_del_ctx(main_current(), ms); } -#ifdef CONFIG_DEBUG +#ifdef CONFIG_UCW_DEBUG void file_debug(struct main_file *fi) @@ -709,7 +711,7 @@ process_hooks(struct main_context *m) hook_min == HOOK_DONE && hook_max == HOOK_DONE || m->shutdown) { - DBG("MAIN: Shut down by %s", m->shutdown ? "main_shutdown" : "a hook"); + DBG("MAIN: Shut down by %s", m->shutdown ? "main_shut_down" : "a hook"); return HOOK_SHUTDOWN; } if (hook_max == HOOK_RETRY) @@ -772,6 +774,8 @@ main_loop(void) struct main_context *m = main_current(); main_get_time_ctx(m); + m->shutdown = 0; + for (;;) { timestamp_t wake = m->now + 1000000000; @@ -785,10 +789,15 @@ main_loop(void) break; default: ; } - if (count_timers(m)) - wake = MIN(wake, m->timer_table[1]->expires); - main_get_time_ctx(m); - int timeout = ((wake > m->now) ? wake - m->now : 0); + + int timeout = 0; + if (!m->single_step) + { + if (count_timers(m)) + wake = MIN(wake, m->timer_table[1]->expires); + main_get_time_ctx(m); + timeout = ((wake > m->now) ? wake - m->now : 0); + } #ifdef CONFIG_UCW_EPOLL recalc_files(m); @@ -809,7 +818,12 @@ main_loop(void) m->idle_time += m->now - old_now; if (n <= 0) - continue; + { + if (m->single_step) + return; + else + continue; + } // Relink all files with a pending event to file_active_list #ifdef CONFIG_UCW_EPOLL @@ -844,17 +858,17 @@ main_loop(void) struct main_file *fi; while (fi = clist_head(&m->file_active_list)) { - if (fi->events & (POLLIN | POLLHUP | POLLERR)) + if (fi->read_handler && (fi->events & (POLLIN | POLLHUP))) { - fi->events &= ~(POLLIN | POLLHUP | POLLERR); + fi->events &= ~(POLLIN | POLLHUP); do DBG("MAIN: Read event on fd %d", fi->fd); while (fi->read_handler && fi->read_handler(fi)); continue; } - if (fi->events & (POLLOUT | POLLERR)) + if (fi->write_handler && (fi->events & (POLLOUT | POLLHUP | POLLERR))) { - fi->events &= ~(POLLOUT | POLLERR); + fi->events &= ~(POLLOUT | POLLHUP | POLLERR); do DBG("MAIN: Write event on fd %d", fi->fd); while (fi->write_handler && fi->write_handler(fi)); @@ -865,3 +879,12 @@ main_loop(void) } } } + +void +main_step(void) +{ + struct main_context *m = main_current(); + m->single_step = 1; + main_loop(); + m->single_step = 0; +}