I've been thinking of modifying my memory management code
that I touched upon in the "how does paging work" thread. As I
mentioned I've got a high level description of a process's address
space. Copying from an old post an address space looks like this:
AddressSpace (range 0x0000 to 0x10000) ---> Pmap (pagetables)
|
\|/
MemRegion7 (0x0000 to 0x1000, mapped) -> pf1
|
MemRegion3 (0x1000 to 0x3000, unmapped)
|
MemRegion1 (0x3000 to 0x6000, mapped) -> pf2 - pf5 - pf7
|
MemRegion4 (0x6000 to 0x8000, mapped) -> pf6 - pf3
|
MemRegion2 (0x8000 to 0x10000, unmapped)
The AddressSpace maintains a linked list of MemRegion structures
sorted by address. There is also a linked list of free MemRegions
to make allocation a little faster. These MemRegions are allocated
from a fixed pool in the kernel, shared by all processes.
Each MemRegion maintains a linked list of Pageframes that have
been allocated for that area, sorted by virtual address. From these
structures the actually page tables in the Pmap can be constructed.
I am thinking of simplifying things a lot as I don't intend to add
swapping or shared memory now.
Instead of having a pool of MemRegions, allocating them and
attaching them onto a linked list I was thinking of having a fixed
size array per process of MemRegions, perhaps room for
1000 entries and a count of the number of MemRegions in use.
struct MemRegion
{
uint32 base;
uint32 ceiling;
uint32 type; AREA_FREE, AREA_PHYS or AREA_ANON
uint32 padding/other;
};
Initially there is one entry in the array that describes the whole
of user mode as free, base = 0 ceiling = 0xF0000000. As
entries are added and the address space is carved up the array
expands.
Finding a specific area within an address space would just be a
binary search on the array. A search for a free area might
be a linear search or an extra field added to the MemRegion
to maintain a list of free areas.
I'm not sure if 1000 entries would be enough for a process. Typically
I allocate areas the size of 64k and malloc() then carves them up
into smaller units, currently using a slab allocator. Bigger allocations
just allocate an area directly.
I only intend to have say 128 processes so 16k for an array of
MemRegion structures isn't bad. Perhaps I could use just the base
and type fields, using only 8 bytes per MemRegion, it could
determine the ceiling of an area from next Memregion's base.
My thinking is that an array of MemRegions is easier to search,
just a simple binary search. Inserting a region may not be that bad,
especially if inserting at or near the tail of the array. Also linked
lists in my current design may go through a lot of TLB entries
when searching.
In the old version above Pageframes are attached to the MemRegion
on linked lists. There is a Pageframe for each page of physical memory
in the system. With the new way, just the page tables are used to
keep track of which pages are allocated for an area of memory.
So a Pageframe might be something simple like:
struct Pageframe
{
uint32 flags;
struct Pageframe *next_free
};
One of the reasons for wanting to simplify my memory management
is that I've been thinking of different ways to do IPC. Currently I've
got an asynchronous message passing system that copies data
between processes using a single copy. It's sort of a mixture of
AmigaOS's and QNX. It works but I was thinking of alternatives
or possibly adding to the existing code.
I was thinking of zero-copy IPC where an area of memory is unmapped
from one address space and then mapped into another. With simpler
data structures it would make remapping pages from one process to
another quicker.
If an area was made irrevocably read-only then it could be shared
between several processes instead of unmapping, that would need
a reference count inside the Pageframe structures. I gather an
old system called MUSS did something similar but perhaps that
used segmentation.
I think KVP had a similar scheme in mind years ago, not sure how
well it worked:
http://groups.google.com/group/alt.os.development/msg/bec3b82a84289d82
If my thoughts get any clearer on it I'll post some more.
--
Marv