Don’t Know, But Managed Anyway

I’ve thought about where these sync points come from over the last few days. I still can’t exactly figure it out.

However, I decided to just enable recording at the beginning of the main method, just like I do with replay. Now the sync points line up. There are two sync points that don’t belong to the ones I’m interested in:

1 0 // 000030b6 00000002 sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
2 0 // 000030b6 00000002 sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;

But these occur both during recording and replaying, so that’s not a problem. I still can’t understand why the sync points didn’t match earlier, because I happened to record them but I tagged them as “comments”. I switched from comment to real sync point exactly at the same time I enable recording now. Fortunately, it seems like I don’t have to dig into this mystery right now…

I modified the logs that the CompactDebugProcessor generates to make it compatible with the other logs. As you can see above, all the annotations about class and method index and the decyphered method signature are now behind // as comments. Therefore, the replay application can parse it without modification.

I’ve begun to design the replay scheduler now. It’s turning out to be more complicated than expected. Here’s an outlide:

  1. If the buffer has never been loaded, or if the index is at the end of the buffer…
    1. Load the buffer.
    2. Reset the index.
    3. Notify all threads waiting on the buffer reload Object().
  2. If there’s a thread waiting for this sync point…
    1. Notify the thread so it can continue to run.
    2. Move on to the next sync point.
  3. Repeat this… (RETRY loop)
    1. If the current sync point is the one we look for…
      1. Move on to the next sync point.
      2. Allow the thread to exit the “RETRY” loop.
    2. Otherwise…
      1. Loop over all sync points, starting with the one after the current sync point… (BUFFER loop)
        1. If this is the sync point we are looking for…
          1. Insert a new Object() into the wait array.
          2. Call wait() on that object (make sure to continue waiting if interrupted).
          3. …other threads will continue…
          4. When notified, break out of the “BUFFER” loop and allow the thread to exit the “RETRY” loop.
        2. Otherwise, if this sync point has the same thread ID as the sync point we’re looking for, but a different event code…
          1. Issue a warning: Somehow a thread has missed a sync point.
          2. Undefined behavior after this; maybe disable scheduled replay.
      2. End “BUFFER” loop.
      3. If the “BUFFER” loop went through the entire rest of the buffer without finding the sync point…
        1. Call wait() on the buffer reload Object() (make sure to continue waiting if interrupted).
        2. …other threads will continue…
        3. When notified, do not allow thread to exit “RETRY” loop.
  4. …until the thread is allowed to exit the loop (end “RETRY” loop).

The questions I have on my mind right now are these:

  1. When threads are notified that a new buffer has been loaded, they might all work with the list of sync points simultaneously. This might create race conditions. Are these important? My gut feeling tells me no, because each thread is only looking for one sync points, so the code-threadID pairs may be treated as unique.
  2. When one thread has to wait inside compactWait, which is a synchronized method, can other threads even enter it?

I think I will create a small-scale model outside the entire system to investigate these issues. Now it’s dinner time.


About Mathias

Software development engineer. Principal developer of DrJava. Recent Ph.D. graduate from the Department of Computer Science at Rice University.
This entry was posted in Concurrent Unit Testing. Bookmark the permalink.

Leave a Reply