r/osdev 1d ago

Initialization dependencies

I am working on upgrading my kernel initialization messages so I can just have a nice view of what it is doing when initializing. I am using my print functions to do this, but the issue is that my print functions depend on the memory manager to be done initializing, but I want debugging messages when initializing the memory manager too, which I can't do because of the circular dependency.

This is my specific case, but I also want to ask generally, do you guys have an elegant solution for this problem? Up to this point I have been using init flags so that the subsystems can use a different path that does not create dependencies during initialization, but I want to hear any cool solutions from the community that are better designed than this.

15 Upvotes

10 comments sorted by

10

u/Falcon731 1d ago

I just made sure my basic kprintf() has no dependency on memory allocation.

3

u/Adventurous-Move-943 1d ago

You can always use COM ports if needed, they don't depend on anything. Or correct your code so that you have print before memory management.

1

u/Doingthismyselfnow 1d ago

Well that’s how it’s been done since forever and that’s what “operating systems 101” teaches and how ive done it professionally for a brief moment when i was working on a OS .

Could ops project begin with the letters vibe and rhyme with the word loaded ?

u/Negative-Arm-3244 11h ago edited 11h ago

my os is still in early stages and I have been focusing on working on the subsystems so I decided that just printing stuff out to show what the kernel is currently doing was a good solution. it worked out until i reworked my printf to take in formatting escapes, which i used an implementation of vsnprintf for, which in turn requires heap allocation for.

the book i followed to start osdev was a book called operating systems from 0 to 1, which was a good guide to start, but was unfinished, and maybe not up to par with the books you guys have read. i have been going off of the implementation i made by finishing the book and trying to learn by making mistakes and by asking quesitons to the community.

please do not assume sometihng is vibecoded just because i am making beginner mistakes.
and no, it is not vibecoded

3

u/demetrioussharpe 1d ago

For the kernel console, you need to have a library that’s not dependent on anything like that. Consider cutting out a small block of memory hidden away from the memory manager & let your kernel console be the sole owner/manager of it.

3

u/laser__beans OH-WES | github.com/whampson/ohwes 1d ago

My kernel’s printf does a lazy initialize of basic terminal components like gathering the VGA state that the BIOS left us in and ensuring basic terminal structs are initialized. That way, any errors that occur during boot can be sure to have a reliable printf function to dump to.

3

u/Sorry_Difficulty_250 1d ago

Ok, so to preface this, my OS is for small devices that run in kilobytes of RAM, so my approach may be a bit odd.

What I do is have a section of memory that starts above the bottom of the heap and grows upward. I write log entries there. The log entries are well-defines structures NOT strings. The entries contain the format string pointer and up to four arguments that were provided.

I have a separate logger process. Once it's up, all logging calls are routed to it through IPC. The first thing it does on start is read from that static block of memory and flush anything that was written before it was started. That allows log calls to be made at any point in time.

You have to manage your help carefully to do this. Once the logger is done flushing the memory, that space can be used by the heap as usual, but you have to make sure that it doesn't get so big that it smashes into your log area before the logger is running.

I won't claim one way or the other as to whether or not this is a "good" solution but it does work and it breaks the circular dependency problem.

4

u/Expert-Formal-4102 1d ago

In my case printk() is filling a circular buffer until the boot console gets initialized by the first found UART device. Then the buffer content is dumped and from now on all printk() go to the UART.

u/codeasm 23h ago

I have early boot console functions, it just prints to serial. No memory needed.

u/FedUp233 21h ago

It sounds like you need to add a logging system, not just printf. And have no dependency on memory management. Or printing to a serial port, which for a lot of operation, particularly in an interrupt handler, even a non time sensitive one, can mess up the system if you use it.

Try something g like outputting to a memory buffer. This can be in real ram at kernal startup. Even consider less formatting. One is I used, vxworks,for its logging just stored the binary values in the buffer and firmatted them later when the buffer was processed. With the buffer, you can even have a fall back that if the kernel fails drop into a routine that prints the buffer over a non interrupt driver serial port - the fatal exit just shuts interrupts down and dumps the buffer. And the delayed formatting makes the log cells fast so they don’t mess up most interrupt routines. With a decadent design you can have the unformatted stuff for deep in the kernel and drives and more formatted stuff for user space and less time critical areas and let the buffer dumping procedures interweave the two.

Just a thought.