Example #1
0
void erts_lc_lock_flg(erts_lc_lock_t *lck, Uint16 op_flags)
{
    erts_lc_locked_locks_t *l_lcks;
    erts_lc_locked_lock_t *l_lck;

    if (lck->inited != ERTS_LC_INITITALIZED)
	uninitialized_lock();

    if (lck->id < 0)
	return;

    l_lcks = make_my_locked_locks();
    l_lck = new_locked_lock(lck, op_flags);

    if (!l_lcks->locked.last) {
	ASSERT(!l_lcks->locked.first);
	l_lcks->locked.last = l_lcks->locked.first = l_lck;
    }
    else if (l_lcks->locked.last->id < lck->id
	     || (l_lcks->locked.last->id == lck->id
		 && l_lcks->locked.last->extra < lck->extra)) {
	if (LOCK_IS_TYPE_ORDER_VIOLATION(lck->flags, l_lcks->locked.last->flags))
	    type_order_violation("locking ", l_lcks, lck);
	l_lck->prev = l_lcks->locked.last;
	l_lcks->locked.last->next = l_lck;
	l_lcks->locked.last = l_lck;
    }
    else if (l_lcks->locked.last->id == lck->id && l_lcks->locked.last->extra == lck->extra)
	lock_twice("Locking", l_lcks, lck, op_flags);
    else
	lock_order_violation(l_lcks, lck);
}
Example #2
0
void
erts_lc_destroy_lock(erts_lc_lock_t *lck)
{
    if (lck->inited != ERTS_LC_INITITALIZED)
	uninitialized_lock();

    lck->inited = 0;
    lck->id = -1;
    lck->extra = THE_NON_VALUE;
    lck->flags = 0;
}
Example #3
0
void erts_lc_trylock_flg_x(int locked, erts_lc_lock_t *lck, Uint16 op_flags,
			   char *file, unsigned int line)
{
    erts_lc_locked_locks_t *l_lcks;
    erts_lc_locked_lock_t *l_lck;

    if (lck->inited != ERTS_LC_INITITALIZED)
	uninitialized_lock();

    if (lck->id < 0)
	return;

    l_lcks = make_my_locked_locks();
    l_lck = locked ? new_locked_lock(lck, op_flags, file, line) : NULL;

    if (!l_lcks->locked.last) {
	ASSERT(!l_lcks->locked.first);
	if (locked)
	    l_lcks->locked.first = l_lcks->locked.last = l_lck;
    }
    else {
	erts_lc_locked_lock_t *tl_lck;
#if 0 /* Ok when trylocking I guess... */
	if (LOCK_IS_TYPE_ORDER_VIOLATION(lck->flags, l_lcks->locked.last->flags))
	    type_order_violation("trylocking ", l_lcks, lck);
#endif

	for (tl_lck = l_lcks->locked.last; tl_lck; tl_lck = tl_lck->prev) {
	    if (tl_lck->id < lck->id
		|| (tl_lck->id == lck->id && tl_lck->extra <= lck->extra)) {
		if (tl_lck->id == lck->id && tl_lck->extra == lck->extra)
		    lock_twice("Trylocking", l_lcks, lck, op_flags);
		if (locked) {
		    l_lck->next = tl_lck->next;
		    l_lck->prev = tl_lck;
		    if (tl_lck->next)
			tl_lck->next->prev = l_lck;
		    else
			l_lcks->locked.last = l_lck;
		    tl_lck->next = l_lck;
		}
		return;
	    }
	}

	if (locked) {
	    l_lck->next = l_lcks->locked.first;
	    l_lcks->locked.first->prev = l_lck;
	    l_lcks->locked.first = l_lck;
	}
    }

}
Example #4
0
void erts_lc_trylock_flg_x(int locked, erts_lc_lock_t *lck, erts_lock_options_t options,
			   char *file, unsigned int line)
{
    lc_thread_t *thr;
    lc_locked_lock_t *ll;

    if (lck->inited != ERTS_LC_INITITALIZED)
	uninitialized_lock();

    if (lck->id < 0)
	return;

    thr = make_my_locked_locks();
    ll = locked ? new_locked_lock(thr, lck, options, file, line) : NULL;

    if (!thr->locked.last) {
	ASSERT(!thr->locked.first);
	if (locked)
	    thr->locked.first = thr->locked.last = ll;
    }
    else {
	lc_locked_lock_t *tl_lck;
#if 0 /* Ok when trylocking I guess... */
	if (LOCK_IS_TYPE_ORDER_VIOLATION(lck->flags, thr->locked.last->flags))
	    type_order_violation("trylocking ", thr, lck);
#endif

	for (tl_lck = thr->locked.last; tl_lck; tl_lck = tl_lck->prev) {
	    if (tl_lck->id < lck->id
		|| (tl_lck->id == lck->id && tl_lck->extra <= lck->extra)) {
		if (tl_lck->id == lck->id && tl_lck->extra == lck->extra && lck->check_order)
		    lock_twice("Trylocking", thr, lck, options);
		if (locked) {
		    ll->next = tl_lck->next;
		    ll->prev = tl_lck;
		    if (tl_lck->next)
			tl_lck->next->prev = ll;
		    else
			thr->locked.last = ll;
		    tl_lck->next = ll;
		}
		return;
	    }
	}

	if (locked) {
	    ll->next = thr->locked.first;
	    thr->locked.first->prev = ll;
	    thr->locked.first = ll;
	}
    }

}
Example #5
0
void erts_lc_lock_flg_x(erts_lc_lock_t *lck, erts_lock_options_t options,
			char *file, unsigned int line)
{
    lc_thread_t *thr;
    lc_locked_lock_t *new_ll;

    if (lck->inited != ERTS_LC_INITITALIZED)
	uninitialized_lock();

    if (lck->id < 0)
	return;

    thr = make_my_locked_locks();
    new_ll = new_locked_lock(thr, lck, options, file, line);

    if (!thr->locked.last) {
	ASSERT(!thr->locked.first);
	thr->locked.last = thr->locked.first = new_ll;
        ASSERT(0 < lck->id && lck->id < ERTS_LOCK_ORDER_SIZE);
        thr->matrix.m[lck->id][0] = 1;
    }
    else if (( ! lck->check_order && thr->locked.last->id == lck->id) ||
             (thr->locked.last->id < lck->id
              || (thr->locked.last->id == lck->id
                  && thr->locked.last->extra < lck->extra))) {
        lc_locked_lock_t* ll;
	if (LOCK_IS_TYPE_ORDER_VIOLATION(lck->flags, thr->locked.last->flags)) {
	    type_order_violation("locking ", thr, lck);
        }

        ASSERT(0 < lck->id && lck->id < ERTS_LOCK_ORDER_SIZE);
        ll = thr->locked.last;
        thr->matrix.m[lck->id][ll->id] |= 1;
        for (ll = ll->prev; ll; ll = ll->prev) {
            ASSERT(0 < ll->id && ll->id < ERTS_LOCK_ORDER_SIZE);
            thr->matrix.m[lck->id][ll->id] |= 2;
        }

	new_ll->prev = thr->locked.last;
	thr->locked.last->next = new_ll;
	thr->locked.last = new_ll;
    }
    else if (thr->locked.last->id == lck->id && thr->locked.last->extra == lck->extra)
	lock_twice("Locking", thr, lck, options);
    else
	lock_order_violation(thr, lck);
}
Example #6
0
void erts_lc_unlock_flg(erts_lc_lock_t *lck, Uint16 op_flags)
{
    erts_lc_locked_locks_t *l_lcks;
    erts_lc_locked_lock_t *l_lck;

    if (lck->inited != ERTS_LC_INITITALIZED)
	uninitialized_lock();

    if (lck->id < 0)
	return;

    l_lcks = get_my_locked_locks();

    if (l_lcks) {
	l_lck = l_lcks->required.first;
	if (find_lock(&l_lck, lck))
	    unlock_of_required_lock(l_lcks, lck);
    }

    for (l_lck = l_lcks ? l_lcks->locked.last : NULL; l_lck; l_lck = l_lck->prev) {
	if (l_lck->id == lck->id && l_lck->extra == lck->extra) {
	    if ((l_lck->flags & ERTS_LC_FLG_LO_ALL) != op_flags)
		unlock_op_mismatch(l_lcks, lck, op_flags);
	    if (l_lck->prev)
		l_lck->prev->next = l_lck->next;
	    else
		l_lcks->locked.first = l_lck->next;
	    if (l_lck->next)
		l_lck->next->prev = l_lck->prev;
	    else
		l_lcks->locked.last = l_lck->prev;
	    lc_free((void *) l_lck);
	    return;
	}
    }
    
    unlock_of_not_locked(l_lcks, lck);
}
Example #7
0
void erts_lc_unlock_flg(erts_lc_lock_t *lck, erts_lock_options_t options)
{
    lc_thread_t *thr;
    lc_locked_lock_t *ll;

    if (lck->inited != ERTS_LC_INITITALIZED)
	uninitialized_lock();

    if (lck->id < 0)
	return;

    thr = get_my_locked_locks();

    if (thr) {
	ll = thr->required.first;
	if (find_lock(&ll, lck))
	    unlock_of_required_lock(thr, lck);
    }

    for (ll = thr ? thr->locked.last : NULL; ll; ll = ll->prev) {
	if (ll->id == lck->id && ll->extra == lck->extra) {
	    if ((ll->taken_options & ERTS_LOCK_OPTIONS_RDWR) != options)
		unlock_op_mismatch(thr, lck, options);
	    if (ll->prev)
		ll->prev->next = ll->next;
	    else
		thr->locked.first = ll->next;
	    if (ll->next)
		ll->next->prev = ll->prev;
	    else
		thr->locked.last = ll->prev;
	    lc_free(thr, ll);
	    return;
	}
    }
    
    unlock_of_not_locked(thr, lck);
}
Example #8
0
void erts_lc_might_unlock_flg(erts_lc_lock_t *lck, Uint16 op_flags)
{
    erts_lc_locked_locks_t *l_lcks;
    erts_lc_locked_lock_t *l_lck;

    if (lck->inited != ERTS_LC_INITITALIZED)
	uninitialized_lock();

    if (lck->id < 0)
	return;

    l_lcks = get_my_locked_locks();

    if (l_lcks) {
	l_lck = l_lcks->required.first;
	if (find_lock(&l_lck, lck))
	    unlock_of_required_lock(l_lcks, lck);
    }

    l_lck = l_lcks->locked.first;
    if (!find_lock(&l_lck, lck))
	unlock_of_not_locked(l_lcks, lck);
}
Example #9
0
void erts_lc_might_unlock_flg(erts_lc_lock_t *lck, erts_lock_options_t options)
{
    lc_thread_t *thr;
    lc_locked_lock_t *ll;

    if (lck->inited != ERTS_LC_INITITALIZED)
	uninitialized_lock();

    if (lck->id < 0)
	return;

    thr = get_my_locked_locks();

    if (thr) {
	ll = thr->required.first;
	if (find_lock(&ll, lck))
	    unlock_of_required_lock(thr, lck);
    }

    ll = thr->locked.first;
    if (!find_lock(&ll, lck))
	unlock_of_not_locked(thr, lck);
}
Example #10
0
int
erts_lc_trylock_force_busy_flg(erts_lc_lock_t *lck, Uint16 op_flags)
{
#ifdef ERTS_LC_DO_NOT_FORCE_BUSY_TRYLOCK_ON_LOCK_ORDER_VIOLATION
    return 0;
#else
    /*
     * Force busy trylock if locking doesn't follow lock order.
     * This in order to make sure that caller can handle
     * the situation without causing a lock order violation.
     */
    erts_lc_locked_locks_t *l_lcks;

    if (lck->inited != ERTS_LC_INITITALIZED)
	uninitialized_lock();

    if (lck->id < 0)
	return 0;

    l_lcks = get_my_locked_locks();

    if (!l_lcks || !l_lcks->locked.first) {
	ASSERT(!l_lcks || !l_lcks->locked.last);
	return 0;
    }
    else {
	erts_lc_locked_lock_t *tl_lck;

	ASSERT(l_lcks->locked.last);

#if 0 /* Ok when trylocking I guess... */
	if (LOCK_IS_TYPE_ORDER_VIOLATION(lck->flags, l_lcks->locked.last->flags))
	    type_order_violation("trylocking ", l_lcks, lck);
#endif

	if (l_lcks->locked.last->id < lck->id
	    || (l_lcks->locked.last->id == lck->id
		&& l_lcks->locked.last->extra < lck->extra))
	    return 0;

	/*
	 * Lock order violation
	 */


	/* Check that we are not trying to lock this lock twice */
	for (tl_lck = l_lcks->locked.last; tl_lck; tl_lck = tl_lck->prev) {
	    if (tl_lck->id < lck->id
		|| (tl_lck->id == lck->id && tl_lck->extra <= lck->extra)) {
		if (tl_lck->id == lck->id && tl_lck->extra == lck->extra)
		    lock_twice("Trylocking", l_lcks, lck, op_flags);
		break;
	    }
	}

#ifndef ERTS_LC_ALLWAYS_FORCE_BUSY_TRYLOCK_ON_LOCK_ORDER_VIOLATION
	/* We only force busy if a lock order violation would occur
	   and when on an even millisecond. */
	{
	    SysTimeval tv;
	    sys_gettimeofday(&tv);

	    if ((tv.tv_usec / 1000) & 1)
		return 0;
	}
#endif

	return 1;
    }
#endif
}