Beispiel #1
0
static ALWAYS_INLINE void
spawn_coro(lwan_connection_t *conn,
            coro_switcher_t *switcher, struct death_queue_t *dq)
{
    assert(!conn->coro);
    assert(!(conn->flags & CONN_IS_ALIVE));
    assert(!(conn->flags & CONN_SHOULD_RESUME_CORO));

    conn->coro = coro_new(switcher, process_request_coro, conn);

    death_queue_insert(dq, conn);
    conn->flags |= (CONN_IS_ALIVE | CONN_SHOULD_RESUME_CORO);
    conn->flags &= ~CONN_WRITE_EVENTS;
}
Beispiel #2
0
static ALWAYS_INLINE void
spawn_or_reset_coro_if_needed(lwan_connection_t *conn,
            coro_switcher_t *switcher, struct death_queue_t *dq)
{
    if (conn->coro) {
        if (conn->flags & CONN_SHOULD_RESUME_CORO)
            return;

        coro_reset(conn->coro, process_request_coro, conn);
    } else {
        conn->coro = coro_new(switcher, process_request_coro, conn);

        death_queue_insert(dq, conn);
        conn->flags |= CONN_IS_ALIVE;
    }
    conn->flags |= CONN_SHOULD_RESUME_CORO;
    conn->flags &= ~CONN_WRITE_EVENTS;
}
Beispiel #3
0
struct lwan_fd_watch *lwan_watch_fd(struct lwan *l,
                                    int fd,
                                    uint32_t events,
                                    coro_function_t coro_fn,
                                    void *data)
{
    struct lwan_fd_watch *watch;

    watch = malloc(sizeof(*watch));
    if (!watch)
        return NULL;

    watch->coro = coro_new(&l->switcher, coro_fn, data);
    if (!watch->coro)
        goto out;

    struct epoll_event ev = {.events = events, .data.ptr = watch->coro};
    if (epoll_ctl(l->epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
        coro_free(watch->coro);
        goto out;
    }

    watch->fd = fd;
    return watch;

out:
    free(watch);
    return NULL;
}

void lwan_unwatch_fd(struct lwan *l, struct lwan_fd_watch *w)
{
    if (l->main_socket != w->fd) {
        if (epoll_ctl(l->epfd, EPOLL_CTL_DEL, w->fd, NULL) < 0)
            lwan_status_perror("Could not unwatch fd %d", w->fd);
    }

    coro_free(w->coro);
    free(w);
}

void lwan_main_loop(struct lwan *l)
{
    struct epoll_event evs[16];
    struct lwan_fd_watch *watch;

    assert(main_socket == -1);
    main_socket = l->main_socket;

    if (signal(SIGINT, sigint_handler) == SIG_ERR)
        lwan_status_critical("Could not set signal handler");

    watch = lwan_watch_fd(l, l->main_socket, EPOLLIN | EPOLLHUP | EPOLLRDHUP,
                          accept_connection_coro, l);
    if (!watch)
        lwan_status_critical("Could not watch main socket");

    lwan_status_info("Ready to serve");

    while (true) {
        int n_evs = epoll_wait(l->epfd, evs, N_ELEMENTS(evs), -1);

        if (UNLIKELY(n_evs < 0)) {
            if (main_socket < 0)
                break;
            if (errno == EINTR || errno == EAGAIN)
                continue;
            break;
        }

        for (int i = 0; i < n_evs; i++) {
            if (!coro_resume_value(evs[i].data.ptr, (int)evs[i].events))
                break;
        }
    }

    lwan_unwatch_fd(l, watch);
}

#ifdef CLOCK_MONOTONIC_COARSE
__attribute__((constructor)) static void detect_fastest_monotonic_clock(void)
{
    struct timespec ts;

    if (!clock_gettime(CLOCK_MONOTONIC_COARSE, &ts))
        monotonic_clock_id = CLOCK_MONOTONIC_COARSE;
}
#endif

void lwan_set_thread_name(const char *name)
{
    char thread_name[16];
    char process_name[PATH_MAX];
    char *tmp;
    int ret;

    if (proc_pidpath(getpid(), process_name, sizeof(process_name)) < 0)
        return;

    tmp = strrchr(process_name, '/');
    if (!tmp)
        return;

    ret = snprintf(thread_name, sizeof(thread_name), "%s %s", tmp + 1, name);
    if (ret < 0)
        return;

    pthread_set_name_np(pthread_self(), thread_name);
}
Beispiel #4
0
void coro_run(coro *next) {
	coro *caller = coro_new(NULL, NULL);
	coro_call(caller, next);
	coro_release(caller);
}