CS333 Lab A-2:
Logical Clocks


A system is distributed if the message transmission delay is not negligible compared to the time between events in a single process.

-- Leslie Lamport, "Time, clocks, and the ordering of events in a distributed system"

Goal of this lab:

Lab Guru:

If you have questions about this lab, you may contact Srihari Sampathkumar (Sam), srihari@cs.wustl.edu, or the instructor.

Introduction:

A distributed system consists of a collection of processes that communicate by passing messages to each other. So, each event in a distributed system is either a local step of a process, a send event, or a receive event. In studying a distributed system, we often need to assign an order to the events. However, since the processes in the system do not have synchronized clocks, the "logical time" order of events in the system does not necessarily agree with the clock times associated with the events at the various processes. For example, we expect a logical view of the system in which the send event for a given message happens before the receive event for that message. However, if the clocks at the sender and the receiver are sufficiently skewed, a clock-based trace of the events might report that the receive occurred before the send.

One approach to this problem is to run algorithms to keep clocks closely synchronized, within some tolerance. However, a simpler approach is to maintain logical clocks at the processes. Logical clocks do not "tick" like real time clocks, but instead keep track of the order of events that occur at each process, and ensure that events are assigned consistent logical times according to the following happens before relation.

We say that event A happens before event B if and only if

  1. A and B occur at the same process (either internal local steps, send events, or receive events) and event A occurs before B at that process, or
  2. A is a send event and B is a receive events for the same message.

We can construct a logical clock algorithm that will assign logical times to all the events in the system in a way that is consistent with the happens before relation, as follows.

Notice that the logical times of events at a given process always increase as the execution proceeds. Furthermore, notice that the logical send time is always less than the logical receive time. The logical times assigned to the events gives us a partial order on all events. Convince yourself that the partial order is consistent with the happens before relation.

Directions:

Read over the entire assignment before starting.

  1. Implement a Logical Clock: Write a Playground module that implements the logical clock algorithm described above. Publish your logical clock so that it's available for visualization in EUPHORIA. Test your implementation by having the modules take internal steps and send messages randomly. Each time an event occurs at a module, have it print out the logical time of the event. Check that the logical times assigned to your events respect the happens before relation.

  2. Use Logical Clocks to Implement Mutual Exclusion: After you have thoroughly tested your logical clock implementation, use it to implement the following resource allocation strategy.

    Consider a collection of processes that contend for a shared resource (such as a file, printer, etc.). It is important that only one process access the resource at a time, or bad things may happen (inconsistent data in the file, garbled printer output, etc.). Therefore, the processes cooperate by running a mutual exclusion protocol to ensure that at most one process has access to the resource at a given time. There are many different approaches to this problem, but the following one exploits the logical clocks you have just implemented.

  3. Convince yourself that the algorithm satisfies the following properties:

    Mutual Exclusion (safety):
    No two processes access the resource simultaneoulsy.
    No Starvation (liveness):
    Provided that any process holding the resource will eventually release it, a process that requests the resource will eventually get it. (Furthermore, it can be bypassed at most once by each other process.)

  4. Exercise your implementation by having the modules periodically request the resource, hold the resource for a short time, and release the resource. Let each module publish a variable indicating whether it is currently waiting for the resource, and another indicating whether it holds the resource. Use these variables to visualize the state of the distributed system in EUPHORIA. Test your implementation thoroughly.

Further Reading:

Logical clocks are described in detail in the following classic paper. This paper is one of the most often cited papers in the distributed computing literature.

Leslie Lamport, Time, clocks, and the ordering of events in a distributed system. Communications of the ACM, Vol. 27, No. 7, July 1978, pp. 558-565.


To receive credit for this lab, you should:

  1. Clean up and print out your code. (Don't turn it in, but save it for your code/design review.)

  2. Turn in a Project Evaluation Form near the beginning of class on the day you want to do your demonstration and code/design review. You should be prepared to demonstrate your working application, explain your design and code, and answer questions.