| 1 | ||
| 1 | ||
| 1 | ||
| 1 | ||
| 1 |
I started yesterday making my own operating system. It's largely vibe-coded. I'm starting completely from scratch. The name of the project is Responsive OS. It's core design theme is that the user should never wait. Or at least never wait more than 5 seconds to be put back in a situation where they can interact. Boot time is currently instantaneous. But it will never be more than 5 seconds ever. Nothing ever will be. Maybe that's rather limiting for what kind of software can exist. But I think it will be interesting to see how problems will be solved around this. Solving problems like network attached resources, aka downloads, is going to lead to some unique ideas.
But getting back to the basics, which is the current stage, I just added a memory allocator. Everything is still running in ring-0, no userland, and not yet using the MMU (hardware-based memory management unit). But that doesn't mean a heap isn't useful.
The one I build is made for sub-allocators. The two important functions are prep_heap(void *start,void *end) and allocate(Heap *heap,int size). Even the main heap makes use of it. I'm just grabbing 20 megabyes of a safe region and passing it to prep_heap.
void *start = 0x200000
void *end = start + 1024*1024*20;
mainheap = prep_heap(start,end);
mainheap is a global variable. If I need more than 20mb I can use some of the info GRUB passes to me to find a larger region. And after that I can start actually using the MMU or go into 64bit mode. Everything is being done in stages when there is a demand for it.
Not that I need a heap for this, but as a proof of concept I used it to dance a logo across the screen.
Offset *randomoffsets(int count) {
Offset *frames = (Offset*)allocate(mainheap,sizeof(Offset)*count);
for(int i=0;i<count;++i) {
frames[i].x=(i*1523%800);
frames[i].y=(i*7841%600);
}
return frames;
}
void kernel_main(struct multiboot_info *info) { //Called from some assembly
drawimage(info,10,10); //Draw something so we can see something even if the test breaks;
Offset *frames = randomoffsets(10);
for(int i=0;i<100;++i) { //Infinite loop
i%=10;
drawimage(info,frames[i].x,frames[i].y);
}
while(1) {
asm volatile("hlt");
}
}
The allocator uses a circular double linked list of blocks. Blocks are either free or non-free. This double linked list is superimposed with a single linked list of free segments so scanning for a good free block can be faster.
typedef struct block_header {
unsigned int size; // Size of the data area (excluding header)
int is_free; // 1 if free, 0 if used
struct block_header *next; // Next block in physical memory
struct block_header *prev; // Previous block in physical memory
struct block_header *next_free; // Next block in the free-only list
} block_header;
Instead of scanning for an available hole from the front of the list, it rotates to avoid scanning through the front of the list over and over. Once it finds an acceptable hole, it checks up to the next 3 (inclusive) to pick the best candidate it 4. That's the smallest one larger than the memory we are trying to allocate (plus it's header).
When a block is freed it checks the block before and after to see if they are free. Then it can merge the hole.
While the system doesn't have seperate processes or time sharing yet, there can still be "programs" I could launch like a game that may want to free up all of their memory at once once done. This is one of the reasons why I built it for sub-allocation.
void *substart = allocate(mainheap,1024*1024*1024); //1 Gig
Heap *subheap = prep_heap(substart,substart+1024*1024*1024);
launch_game(subheap);
//Game exited
free(substart);
Other advantages:
Once persistence is in, a program could segment heaps they want to dump to disk or not for persistence.
A program could seperate their heap use by rough object size to encourage better hole alignment.
A program that intendes to temporarally create a lot of small objects as part of a sub-routine can make use of one to avoid punching a lot of small holes into the main heap, then bulk free at the end.
Keeps memory from one program near itself for better RAM-caching once time sharing is in.
Side benefit of this project. This little "OS" I created doesn't seem to be suseptable to the ACPI-bug that's plauging me in Linux right now. Inside this OS my computer does not freeze when the power state changes. So that's nice. This is what the logo test actually helped me prove.
Comment preview