Re: AW: [Fwd: Re: EDE - Personal Suggestions and Ideas]

Eduardo Pereira Habkost
2004-05-26T17:19:54Z

[-- Attachment #1: Type: text/plain, Size: 5190 bytes --]

On Wed, May 26, 2004 at 05:49:42PM +0100, David Given wrote:
> On Wednesday 26 May 2004 16:10, Gábor Lénárt wrote:
> > However,
> > in my 286OS (which source was destroyed several years ago, when my sister
> > tries to drink my computer with some cola ...) there was a signaling
> > mechanism and the kernel can notify application that it SHOULD reload
> > segment IDs and this signal is unblockable one. Sure, still ugly, but at
> > least we haven't got reload segment IDs every time ;-)
>
> The only issue with this is, what happens if it's the code or data segments
> that have changed... you can't execute any user code until the segments have
> been updated and you can't update segments without running user code!

Erm... shouldn't be this exactly the task of the scheduler? Simply the
scheduler should be sure that the segment registers are updated and
data is in the right place before switching to user code again. Before
returning to the user process, the structure storing the 'context' will
be updated before returning to user context. I think I didn't get what
is the point.

>
> [...]
> > But you can assume that its
> > assembly programmer say: OK, CS (code segment register) points to code
> > segment, DS (data segment register) points to data segment *AND* ES (extra
> > segment register) points to the ACTUAL user data segment.
>
> Ha! Great minds think alike, and fools seldom differ... I was going to propose
> something like this. Except from C, and only allowing a single extra segment
> (so that the user process never concerns itself with the contents of ES). I
> was going to call it the buffer area and allow you to do things like:
>
> {
> resize_buffer(32*1024); /* request 32kB buffer area */
> copy_from_buffer(data, 2*1024, 32); /* copy 32 bytes to data from 2kB
> into buffer area */
> }
>
> However, I didn't mention it because I had vague memories that part of ELKS'
> libc uses ES for some of its loops, and wanted to check on that.
>
> But yeah, that would work. It might make a suitable compromise between
> single-segment code and multi-segment code.
>
> If you want to use more than one extra segment, however, you end up with
> exactly the same problem as before --- the kernel doesn't know where the
> segment addresses are in the app's address space. Giving the kernel a pointer
> to where it's stored is really, really ugly.
>
> Perhaps a better approach would be to have the kernel mediate all this; use
> syscalls to tell the kernel to allocate out-of-process memory. (Or, actually,
> a device driver would be better because then it would all get cleared up
> automatically when the process exits.)
>
> {
> int handle1 = allocate_buffer(48*1024); /* request 48kB buffer area */
> int handle2 = allocate_buffer(48*1024); /* and another one */
>
> use_buffer(handle1); /* tell the kernel to look up what selector
> handle1 refers to and set it to ES */
> copy_from_buffer(data, 2*1024, 32);
> use_buffer(handle2);
> copy_to_buffer(3*1024, data, 32);
> }
>
> You'd get fast copying from a buffer to normal data and vice versa, but not
> from one buffer to another buffer (unless you were to implement another
> syscall so the kernel did it).
>
> Ideally you don't want your user process playing with the segment registers.
> Ever. That way lies madness, and horrible bugs when, e.g., the compiler
> decides to cache a selector on the stack without telling you, and the kernel
> changes the selector without updating the version on the stack...

I was thinking on this, too: things will be simpler if we explicitly
state that user processes cannot touch the segment registers.

The compiler be aware of that, too. But given that we have only one
data segment, one code segment, and maybe one ES segment pointing to
out of process data, the compiler shouldn't need to touch the segment
registers, ever.

We could have, instead of a "copy_{to,from}_buffer", a "map_buffer_to_es",
that will make sure that the ES register for the process point to the
selected buffer (reading your example again, I saw that this is exactly
what your use_buffer() is supposed to do), but the way C sees the memory
don't make this so simple. Unless the compiler give us some help to
easily accessing data in the ES segment.

If someday the compiler is supposed to support 'far' pointers, we could
use them, but instead of storing the ES value on the pointer, and updating
ES before accessing data, store the buffer handle on the pointer and call
use_buffer() before using it. Yes, more expensive than simply setting
the ES register, but would allow the OS to move the data, if needed.

And that would be compatible with 286pmode, too. The difference is that
on 286, we would need fewer copy operations, and fewer segment register
changing. And if we want to have 286pmode-only, but slightly faster,
applications, we can allow them to simply set ES to the returned handle,
without a syscall. Obviously the returned handle, in this case, will be
a segment identifier that can be directly put on a segment register.

--
Eduardo

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]