See LLL difficulties.
Having some hardware independence while limiting inefficiencies.
To be sure that buffers are flushed, we must fsync()
, but this is a blocking call. Hence, fsync()
and similar calls should be delegated to a forked process that will queue blocking calls and warn the main process back when they are finished.
Modifying the memory-mapping tables to do garbage collection is very slow, as it involves a syscall for each operation, and leads to big memory-mapping tables which POSIX implementations are not optimized for at all. Hence, we can't use the mmap()
mechanism for fine-grained memory mapping. Microkernels might allow user-level pagers, though.
There is no standard or reliable way to reserve a large chunk of address space without cluttering up swap memory and without creating a mess with the C library, particularly if we want to reuse addresses from a swap file across sessions. On each architecture, we will have to add some architecture-dependent memory mapping instructions. Most likely, we will mmap()
a huge sparse file on a filesystem that supports it; but then there's block leakage, and the only standard way to reclaim blocks is that when the filesystem overflows, it is time to erase the file, and begin again.
When resuming connections, there is absolutely no way to trust the files to be in the right format; we must re-check each time, or blindly trust. The persistent files must be in read-only mode, and be changed to read/write mode just when open by the right process (use the permission mode as an open indicator ?).
To allow multithreading, special care will have to be taken to do only non-blocking I/O with select()
and such, to queue requests, etc. Yuck.
There no way to have safe real-time response. So games, animations, etc. will have to run in separate, untrusted spaces.
Paging under POSIX is too slow and messy. Should be done as seldom as possible (only at minor and major GC).
We'll sacrify the low bit of words, but use macros to choose whether integers or pointers will be unchanged.