/**
 * Unlocks thin monitor.
 * 
 * @param[in] lockword_ptr monitor addr 
 */
IDATA VMCALL hythread_thin_monitor_exit(hythread_thin_monitor_t *lockword_ptr) {
    U_32 lockword = *lockword_ptr;
    hythread_monitor_t fat_monitor;
    IDATA this_id = tm_self_tls->thread_id; // obtain current thread id   
    assert(this_id > 0 && this_id < 0xffff);
    assert(!hythread_is_suspend_enabled());

    if (THREAD_ID(lockword) == this_id) {
        if (RECURSION(lockword)==0) {
#ifdef LOCK_RESERVATION
            if (IS_RESERVED(lockword)) {
                CTRACE(("ILLEGAL_STATE %x\n", lockword));
                return TM_ERROR_ILLEGAL_STATE;
            }
#endif
            *lockword_ptr = lockword & 0xffff;
        } else {
            RECURSION_DEC(lockword_ptr, lockword);
            //CTRACE(("recursion_dec: 0x%x", *lockword_ptr)); 
        }
        //CTRACE(("unlocked: 0x%x id: %d\n", *lockword_ptr, THREAD_ID(*lockword_ptr)));
        //hythread_safe_point();
        return TM_ERROR_NONE;     
    }  else if (IS_FAT_LOCK(lockword)) {
        CTRACE(("exit fat monitor %d thread: %d\n", FAT_LOCK_ID(lockword), tm_self_tls->thread_id));
        fat_monitor = locktable_get_fat_monitor(FAT_LOCK_ID(lockword)); // find fat_monitor
        return hythread_monitor_exit(fat_monitor); // unlock fat_monitor
    }
    CTRACE(("ILLEGAL_STATE %d\n", FAT_LOCK_ID(lockword)));
    return TM_ERROR_ILLEGAL_STATE;
}
Example #2
0
extern HY_CFUNC void VMCALL 
hythread_exit (hythread_monitor_t monitor) {
   
    if (monitor !=NULL && monitor->owner == hythread_self()) {
        monitor->recursion_count = 0;
        hythread_monitor_exit(monitor);
    }
    hythread_detach_ex(NULL);
    port_thread_exit(0);
    // unreachable statement
    abort();
}
Example #3
0
/**
 * Releases the ownership over monitor.
 *
 * @param[in] mon_ptr monitor
 */
IDATA VMCALL jthread_raw_monitor_exit(jrawMonitorID mon_ptr)
{
    hythread_monitor_t monitor =
         (hythread_monitor_t)array_get(jvmti_monitor_table, (UDATA)mon_ptr);
    if (!monitor) {
        return TM_ERROR_INVALID_MONITOR;
    }
    IDATA status = hythread_monitor_exit(monitor);
    hythread_safe_point();
    hythread_exception_safe_point();
    return status;
} // jthread_raw_monitor_exit
/** 
 * Interrupt a thread.
 * 
 * If the thread is currently blocked (i.e. waiting on a monitor_wait or sleeping)
 * resume the thread and cause it to return from the blocking function with
 * HYTHREAD_INTERRUPTED.
 * 
 * @param[in] thread a thread to be interrupted
 * @return none
 */
void VMCALL hythread_interrupt(hythread_t thread) {
    IDATA status;
    hythread_monitor_t mon;

    apr_atomic_set32(&thread->interrupted, TRUE);

    mon = thread->waited_monitor;
    if (mon) {
        // If thread was doing any kind of wait, notify it.
        if (hythread_monitor_try_enter(mon) == TM_ERROR_NONE) {
            status = hycond_notify_all(&mon->condition);
            assert(status == TM_ERROR_NONE);
            status = hythread_monitor_exit(mon);
            assert(status == TM_ERROR_NONE);
        } else {
            status = hythread_create(NULL, 0, 0, 0,
                hythread_interrupter, (void *)mon);
            assert (status == TM_ERROR_NONE);
        }
    }
} // hythread_interrupt
Example #5
0
/**
 * Destroys raw monitor. 
 *
 * @param[in] mon_ptr address where monitor needs to be destroyed.
 */
IDATA VMCALL jthread_raw_monitor_destroy(jrawMonitorID mon_ptr)
{
    hythread_monitor_t monitor =
         (hythread_monitor_t)array_get(jvmti_monitor_table, (UDATA)mon_ptr);
    if (!monitor) {
        return TM_ERROR_INVALID_MONITOR;
    }

    while (hythread_monitor_destroy((hythread_monitor_t)monitor) != TM_ERROR_NONE)
    {
        IDATA status = hythread_monitor_exit((hythread_monitor_t) monitor);
        if (status != TM_ERROR_NONE) {
            return status;
        }
    }

    IDATA status = port_mutex_lock(&jvmti_monitor_table_lock);
    if (status != TM_ERROR_NONE) {
        return status;
    }
    array_delete(jvmti_monitor_table, (UDATA) mon_ptr);
    status = port_mutex_unlock(&jvmti_monitor_table_lock);
    return status;
} // jthread_raw_monitor_destroy
Example #6
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;
}