diff --git a/Makefile.target b/Makefile.target
index 962d004..8956afe 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -131,7 +131,7 @@ endif #CONFIG_BSD_USER
 #########################################################
 # System emulator target
 ifdef CONFIG_SOFTMMU
-obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
+obj-y += arch_init.o qqq.o cpus.o monitor.o gdbstub.o balloon.o ioport.o
numa.o
 obj-y += qtest.o bootdevice.o
 obj-y += hw/
 obj-$(CONFIG_KVM) += kvm-all.o
diff --git a/cpus.c b/cpus.c
index 877bd70..b040285 100644
--- a/cpus.c
+++ b/cpus.c
@@ -44,6 +44,8 @@
 #include "hw/nmi.h"
 #include "sysemu/replay.h"

+#include "qqq.h"
+
 #ifndef _WIN32
 #include "qemu/compatfd.h"
 #endif
@@ -998,7 +1000,12 @@ static void qemu_tcg_wait_io_event(CPUState *cpu)
        /* Start accounting real time to the virtual clock if the CPUs
           are idle.  */
         qemu_clock_warp(QEMU_CLOCK_VIRTUAL);
-        qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
+       /* If qqq is running then this wait must timeout so that the
+        * simulation does not become stuck when the cpu idles */
+        if (qqq_enabled())
+            qemu_cond_wait_timeout_ns(cpu->halt_cond, &qemu_global_mutex,
10000);
+        else
+            qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
     }

     while (iothread_requesting_mutex) {
diff --git a/include/qemu/thread.h b/include/qemu/thread.h
index 5114ec8..c0f6009 100644
--- a/include/qemu/thread.h
+++ b/include/qemu/thread.h
@@ -36,6 +36,14 @@ void qemu_cond_destroy(QemuCond *cond);
 void qemu_cond_signal(QemuCond *cond);
 void qemu_cond_broadcast(QemuCond *cond);
 void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex);
+/* This defaults to qemu_cond_wait() on Windows */
+#ifndef _WIN32
+void qemu_cond_wait_timeout_ns(QemuCond *cond, QemuMutex *mutex, int64_t
timeout_ns);
+#else
+void qemu_cond_wait_timeout_ns(QemuCond *cond, QemuMutex *mutex, int64_t
timeout_ns) {
+  qemu_cond_wait(cond,mutex);
+}
+#endif

 void qemu_sem_init(QemuSemaphore *sem, int init);
 void qemu_sem_post(QemuSemaphore *sem);
diff --git a/qqq.c b/qqq.c
new file mode 100644
index 0000000..5c2a786
--- /dev/null
+++ b/qqq.c
@@ -0,0 +1,101 @@
+
+/* This is a Linux only feature */
+
+#ifndef _WIN32
+
+#include "qemu/main-loop.h"
+#include "qemu/timer.h"
+#include "qemu/thread.h"
+#include "sysemu/cpus.h"
+#include <stdio.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <unistd.h>
+#include <pthread.h>
+#include "qqq.h"
+
+/* Shared memory data */
+static void* shm = NULL;
+static int64_t t = 0;
+static QEMUTimer* sync_timer = NULL;
+
+static void write_mem_value(int val)
+{
+  /* I AM ASSUMING THE MEMORY WRITE WILL BE ATOMIC AND WILL
+   * NOT BE CACHED */
+  (*((volatile int*)shm)) = val;
+}
+
+static int read_mem_value(void)
+{
+  /* I AM ASSUMING THE MEMORY READ WILL BE ATOMIC AND WILL
+   * NOT BE CACHED */
+  return (*((volatile int*)shm));
+}
+
+static void schedule_next_event(void)
+{
+  int time_advance;
+  /* Get the time advance allowed by the simulator. This is provided
+   * as a positive value that is written by the simulator to the
+   * shared memory location. */
+  while ((time_advance = read_mem_value()) < 0);
+  /* A zero time advance is an instruction to shutdown */
+  if (time_advance == 0)
+  {
+    munmap(shm,sizeof(int));
+    exit(0);
+  }
+  /* Schedule the next syncronization point */
+  timer_mod(sync_timer,t+time_advance);
+}
+
+static void sync_func(void* data)
+{
+  /* Report the actual elapsed time. The value written will be
+   * -(elapsed time), and the simulator will recognized the negative
+   * value as a signal that the write has been done. */
+  int64_t tnow = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
+  int usecs = tnow-t;
+  write_mem_value((usecs > 0) ? -usecs : -1);
+  /* Update our time of last event */
+  t = tnow;
+  /* Schedule the next event */
+  schedule_next_event();
+}
+
+bool qqq_enabled(void) { return (shm != NULL); }
+
+void setup_qqq(void)
+{
+  char shm_key[100];
+  /* Attach to the shared memory region */
+  sprintf(shm_key,"/qemu_%d",getpid());
+  errno = 0;
+  int fd = shm_open(shm_key,O_RDWR,S_IRWXU);
+  if (fd == -1)
+  {
+    perror("Could not open shared memory, qqq not enabled");
+    return;
+  }
+  shm = mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
+  if (shm == NULL)
+  {
+    perror("Could not map shared memory, qqq not enabled");
+    shm_unlink(shm_key);
+    return;
+  }
+  /* Done with the shared memory file handle */
+  close(fd);
+  shm_unlink(shm_key);
+  /* Start the timer to ensure time warps advance the clock */
+  sync_timer = timer_new_us(QEMU_CLOCK_VIRTUAL,sync_func,NULL);
+  /* Get the time advance that is requested by the simulation */
+  schedule_next_event();
+}
+
+#endif
diff --git a/qqq.h b/qqq.h
new file mode 100644
index 0000000..687a9f3
--- /dev/null
+++ b/qqq.h
@@ -0,0 +1,67 @@
+/*
+ * A module for pacing the rate of advance of the computer clock
+ * in reference to an external simulation clock. The basic approach
+ * used here is adapted from QBox from Green Socs (hence the name, Q?
+ * Q? Q? - qqq!). The basic mode of operation is as follows:
+ *
+ * The simulator creates a shared memory of size sizeof(int) that will be
+ * used to exchange time advance information, writes a negative value
+ * to that shared memory segment, and then forks a process
+ * to execute qemu. Qemu attaches to this shared memory segment using
+ * a key that includes the PID of the forked child (see qqq.c for the
+ * expected shared memory key).
+ *
+ * Qemu waits for a positive to appear in the shared memory. Meanwhile
+ * the simulator writes a positive value to indicate the maximum time
+ * advance that it allows to qemu. When qemu receives this positive value
+ * it schedules a timer event for time advance microseconds in the future.
+ *
+ * Now the simulator spins on the shared memory value waiting for it to
become
+ * negative. When qemu executes the scheduled timer event, qemu writes a
+ * negative value indicating the actual time advanced. At this time, the
simulator
+ * is able to run again and this cycle is repeated until the simulation
ends.
+ *
+ * Authors:
+ *   James Nutaro <nutarojj@ornl.gov>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#ifndef QQQ_H
+#define QQQ_H
+
+/* This is a Linux only feature */
+
+#ifdef _WIN32
+
+/* Windows functions that do nothing */
+static inline bool qqq_enabled(void) { return false; }
+static inline void setup_qqq(void){}
+
+#else
+
+/* The Linux implementation */
+
+#include "qemu/main-loop.h"
+#include "qemu/timer.h"
+#include "qemu/thread.h"
+#include "sysemu/cpus.h"
+#include <stdio.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <unistd.h>
+#include <pthread.h>
+
+void setup_qqq(void);
+/* Returns true if qqq is enabled and false otherwise.
+ * It will be enabled only if setup_qqq() is able to
+ * attach to the shared memory segment. */
+bool qqq_enabled(void);
+
+#endif
+#endif
diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
index dbd8094..c6396c4 100644
--- a/util/qemu-thread-posix.c
+++ b/util/qemu-thread-posix.c
@@ -134,6 +134,20 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
         error_exit(err, __func__);
 }

+void qemu_cond_wait_timeout_ns(QemuCond *cond, QemuMutex *mutex, int64_t
timeout_ns)
+{
+    static const long ns_sec = 1000000000LL;
+    struct timeval tv;
+    struct timespec ts;
+    int err;
+    gettimeofday(&tv, NULL);
+    ts.tv_sec = tv.tv_sec + (timeout_ns + tv.tv_usec*1000) / ns_sec;
+    ts.tv_nsec = (timeout_ns + tv.tv_usec*1000) % ns_sec;
+    err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts);
+    if (err != 0 && err != ETIMEDOUT)
+        error_exit(err, __func__);
+}
+
 void qemu_sem_init(QemuSemaphore *sem, int init)
 {
     int rc;
diff --git a/vl.c b/vl.c
index 21e8876..8a2facc 100644
--- a/vl.c
+++ b/vl.c
@@ -125,6 +125,8 @@ int main(int argc, char **argv)
 #include "sysemu/replay.h"
 #include "qapi/qmp/qerror.h"

+#include "qqq.h"
+
 #define MAX_VIRTIO_CONSOLES 1
 #define MAX_SCLP_CONSOLES 1

@@ -4402,6 +4404,9 @@ int main(int argc, char **argv, char **envp)
     /* spice needs the timers to be initialized by this point */
     qemu_spice_init();
 #endif
+    /* try to setup the qqq interface for syncing advance of the virtual
clock
+     * with an external simulator */
+    setup_qqq();

     cpu_ticks_init();
