Multitasking
Buddy Betts had some interesting thoughts about multitasking on BMOW. That’s so far off in the future that it’s probably useless to speculate about it now, but what the heck. Running several programs at once would require:
- A timer interrupt that fires periodically, to initiate task switching.
- Some way to clear the timer interrupt, so exiting the interrupt service routine doesn’t immediately jump back into it.
- An ISR (dare I call it an operating system?) that saves the processor state for one task, and restores the processor state for the next task.
- Some dedicated place to store the processor state of tasks.
- Relocatable code, or segmented memory, or virtual memory, so that the address spaces of programs won’t collide.
Unfortunately, restoring the complete processor state of a task is impossible with the current hardware design. If you look at the block diagram way down at the bottom of the page, you’ll see that there’s no way to load the stack pointer registers with an arbitrary value. That was intentional, because I didn’t need it before, and it meant the machine had exactly 8 possible load destinations, which could be encoded into 3 control ROM bits. Servicing an interrupt involves pushing more data onto the existing stack, then popping it off at the end of the ISR, but never setting the stack pointer to a completely different value. Task switching requires switching between totally different stacks, however. I could make the SP loadable, but then I’d have 10 load destinations (with SPLO and SPHI), requiring 4 control ROM bits (could be a problem), and a larger mux.
I’m beginning to realize that control ROM outputs are precious commodities, since new hardware capabilities tend to require new control inputs, but there’s a hard limit on the number of outputs from the control ROM (8 bits per ROM, and I have 3 ROMs).
A dedicated place for stored processor state isn’t any problem in theory, although it implies an OS-reserved area of memory, and some way of preventing programs from writing to that memory (or just trusting the programs to play nice).
Relocatable code and/or virtual memory seems like the trickiest issue. With a single program machine, the programs can contain absolute memory addresses and jump locations with no problems. But if the OS can potentially load the program anywhere into memory, the programs will need to account for that. One approach might be to have the OS loader modify the program’s code as it was loading it, adjusting any absolute memory references as needed. That could be difficult. Another possibility might be to add a base pointer register, managed by the OS, and to make memory references interpreted relative to the base pointer. That would probably involve extra hardware or extra cycles to adjust each memory reference.
It might be possible to provide a powerful-enough set of relative addressing instructions that programs wouldn’t need to use absolute addressing at all. After all, I am designing the instruction set, so I can do whatever I want. That would be easy enough for relative branches or jumps (although computing the branch destination would be slower than a branch to an absolute address), but I’m not sure how global program variables would be handled. You might still need a base pointer anyway.
A simpler approach might be to use a larger SRAM, and segment memory into a fixed number of blocks, one per process. For example, if I used a 512K SRAM, address lines 0-15 would be the address as the process sees it, and address lines 16-18 would be the 3-bit process ID. The ROM could be configured so that it was mapped into the same location in every processes’ address space. One big drawback of this approach is that each process would get a fixed size address space, regardless of how much memory it actually needed, putting a hard limit on the total number of processes. A more practical drawback is that 5V TTL-compatible SRAMs larger than 128K generally aren’t available, so the machine would be limited to a maximum of 2 or 4 processes, depending on the size of the process address space. Maybe DRAM or other memory technologies could be used instead. I need to investigate how difficult that would be.
Follow up: It seems that André Fachat has already invented a relocatable executable file format (specifically for the 6502) called .o65. See http://www.6502.org/users/andre/o65/fileformat.html for the spec. It embeds extra information in the executable file that enables the OS loader to modify the program’s code as it’s loaded, similar to how I was considering. Given that it was designed for a pre-existing processor, however, inventing a base pointer register or segmented address space out of thin air obviously wasn’t possible, and so a load-time fix-up was the only possible solution.
Be the first to comment!No comments yet. Be the first.
Leave a reply. For customer support issues, please use the Customer Support link instead of writing comments.