Ejemplo n.º 1
0
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
}
Ejemplo n.º 2
0
/**
 * 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;
}
Ejemplo n.º 3
0
/*
 * 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"));
}
Ejemplo n.º 4
0
/**
 * 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));
}
Ejemplo n.º 5
0
/**
 * 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;
}
Ejemplo n.º 6
0
/**
 * 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;
}
Ejemplo n.º 7
0
/**
 * 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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
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;
}