int lthread_close(int fd) { struct lthread *lt = NULL; /* wake up the lthreads waiting on this fd and notify them of close */ lt = _lthread_desched_event(fd, LT_EV_READ); if (lt) { TAILQ_INSERT_TAIL(<hread_get_sched()->ready, lt, ready_next); lt->state |= BIT(LT_ST_FDEOF); } lt = _lthread_desched_event(fd, LT_EV_WRITE); if (lt) { TAILQ_INSERT_TAIL(<hread_get_sched()->ready, lt, ready_next); lt->state |= BIT(LT_ST_FDEOF); } /* clear the eof bit of the calling lthread */ lt = lthread_get_sched()->current_lthread; if (lt->state & BIT(LT_ST_FDEOF)) { lt->state &= CLEARBIT(LT_ST_FDEOF); } /* closing fd removes its registered events from poller */ return (close(fd)); }
int lthread_sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr *hdtr) { off_t sbytes = 0; int ret = 0; lthread_t *lt = lthread_get_sched()->current_lthread; do { ret = sendfile(fd, s, offset, nbytes, hdtr, &sbytes, 0); if (ret == 0) return 0; if (sbytes) offset += sbytes; sbytes = 0; if (ret == -1 && EAGAIN == errno) _lthread_wait_for(lt, s, LT_WRITE); else if (ret == -1) return -1; } while (1); }
int lthread_connect(int fd, struct sockaddr *name, socklen_t namelen, uint64_t timeout) { int ret = 0; lthread_t *lt = lthread_get_sched()->current_lthread; while (1) { _lthread_renice(lt); ret = connect(fd, name, namelen); if (ret == 0) break; if (ret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS)) { if (timeout) _sched_lthread(lt, timeout); _lthread_wait_for(lt, fd, LT_WRITE); if (lt->state & bit(LT_EXPIRED)) return -2; ret = 0; break; } else { break; } } return ret; }
ssize_t lthread_writev(int fd, struct iovec *iov, int iovcnt) { LTHREAD_SOCKET_CHECK_SCHED(writev(fd, iov, iovcnt)); ssize_t total = 0; int iov_index = 0; struct lthread *lt = lthread_get_sched()->current_lthread; do { _lthread_renice(lt); ssize_t n = writev(fd, iov + iov_index, iovcnt - iov_index); if (n > 0) { int i = 0; total += n; for (i = iov_index; i < iovcnt && n > 0; i++) { if (n < iov[i].iov_len) { iov[i].iov_base += n; iov[i].iov_len -= n; n = 0; } else { n -= iov[i].iov_len; iov_index++; } } } else if (-1 == n && EAGAIN == errno) { _lthread_sched_event(lt, fd, LT_EV_WRITE, 0); } else { return (n); } } while (iov_index < iovcnt); return (total); }
int lthread_connect(int fd, struct sockaddr *name, socklen_t namelen, uint64_t timeout) { int ret = 0; struct lthread *lt = lthread_get_sched()->current_lthread; while (1) { _lthread_renice(lt); ret = connect(fd, name, namelen); if (ret == 0) break; if (ret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EALREADY)) { _lthread_sched_event(lt, fd, LT_EV_WRITE, timeout); if (lt->state & BIT(LT_ST_EXPIRED)) return (-2); continue; } else { break; } } return (ret); }
void bd_lt_listener(lthread_t *lt, int args) { lthread_t *lt_new; socklen_t addrlen; int s_fd, c_fd; struct sockaddr_in cin; DEFINE_LTHREAD(lt); s_fd = e_listener("0.0.0.0", 5557); if (!s_fd) { perror("Cannot listen on socket"); return; } while (1) { c_fd = lthread_accept(lt, s_fd, (struct sockaddr *)&cin, &addrlen); if (!c_fd) { continue; } lthread_create(lthread_get_sched(lt), <_new, bd_lt_cli, (void *)c_fd); } }
inline void _lthread_poller_ev_clear_trigger(void) { uint64_t tmp; struct lthread_sched *sched = lthread_get_sched(); assert(read(sched->eventfd, &tmp, sizeof(uint64_t)) == sizeof(uint64_t)); }
ssize_t lthread_writev(int fd, struct iovec *iov, int iovcnt) { ssize_t total = 0; int iov_index = 0; lthread_t *lt = lthread_get_sched()->current_lthread; do { _lthread_renice(lt); ssize_t n = writev(fd, iov + iov_index, iovcnt - iov_index); if (n > 0) { int i = 0; total += n; for (i = iov_index; i < iovcnt && n > 0; i++) { if (n < iov[i].iov_len) { iov[i].iov_base += n; iov[i].iov_len -= n; n = 0; } else { n -= iov[i].iov_len; iov_index++; } } } else if (-1 == n && EAGAIN == errno) { _lthread_wait_for(lt, fd, LT_WRITE); } else { return n; } } while (iov_index < iovcnt); return total; }
inline int poll_events(struct timespec t) { sched_t *sched = lthread_get_sched(); return kevent(sched->poller, sched->changelist, sched->nevents, sched->eventlist, LT_MAX_EVENTS, &t); }
static inline int _lthread_connect(int fd, struct sockaddr *name, socklen_t namelen, uint64_t timeout) { LTHREAD_SOCKET_CHECK_SCHED(connect(fd, name, namelen)); int ret = 0; struct lthread *lt = lthread_get_sched()->current_lthread; while (1) { _lthread_renice(lt); ret = connect(fd, name, namelen); if (ret == 0) break; if (ret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS)) { _lthread_sched_event(lt, fd, LT_EV_WRITE, timeout); if (lt->state & BIT(LT_ST_EXPIRED)) { errno = ETIMEDOUT; return (-1); } continue; } else { break; } } return (ret); }
inline void register_wr_interest(int fd) { sched_t *sched = lthread_get_sched(); EV_SET(&sched->changelist[sched->nevents++], fd, EVFILT_WRITE, EV_ADD | EV_ENABLE | EV_ONESHOT, 0, 0, sched->current_lthread); sched->current_lthread->state |= bit(LT_WAIT_WRITE); }
inline int _lthread_poller_poll(struct timespec t) { struct lthread_sched *sched = lthread_get_sched(); return (epoll_wait(sched->poller_fd, sched->eventlist, LT_MAX_EVENTS, t.tv_sec*1000.0 + t.tv_nsec/1000000.0)); }
void cmd_ls(cmd_opt_t *cmd) { char *tmp = lthread_summary(lthread_get_sched(cmd->lt)); lthread_send(cmd->lt, cmd->fd, tmp, strlen(tmp), 0); free(tmp); return; }
int lthread_poll(struct pollfd *fds, nfds_t nfds, int timeout) { if (timeout == 0) return poll(fds, nfds, 0); LTHREAD_SOCKET_CHECK_SCHED(poll(fds, nfds, timeout)); struct lthread *lt = lthread_get_sched()->current_lthread; _lthread_renice(lt); /* doubt if it's necessary */ return _lthread_sched_events_poll(lt, fds, nfds, timeout); }
int lthread_close(int fd) { lthread_t *lt = lthread_get_sched()->current_lthread; close(fd); _desched_lthread(lt); clear_rd_wr_state(lt); return 0; }
inline void _lthread_poller_ev_clear_wr(int fd) { struct epoll_event ev; int ret = 0; struct lthread_sched *sched = lthread_get_sched(); ev.data.u64 = 0; ev.data.fd = fd; ev.events = EPOLLOUT | EPOLLONESHOT | EPOLLRDHUP; ret = epoll_ctl(sched->poller_fd, EPOLL_CTL_DEL, fd, &ev); assert(ret != -1); }
inline void _lthread_poller_ev_clear_rd(int fd) { struct epoll_event ev; int ret = 0; struct lthread_sched *sched = lthread_get_sched(); ev.data.u64 = 0; /* without it, there s uninitialised variable warning with valgrind */ ev.data.fd = fd; ev.events = EPOLLIN | EPOLLONESHOT | EPOLLRDHUP; ret = epoll_ctl(sched->poller_fd, EPOLL_CTL_DEL, fd, &ev); assert(ret != -1); }
int lthread_close(int fd) { LTHREAD_SOCKET_CHECK_SCHED(close(fd)); struct lthread *lt = NULL; /* wake up the lthreads waiting on this fd and notify them of close */ lt = _lthread_desched_event(fd, LT_EV_READ); if (lt) { TAILQ_INSERT_TAIL(<hread_get_sched()->ready, lt, ready_next); lt->state |= BIT(LT_ST_FDEOF); } lt = _lthread_desched_event(fd, LT_EV_WRITE); if (lt) { TAILQ_INSERT_TAIL(<hread_get_sched()->ready, lt, ready_next); lt->state |= BIT(LT_ST_FDEOF); } /* closing fd removes its registered events from poller */ return (close(fd)); }
inline void _lthread_poller_ev_register_rd(int fd) { struct epoll_event ev; int ret = 0; struct lthread_sched *sched = lthread_get_sched(); ev.events = EPOLLIN | EPOLLONESHOT | EPOLLRDHUP; ev.data.u64 = 0; ev.data.fd = fd; ret = epoll_ctl(sched->poller_fd, EPOLL_CTL_MOD, fd, &ev); if (ret < 0) ret = epoll_ctl(sched->poller_fd, EPOLL_CTL_ADD, fd, &ev); assert(ret != -1); }
inline void _lthread_poller_ev_register_trigger(void) { struct lthread_sched *sched = lthread_get_sched(); int ret = 0; struct epoll_event ev; if (!sched->eventfd) { sched->eventfd = eventfd(0, EFD_NONBLOCK); assert(sched->eventfd != -1); } ev.events = EPOLLIN; ev.data.u64 = 0; ev.data.fd = sched->eventfd; ret = epoll_ctl(sched->poller_fd, EPOLL_CTL_ADD, sched->eventfd, &ev); assert(ret != -1); }
inline void clear_interest(int fd) { struct kevent change; struct kevent event; struct timespec tm = {0, 0}; int ret = 0; sched_t *sched = lthread_get_sched(); //printf("sched is %p and fd is %d\n", sched, fd); /*EV_SET(&sched->changelist[sched->nevents++], fd, 0, EV_DELETE, 0, 0, NULL);*/ EV_SET(&change, fd, EVFILT_READ|EVFILT_WRITE, EV_DELETE, 0, 0, NULL); ret = kevent(sched->poller, &change, 1, &event, 0, &tm); //assert(ret == 0); }
int lthread_accept(int fd, struct sockaddr *addr, socklen_t *len) { LTHREAD_SOCKET_CHECK_SCHED(accept(fd, addr, len)); int ret = -1; struct lthread *lt = lthread_get_sched()->current_lthread; while (1) { _lthread_renice(lt); ret = accept(fd, addr, len); if (ret == -1 && (errno == ENFILE || errno == EWOULDBLOCK || errno == EMFILE)) { _lthread_sched_event(lt, fd, LT_EV_READ, 0); continue; } if (ret > 0) break; if (ret == -1 && errno == ECONNABORTED) { perror("Cannot accept connection"); continue; } if (ret == -1 && errno != EWOULDBLOCK) { fprintf(stderr, "Cannot accept connection on %d: %s\n", fd, strerror(errno)); return (-1); } } #ifndef __FreeBSD__ if ((fcntl(ret, F_SETFL, O_NONBLOCK)) == -1) { close(ret); perror("Failed to set socket properties"); return (-1); } #endif return (ret); }
int lthread_accept(int fd, struct sockaddr *addr, socklen_t *len) { int ret = -1; lthread_t *lt = lthread_get_sched()->current_lthread; while (1) { _lthread_renice(lt); ret = accept(fd, addr, len); if (ret == -1 && (errno == ENFILE || errno == EWOULDBLOCK || errno == EMFILE)) { _lthread_wait_for(lt, fd, LT_READ); continue; } if (ret > 0) break; if (ret == -1 && errno == ECONNABORTED) { perror("Cannot accept connection"); continue; } if (ret == -1 && errno != EWOULDBLOCK) { perror("Cannot accept connection"); return -1; } } #ifndef __FreeBSD__ if ((fcntl(ret, F_SETFL, O_NONBLOCK)) == -1) { close(fd); perror("Failed to set socket properties"); return -1; } #endif return ret; }
int lthread_poll(struct pollfd *fds, nfds_t nfds, int timeout) { int i = 0; if (timeout == 0) return poll(fds, nfds, 0); struct lthread *lt = lthread_get_sched()->current_lthread; /* schedule fd events, pass -1 to avoid yielding */ for (i = 0; i < nfds; i++) { if (fds[i].events & POLLIN) _lthread_sched_event(lt, fds[i].fd, LT_EV_READ, -1); else if (fds[i].events & POLLOUT) _lthread_sched_event(lt, fds[i].fd, LT_EV_WRITE, -1); else assert(0); } lt->ready_fds = 0; lt->fd_wait = -1; /* clear wait_read/write flags set by _lthread_sched_event */ lt->state &= CLEARBIT(LT_ST_WAIT_READ); lt->state &= CLEARBIT(LT_ST_WAIT_WRITE); /* we are waiting on multiple fd events */ lt->state |= BIT(LT_ST_WAIT_MULTI); lt->pollfds = fds; lt->nfds = nfds; /* go to sleep until one or more of the fds are ready or until we timeout */ _lthread_sched_sleep(lt, (uint64_t)timeout); lt->pollfds = NULL; lt->nfds = 0; lt->state &= CLEARBIT(LT_ST_WAIT_MULTI); if (lt->state & BIT(LT_ST_EXPIRED)) return (0); return (lt->ready_fds); }