/** * 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; }
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(); }
/** * 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
/** * 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
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; }