603d86bb61
TRACEF() macro from utils.h
173 lines
3.8 KiB
C
173 lines
3.8 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include "ucore/clock.h"
|
|
#include "ucore/backtrace.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->ops.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;
|
|
}
|
|
}
|
|
|
|
static int iomux_run_timers(struct IOMux *mux, struct timeval *timeout)
|
|
{
|
|
struct timeval first_timer;
|
|
|
|
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);
|
|
/*TRACEF("now %d %d future %d %d interval %d %d\n", now.tv_sec, 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);
|
|
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int iomux_run(struct IOMux *mux)
|
|
{
|
|
for (;;) {
|
|
int rc;
|
|
struct timeval timeout;
|
|
struct timeval *timeoutp;
|
|
|
|
if (iomux_run_timers(mux, &timeout)) {
|
|
timeoutp = &timeout;
|
|
} else {
|
|
timeoutp = NULL;
|
|
}
|
|
|
|
rc = mux->ops.run_impl(mux, timeoutp);
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
if (rc == 0 && timeoutp == NULL) //no more fd or timer events, ever
|
|
return 0;
|
|
}
|
|
|
|
UC_NOT_REACED();
|
|
return -44;
|
|
}
|
|
|
|
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->ops.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->ops.unregister_fd_impl(mux, fd);
|
|
}
|
|
|
|
int iomux_update_events(struct IOMux *mux, struct IOMuxFD *fd, unsigned int what)
|
|
{
|
|
int rc = 0;
|
|
assert(mux != NULL);
|
|
assert(fd != NULL);
|
|
assert(fd->callback != NULL);
|
|
assert(fd->fd >= 0);
|
|
|
|
if (fd->what != what) {
|
|
rc = mux->ops.update_events_impl(mux, fd);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
struct UCoreClock *iomux_get_clock(struct IOMux *mux)
|
|
{
|
|
return mux->uclock;
|
|
}
|
|
|
|
struct UCTimers *iomux_get_timers(struct IOMux *mux)
|
|
{
|
|
return &mux->timers;
|
|
}
|
|
|
|
struct IOMux *iomux_from_timers(struct UCTimers *timers)
|
|
{
|
|
return (struct IOMux*)timers; //timers is the 1. member of IOMux
|
|
}
|
|
|