Beispiel #1
0
int
dcethread__end_block(dcethread* thread, int (*interrupt)(dcethread*, void*), void* data)
{
    int state;
    int interruptible;

    dcethread__lock(thread);
    state = thread->state;
    interruptible = thread->flag.interruptible;

    /* Switch state back to active if:
       - We were not interrupted during the block
       - We were interrupted and the thread is interruptible

       If we were interrupted but are not currently interruptible,
       we want to leave the state alone so that is is caught when
       interruptiblility is enabled again.
    */
    if ((interruptible && state == DCETHREAD_STATE_INTERRUPT) ||
        (state == DCETHREAD_STATE_BLOCKED))
    {
        if (interrupt)
            thread->interrupt = interrupt;
        if (data)
            thread->interrupt_data = data;
        dcethread__change_state(thread, DCETHREAD_STATE_ACTIVE);
    }

    dcethread__unlock(thread);

    return state == DCETHREAD_STATE_INTERRUPT && interruptible;
}
void
dcethread_checkinterrupt(void)
{
    dcethread* thread = dcethread__self();
    int interruptible;
    int state;

    dcethread__lock(thread);
    state = thread->state;
    interruptible = thread->flag.interruptible;

    if (state == DCETHREAD_STATE_INTERRUPT && interruptible)
    {
        dcethread__change_state(thread, DCETHREAD_STATE_ACTIVE);
    }

    dcethread__unlock(thread);

    if (state == DCETHREAD_STATE_INTERRUPT && interruptible)
    {
        dcethread__dispatchinterrupt(thread);
    }

    return;
}
Beispiel #3
0
int
dcethread__poll_end_block(dcethread* thread, int (*interrupt)(dcethread*, void*), void* data)
{
    int state;
    int interruptible;

    dcethread__lock(thread);
    state = thread->state;
    interruptible = thread->flag.interruptible;
    
    if (state == DCETHREAD_STATE_INTERRUPT)
    {
        if (interrupt)
            thread->interrupt = interrupt;
        if (data)
            thread->interrupt_data = data;
        if ((interruptible && state == DCETHREAD_STATE_INTERRUPT) ||
            (state == DCETHREAD_STATE_BLOCKED))
            dcethread__change_state(thread, DCETHREAD_STATE_ACTIVE);
    }

    dcethread__unlock(thread);

    return state == DCETHREAD_STATE_INTERRUPT && interruptible;
}
Beispiel #4
0
static void *
proxy_start(void *arg)
{
    dcethread_start_args *args = (dcethread_start_args*) arg;
    void *result;
    int prev_cancel_state;
    int prev_cancel_type;

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &prev_cancel_state);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &prev_cancel_type);
    dcethread__init_self(args->self);

    result = args->start(args->data);

    (void) pthread_setcancelstate(prev_cancel_state, NULL);
    (void) pthread_setcanceltype(prev_cancel_type, NULL);

    dcethread__lock(args->self);
    args->self->status = result;
    dcethread__cleanup_self(args->self);
    dcethread__unlock(args->self);

    free(args);

    return result;
}
Beispiel #5
0
void
dcethread__init_self(dcethread* thread)
{
    /* Ensure thread system is initialized */
    dcethread__init();

    pthread_setspecific(dcethread_self_key, (void*) thread);
    dcethread__lock(thread);
    dcethread__change_state(thread, DCETHREAD_STATE_ACTIVE);
    dcethread__unlock(thread);
}
Beispiel #6
0
static void
self_destructor(void* data)
{
    if (data)
    {
        dcethread* self = (dcethread*) data;
        dcethread__lock(self);
        dcethread__change_state(self, DCETHREAD_STATE_DEAD);
        dcethread__release(self);
        dcethread__unlock(self);
    }
}
int
dcethread_enableasync(int on)
{
    dcethread* thread = dcethread__self();
    int old;

    dcethread__lock(thread);
    old = thread->flag.async;
    thread->flag.async = on;
    dcethread__unlock(thread);

    (void) dcethread__set_errno(0);
    return old;
}
Beispiel #8
0
int
dcethread_create(dcethread** _thread, dcethread_attr* attr, void *(*start_routine)(void *), void *arg)
{
    dcethread_start_args *start_args;
    dcethread* thread;
    int detachstate;

    start_args = (dcethread_start_args *) malloc(sizeof(*start_args));
    if (start_args == NULL)
    {
	return dcethread__set_errno(ENOMEM);
    }

    start_args->start = start_routine;
    start_args->data = arg;
    start_args->self = thread = dcethread__new();

    /* Record if this thread was created joinably */
    if (!attr || (pthread_attr_getdetachstate(attr, &detachstate), detachstate == PTHREAD_CREATE_JOINABLE))
    {
	thread->flag.joinable = 1;
    }

    /* If thread is joinable, give it an extra reference */
    if (thread->flag.joinable)
    {
	thread->refs++;
    }

    if (dcethread__set_errno(pthread_create((pthread_t*) &thread->pthread, attr, proxy_start, start_args)))
    {
	dcethread__delete(thread);
	free(start_args);
	return -1;
    }

    DCETHREAD_TRACE("Thread %p: created (pthread %lu)", thread, (unsigned long) thread->pthread);

    dcethread__lock(thread);
    while (thread->state == DCETHREAD_STATE_CREATED)
    {
	dcethread__wait(thread);
    }
    dcethread__unlock(thread);

    DCETHREAD_TRACE("Thread %p: started", thread);

    *_thread = thread;
    return dcethread__set_errno(0);
}
/* 
 * A S Y N C _ S I G N A L _ H A N D L E R
 * 
 * This async signal handler is already running on the correct thread
 * stack.   ALL async signals map to a "cancel".  A cancel unwind happens
 * only at well defined points, so we can't RAISE the exception; just
 * post the cancel.
 */
static void *async_signal_handler(void *dummy)
{
    /*
     * Wait for and handle asynchronous signals.
     */
    while (1)
    {
        int sig;

        sigwait(&async_sigset, &sig);
	dcethread__lock(thread_to_interrupt);
	dcethread__interrupt(thread_to_interrupt);
	dcethread__unlock(thread_to_interrupt);
    }

    return NULL;
}
Beispiel #10
0
int
dcethread__begin_block(dcethread* thread, int (*interrupt)(dcethread*, void*), void* data,
                       int (**old_interrupt)(dcethread*, void*), void** old_data)
{
    int state;
    int interruptible;

    dcethread__lock(thread);
    state = thread->state;
    interruptible = thread->flag.interruptible;
    /* If thread is currently active */
    if (state == DCETHREAD_STATE_ACTIVE)
    {
	/* Set up interruption callbacks */
	if (old_interrupt)
	    *old_interrupt = thread->interrupt;
	if (old_data)
	    *old_data = thread->interrupt_data;
	if (interrupt)
	    thread->interrupt = interrupt;
	if (data)
	    thread->interrupt_data = data;
	
	/* Change to blocked state */
	dcethread__change_state(thread, DCETHREAD_STATE_BLOCKED);
    }
    /* If an interrupt request has been posted (and we can be interrupted) */
    else if (state == DCETHREAD_STATE_INTERRUPT && interruptible)
    {
	/* Clear request */
	dcethread__change_state(thread, DCETHREAD_STATE_ACTIVE);
    }
    dcethread__unlock(thread);

    return state == DCETHREAD_STATE_INTERRUPT && interruptible;
}