Beispiel #1
0
int
lthread_sendfile(int fd, int s, off_t offset, size_t nbytes,
    struct sf_hdtr *hdtr)
{

    off_t sbytes = 0;
    int ret = 0;
    struct lthread *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_sched_event(lt, s, LT_EV_WRITE, 0);
        else if (ret == -1)
            return (-1);

    } while (1);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
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);
}
Beispiel #6
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);
}