IDATA VMCALL hythread_owns_thin_lock(hythread_t thread, hythread_thin_monitor_t lockword) { IDATA this_id = thread->thread_id; assert(!IS_FAT_LOCK(lockword)); #ifdef LOCK_RESERVATION return THREAD_ID(lockword) == this_id && (!IS_RESERVED(lockword) || RECURSION(lockword) !=0); #else return THREAD_ID(lockword) == this_id; #endif }
/** * 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; }
/* * Unreserves the lock already owned by this thread */ void unreserve_self_lock(hythread_thin_monitor_t *lockword_ptr) { U_32 lockword = *lockword_ptr; U_32 lockword_new; CTRACE(("unreserve self_id %d lock owner %d", hythread_get_self_id(), THREAD_ID(lockword))); assert(hythread_get_self_id() == THREAD_ID(lockword)); assert (!IS_FAT_LOCK(*lockword_ptr)); assert (IS_RESERVED(lockword)); CTRACE(("Unreserved self %d \n", ++unreserve_count_self/*, vm_get_object_class_name(lockword_ptr-1)*/)); // Set reservation bit to 1 and reduce recursion count lockword_new = (lockword | RESERVED_BITMASK); if (RECURSION(lockword_new) != 0) { RECURSION_DEC(lockword_ptr, lockword_new); } else { lockword_new = lockword_new & 0x0000ffff; *lockword_ptr = lockword_new; } assert(!IS_RESERVED(*lockword_ptr)); CTRACE(("unreserved self")); }
/** * Returns the owner of the given thin monitor. * * @param[in] lockword_ptr monitor addr */ hythread_t VMCALL hythread_thin_monitor_get_owner(hythread_thin_monitor_t *lockword_ptr) { U_32 lockword; hythread_monitor_t fat_monitor; assert(lockword_ptr); lockword = *lockword_ptr; if (IS_FAT_LOCK(lockword)) { // find fat_monitor in lock table fat_monitor = locktable_get_fat_monitor(FAT_LOCK_ID(lockword)); return fat_monitor->owner; } if (THREAD_ID(lockword)== 0) { return NULL; } #ifdef LOCK_RESERVATION if (RECURSION(lockword)==0 && IS_RESERVED(lockword)) { return NULL; } #endif return hythread_get_thread(THREAD_ID(lockword)); }
/** * Returns the recursion count of the given monitor. * * @param[in] lockword_ptr monitor addr */ IDATA VMCALL hythread_thin_monitor_get_recursion(hythread_thin_monitor_t *lockword_ptr) { U_32 lockword; hythread_monitor_t fat_monitor; assert(lockword_ptr); lockword = *lockword_ptr; if (IS_FAT_LOCK(lockword)) { // find fat_monitor in lock table fat_monitor = locktable_get_fat_monitor(FAT_LOCK_ID(lockword)); return fat_monitor->recursion_count+1; } if (THREAD_ID(lockword) == 0) { return 0; } #ifdef LOCK_RESERVATION if (IS_RESERVED(lockword)) { return RECURSION(lockword); } #endif return RECURSION(lockword)+1; }
/** * Attempts to lock thin monitor. * If the monitor is already locked, this call returns immediately with TM_BUSY. * * @param[in] lockword_ptr monitor addr */ IDATA hythread_thin_monitor_try_enter(hythread_thin_monitor_t *lockword_ptr) { U_32 lockword; // warkaround strange intel compiler bug #if defined (__INTEL_COMPILER) && defined (LINUX) volatile #endif IDATA this_id = tm_self_tls->thread_id; IDATA lock_id; IDATA status; hythread_monitor_t fat_monitor; int UNUSED i; assert(!hythread_is_suspend_enabled()); assert((UDATA)lockword_ptr > 4); assert(tm_self_tls); // By DRLVM design rules lockword (see description in thin locks paper) // is only modified without compare-and-exchange by owner thread. If tools // like Intel Thread Checker find a bug about this line, it may actually be a // false-positive. lockword = *lockword_ptr; lock_id = THREAD_ID(lockword); //CTRACE(("try lock %x %d", this_id, RECURSION(lockword))); // Check if the lock is already reserved or owned by this thread if (lock_id == this_id) { if (RECURSION(lockword) == MAX_RECURSION) { //inflate lock in case of recursion overflow fat_monitor = hythread_inflate_lock(lockword_ptr); if (fat_monitor == NULL) { return TM_ERROR_OUT_OF_MEMORY; } return hythread_monitor_try_enter(fat_monitor); //break FAT_LOCK; } else { CTRACE(("try lock %x count:%d", this_id, res_lock_count++)); // increase recursion RECURSION_INC(lockword_ptr, lockword); return TM_ERROR_NONE; } } // Fast path didn't work, someoneelse is holding the monitor (or it isn't reserved yet): // DO SPIN FOR A WHILE, this will decrease the number of fat locks. #ifdef SPIN_COUNT for (i = SPIN_COUNT; i >=0; i--, lockword = *lockword_ptr, lock_id = THREAD_ID(lockword)) { #endif // Check if monitor is free and thin if (lock_id == 0) { // Monitor is free assert( RECURSION(lockword) < 1); assert(this_id > 0 && this_id < 0x8000); // Acquire monitor if (0 != port_atomic_cas16 (((volatile apr_uint16_t*) lockword_ptr)+1, (apr_uint16_t) this_id, 0)) { #ifdef SPIN_COUNT continue; #else return TM_ERROR_EBUSY; #endif } #ifdef LOCK_RESERVATION //lockword = *lockword_ptr; // this reloading of lockword may be odd, need to investigate; if (IS_RESERVED(lockword)) { CTRACE(("initially reserve lock %x count: %d ", *lockword_ptr, init_reserve_cout++)); RECURSION_INC(lockword_ptr, *lockword_ptr); } #endif CTRACE(("CAS lock %x count: %d ", *lockword_ptr, cas_cout++)); return TM_ERROR_NONE; } else // Fat monitor if (IS_FAT_LOCK(lockword)) { CTRACE(("FAT MONITOR %d \n", ++fat_lock2_count/*, vm_get_object_class_name(lockword_ptr-1)*/)); fat_monitor = locktable_get_fat_monitor(FAT_LOCK_ID(lockword)); // find fat_monitor in lock table status = hythread_monitor_try_enter(fat_monitor); #ifdef SPIN_COUNT if (status == TM_ERROR_EBUSY) { continue; } #endif return status; } #ifdef LOCK_RESERVATION // unreserved busy lock else if (IS_RESERVED(lockword)) { status = hythread_unreserve_lock(lockword_ptr); if (status != TM_ERROR_NONE) { #ifdef SPIN_COUNT if (status == TM_ERROR_EBUSY) { continue; } #endif //SPIN_COUNT return status; } return hythread_thin_monitor_try_enter(lockword_ptr); } #endif #ifdef SPIN_COUNT hythread_yield(); } #endif return TM_ERROR_EBUSY; }
/** * Used lockword * Thin monitor functions used java monitor. */ IDATA VMCALL hythread_unreserve_lock(hythread_thin_monitor_t *lockword_ptr) { U_32 lockword = *lockword_ptr; U_32 lockword_new; uint16 lock_id; hythread_t owner; IDATA status; I_32 append; // trylock used to prevent cyclic suspend deadlock // the java_monitor_enter calls safe_point between attempts. /*status = port_mutex_trylock(&TM_LOCK); if (status !=TM_ERROR_NONE) { return status; }*/ if (IS_FAT_LOCK(lockword)) { return TM_ERROR_NONE; } lock_id = THREAD_ID(lockword); owner = hythread_get_thread(lock_id); CTRACE(("Unreserved other %d \n", ++unreserve_count/*, vm_get_object_class_name(lockword_ptr-1)*/)); if (!IS_RESERVED(lockword) || IS_FAT_LOCK(lockword)) { // port_mutex_unlock(&TM_LOCK); return TM_ERROR_NONE; } // suspend owner if (owner) { assert(owner); assert(hythread_get_id(owner) == lock_id); assert(owner != hythread_self()); if(owner->state & (TM_THREAD_STATE_TERMINATED | TM_THREAD_STATE_WAITING | TM_THREAD_STATE_WAITING_INDEFINITELY | TM_THREAD_STATE_WAITING_WITH_TIMEOUT | TM_THREAD_STATE_SLEEPING | TM_THREAD_STATE_PARKED | TM_THREAD_STATE_SUSPENDED | TM_THREAD_STATE_IN_MONITOR_WAIT)) { append = 0; } else { append = RESERVED_BITMASK; } status=hythread_suspend_other(owner); if (status !=TM_ERROR_NONE) { return status; } } else { append = 0; } if(!tm_properties || !tm_properties->use_soft_unreservation) { append = RESERVED_BITMASK; } // prepare new unreserved lockword and try to CAS it with old one. while (IS_RESERVED(lockword)) { assert(!IS_FAT_LOCK(lockword)); CTRACE(("unreserving lock")); if (RECURSION(lockword) != 0) { lockword_new = (lockword | RESERVED_BITMASK); assert(RECURSION(lockword) > 0); assert(RECURSION(lockword_new) > 0); RECURSION_DEC(&lockword_new, lockword_new); } else { lockword_new = (lockword | append); lockword_new = lockword_new & 0x0000ffff; } if (lockword == apr_atomic_cas32 (((volatile apr_uint32_t*) lockword_ptr), (apr_uint32_t) lockword_new, lockword)) { CTRACE(("unreserved lock")); break; } lockword = *lockword_ptr; } // resume owner if (owner) { hythread_yield_other(owner); hythread_resume(owner); } /* status = port_mutex_unlock(&TM_LOCK);*/ // Gregory - This lock, right after it was unreserved, may be // inflated by another thread and therefore instead of recursion // count and reserved flag it will have the fat monitor ID. The // assertion !IS_RESERVED(lockword) fails in this case. So it is // necessary to check first that monitor is not fat. // To avoid race condition between checking two different // conditions inside of assert, the lockword contents has to be // loaded before checking. // lockword = *lockword_ptr; // assert(IS_FAT_LOCK(lockword) || !IS_RESERVED(lockword)); return TM_ERROR_NONE; }
static PyObject * rootstate_getattr(PyObject *obj, PyObject *name) { char *s = PyString_AsString(name); PyInterpreterState *is; int ino; unsigned long tno; char buf[100]; if (!s) return 0; if (sscanf(s, "i%d_%50s", &ino, buf) == 2) { int countis; int numis; for (is = PyInterpreterState_Head(), numis = 0; is; is = PyInterpreterState_Next(is), numis++) ; for (is = PyInterpreterState_Head(), countis = 0; is; is = PyInterpreterState_Next(is), countis++) { int isno = numis - countis - 1; if (isno == ino) { PyObject *ret = PyMember_Get((char *)is, is_members, buf); if (!ret) PyErr_Format(PyExc_AttributeError, "interpreter state has no attribute '%s'", buf); return ret; } } PyErr_SetString(PyExc_AttributeError, "no such interpreter state number"); return 0; } if (sscanf(s, "t%lu_%50s", &tno, buf) == 2) { for (is = PyInterpreterState_Head(); is; is = PyInterpreterState_Next(is)) { PyThreadState *ts; for (ts = is->tstate_head; ts; ts = ts->next) { if (THREAD_ID(ts) == tno) { int frameno = 0; if (sscanf(buf, "f%d", &frameno) == 1) { PyFrameObject *frame; int numframes = 0; for (frame = ts->frame; frame; frame = frame->f_back) { numframes ++; } for (frame = ts->frame; frame; frame = frame->f_back) { numframes --; if (numframes == frameno) { Py_INCREF(frame); return (PyObject *)frame; } } PyErr_Format(PyExc_AttributeError, "thread state has no frame numbered %d from bottom", frameno); return 0; } else { PyObject *ret = PyMember_Get((char *)ts, ts_members, buf); if (!ret) PyErr_Format(PyExc_AttributeError, "thread state has no attribute '%s'", buf); return ret; } } } } } PyErr_Format(PyExc_AttributeError, "root state has no attribute '%.200s'", s); return 0; }
static int rootstate_relate(NyHeapRelate *r) { NyHeapViewObject *hv = (void *)r->hv; PyThreadState *ts, *bts = PyThreadState_GET(); PyInterpreterState *is; int isframe = PyFrame_Check(r->tgt); int isno; for (is = PyInterpreterState_Head(), isno = 0; is; is = PyInterpreterState_Next(is), isno++) ; for (is = PyInterpreterState_Head(), isno--; is; is = PyInterpreterState_Next(is), isno--) { char buf[100]; ISATTR(modules); ISATTR(sysdict); ISATTR(builtins); #if PY_VERSION_HEX >= 0x020303f0 ISATTR(codec_search_path); ISATTR(codec_search_cache); ISATTR(codec_error_registry); #endif for (ts = is->tstate_head; ts; ts = ts->next) { if ((ts == bts && r->tgt == hv->limitframe) || (!hv->limitframe && isframe)) { int frameno = -1; int numframes = 0; PyFrameObject *frame; for (frame = (PyFrameObject *)ts->frame; frame; frame = frame->f_back) { numframes ++; if (r->tgt == (PyObject *)frame) frameno = numframes; } if (frameno != -1) { frameno = numframes - frameno; sprintf(buf,"t%lu_f%d", THREAD_ID(ts), frameno); if (r->visit(NYHR_ATTRIBUTE, PyString_FromString(buf), r)) return 1; } } TSATTR(ts, c_profileobj); TSATTR(ts, c_traceobj); TSATTR(ts, curexc_type); TSATTR(ts, curexc_value); TSATTR(ts, curexc_traceback); TSATTR(ts, exc_type); TSATTR(ts, exc_value); TSATTR(ts, exc_traceback); TSATTR(ts, dict); #if PY_VERSION_HEX >= 0x020303f0 TSATTR(ts, async_exc); #endif } } return 0; }