no MMU - discussion how to run a multitasking OS without a memory management unit on a 6502.
Using OS/A65 without an MMU used to require some special measures. One of it was to coordinate all running tasks concerning their memory usage. With the new relocatabel o65 fileformat the lib6502 implemetation takes care of that.
This means when building lib6502 programs, you do not have to actively care about the stuff below, but it is probably good to know anyway.
There is one thing that is difficult to handle on a 6502, the stack. It is only 256 byte large (small that is…). And with a multitasking OS the stack has to be used by several programs at the same time. One approach is to copy the stack contents to another place every time a task switch is done. But that is a speed penalty.
There is an option to not copy but split the stack, but it allows 5 running tasks in parallel only: I split the stack into 6 pieces, 5 of them for a task and the last one for the system.
With version 1.3.9 we got a new config option, STACKCOPY. With this option only the used parts of the stack of a task is saved in some save area when doing a task switch. This is slower, but allows much more stack space in a task and much more
So copying only the used parts of the stack seems like a good comprimise and is the default for the C64 port. But embedded ports may profit from the split stack option.
There is one other thing that cannot easily be coordinated - the SEND buffer. This buffer is used for communication with the kernel. As OS/A65 originated from a system with MMU, there was no real need not to use an absolute address for the buffer, thus saving registers for other purposes.<br> For all systems now the usage of the SEND buffer has to be coordinated between the tasks. Therefore a system semaphore SEM_SENDBUF is used.
Before accessing the SEND buffer at $02xx, the task has to allocate it with a PSEM operation on the SEM_SENDBUF semaphore. After the system call, it has to be freed with a VSEM operation.
Note
|
the ownership of the semaphore moves when a message is sent from one task to another, so the receiver has to free the semaphore (or can opt to send a reply message back) |
Well, and here we are with the known resource allocation problem. Imagine two tasks communicating via send/receive. Then, if the order in which messages are sent is not fixed and therefore predictable, precautions against a lock have to be taken: task 1 allocating the send buffer to send a message to task 2. The same time task 2 tries to allocate the send buffer to send a message to task 1. If it not tries to receive messages while waiting for the semaphore, it will lock.
Therefore the filesystems, for example, do not release the send buffer while executing a command or open a file. In the meantime another task could send a message to the filesystem, locking the send buffer. But the buffer is needed by the filesystem to send the reply message. The filesystems in their current form are not prepared for this situation, so that they don’t release the send buffer.
The kernel does not handle dynamic memory management within an environment, i.e. within a defined memory mapping. Tasks running in the same environment must coordinate the allocation of free memory - and also free zeropage - among themselves. This is implemented in the lib6502 library.
The lib6502 library is thread-save. It can be used by any thread at any time. Internal locks (semaphores) are used to avoid any interference if necessary.
lib6502 provides the necessary malloc(3) call to dynmically allocate main memory within the environment. Zeropage cannot be allocated.
The lib6502 forkto(3) code loads a relocatable (o65) file from disk, allocates main and zeropage memory for it, relocates it to the given addresses and starts it via the kernel.
There is a NOMMU define for various functionalities although this has been mostly eliminated. Most notably, it is not used in the kernel. The main use of this define is, in some of the programs, enable the SEM_SENDBUF handling when this buffer is needed.
This NOMMU switch will go away when the shared SENDBUF is not needed anymore.
Suggested reading: "Operating Systems, design and implementation", Andrew S. Tanenbaum, Prentice-Hall
Please report bugs at https://github.com/fachat/GeckOS-V2/issues