Reading the Wikipedia article about real-time computing, I found written that:

Once when the MOS Technology 6502 (used in the Commodore 64 and Apple II), and later when the Motorola 68000 (used in the Macintosh, Atari ST, and Commodore Amiga) were popular, anybody could use their home computer as a real-time system.

The next sentence elaborates a little on that claim:

The possibility to deactivate other interrupts allowed for hard-coded loops with defined timing and the low interrupt latency allowed the implementation of a real-time operating system, giving the user interface and the disk drives lower priority than the real-time thread.

After this they are contrasted with the modern CPUs and operating systems depending on them:

Compared to these the programmable interrupt controller of the Intel CPUs (8086..80586) generates a very large latency and the Windows operating system is neither a real-time operating system nor does it allow a program to take over the CPU completely and use its own scheduler, without using native machine language and thus surpassing all interrupting Windows code.

Could someone elaborate a bit more on this information and give some examples for "deactivating other interupts" and "hard-coded loops with defined timing" to clear what it exactly means and to give some additional reasons with appropriate examples, if any?

  • 5
    I don't think it has nothing to do with the CPU at all, or even the interrupt controller, but running on a real-time OS or on bare metal without OS at all, and Windows is not a real-time OS. If you make a 8086 system that runs with code on ROM and data on SRAM, it would be a very real time system, as not even DRAM refresh would steal CPU cycles. – Justme Oct 16 at 18:25
  • 27
    Real-time systems aren't about the latency - it just needs to be low enough. It's mostly about the predictability. The jitter in the latency, if you will. So controlling every aspect of execution so that timing predictions are accurate and consistent... – Brian H Oct 16 at 18:40
  • 6
    A 8086 to 80586 CPU isn't any more "modern" than a 68k CPU - they were contemporary. – tofro Oct 16 at 19:42
  • 3
    That Wikipedia article seems to mix up interrupt architecture and OS structure, The second is irrelevant, you don't use a non-real-time OS if you want real-time response. But the paragraph in question is about "using your home computer", so perhaps their self-imposed restriction is using it with the vendor-supplied OS. – another-dave Oct 16 at 22:35
  • 1
    I think "modern" doesn't belong in the question title. Nothing about the body of the question seems to relate to what I would call "modern" x86 (really x64 but that's just confusing) processors. For one thing, the PIC mentioned in the quotes has been superseded by a much more sophisticated system. For another, the clock speeds and parallel processing cores in a modern Intel compatible CPU means you can't really compare with a 68000 series architecture any more. – Todd Wilcox Oct 17 at 3:51

On a typical 6502, Z80, or 68000 system, it's possible to predict very precisely exactly how long a piece of code will take to execute. The same is true, incidentally, of many small microcontrollers produced today. In many cases, this allows some operations to be done more efficiently than would otherwise be possible.

For example, if both function-control latches are set, the Apple's Disk II controller card will, once every four cycles, grab whatever happens to be on the CPU bus into its shift register for transmission to disk. To output a stream of data, the CPU must compute each byte byte, write it to a register which turns on control latch #1 [this operation takes four cycles, and will both set the latch and put the proper value on the data bus during the fourth cycle], and then turn off control latch #1 [which also takes four cycles, clearing the latch on the fourth cycle], then compute the next byte and repeat the sequence, with each byte's "set control latch #1" operation starting exactly 32 cycles after that of the previous byte. Disk-writing code wouldn't include any data to check whether the controller is ready for a byte of data; instead, it would blindly expect that if latch #1 is on and #2 is off, the controller will look for data at a fixed intervals starting a certain amount of time after latch #2 turns on.

On modern CPUs, out-of-order execution, memory caching, and many other features will improve the speed with which many operations are performed, most of the time, but predicting how much the speed will be improved would often be impractical. If code accesses a piece of memory that had not been accessed in a long time and wasn't in a region of fast memory called the cache, the access would need to be performed using slow memory, but the data would get copied to the cache so that if it's needed again soon, it can be fetched more quickly--often more than an order of magnitude faster. Because the cache is much smaller than main memory, however, data which is in the cache but hasn't been used for awhile will often need to be displaced to make room for other data. Although it's unlikely, one may end up with situations where the CPU repeatedly selects for displacement information that's about to be used again. Fetching data from memory in a sequence that causes that to occur may take an order of magnitude longer than fetching that same data in a slightly different sequence.

On systems using a simple processor or controller, in most cases where the CPU would usually be significantly faster than needed to accomplish what needs to be done, one could establish that it will always be at least fast enough. There may be some timing uncertainties with regard to how long it will take to handle an event if some other event happens simultaneously, but it's usually possible to compute worst-case timings and will be fairly close to what could realistically occur. On fancier high-performance machines, however, it may be possible to guarantee that timing targets will be met unless more than 50% of memory accesses in a stretch of code result in cache misses, and one may determine that it would be unlikely for even 20% of the accesses to result in cache misses, but it may be very hard to prove that no sequence of inputs could cause 80% or more of the accesses to result in cache misses, which could in turn prevent a program from meeting a timing deadline.

| improve this answer | |

This paragraph in Wikipedia really is no candidate for the best entry-of-the-year award. It seems to be comparing Apples with Oranges. (Or rather starts talking about CPUs, then commences on PCs vs. "something else", i.e. system architecture). A comparison of interrupt latency and predictability thereof doesn't make much sense on CPU level - It must be done on system level, as all components of a system can affect this timing and need to be taken into account for comparison.

Wikipedia seems to have realized that and warns you with a "largely unverified" banner. So, take it with a grain of salt (or, rather, a spoonful).

While it is true that the 8259 in a PC (contemporary to the mentioned 68k and 6510, not a modern one) adds some overhead to the interrupt latency, this is not at all a trait of the x86 CPU, but rather one of the IBM PC's architecture. You can easily add an interrupt controller to a 68k system and it will add the same latency there. Lots of 68k computers BTW did that - The Atari ST (with its MFP) and the Amiga, had both interrupt and DMA controllers that introduced similar latency and bus contention overheads.

Intel's x86 architecture can just as well be used for real-time applications - and this has been done successfully in the past - many embedded systems were based on 80186 and 80386 CPUs - just not on an IBM PC architecture.

MS Windows didn't help much as well, so it was out of the question for running realtime applications - But there were (and are) quite some real-time OS for x86, like QNX or VxWorks, and there are even real-time Linux derivates for x86 CPUs.

Of the three computers mentioned, the Commodore Amiga is probably the computer with the least predictable interrupt latency - Its custom chips are allowed to take over and occupy the bus for a significant and relatively unpredictable amount of time (length of a possible DMA access is of concern here).

Taking superscalar traits of a CPU (like out-of-order-execution, parallel instruction execution, branch prediction, caches,...) into the argument (started with the Pentium on Intel's range of CPUs), still doesn't distinguish the Intel CPU range as particularly bad - Motorola had, with the 68060, very similar technology in its portfolio with very similar consequences on predictability (obviously, there is no 6502 derivate with such features).

Some more comments on the Wikipedia paragraph:

On ...anybody could use their home computer as a real-time system.:

Well, yes and no. To my knowledge, there was no real-time multitasking OS available for any of the mentioned home computers other than the Atari ST, which had OS-9 and RTOS-UH, both respectable RTOSs. So, using any other such HC as a real-time system required you to write your OS from scratch - Not a task for the faint-hearted, and not distinguishing these computers at all from x86-based computers - you could have done the very same thing there.

On ... possibility to deactivate other interrupts allowed for hard-coded loops with defined timing and the low interrupt latency

Deactivating interrupts and hard-coded tight loops are both definite no-nos for real-time systems. This seems to be eluding to "racing-the-beam" applications and other tight synchronisation to video timing techniques, mainly used in the home computer demo scene. While those techniques are definitly closely dependant on timing, they are basically the opposite of a real-time system - as they hog the CPU for quite a long time for one single task, like busy-waiting until the CRT beam reaches some definite position. This indeed does rely on low interrupt latency, but also heavily increases latency for anything else. Nonwithstanding that, there is no reason you couldn't do the same thing on an x86-based computer (maybe not the IBM PC, again because of its architecture)

| improve this answer | |
  • I know the 8259 best out of all the components mentioned here, but with my limited knowledge this answer rings the truest for me. Certainly I've studied the 586 architecture pretty well, and even have some experience (back in the before times) with an Amiga 3000UX with a 68030, what we might today call a rudimentary GPU, and asynchronous busses, and all I know tells me that the chipset used around a CPU has a huge impact in how the overall system works. – Todd Wilcox Oct 17 at 3:57
  • 1
    Deactivating interrupts also allows for bit-banging I/O with well defined timing, and for deterministic response times when polling a port. – Michael Graf Oct 17 at 10:36
  • @MichaelGraf ... while it kills any deterministic response times for everything else. Nothing comes for free. – tofro Oct 17 at 12:43
  • 2
    Many home computers were used as hard real-time systems when doing home-computer tasks such as writing or reading data from/to tape or (on the Apple II series) disk. Even an unexpected one-cycle delay while writing a disk sector on the Apple II would totally corrupt all the data thereon. – supercat Oct 17 at 16:53
  • I encountered an old product our company had that did hard-realtime work on MS-DOS. The built the realtime scheduler into the application. – Joshua Oct 18 at 18:45

It's the simplicity.

Under modern general purpose operating systems, you don't usually have hard real-time guarantees. Too many things are going on. Context switching is slow. Interrupts are slow. The kernel is often not fully pre-emptable.

On top of all that, modern hardware incorporates features like speculative execution, extensive pipelining, multiple levels of cache and other features that make instruction execution timings very complex. It can be impossible to predict instruction timing, except to give an upper limit.

This means that, if you have a process running on a Linux system in a tight loop, you don't know when the next instruction will run. It could be in 2 nanoseconds, in 2 microseconds, or in 2 milliseconds.

On a 6502 running at 1 MHz, you know it takes exactly 2 microseconds to execute a CLC instruction. You can trace your code lock-step with real-time if you want.

There is no real barrier to that level of control on a modern x86 machine in principle; it's just very complicated compared to the simplicity of simpler machines.

| improve this answer | |
  • 1
    Getting exactly-known execution time on modern x86 (to avoid timing jitter as @Brian H commented) could means burning a lot of those very short clock cycles checking an accurate timesource to make the normal case run at the same speed as the worst case for cache misses, branch mispredicts, or whatever. e.g. this rdtsc deadline spin loop (under a non-Linux OS, or on an isolated core). – Peter Cordes Oct 17 at 14:41

There are three principal reasons:

1: Realtime software demands CPUs whose execution time is highly predictable. That is true mostly of CPUs without speculative features such as caching and dynamic branch prediction. Some modern CPUs (eg. ARM Cortex-R series) are specifically designed to provide this property.

2: Low interrupt latency and overhead, on the order of a single-digit cycle count. This is a feature of the 6502 (which has a maximum interrupt latency of about 15 cycles to the first instruction in the ISR, and a minimum of one cycle if correctly prepared with the WAI instruction) and the ARM (which has a dedicated alternate register bank for handling FIRQs, eliminating the overhead of saving registers to stack), but decidedly not of the 68000 and x86 families. The 68000 and 68020 are sometimes used where interrupt latency is less of a concern.

3: Ability to run at "micropower", ie. less than a milliwatt, in embedded applications that demand extremely long battery life, sometimes on the order of several years (eg. 6502s are used in pacemakers). This practically demands a "fully static" CMOS implementation. Current production 6502 and ARM CPUs can achieve that in practice; your average x86 CPU and its auxiliary hardware eats several watts at full idle sleep.

| improve this answer | |
  • 5
    I can't see why low power consumption is a precondition for suitability in real-time applications. It might be for some embedded systems, but has nothing to do with real-time performance. – tofro Oct 17 at 8:27
  • 6
    @tofro High-performance CPUs, especially modern x86 designs, typically can't go from sleep mode to full execution instantaneously, because they have to go through power gating and clock frequency settling steps which, under ideal conditions, take milliseconds. A CPU which can sit at full nominal clock speed without consuming any significant power is ready to do useful work in less than a microsecond from a standing start. – Chromatix Oct 17 at 11:19
  • 1
    No, soundly engineered realtime systems do not depend on predictable execution time, but only on boundable time, as they use hardware timers for the precise part. Things like reduced power modes only come into it if system software uses them; a typical mains-powered real time system would not, but would rather run the processor at a suitable performance tier all the time. – Chris Stratton Oct 19 at 17:38
  • @ChrisStratton Verifying that the execution time will always be within the bounds over the life of the system requires that the execution time is consistent, hence predictable. It is possible to implement branch prediction and caching in ways that do not result in unpredictable variations in performance, and that is what Cortex-R does. But a CPU that lacks those features entirely is even more predictable. – Chromatix Oct 20 at 0:49
  • @ChrisStratton Let's suppose you have an algorithm that needs to run in bounded time. You test the execution time many times, and it does in fact run within that time under test. But you tested it on an unloaded system, so the branch predictors and caches remain primed for the algorithm between runs. After transferring to a loaded system, the predictors and caches are re-primed for these other loads, and memory bandwidth is occupied by other threads, so sometimes your algorithm takes significantly longer. That's the problem. – Chromatix Oct 20 at 0:54

While many of the performance capabilities of modern desktop processors intended to run multi-tasking operating systems are somewhat wasted in a real time context, they are not actually impediments.

A soundly designed real time operating system uses hardware timers for the precise timing needs in terms of scheduling when code runs. Desktop operating systems typically have trouble performing to the true capability of the hardware, though there are various strategies for altering scheduling to prioritize certain tasks; at an extreme, a hard realtime schedular can own the actual hardware, and run the kernel of a conventional multi-tasking operating system as its lowest priority task. Most of the software architecture problems inherent in using commodity desktop hardware for real time control are thus solvable. Ad

However, most modern commodity computer boards are ill-suited for realtime control for another reason: the lack of low-latency I/O, at least in any easily interfaced form. Once local-bus I/O channels like true parallel ports were replace by things proxied through multiple levels of protocol indirection (USB being the notorious case) it became far harder for even carefully engineering code to interact with the external world in a timely fashion.

What's fundamentally different about a modern ARM SoC or MCU that is suitable for real time applications, vs a typical x86 desktop platform that is not, is the provision of simple I/O schemes directly from the processor, eg, memory-mapped GPIOs, hardware timers with input/output channels, etc. Nothing says that a part with a computational architecture in the x86 tradition could not have these (and indeed, from time to time vendors try an offering...) but these tend to lose in the marketplace, both to the flash-based ARM parts suitable for small problems, and the more tablet/router-class ARM/MIPS/etc SoC's used for larger ones.

Typically what this all points to is the use of an distinct processor for real time tasks. Some modern control-oriented SoC's even include one right on chip; in the PC world the existence of I/O copressors goes right back to the start and far simpler problems, eg, the original IBM PC has an early MCU on it simply to deal with the keyboard interface (and another in the keyboard) and the presence of additional processor continues to this day. In the control realm, it's common to see things like a 3d printer which has a realtime G-code interpreter running in a small flash based MCU, and then a larger platform like PC or raspberry pi (or an ESP8266 talking to an Android tablet) which then provides a user interface and drip-feeds stored programs just ahead of need. This not only solves the I/O latency problem, it also simplifies software by having the real-time and non-real-time code run on entirely separate computational engines, rather than having to fight over a single execution core.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.