I would do this as follows:
1. thread/process one, real user interface that maps X api calls to memory mapped IO in block of memory.
2. thread/process two, a CPU emulator that just continually runs the fetch/execute cycle using the same block of memory as it's address space.
3. Signals delivered to the second process I mentioned count as interrupts to the processor, eg the signal handler causes the emulated CPU to emulate an interrupt
4. the UI thread/process responds to notifications from the CPU thread/process.
5. In the CPU thread/process everytime a memory access occurs on a guarded piece of memory notify the UI process, this can be done by doing an AND/XOR on every address to which a write is done, if the result is zero then signal the UI process.
This could either be done as a single process with two threads, or a pair of processes with shared memory to act as the memory space of the emulated CPU.
