/*
 * (C) Copyright IBM Corp. 2002
 */
//$Id: Lock.java,v 1.4 2004/01/28 22:08:30 pmcgache Exp $

package s3.core.services.memory.vmInterface;

import ovm.core.services.threads.OVMDispatcher;
import ovm.core.stitcher.ThreadServiceConfigurator;
import ovm.core.stitcher.ThreadDispatchServicesFactory;
import s3.core.services.memory.JMTk.VM_Uninterruptible;

/**
 * Simple, fair locks with deadlock detection. The implementation mimics a
 * deli-counter and consists of two values: the ticket dispenser and the
 * now-serving display, both initially zero. Acquiring a lock involves grabbing
 * a ticket number from the dispenser using a fetchAndIncrement and waiting
 * until the ticket number equals the now-serving display. On release, the
 * now-serving display is also fetchAndIncremented. This implementation relies
 * on there being less than 1 <<32 waiters.
 * @author Perry Cheng
 * @author Christian Grothoff (adaptation to OVM, cutting out debugging code to
 *         simplify)
 * @version $Revision: 1.4 $ @date $Date: 2004/01/28 22:08:30 $
 */
public class Lock implements VM_Uninterruptible {

    private int dispenser; // ticket number of next customer
    private int serving; // number of customer being served
    private final OVMDispatcher disp_;

    public Lock(String str) {
        dispenser = serving = 0;
        this.disp_ =
            ((ThreadDispatchServicesFactory) ThreadServiceConfigurator
                .config
                .getServiceFactory(ThreadDispatchServicesFactory.name))
                .getThreadDispatcher();
    }

    // Try to acquire a lock and spin-wait until acquired.
    public void acquire() {
        int ticket =  dispenser++;
        //TODO: dispenserFieldOffset++;
        // This IS atomic in OVM since we are uni-processor AND there is no
	// scheduling point in the generated bytecode sequence!
        while (ticket != serving)
	  disp_.yieldCurrentThread();
    }

    public void check(int w) {
    }

    // Release the lock by incrementing serving counter.
    public void release() {
      serving++;
        //TODO:??? servingFieldOffset++;
        // This IS atomic in OVM since we are uni-processor AND there is no
	// scheduling point in the generated bytecode sequence!
    }

    /**
     * 
     */
    public static void fullyBooted() {
        // TODO Auto-generated method stub
        
    }

} // end of Lock
