4 ms·
A MMU is not needed for multi-tasking, but it is needed for memory protection. I wonder how well a system could work if its binaries were written on a bytecode
by marcodiego 6y ago
A MMU is not needed for multi-tasking, but it is needed for memory protection. I wonder how well a system could work if its binaries were written on a bytecode that could be compiled to safe native code, making sure that it would not access non-permitted memory. This bytecode would be compiled at program load time. This could guarantee memory safety and a very small performance penalty.
- pjmlp 6y agoPlenty of mainframes have worked like that. IBM mainframes still do on their classical mode, the bytecode gets AOT compiled at installation time, or when the binaries need to be refreshed due to changes on the hardware. Burroughs B5500, nowadays still sold by Unisys as ClearPath MCP, was already doing this in 1961.
- skissane 6y ago> IBM mainframes still do on their classical mode, the bytecode gets AOT compiled at installation time, or when the binaries need to be refreshed due to changes on the hardware. I suspect in this comment you are confusing IBM i and its predecessors (i5, AS/400, System/38) with IBM mainframes (z, 390, 370, 360). The former do what you are talking about, the later don't. In proper IBM terminology, the former are called midrange systems, not mainframes.
- pjmlp 6y agoNope, IBM z still has language environments, and I call all of them mainframes, instead of precise definitions, because everyone without experience has a vague idea what a mainframe is, whereas midrange systems, most likely requires a Wikipedia visit for most of the audience.
- skissane 6y ago> Nope, IBM z still has language environments What are you talking about? When you say "IBM z", which OS are you talking about – z/OS, z/VM, z/VSE, z/TPF or z/Linux? Which "language environments" are you referring to? Do you mean "z/OS Language Environment"? That doesn't involve "bytecode" in the sense that OPM/EPM/ILE on OS/400 do. LE (on z/OS, z/VM and z/VSE) and ILE (on OS/400) are descendants of the same code base (and I believe that code base was even ported to OS/2 at one point), but ILE on OS/400 does some very OS/400-specific things which never happened on MVS, VM/CMS, DOS/VSE or OS/2. You started out by saying: > IBM mainframes still do on their classical mode, the bytecode gets AOT compiled at installation time, or when the binaries need to be refreshed due to changes on the hardware. That is kind of true for IBM i, but just false for IBM z. > I call all of them mainframes, instead of precise definitions, because everyone without experience has a vague idea what a mainframe is, whereas midrange systems, most likely requires a Wikipedia visit for most of the audience. While "midrange" is a bit of an obscure IBMism, most people have heard of "minicomputer", and have the historic understanding of a "minicomputer" as something in between a microcomputer and a mainframe. I think "minicomputer" would be more accurate than "mainframe" when referring to the S/38 and its successors. Calling the later "mainframes" is just going to confuse anyone familiar with the proper IBM terminology. I get the impression you like to make comments like "IBM did X years before this did" but they make you come across as someone opining on something they don't know a lot about, and you end up saying things which make people who know more about the topic than you do cringe.
- pjmlp 6y agoI hit a nerve, as you wish.
- kragen 6y agoEUMEL, Oberon, Smalltalk-80 (including Squeak), and Cedar worked in approximately this way, but they did not have "a very small performance penalty". Modern browsers mostly do, with JS and wasm, but backstop compiler security (historically pretty iffy) with the MMU. eBPF in Linux is another go at the mule.
- Volt 6y ago>they did not have "a very small performance penalty" Can you clarify what kind of penalty it had then?
- kragen 6y agoDoubt anyone can.
- retrac 6y agoMesa/Cedar, early Smalltalk, and Oberon are/were all primarily interpreted languages. And this was before JIT was common. So, significant overhead. Some of them had special hardware assists, like Mesa and the Xerox Alto with a processor designed around the language. Still not a speed demon, despite that. I believe they were more concerned with code density than speed. Cramming a networked multitasking operating system into about 128 KB of RAM is not trivial. Such languages would be pretty painful on another architecture implemented as interpreters. I don't have exact numbers. But roughly an order of magnitude slower. Think Perl and Python vs. Pascal and C. Things have changed a bit since then. Oberon is usually compiled to native code now and Squeak uses a JIT compiler. And Mesa/Cedar are extinct.
- kragen 6y agoHmm, I think Cedar and Oberon compiled to native code from very early on, perhaps the very beginning (I don't know of an interpreted version of either), and the reason I mentioned Smalltalk-80 in particular was Deutsch & Schiffman 01983 where they popularized JIT compilation and in particular introduced the first version of the inline-cache technique that makes Java monomorphic (and non-megamorphic) method calls fast today. To quibble about one more thing, multitasking doesn't increase memory requirements significantly on anything big enough to run an interpreter. On this amd64 machine under Linux, sizeof(jmp_buf) is 200 bytes; that's how much space each new task would needs, plus of course the size of its stack. If I build for i386, it's 156 bytes. But of course you can define the calling convention to reduce this: on 16-bit Forth systems a suspended (cooperative!) thread was typically a data stack pointer, a return stack pointer: 4 bytes. (But typically each thread had its own dictionary of at least 4K.) Preemptive multitasking generally requires at least the size of the register file, since you can't discard caller-save registers on every context switch. What does increase memory requirements enormously is memory protection — not mere multitasking but allocating exclusive segments or pages to each new program. That's a big part of the appeal of systems like Oberon, Smalltalk-80, and of course early Oak/Java: by implementing memory protection at the language level rather than the hardware level, you could get very fine-grained memory sharing without endangering system stability.
- qu4z-2 6y agoReminds me of Microsoft Research's work with software isolated processes[0] (SIPs). [0]: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/osr2007_rethinkingsoftwarestack.pdf https://www.microsoft.com/en-us/research/wp-content/uploads/... Edit: Fine, I'll put the link in a footnote.
- retrac 6y agoYou may just want to run a little bytecode interpreter, period. This was the approach used to implement many languages on the 6502 and other 8-bitters. UCSD Pascal comes to mind, but I know it was used to implement some C versions as well. Those architectures are just so painful for generating reasonable code, mostly with regards to size, that a clean 16 bit VM starts looking attractive. Memory use is often more critical than speed on an 8-bitter, and for large applications even with the interpreter the bytecode is almost always smaller. And if you're doing a full VM, it's not too painful to add a memory protection check. One can sustain about 5 - 10K virtual instructions a second on a 6502 @ 1 MHz. As insanely inefficient as this all sounds, it was actually done back in the day. One notable example would be the old Business Operating System which was basically a bytecode interpreter glued to a small multitasking operating system. All the compilers and applications and most of the OS itself ran in interpreted bytecode.
- codebje 6y ago> As insanely inefficient as this all sounds, it was actually done back in the day. Java, Python, Perl, Ruby, and a host of others say this isn't a dead technique. Another reason for it back then was to only need to port the interpreter to each different architecture and platform, an important consideration in the 80s with the bloom of CPUs and machines.
- tachyonbeam 6y agoIn a language without pointers, you don't need to do anything fancy. Your program just doesn't get any references to objects from other processes, and it can't touch what it can't see. In a language like C, you would need some kind of bounds-checking to make sure addresses live within the correct range, which, if you're going to implement without hardware support, is going to be dog slow, unless you can optimize some of them away with the compiler. However, either way, hardware memory protection adds another layer of safety/security, just like the no-execute (NX) bit. It makes it harder for attackers to hijack your VM, and also less likely that a program, because of a bug in your VM, could crash other processes or even the kernel.
- q-big 6y ago> A MMU is not needed for multi-tasking, but it is needed for memory protection. For memory protection, you don't need an MMU; an MPU (memory protection unit) suffices: https://en.wikipedia.org/w/index.php?title=Memory_protection_unit&oldid=951074029 https://en.wikipedia.org/w/index.php?title=Memory_protection...
- scoutt 6y agoMMU is mostly for managing virtual memory. Memory protection is "kind of" a consequence. Most RTOSes out there work just fine even without MMU or MPU.
- MisterTea 6y agoThe Inferno operating system released in 1996 does this. It was designed to run on anything from light weight mmu-less bare metal embedded with no graphics to full fledged PC class hardware. It included a hosted mode where the kernel is built as a program that runs on plan 9, unix, unix-likes, and windows. The kernel is a vm with no way to implement native code unless you add it to the kernel. Since everything runs in the dis vm you can have a truly portable os where the same program that runs on a headless embedded mips box will run unmodified in hosted inferno on an x86 Linux machine. Unfortunately it does not yet run on x86-64 due to dis having hard coded 32bit constraints. However, someone is actively working on that little issue. http://inferno-os.org/ http://inferno-os.org/ A fork that aims to make inferno easier to run out of the box and develop on: https://code.9front.org/hg/purgatorio/ https://code.9front.org/hg/purgatorio/