Exemplo n.º 1
0
//wait method implementation
////
static IDATA latch_wait_impl(hylatch_t latch, I_64 ms, IDATA nano, IDATA interruptable) {
    IDATA status;
        
    status = port_mutex_lock(&latch->mutex);
    if (status != TM_ERROR_NONE) {
        return status;
    }
    while (latch->count) {
        status = condvar_wait_impl(&latch->condition, &latch->mutex, ms, nano, interruptable);
        //check interruption and other problems
        if (status != TM_ERROR_NONE) {
            port_mutex_unlock(&latch->mutex);
            return status;
        }

        if (ms || nano) break;
    }
    status = port_mutex_unlock(&latch->mutex);

    return status;
}
Exemplo n.º 2
0
IDATA monitor_wait_impl(hythread_monitor_t mon_ptr, I_64 ms, IDATA nano, IDATA interruptable) {
    IDATA status;
    int saved_recursion;
    //int saved_disable_count;
    hythread_t self = tm_self_tls;
    if (mon_ptr->owner != self) {
        return TM_ERROR_ILLEGAL_STATE;
    }

    saved_recursion = mon_ptr->recursion_count;

    assert(saved_recursion>=0);

    mon_ptr->owner = NULL;
    mon_ptr->recursion_count =0;
    mon_ptr->wait_count++;
    port_mutex_lock(&self->mutex);
    self->state |= TM_THREAD_STATE_IN_MONITOR_WAIT;
    self->waited_monitor = mon_ptr;
    port_mutex_unlock(&self->mutex);

    do {
        apr_time_t start;
        assert(mon_ptr->notify_count >= 0);
        assert(mon_ptr->notify_count < mon_ptr->wait_count);
        start = apr_time_now();
        status = condvar_wait_impl(&mon_ptr->condition, &mon_ptr->mutex, ms, nano, interruptable);
        if (status != TM_ERROR_NONE || mon_ptr->notify_count) {
            break;
        }
        // we should not change ms and nano if both are 0 (meaning "no timeout")
        if (ms || nano) {
            apr_interval_time_t elapsed;
            elapsed = apr_time_now() - start; // microseconds
            nano -= (IDATA)((elapsed % 1000) * 1000);
            if (nano < 0) {
                ms -= elapsed/1000 + 1;
                nano += 1000000;
            } else {
                ms -= elapsed/1000;
            }
            if (ms < 0) {
                assert(status == TM_ERROR_NONE);
                status = TM_ERROR_TIMEOUT;
                break;
            }
            assert(0 <= nano && nano < 1000000);
        }
    } while (1);

    // consume the notify_count unless we got an error (or were interrupted)
    if (mon_ptr->notify_count > 0
        && (status == TM_ERROR_NONE || mon_ptr->notify_count == mon_ptr->wait_count))
    {
        mon_ptr->notify_count--;
    }

    port_mutex_lock(&self->mutex);
    self->state &= ~TM_THREAD_STATE_IN_MONITOR_WAIT;
    self->waited_monitor = NULL;
    port_mutex_unlock(&self->mutex);

    mon_ptr->wait_count--;
    assert(mon_ptr->notify_count <= mon_ptr->wait_count);

    if (self->request) {
        int save_count;
        port_mutex_unlock(&mon_ptr->mutex);
        hythread_safe_point();
        hythread_exception_safe_point();
        save_count = hythread_reset_suspend_disable();
        port_mutex_lock(&mon_ptr->mutex);
        hythread_set_suspend_disable(save_count);
    }

    mon_ptr->recursion_count = saved_recursion;
    mon_ptr->owner = self;
    assert(mon_ptr->owner);
    return status;
}
Exemplo n.º 3
0
IDATA thread_sleep_impl(I_64 millis, IDATA nanos, IDATA interruptable) {
    IDATA status;
    IDATA result;
    hythread_t self;
    hythread_monitor_t mon;

    if (nanos == 0 && millis == 0) {
        hythread_yield();
        return TM_ERROR_NONE;
    }
    if (!(self = hythread_self())) {
        // Report error in case current thread is not attached
        return TM_ERROR_UNATTACHED_THREAD;
    }

    // Grab thread monitor
    mon = self->monitor;
    status = hythread_monitor_enter(mon);
    assert(status == TM_ERROR_NONE);
    assert(mon->recursion_count == 0);
    mon->owner = NULL;
    mon->wait_count++;

    // Set thread state
    status = port_mutex_lock(&self->mutex);
    assert(status == TM_ERROR_NONE);
    self->waited_monitor = mon;
    self->state |= TM_THREAD_STATE_SLEEPING;
    status = port_mutex_unlock(&self->mutex);
    assert(status == TM_ERROR_NONE);

    do {
        apr_time_t start;
        assert(mon->notify_count >= 0);
        assert(mon->notify_count < mon->wait_count);
        start = apr_time_now();

        result = condvar_wait_impl(&mon->condition, &mon->mutex, millis, nanos, interruptable);
        if (result != TM_ERROR_NONE) {
            break;
        }
        // we should not change millis and nanos if both are 0 (meaning "no timeout")
        if (millis || nanos) {
            apr_interval_time_t elapsed = apr_time_now() - start;
            nanos -= (IDATA)((elapsed % 1000) * 1000);
            if (nanos < 0) {
                millis -= elapsed/1000 + 1;
                nanos += 1000000;
            } else {
                millis -= elapsed/1000;
            }
            if (millis < 0) {
                assert(status == TM_ERROR_NONE);
                status = TM_ERROR_TIMEOUT;
                break;
            }
            assert(0 <= nanos && nanos < 1000000);
        }
    } while(1);

    // Restore thread state
    status = port_mutex_lock(&self->mutex);
    assert(status == TM_ERROR_NONE);
    self->state &= ~TM_THREAD_STATE_SLEEPING;
    self->waited_monitor = NULL;
    status = port_mutex_unlock(&self->mutex);
    assert(status == TM_ERROR_NONE);

    // Release thread monitor
    mon->wait_count--;
    mon->owner = self;
    assert(mon->notify_count <= mon->wait_count);
    status = hythread_monitor_exit(mon);
    assert(status == TM_ERROR_NONE);

    if (self->request) {
        hythread_safe_point();
        hythread_exception_safe_point();
    }

    return (result == TM_ERROR_INTERRUPT && interruptable)
        ? TM_ERROR_INTERRUPT : TM_ERROR_NONE;
}
/**
 * Instructs the current thread to wait until signaled to wake up or
 * the specified timeout is elapsed.
 *
 * @param[in] cond the condition variable on which to block.
 * @param[in] mutex the mutex that must be locked upon entering this function
 * @param[in] ms amount of time in milliseconds to wait
 * @param[in] nano amount of time in nanoseconds to wait
 * @sa apr_thread_cond_timedwait()
 * @return  
 *      TM_NO_ERROR on success 
 */
IDATA VMCALL hycond_wait_timed(hycond_t *cond, osmutex_t *mutex, I_64 ms, IDATA nano) {
    return condvar_wait_impl(cond, mutex, ms, nano, WAIT_NONINTERRUPTABLE);
}
/**
 * Instructs the current thread to wait until it is signaled to wake up.
 * 
 * @param[in] cond the condition variable on which to block
 * @param[in] mutex the mutex that must be locked upon entering this function
 * @sa apr_thread_cond_wait()
 * @return  
 *      TM_NO_ERROR on success 
 */
IDATA VMCALL hycond_wait(hycond_t *cond, osmutex_t *mutex) {
    return condvar_wait_impl(cond, mutex, 0, 0, WAIT_NONINTERRUPTABLE);
}
/**
 * Instructs the current thread to wait until signaled to wake up or
 * the specified timeout is elapsed.
 *
 * @param[in] cond the condition variable on which to block.
 * @param[in] mutex the mutex that must be locked upon entering this function
 * @param[in] ms amount of time in milliseconds to wait
 * @param[in] nano amount of time in nanoseconds to wait
 * @sa apr_thread_cond_timedwait()
 * @return  
 *      TM_NO_ERROR on success 
 *      TM_THREAD_INTERRUPTED in case thread was interrupted during wait.
 */
IDATA VMCALL hycond_wait_interruptable(hycond_t *cond, osmutex_t *mutex, I_64 ms, IDATA nano) {
    return condvar_wait_impl(cond, mutex, ms, nano, WAIT_INTERRUPTABLE);
}