diff --git a/lib_fiber/c/Makefile b/lib_fiber/c/Makefile index b8c5f5f63..ad22fed94 100644 --- a/lib_fiber/c/Makefile +++ b/lib_fiber/c/Makefile @@ -21,9 +21,9 @@ CFLAGS = -c -g -W \ -Wcast-qual \ -DUSE_FAST_RING \ -DUSE_JMP_DEF \ +#-DUSE_FAST_TIME \ #-DUSE_VALGRIND \ #-DUSE_BOOST_JMP \ -#-DUSE_FAST_TIME \ #-Waggregate-return \ #-DDEBUG_MEM \ #-I/usr/local/include diff --git a/lib_fiber/c/src/event.c b/lib_fiber/c/src/event.c index 716be58f9..e70d4ce2d 100644 --- a/lib_fiber/c/src/event.c +++ b/lib_fiber/c/src/event.c @@ -67,6 +67,7 @@ EVENT *event_create(int size) ev->maxfd = -1; ev->waiter = 0; + SET_TIME(ev->stamp); // init the event's stamp when create each event #ifdef HAS_POLL ring_init(&ev->poll_list); #endif @@ -97,6 +98,17 @@ void event_free(EVENT *ev) ev->free(ev); } +long long event_set_stamp(EVENT *ev) +{ + SET_TIME(ev->stamp); // decrease the SET_TIME's calling count. + return ev->stamp; +} + +long long event_get_stamp(EVENT *ev) +{ + return ev->stamp; +} + #ifdef SYS_WIN int event_checkfd(EVENT *ev, FILE_EVENT *fe) { @@ -374,6 +386,7 @@ static void event_prepare(EVENT *ev) #ifdef HAS_POLL static void event_process_poll(EVENT *ev) { +#if 0 while (1) { POLL_EVENT *pe; RING *head = ring_pop_head(&ev->poll_list); @@ -387,12 +400,32 @@ static void event_process_poll(EVENT *ev) } ring_init(&ev->poll_list); +#else + POLL_EVENT *pe; + RING *next, *curr; + long long now; + + now = event_get_stamp(ev); + + for (next = ring_succ(&ev->poll_list); next != &ev->poll_list;) { + pe = ring_to_appl(next, POLL_EVENT, me); + if (pe->nready != 0 || (pe->expire >= 0 && now >= pe->expire)) { + curr = next; + next = ring_succ(next); + ring_detach(curr); + pe->proc(ev, pe); + } else { + next = ring_succ(next); + } + } +#endif } #endif #ifdef HAS_EPOLL static void event_process_epoll(EVENT *ev) { +#if 0 while (1) { EPOLL_EVENT *ee; RING *head = ring_pop_head(&ev->epoll_list); @@ -402,6 +435,25 @@ static void event_process_epoll(EVENT *ev) ee = TO_APPL(head, EPOLL_EVENT, me); ee->proc(ev, ee); } +#else + EPOLL_EVENT *ee; + RING *next, *curr; + long long now; + + now = event_get_stamp(ev); + + for (next = ring_succ(&ev->epoll_list); next != &ev->epoll_list;) { + ee = ring_to_appl(next, EPOLL_EVENT, me); + if (ee->nready != 0 || (ee->expire >= 0 && now >= ee->expire)) { + curr = next; + next = ring_succ(next); + ring_detach(curr); + ee->proc(ev, ee); + } else { + next = ring_succ(next); + } + } +#endif } #endif @@ -427,8 +479,12 @@ int event_process(EVENT *ev, int timeout) } event_prepare(ev); + + // call the system event waiting API for any event arriving. ret = ev->event_wait(ev, timeout); + (void) event_set_stamp(ev); // reset the stamp after event waiting. + #ifdef HAS_POLL event_process_poll(ev); #endif diff --git a/lib_fiber/c/src/event.h b/lib_fiber/c/src/event.h index 457df92e8..7b35697b7 100644 --- a/lib_fiber/c/src/event.h +++ b/lib_fiber/c/src/event.h @@ -159,6 +159,7 @@ struct POLL_EVENT { RING me; ACL_FIBER *fiber; poll_proc *proc; + long long expire; int nready; int nfds; POLLFD *fds; @@ -181,6 +182,7 @@ struct EPOLL_EVENT { ACL_FIBER *fiber; epoll_proc *proc; size_t nfds; + long long expire; EPOLL_CTX **fds; int epfd; @@ -197,6 +199,7 @@ struct EVENT { ssize_t setsize; socket_t maxfd; + long long stamp; // the stamp of the current fiber scheduler unsigned flag; #define EVENT_F_IOCP (1 << 0) #define EVENT_IS_IOCP(x) ((x)->flag & EVENT_F_IOCP) @@ -237,6 +240,8 @@ acl_handle_t event_handle(EVENT *ev); ssize_t event_size(EVENT *ev); void event_free(EVENT *ev); void event_close(EVENT *ev, FILE_EVENT *fe); +long long event_set_stamp(EVENT *ev); +long long event_get_stamp(EVENT *ev); // check if the fd in fe is a valid socket, return 1 if yes, -1 if the fd // is not a valid fd, 0 if the fd is valid but not a socket. diff --git a/lib_fiber/c/src/fiber_io.c b/lib_fiber/c/src/fiber_io.c index 16bd9a072..3b571c435 100644 --- a/lib_fiber/c/src/fiber_io.c +++ b/lib_fiber/c/src/fiber_io.c @@ -14,7 +14,7 @@ typedef struct { int nsleeping; int io_stop; #ifdef SYS_WIN - HTABLE *events; + HTABLE *events; #else FILE_EVENT **events; #endif @@ -162,6 +162,12 @@ EVENT *fiber_io_event(void) return __thread_fiber->event; } +static long long fiber_io_stamp(void) +{ + EVENT *ev = fiber_io_event(); + return event_get_stamp(ev); +} + static void fiber_io_loop(ACL_FIBER *self fiber_unused, void *ctx) { EVENT *ev = (EVENT *) ctx; @@ -177,7 +183,7 @@ static void fiber_io_loop(ACL_FIBER *self fiber_unused, void *ctx) if (timer == NULL) { left = -1; } else { - SET_TIME(now); + now = event_get_stamp(__thread_fiber->event); last = now; if (now >= timer->when) { left = 0; @@ -205,8 +211,7 @@ static void fiber_io_loop(ACL_FIBER *self fiber_unused, void *ctx) break; } - SET_TIME(now); - + now = event_get_stamp(__thread_fiber->event); if (now - last < left) { continue; } @@ -220,7 +225,6 @@ static void fiber_io_loop(ACL_FIBER *self fiber_unused, void *ctx) acl_fiber_ready(timer); timer = FIRST_FIBER(&__thread_fiber->ev_timer); - } while (timer != NULL && now >= timer->when); } @@ -263,7 +267,7 @@ unsigned int acl_fiber_delay(unsigned int milliseconds) ev = fiber_io_event(); - SET_TIME(now); + now = event_get_stamp(ev); when = now + milliseconds; /* The timers in the ring were stored from small to large in ascending @@ -309,7 +313,7 @@ unsigned int acl_fiber_delay(unsigned int milliseconds) ev->timeout = -1; } - SET_TIME(now); + now = event_get_stamp(ev); if (now < when) { return 0; } @@ -321,7 +325,7 @@ static void fiber_timer_callback(ACL_FIBER *fiber, void *ctx) { long long now, left; - SET_TIME(now); + now = fiber_io_stamp(); for (;;) { left = fiber->when > now ? fiber->when - now : 0; @@ -331,7 +335,7 @@ static void fiber_timer_callback(ACL_FIBER *fiber, void *ctx) acl_fiber_delay((unsigned int) left); - SET_TIME(now); + now = fiber_io_stamp(); if (fiber->when <= now) { break; } @@ -349,7 +353,7 @@ ACL_FIBER *acl_fiber_create_timer(unsigned int milliseconds, size_t size, fiber_io_check(); - SET_TIME(when); + when = fiber_io_stamp(); when += milliseconds; fiber = acl_fiber_create(fiber_timer_callback, ctx, size); @@ -364,7 +368,7 @@ void acl_fiber_reset_timer(ACL_FIBER *fiber, unsigned int milliseconds) fiber_io_check(); - SET_TIME(when); + when = fiber_io_stamp(); when += milliseconds; fiber->when = when; fiber->status = FIBER_STATUS_READY; diff --git a/lib_fiber/c/src/hook/epoll.c b/lib_fiber/c/src/hook/epoll.c index 879cc31bc..44683c765 100644 --- a/lib_fiber/c/src/hook/epoll.c +++ b/lib_fiber/c/src/hook/epoll.c @@ -376,8 +376,13 @@ static void event_epoll_set(EVENT *ev, EPOLL_EVENT *ee, int timeout) ee->events[i].events = 0; } - if (timeout >= 0 && (ev->timeout < 0 || timeout < ev->timeout)) { - ev->timeout = timeout; + if (timeout >= 0) { + ee->expire = event_get_stamp(ev) + timeout; + if (ev->timeout < 0 || timeout < ev->timeout) { + ev->timeout = timeout; + } + } else { + ee->expire = -1; } } @@ -385,7 +390,7 @@ int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) { EVENT *ev; EPOLL_EVENT *ee; - long long begin, now; + long long now; int old_timeout; if (sys_epoll_wait == NULL) { @@ -418,7 +423,6 @@ int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) old_timeout = ev->timeout; event_epoll_set(ev, ee, timeout); - SET_TIME(begin); ev->waiter++; while (1) { @@ -441,8 +445,9 @@ int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) if (ee->nready != 0 || timeout == 0) { break; } - SET_TIME(now); - if (timeout > 0 && (now - begin >= timeout)) { + + now = event_get_stamp(ev); + if (ee->expire > 0 && now >= ee->expire) { break; } } diff --git a/lib_fiber/c/src/hook/poll.c b/lib_fiber/c/src/hook/poll.c index 9d4a48a6f..c2aaf13a6 100644 --- a/lib_fiber/c/src/hook/poll.c +++ b/lib_fiber/c/src/hook/poll.c @@ -115,8 +115,13 @@ static void poll_event_set(EVENT *ev, POLL_EVENT *pe, int timeout) pfd->pfd->revents = 0; } - if (timeout >= 0 && (ev->timeout < 0 || timeout < ev->timeout)) { - ev->timeout = timeout; + if (timeout >= 0) { + pe->expire = event_get_stamp(ev) + timeout; + if (ev->timeout < 0 || timeout < ev->timeout) { + ev->timeout = timeout; + } + } else { + pe->expire = -1; } } @@ -128,8 +133,9 @@ static void poll_event_clean(EVENT *ev, POLL_EVENT *pe) POLLFD *pfd = &pe->fds[i]; /* maybe has been cleaned in read_callback/write_callback */ - if (pfd->fe == NULL) + if (pfd->fe == NULL) { continue; + } CLR_POLLING(pfd->fe); @@ -190,7 +196,7 @@ static void pollfd_free(POLLFD *pfds) int WINAPI acl_fiber_poll(struct pollfd *fds, nfds_t nfds, int timeout) { - long long begin, now; + long long now; POLL_EVENT pe; EVENT *ev; int old_timeout; @@ -212,7 +218,6 @@ int WINAPI acl_fiber_poll(struct pollfd *fds, nfds_t nfds, int timeout) old_timeout = ev->timeout; poll_event_set(ev, &pe, timeout); - SET_TIME(begin); ev->waiter++; while (1) { @@ -242,8 +247,9 @@ int WINAPI acl_fiber_poll(struct pollfd *fds, nfds_t nfds, int timeout) if (pe.nready != 0 || timeout == 0) { break; } - SET_TIME(now); - if (timeout > 0 && (now - begin >= timeout)) { + + now = event_get_stamp(ev); + if (pe.expire > 0 && now >= pe.expire) { acl_fiber_set_error(FIBER_ETIMEDOUT); break; }