Beispiel #1
0
void
lock_acquire(struct lock *lock)
{
    if(!lock_do_i_hold(lock)) {
        spinlock_acquire(&lock->spin_lock);
        while(spinlock_data_testandset(&lock->lk_busy) != 0) {
            wchan_sleep(lock->lk_wchan, &lock->spin_lock);
        }
        lock->lk_cpu = curcpu;
        lock->lk_thread = curthread;
        spinlock_release(&lock->spin_lock);
    }
}
Beispiel #2
0
/*
 * Get the lock.
 *
 * First disable interrupts (otherwise, if we get a timer interrupt we
 * might come back to this lock and deadlock), then use a machine-level
 * atomic operation to wait for the lock to be free.
 */
void
spinlock_acquire(struct spinlock *lk)
{
	struct cpu *mycpu;

	splraise(IPL_NONE, IPL_HIGH);

	/* this must work before curcpu initialization */
	if (CURCPU_EXISTS()) {
		mycpu = curcpu->c_self;
		if (lk->lk_holder == mycpu) {
			panic("Deadlock on spinlock %p\n", lk);
		}
	}
	else {
		mycpu = NULL;
	}

	while (1) {
		/*
		 * Do test-test-and-set, that is, read first before
		 * doing test-and-set, to reduce bus contention.
		 *
		 * Test-and-set is a machine-level atomic operation
		 * that writes 1 into the lock word and returns the
		 * previous value. If that value was 0, the lock was
		 * previously unheld and we now own it. If it was 1,
		 * we don't.
		 */
		if (spinlock_data_get(&lk->lk_lock) != 0) {
			continue;
		}
		if (spinlock_data_testandset(&lk->lk_lock) != 0) {
			continue;
		}
		break;
	}

	lk->lk_holder = mycpu;
}