예제 #1
0
파일: network.c 프로젝트: djs55/stunnel
int s_poll_wait(s_poll_set *fds, int timeout) {
    CONTEXT *ctx; /* current context */
    static CONTEXT *to_free=NULL; /* delayed memory deallocation */

    /* remove the current context from ready queue */
    ctx=ready_head;
    ready_head=ready_head->next;
    if(!ready_head) /* the queue is empty */
        ready_tail=NULL;

    if(fds) { /* something to wait for -> swap the context */
        ctx->fds=fds; /* set file descriptors to wait for */
        ctx->finish=timeout<0 ? -1 : time(NULL)+timeout;
        /* move (append) the current context to the waiting queue */
        ctx->next=NULL;
        if(waiting_tail)
            waiting_tail->next=ctx;
        waiting_tail=ctx;
        if(!waiting_head)
            waiting_head=ctx;
        while(!ready_head) /* no context ready */
            scan_waiting_queue();
        if(ctx->id!=ready_head->id) {
            s_log(LOG_DEBUG, "Context swap: %ld -> %ld",
                ctx->id, ready_head->id);
            swapcontext(&ctx->ctx, &ready_head->ctx);
            s_log(LOG_DEBUG, "Current context: %ld", ready_head->id);
            if(to_free) {
                s_log(LOG_DEBUG, "Releasing context %ld", to_free->id);
                free(to_free);
                to_free=NULL;
            }
        }
        return ready_head->ready;
    } else { /* nothing to wait for -> drop the context */
        /* it's illegal to deallocate the stack of the current context */
        if(to_free) {
            s_log(LOG_DEBUG, "Releasing context %ld", to_free->id);
            free(to_free);
        }
        to_free=ctx;
        while(!ready_head) /* no context ready */
            scan_waiting_queue();
        s_log(LOG_DEBUG, "Context set: %ld (dropped) -> %ld",
            ctx->id, ready_head->id);
        setcontext(&ready_head->ctx);
        ioerror("setcontext"); /* should not ever happen */
        return 0;
    }
}
예제 #2
0
파일: network.c 프로젝트: Jimdo/stunnel
int s_poll_wait(s_poll_set *fds, int sec, int msec) {
    CONTEXT *context; /* current context */
    static CONTEXT *to_free=NULL; /* delayed memory deallocation */

    /* FIXME: msec parameter is currently ignored with UCONTEXT threads */
    (void)msec; /* skip warning about unused parameter */

    /* remove the current context from ready queue */
    context=ready_head;
    ready_head=ready_head->next;
    if(!ready_head) /* the queue is empty */
        ready_tail=NULL;
    /* it it safe to s_log() after new ready_head is set */

    /* it's illegal to deallocate the stack of the current context */
    if(to_free) { /* a delayed deallocation is scheduled */
#ifdef DEBUG_UCONTEXT
        s_log(LOG_DEBUG, "Releasing context %ld", to_free->id);
#endif
        str_free(to_free->stack);
        str_free(to_free);
        to_free=NULL;
    }

    /* manage the current thread */
    if(fds) { /* something to wait for -> swap the context */
        context->fds=fds; /* set file descriptors to wait for */
        context->finish=sec<0 ? -1 : time(NULL)+sec;

        /* append the current context to the waiting queue */
        context->next=NULL;
        if(waiting_tail)
            waiting_tail->next=context;
        waiting_tail=context;
        if(!waiting_head)
            waiting_head=context;
    } else { /* nothing to wait for -> drop the context */
        to_free=context; /* schedule for delayed deallocation */
    }

    while(!ready_head) /* wait until there is a thread to switch to */
        scan_waiting_queue();

    /* switch threads */
    if(fds) { /* swap the current context */
        if(context->id!=ready_head->id) {
#ifdef DEBUG_UCONTEXT
            s_log(LOG_DEBUG, "Context swap: %ld -> %ld",
                context->id, ready_head->id);
#endif
            swapcontext(&context->context, &ready_head->context);
#ifdef DEBUG_UCONTEXT
            s_log(LOG_DEBUG, "Current context: %ld", ready_head->id);
#endif
        }
        return ready_head->ready;
    } else { /* drop the current context */
#ifdef DEBUG_UCONTEXT
        s_log(LOG_DEBUG, "Context set: %ld (dropped) -> %ld",
            context->id, ready_head->id);
#endif
        setcontext(&ready_head->context);
        ioerror("setcontext"); /* should not ever happen */
        return 0;
    }
}