Memory Segmentation in the x86 platform and elsewhere
Posted: Fri Feb 03, 2017 10:53 am
I have collected the (recent) discussions on memory segmentation from previous threads to move it out of the 'architectural lowest common denominator' discussion. I think that this needs to be aired, and I would like to give rdos a chance to both address standing critiques (including my own) and present his case for segmentation.
Now, to anticipate one particular point, I should mention that in the end, the decision is rdos's, not ours. I am asking this mainly to understand his reasoning, and see if it applies more generally, but for RDOS itself, it is his call, and in this particular case, he had reasons why (in particular) AMD64/EMT64 support isn't relevant to the system's immediate future.
---------------------------------------
From Why do people say C is better than Assembly?:
From "What features can I rely on the existence of across arch":
Now, to anticipate one particular point, I should mention that in the end, the decision is rdos's, not ours. I am asking this mainly to understand his reasoning, and see if it applies more generally, but for RDOS itself, it is his call, and in this particular case, he had reasons why (in particular) AMD64/EMT64 support isn't relevant to the system's immediate future.
---------------------------------------
From Why do people say C is better than Assembly?:
rdos wrote:From my point of view, the major reason why C sucks for OS development is that it cannot handle segmentation properly, and thus any C coded OS always rely on paging and IPC, which is horribly slow, or use a memory model that can easily create errors that never will be detected and that lies in the kernel as latent bombs.
So, the argument really isn't if hand-coded assembly is faster than an optimizing C compiler, but if a micro-kernel design with lots of TLB shootdowns and context switches ever can beat a monolithic kernel written in assembly using segmentation, which I think it never can. So the C people continue with their flat monolithic kernels that are prone to memory corruption issues, as this is the only way they can reach decent performance.
Schol-R-LEA wrote:Far be it from me to defend C, but I really don't think you are right in this, for a number of reasons.
First, the main complaint you make has no applicability to long mode, nor to CPU architectures which have never had memory segmentation to begin with. Memory segmentation is a peculiarity of the 8086 borne of the cost of memory addressing hardware at the time it was designed - memory protection wasn't a significant consideration, as the 8086 was only meant to be a short-term design primarily intended for embedded controllers anyway - and one which even Intel has admitted was a mistake. The only other segmented-memory CPU architecture of any note, the IBM System/360, similarly abandoned segmentation as a bad design choice in the mid 1970s.
Second, segmentation is actually significantly slower than page-based memory protection for 32-bit protected mode in most current x86 models. Now, admittedly, this is because Intel has de-emphasized support for segmentation since the 80386, and not an inherent aspect of the segmented model, but it is still the case.
Third, the question of segmentation had nothing to do with the C language at all. While the current dominant implementations (GCC and Visual C++) only work with a flat memory model, both the Borland and Watcom C compilers handled segmentation quite satisfactorily, and AFAIK their successors still do. The Amsterdam Compiler Kit C compiler used in early versions of Minix had no problems providing for a segmented OS written in C.
Fourth, the issue of monolithic vs. micro-kernel is orthogonal to the issues of languages and memory models. Both micro kernel systems (such as the above mentioned Minix) and monolithic kernel designs (e.g., Xenix, Coherent, UCSD Pascal) have been written for x86 real mode, using assembly, C, or even some other languages (e.g., Pascal, Parasol, Modula-2), so arguing about the kernel design methodology is pretty meaningless here.
(As an aside, I would like to remind you that the original impetus for developing the micro-kernel model in the late 1970s was to provide better process isolation in systems with no hardware memory protection - such as the 8086.)
Finally, segmentation does not actually provide any improvement in the level of memory protection from paged protection in 32-bit protected mode, and [erroneous statements about current implementations elided].
[W]hat does matter is that segmentation is both less flexible than paging, and provides no protections which paging doesn't - it provides fewer, in fact, as the read-only limitations on user-space memory in a given segment are all-or-nothing, whereas page protection can be set on a per-process and per-page basis. While it is true that a given segment can be as small as a page or as large as the full addressing space, whereas paging requires all pages to be the same relatively small size, using segments in a fine-grained manner would, in effect, be using the segmentation to emulate paging - there would be no significant advantages.
While it is true that C compilers running in flat mode rarely take proper care in handling the page settings, and for that matter few operating systems give the compilers fine-grained control over setting page protection to begin with, that is a flaw in the OS and/or the compiler, not in the language itself, I would say.
---------------------------------------Brendan wrote:You only need to see the "small address spaces" research done by L4 to see that there's some potential benefits in using segmentation to reduce task switch costs (at least for artificial micro-benchmarks that may or may not have any practical value, for systems that don't use asynchronousity to reduce the number of task switches).Kazinsal wrote:Your efficiency claims are as good as fiction without proof.rdos wrote:and far more efficient than any C compiler would be able to produce
Of course that has nothing to do with "C vs. assembly" and nothing to do with the relatively bizarre (and likely very erroneous) "assembly is less error prone because it can use segmentation while most C compilers can't" issue.
From "What features can I rely on the existence of across arch":
Korona wrote:x86_64 does not support segmentation. You're basically saying "Rather than designing my kernel so that it can adapt to different scenarios I optimize for an architecture that have been obsolete for at least 10 years and today only serves a niche market".rdos wrote:Yeah, thinking in terms of "how many architectures can I support" is all wrong. Portability always sacrifices speed and the ability to exploit specific features of a CPU. That might be ok if you want something that is mediocre on many CPUs, but not otherwise. I only support x86 because only x86 has segmentation, which I consider a vital component of memory protection. I also rely heavily on assembler code instead of C, which I can do since I only support x86.
I also really doubt the "portability hurts performance" statement. Supporting a feature on one architecture does not mean that you have to require it on every architecture. However it is very easy to convince me if that statement is indeed true: Just show me a single (general purpose) OS that exploits all the nice special features of x86 and outperforms Linux or Windows on common workloads (or even a single real-world workload; microbenchmarks don't count). Hint: You can't; performance depends on the design of your algorithms and not on "Let me use segmentation instead of paging".