/*
 * Memory Locking and unlocking functions.
 * VM_Lock :
 *   Check if the lock is 'valid'
 *   'Remove()' it from the reserve list if needed
 *   If the lock is invalid, allocate memory and read the
 *   section from the file.
 *
 * VM_UnLock :
 *   If the lock list contained 10 items, then free the tail.
 *   Move the lock to the reserved list.
 */

#include "vm.h"

/*
 * To 'Lock' an area of VMEM, you must allocate room for the memory, read the
 * file segment into memory, and return the address of the physical memory.
 *
 * This is further confused by the fact that the lock COULD be part of the 
 * reserved list. If so, then it is removed from the list, and does not need
 * to be processed.
 */
void *
VM_Lock(struct VM_Lock *VM_L) {
   ULONG Err ;

   /*
    * Flags == 0 if the lock is flushed.
    */
   if (!( VM_L->VM_Flags & (VM_INUSE|VM_RESERVED)) ) {
      Err = VM_ReadLock(VM_L) ;
      if (Err)
         return NULL ;
      }
   else 
      /*
       * Flags & VM_RESERVED If the lock is in the reserved list.
       */
      if (VM_L->VM_Flags & VM_RESERVED) {
	 /*
	  * Remove the node from the reserved list.
	  */
	 Remove((struct Node *) VM_L) ;
	 /*
	  * Mark the lock as IN_USE.
	  */
	 VM_L->VM_Flags ^= (VM_INUSE|VM_RESERVED) ;
         }

   VM_L->VM_Flags &= ~(VM_READONLY) ;
   return VM_L->VM_Addr ;
   }

ULONG
VM_UnLock(struct VM_Lock *VM_L) {

   ULONG Err ;

   if (VM_L->VM_Flags & VM_INUSE) {
      AddHead( (struct List *) &(VM_L->VM_C->VM_LockList) , (struct Node *) VM_L );
      VM_L->VM_Flags ^= (VM_RESERVED|VM_INUSE) ;
      VM_L->VM_C->VM_NumLocks ++ ;

      if (VM_L->VM_C->VM_NumLocks > 10) {
         Err = VM_FlushLock((struct VM_Lock *)
	                    (VM_L->VM_C->VM_LockList.mlh_TailPred)) ;
         return Err ;
         }
      }

   return 0 ;
   }

void
VM_ReadOnly(struct VM_Lock *VM_L) {

   if (VM_L->VM_Flags & VM_INUSE)
      VM_L->VM_Flags |= VM_READONLY ;
   }
