#include #include #include #include #include "ucore/clock.h" #include "iomux_impl.h" //dispatchers for the IOMux implementations */ struct IOMux *iomux_create(enum IOMUX_TYPE type) { return iomux_create_ex(type, &uc_timeofday_clock); } struct IOMux *iomux_create_ex(enum IOMUX_TYPE type, struct UCoreClock *uclock) { struct IOMux *mux = calloc(1, sizeof *mux); int rc = -1; switch (type) { case IOMUX_TYPE_DEFAULT: case IOMUX_TYPE_EPOLL: rc = iomux_epoll_init(mux); break; case IOMUX_TYPE_SELECT: rc = iomux_select_init(mux); break; } if (rc != 0) { //try fallback to select rc = iomux_select_init(mux); } if (rc == 0) { mux->uclock = uclock; uc_timers_init_ex(&mux->timers, mux->uclock); } else { free(mux); mux = NULL; } return mux; } void iomux_delete(struct IOMux *mux) { mux->delete_impl(mux); memset(mux, 0xfa, sizeof *mux); free(mux); } //convert the difference between future and now static inline void future_to_interval(const struct timeval *future, const struct timeval *now, struct timeval *result) { if (timercmp(future, now, >)) { timersub(future, now, result); } else { result->tv_sec = 0; result->tv_usec = 0; } } int iomux_run(struct IOMux *mux) { for (;;) { int rc; struct timeval first_timer; struct timeval timeout; struct timeval *timeoutp;; int has_timers = 0; if (uc_timers_first(&mux->timers, &first_timer) == 0) { struct timeval now; mux->uclock->now(mux->uclock, &now); future_to_interval(&first_timer, &now, &timeout); timeoutp = &timeout; /* TRACEF("now %d %d future %d %d interval %d %d\n", mux->now.tv_sec, mux->now.tv_usec, first_timer.tv_sec, first_timer.tv_usec, timeout.tv_sec, timeout.tv_usec); */ assert(timeout.tv_sec >= 0); assert(timeout.tv_usec >= 0); has_timers = 1; } else { timeoutp = NULL; //no timeout } rc = mux->run_impl(mux, timeoutp); if (rc < 0) return rc; if (rc == 0 && !has_timers) //no more events, ever return 0; } return 0; } int iomux_timers_run(struct IOMux *mux) { int event_cnt; event_cnt = uc_timers_run(&mux->timers); assert(event_cnt >= 0); return event_cnt; } int iomux_register_fd(struct IOMux *mux, struct IOMuxFD *fd) { assert(mux != NULL); assert(fd != NULL); assert(fd->callback != NULL); assert(fd->fd >= 0); return mux->register_fd_impl(mux, fd); } int iomux_unregister_fd(struct IOMux *mux, struct IOMuxFD *fd) { assert(mux != NULL); assert(fd != NULL); assert(fd->fd >= 0); return mux->unregister_fd_impl(mux, fd); } int iomux_update_events(struct IOMux *mux, struct IOMuxFD *fd) { assert(mux != NULL); assert(fd != NULL); assert(fd->callback != NULL); assert(fd->fd >= 0); return mux->update_events_impl(mux, fd); } struct UCoreClock *iomux_get_clock(struct IOMux *mux) { return mux->uclock; } struct UCTimers *iomux_get_timers(struct IOMux *mux) { return &mux->timers; }