/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:lock.c 12.1$ */
/* $ACIS:lock.c 12.1$ */
/* $Source: /ibm/acis/usr/sys/afs/RCS/lock.c,v $ */

#ifndef lint
static char *rcsid = "$Header:lock.c 12.1$";
#endif

/*******************************************************************\
* 								    *
* 	Information Technology Center				    *
* 	Carnegie-Mellon University				    *
* 								    *
* 								    *
* 								    *
\*******************************************************************/


/*
	Locking routines for Vice.

*/

#ifdef ibm032
#include "../h/param.h"
#endif ibm032
#include "../h/time.h"
#include "../h/kernel.h"

#include "../afs/osi.h"
#include "../afs/lock.h"

#define FALSE	0
#define TRUE	1

Lock_Init(lock)
    register struct lock *lock;
{
    lock -> readers_reading = 0;
    lock -> excl_locked = 0;
    lock -> wait_states = 0;
    lock -> num_waiting = 0;
}

Lock_Obtain(lock, how)
    register struct lock *lock;
    int how;
{
    switch (how) {

	case READ_LOCK:		lock->num_waiting++;
				do {
				    lock -> wait_states |= READ_LOCK;
				    osi_Sleep(&lock->readers_reading);
				} while (lock->excl_locked & WRITE_LOCK);
				lock->num_waiting--;
				lock->readers_reading++;
				break;

	case WRITE_LOCK:	lock->num_waiting++;
				do {
				    lock -> wait_states |= WRITE_LOCK;
				    osi_Sleep(&lock->excl_locked);
				} while (lock->excl_locked || lock->readers_reading);
				lock->num_waiting--;
				lock->excl_locked = WRITE_LOCK;
				break;

	case SHARED_LOCK:	lock->num_waiting++;
				do {
				    lock->wait_states |= SHARED_LOCK;
				    osi_Sleep(&lock->excl_locked);
				} while (lock->excl_locked);
				lock->num_waiting--;
				lock->excl_locked = SHARED_LOCK;
				break;

	case BOOSTED_LOCK:	lock->num_waiting++;
				do {
				    lock->wait_states |= WRITE_LOCK;
				    osi_Sleep(&lock->excl_locked);
				} while (lock->readers_reading);
				lock->num_waiting--;
				lock->excl_locked = WRITE_LOCK;
				break;

	default:		panic("afs locktype");
    }
}

/* release a lock, giving preference to new readers */
Lock_ReleaseR(lock)
    register struct lock *lock;
{
    if (lock->wait_states & READ_LOCK) {
	lock->wait_states &= ~READ_LOCK;
	osi_Wakeup(&lock->readers_reading);
    }
    else {
	lock->wait_states &= ~EXCL_LOCKS;
	osi_Wakeup(&lock->excl_locked);
    }
}

/* release a lock, giving preference to new writers */
Lock_ReleaseW(lock)
    register struct lock *lock;
{
    if (lock->wait_states & EXCL_LOCKS) {
	lock->wait_states &= ~EXCL_LOCKS;
	osi_Wakeup(&lock->excl_locked);
    }
    else {
	lock->wait_states &= ~READ_LOCK;
	osi_Wakeup(&lock->readers_reading);
    }
}

/*
Wait for some change in the lock status.
Lock_Wait(lock)
    register struct lock *lock; {
    if (lock->readers_reading || lock->excl_locked) return 1;
    lock->wait_states |= READ_LOCK;
    osi_Sleep(&lock->readers_reading);
    return 0;
}
*/
