static void iv_event_raw_got_event(void *_this) { struct iv_event_raw *this = (struct iv_event_raw *)_this; int toread; char buf[1024]; int ret; toread = eventfd_unavailable ? sizeof(buf) : 8; do { ret = read(this->event_rfd.fd, buf, toread); } while (ret < 0 && errno == EINTR); if (ret <= 0) { if (ret == 0) { iv_fatal("iv_event_raw: reading from event fd " "returned zero"); } else if (errno != EAGAIN) { iv_fatal("iv_event_raw: reading from event fd " "returned error %d[%s]", errno, strerror(errno)); } return; } this->handler(this->cookie); }
static void iv_fd_kqueue_poll(struct iv_state *st, struct iv_list_head *active, const struct timespec *abs) { struct kevent kev[UPLOAD_BATCH]; int num; struct kevent batch[st->numfds ? 2 * st->numfds : 1]; struct timespec rel; int ret; int run_events; int i; iv_fd_kqueue_upload(st, kev, UPLOAD_BATCH, &num); ret = kevent(st->u.kqueue.kqueue_fd, kev, num, batch, ARRAY_SIZE(batch), to_relative(st, &rel, abs)); __iv_invalidate_now(st); if (ret < 0) { if (errno == EINTR) return; iv_fatal("iv_fd_kqueue_poll: got error %d[%s]", errno, strerror(errno)); } run_events = 0; for (i = 0; i < ret; i++) { struct iv_fd_ *fd; if (batch[i].filter == EVFILT_USER) { run_events = 1; continue; } if (batch[i].flags & EV_ERROR) { int err = batch[i].data; int fd = batch[i].ident; iv_fatal("iv_fd_kqueue_poll: got error %d[%s] " "polling fd %d", err, strerror(err), fd); } fd = (void *)batch[i].udata; if (batch[i].filter == EVFILT_READ) { iv_fd_make_ready(active, fd, MASKIN); } else if (batch[i].filter == EVFILT_WRITE) { iv_fd_make_ready(active, fd, MASKOUT); } else { iv_fatal("iv_fd_kqueue_poll: got message from " "filter %d", batch[i].filter); } } if (run_events) iv_event_run_pending_events(); }
static void iv_fd_port_event_send(struct iv_state *dest) { if (port_send(dest->u.port.port_fd, 0, NULL) < 0) { iv_fatal("iv_fd_port_event_send: port_send got " "error %d[%s]", errno, strerror(errno)); } }
static void iv_fd_port_upload_one(struct iv_state *st, struct iv_fd_ *fd) { if (__iv_fd_port_upload_one(st, fd) < 0) { iv_fatal("iv_fd_port_upload_one: got error %d[%s]", errno, strerror(errno)); } }
static void iv_fd_init_first_thread(struct iv_state *st) { int euid; char *exclude; euid = geteuid(); signal(SIGPIPE, SIG_IGN); signal(SIGURG, SIG_IGN); sanitise_nofile_rlimit(euid); exclude = getenv("IV_EXCLUDE_POLL_METHOD"); if (exclude != NULL && getuid() != euid) exclude = NULL; #ifdef HAVE_PORT_CREATE consider_poll_method(st, exclude, &iv_fd_poll_method_port); #endif #ifdef HAVE_SYS_DEVPOLL_H consider_poll_method(st, exclude, &iv_fd_poll_method_dev_poll); #endif #ifdef HAVE_EPOLL_CREATE consider_poll_method(st, exclude, &iv_fd_poll_method_epoll); #endif #ifdef HAVE_KQUEUE consider_poll_method(st, exclude, &iv_fd_poll_method_kqueue); #endif consider_poll_method(st, exclude, &iv_fd_poll_method_poll); if (method == NULL) iv_fatal("iv_init: can't find suitable event dispatcher"); }
static int iv_fd_port_timer_create(struct iv_state *st) { port_notify_t pn; struct sigevent se; timer_t id; int ret; se.sigev_notify = SIGEV_PORT; se.sigev_value.sival_ptr = &pn; pn.portnfy_port = st->u.port.port_fd; pn.portnfy_user = NULL; ret = timer_create(CLOCK_MONOTONIC, &se, &id); if (ret < 0) { if (errno == EPERM) return 0; iv_fatal("iv_fd_port_timer_create: got error %d[%s]", errno, strerror(errno)); } st->u.port.timer_id = id; return 1; }
static void iv_popen_child(void *cookie) { struct iv_popen_spawn_info *info = cookie; int devnull; devnull = open("/dev/null", O_RDWR); if (devnull < 0) { iv_fatal("iv_popen_child: got error %d[%s] opening " "/dev/null", errno, strerror(errno)); } if (info->for_read) { dup2(devnull, 0); dup2(info->data_pipe[1], 1); dup2(devnull, 2); } else { dup2(info->data_pipe[0], 0); dup2(devnull, 1); dup2(devnull, 2); } close(info->data_pipe[0]); close(info->data_pipe[1]); close(devnull); execvp(info->this->file, info->this->argv); perror("execvp"); }
void iv_fd_init(struct iv_state *st) { if (method == NULL) iv_fd_init_first_thread(st); else if (method->init(st) < 0) iv_fatal("iv_init: can't initialize event dispatcher"); st->numfds = 0; st->handled_fd = NULL; }
void iv_task_register(struct iv_task *_t) { struct iv_state *st = iv_get_state(); struct iv_task_ *t = (struct iv_task_ *)_t; if (!iv_list_empty(&t->list)) iv_fatal("iv_task_register: called with task still on a list"); st->numobjs++; iv_list_add_tail(&t->list, &st->tasks); }
void iv_task_unregister(struct iv_task *_t) { struct iv_state *st = iv_get_state(); struct iv_task_ *t = (struct iv_task_ *)_t; if (iv_list_empty(&t->list)) iv_fatal("iv_task_unregister: called with task not on a list"); st->numobjs--; iv_list_del_init(&t->list); }
/* worker thread ************************************************************/ static void __iv_work_thread_die(struct work_pool_thread *thr) { struct work_pool_priv *pool = thr->pool; if (thr->kicked) iv_fatal("__iv_work_thread_die: called on kicked thread"); if (!iv_list_empty(&thr->list)) iv_fatal("__iv_work_thread_die: thread still on list"); iv_event_unregister(&thr->kick); free(thr); pool->started_threads--; if (pool->thread_stop != NULL) pool->thread_stop(pool->cookie); if (pool->shutting_down && !pool->started_threads) iv_event_post(&pool->ev); }
void iv_fd_set_handler_err(struct iv_fd *_fd, void (*handler_err)(void *)) { struct iv_state *st = iv_get_state(); struct iv_fd_ *fd = (struct iv_fd_ *)_fd; if (!fd->registered) { iv_fatal("iv_fd_set_handler_err: called with fd which " "is not registered"); } fd->handler_err = handler_err; notify_fd(st, fd); }
void iv_timer_unregister(struct iv_timer *_t) { struct iv_state *st = iv_get_state(); struct iv_timer_ *t = (struct iv_timer_ *)_t; struct iv_timer_ **m; struct iv_timer_ **p; if (t->index == -1) { iv_fatal("iv_timer_unregister: called with timer not " "on the heap"); } if (t->index > st->num_timers) { iv_fatal("iv_timer_unregister: timer index %d > %d", t->index, st->num_timers); } p = get_node(st, t->index); if (*p != t) { iv_fatal("iv_timer_unregister: unregistered timer " "index belonging to other timer"); } st->numobjs--; m = get_node(st, st->num_timers); st->num_timers--; *p = *m; (*p)->index = t->index; *m = NULL; if (p != m) { pull_up(st, (*p)->index, p); push_down(st, (*p)->index, p); } t->index = -1; }
void iv_timer_register(struct iv_timer *_t) { struct iv_state *st = iv_get_state(); struct iv_timer_ *t = (struct iv_timer_ *)_t; struct iv_timer_ **p; int index; if (t->index != -1) { iv_fatal("iv_timer_register: called with timer still " "on the heap"); } st->numobjs++; index = ++st->num_timers; p = get_node(st, index); if (p == NULL) iv_fatal("iv_timer_register: timer list overflow"); *p = t; t->index = index; pull_up(st, index, p); }
static void iv_fd_register_prologue(struct iv_state *st, struct iv_fd_ *fd) { if (fd->registered) { iv_fatal("iv_fd_register: called with fd which is " "still registered"); } if (fd->fd < 0 || fd->fd >= maxfd) { iv_fatal("iv_fd_register: called with invalid fd %d " "(maxfd=%d)", fd->fd, maxfd); } fd->registered = 1; INIT_IV_LIST_HEAD(&fd->list_active); fd->ready_bands = 0; fd->registered_bands = 0; #if defined(HAVE_SYS_DEVPOLL_H) || defined(HAVE_EPOLL_CREATE) || \ defined(HAVE_KQUEUE) || defined(HAVE_PORT_CREATE) INIT_IV_LIST_HEAD(&fd->list_notify); #endif if (method->register_fd != NULL) method->register_fd(st, fd); }
static void iv_fd_port_clear_poll_timeout(struct iv_state *st) { struct itimerspec val; int ret; val.it_interval.tv_sec = 0; val.it_interval.tv_nsec = 0; val.it_value.tv_sec = 0; val.it_value.tv_nsec = 0; ret = timer_settime(st->u.port.timer_id, TIMER_ABSTIME, &val, NULL); if (ret < 0) { iv_fatal("iv_fd_port_clear_poll_timeout: got error %d[%s]", errno, strerror(errno)); } }
static void got_ev_parent(void *_dummy) { ev_received++; if (die == 0) { iv_event_post(&ev_child); } else if (die == 1) { die = 2; iv_event_post(&ev_child); } else if (die == 2) { iv_fatal("iv_event_bench: entered invalid state"); } else if (die == 3) { iv_validate_now(); tim_end = iv_now; iv_event_unregister(&ev_parent); } }
int log_open(char *file_path) { if (!file_path) { file_path = log_file_path_default; printf("Log file is not defined. Using default file: %s\n", file_path); } if( access(file_path, F_OK) == 0) unlink(file_path); log_file = fopen(file_path, "a"); if(log_file == NULL) { iv_fatal("%s, fopen failed: %s\n", __func__, strerror(errno)); } return 0; }
void iv_init(void) { struct iv_state *st; if (iv_state_index == -1) { iv_state_index = TlsAlloc(); if (iv_state_index == TLS_OUT_OF_INDEXES) iv_fatal("iv_init: failed to allocate TLS key"); } st = calloc(1, iv_tls_total_state_size()); TlsSetValue(iv_state_index, st); iv_handle_init(st); iv_task_init(st); iv_time_init(st); iv_timer_init(st); iv_tls_thread_init(st); }
void iv_init(void) { struct iv_state *st; if (!iv_state_key_allocated) { if (pthr_key_create(&iv_state_key, iv_state_destructor)) iv_fatal("iv_init: failed to allocate TLS key"); iv_state_key_allocated = 1; } st = calloc(1, iv_tls_total_state_size()); pthr_setspecific(&iv_state_key, st); iv_fd_init(st); iv_task_init(st); iv_timer_init(st); iv_event_init(st); iv_tls_thread_init(st); }
void iv_fd_unregister(struct iv_fd *_fd) { struct iv_state *st = iv_get_state(); struct iv_fd_ *fd = (struct iv_fd_ *)_fd; if (!fd->registered) { iv_fatal("iv_fd_unregister: called with fd which is " "not registered"); } fd->registered = 0; iv_list_del(&fd->list_active); notify_fd(st, fd); if (method->unregister_fd != NULL) method->unregister_fd(st, fd); st->numobjs--; st->numfds--; if (st->handled_fd == fd) st->handled_fd = NULL; }
static int iv_fd_port_set_poll_timeout(struct iv_state *st, const struct timespec *abs) { struct itimerspec val; int ret; if (st->u.port.timer_id == -1 && !iv_fd_port_timer_create(st)) { method = &iv_fd_poll_method_port; return 0; } val.it_interval.tv_sec = 0; val.it_interval.tv_nsec = 0; val.it_value = *abs; ret = timer_settime(st->u.port.timer_id, TIMER_ABSTIME, &val, NULL); if (ret < 0) { iv_fatal("iv_fd_port_set_poll_timeout: got error %d[%s]", errno, strerror(errno)); } return 1; }
void iv_init(void) { struct iv_state *st; if (!iv_state_key_allocated) { if (pthread_key_create(&iv_state_key, iv_state_destructor)) iv_fatal("iv_init: failed to allocate TLS key"); iv_state_key_allocated = 1; } st = calloc(1, iv_tls_total_state_size()); pthread_setspecific(iv_state_key, st); #ifdef HAVE_THREAD __st = st; #endif st->numobjs = 0; iv_fd_init(st); iv_task_init(st); iv_timer_init(st); iv_tls_thread_init(st); }
void iv_timer_init(struct iv_state *st) { if (get_node(st, 1) == NULL) iv_fatal("iv_timer_init: can't alloc memory for root ratnode"); }
static void kevent_retry(char *name, struct iv_state *st, const struct kevent *changelist, int nchanges) { if (__kevent_retry(st->u.kqueue.kqueue_fd, changelist, nchanges) < 0) iv_fatal("%s: got error %d[%s]", name, errno, strerror(errno)); }
static int iv_fd_port_poll(struct iv_state *st, struct iv_list_head *active, const struct timespec *abs) { struct timespec _rel; struct timespec *rel; int run_timers; int run_events; unsigned int nget; port_event_t pe[PORTEV_NUM]; int ret; int i; iv_fd_port_upload(st); rel = to_relative(st, &_rel, abs); run_timers = 0; if (rel != NULL && rel->tv_sec == 0 && rel->tv_nsec == 0) run_timers = 1; run_events = 0; poll_more: nget = 1; /* * If we get EINTR from port_getn(), no events are returned * and nget will not have been updated, but if we get ETIME, * events may be returned, and nget will be set to the number * of events in the array, and we need to process those * events as usual. */ ret = port_getn(st->u.port.port_fd, pe, PORTEV_NUM, &nget, rel); __iv_invalidate_now(st); if (ret < 0 && errno != ETIME) { if (errno == EINTR) return run_timers; iv_fatal("iv_fd_port_poll: got error %d[%s]", errno, strerror(errno)); } if (ret < 0 && errno == ETIME) run_timers = 1; for (i = 0; i < nget; i++) { int source; source = pe[i].portev_source; if (source == PORT_SOURCE_FD) { int revents; struct iv_fd_ *fd; revents = pe[i].portev_events; fd = pe[i].portev_user; if (revents & (POLLIN | POLLERR | POLLHUP)) iv_fd_make_ready(active, fd, MASKIN); if (revents & (POLLOUT | POLLERR | POLLHUP)) iv_fd_make_ready(active, fd, MASKOUT); if (revents & (POLLERR | POLLHUP)) iv_fd_make_ready(active, fd, MASKERR); fd->registered_bands = 0; iv_list_del_init(&fd->list_notify); if (fd->wanted_bands) { iv_list_add_tail(&fd->list_notify, &st->u.port.notify); } } else if (source == PORT_SOURCE_TIMER) { run_timers = 1; } else if (source == PORT_SOURCE_USER) { run_events = 1; } else { iv_fatal("iv_fd_port_poll: received event " "from unknown source %d", source); } } if (nget == PORTEV_NUM) { run_timers = 1; rel = &_rel; rel->tv_sec = 0; rel->tv_nsec = 0; goto poll_more; } if (run_events) iv_event_run_pending_events(); return run_timers; }