Hi, I'm going to make an OS for my virtual machine that runs on a homebrew CPU. Actually it's a gmod computer. The instruction set seems to have all the necessary stuff like indirect adressing and interrupts;
Am I missing anything? Boot order:
[list]Boot:check boot flags - was there errors, what OS to boot first, etc.[/list]
[list]Detect devices.[/list]
[list]On timer, report to screen the progress of booting untill OS starts.[/list]
[list]Find the memory device with highest priority and start OS from there.[/list]
[list]OS: init filesystem (file acess API)[/list]
[list]start AV, if any, and memory protection.[/list]
[list]init drivers (set default text output device/function, drawing API, etc)[/list]
[list]init thread pool (aka task manager)[/list]
[list]init messanger (like windows messages)[/list]
[list]start default window system[/list]
[list]start autoexec or a list of programs that run on start-up[/list]
Makes sense, no? Ask me if something's not clear, I don't know if I have the right idea of how an average OS works but I have a plan. Also, I will make a C and assembler compilers for the processor. I don't know if I should write all of this stuff in asm or C, since it's ALOT of coding, but at the same time, the essential stuff, so it needs to be fast.
Yes, I'm making a computer in Garry's mod, just for the lulz.
Do you have a good ABI scheme worked out? You're going to have to write a lot of the standard library on a low level without a compiler, and even making a compiler for a custom platform is nigh-advanced (on x86 it's as simple as hacking together a cross-compiler).
[editline]11:07AM[/editline]
...also, I smell a fish. You don't need an AV that early on. And what the hell is an ISO
also, read a book, you don't compile assembly
[quote]so it needs to be fast.[/quote]
[quote] I'm making a computer in Garry's mod[/quote]
does not compute
[QUOTE=r4nk_;16940108]does not compute[/QUOTE]
It has to be as fast as possible to get the most of the the computer, if the code is poorly optimised the software will run really slowly.
Good ABI scheme? So far I think programs would just call some function in OS that have set adress, the functions are either for asking OS to do something with files or devices, or to create a message, that is then sent to all programs that subscribed for this kind of message.
ISO: Sorry, I meant ISA, instruction set architecture.
If I don't compile assembly then maybe I translate it? I remember assembler code is unambiguously translated straight into machine codes, while any higher languages are firstly compiled into assembly, and then assembly is translated. There are many ways to compile something into asm but asm translates into machine codes word to word.
There are numerous computers in Garry's mod, zCPU based ones like WirePC and Alcyone PC; E2 gates can run up to 3 million ops per second; And lastly garrysmod entities can be merely a lua interface to a virtual machine that runs from a compiled dll.
Pfft. No matter how good my English gets, I still use strict terms carelessly.
No, because you're building an architecture from scratch, remember?
That's not what an ABI does, by the way - to *call* a function you need an ABI to determine the function calling convention.
Also, "ISA" doesn't fit there. Assembly gives you another layer of abstraction (especially when it comes to indirect addressing), it isn't translated "word-for-word" - it also resolves symbols you've declared if you plan to write an assembler that supports it, which means you'll also have to most likely write your own assembler. But, yes, some compilers use assembly as an intermediate language.
I'm not sure whether making an interface to a library makes something a proper OS, though.
In that case my ABI seems dumb to me: 1)write all arguments in the few designated cells before the function, goto that function; 2)function does something and returns to where it was called from; 3)read results from cells after the function.
That's actually alright, I believe fastcall writes parameters directly to two registers, pushes the rest on stack and then goes to the function. I don't know everything, though, so I assume you've decided how to implement returning values from a function consistently.
[editline]11:51AM[/editline]
Nothing's stopping you from writing something simplified, though.
[editline]12:12PM[/editline]
Actually, I was a bit of a dick earlier. Sorry.
You're mistaken about how a lot of fundamental things work in a computer, you should try coding for a real architecture first.
I think you'd gain a lot by writing a basic bootloader and OS for a real architecture, your PC for example. If you're going to write an assembler, you should get some experience with a real assembly language first.
(The process of converting assembly to machine code is called [I]assembling[/I], which is done by an [I]assembler[/I])
[QUOTE=Nikita;16940255]
Pfft. No matter how good my English gets, I still use strict terms carelessly.[/QUOTE]
Start with spelling :v:
(Referring to address* and access* etc)
You may find [url]http://wiki.osdev.org/[/url] and [url]http://www.osdever.net/[/url] useful, though any code examples won't be applicable to your homebrew CPU.
[QUOTE=Nikita;16940255]Good ABI scheme? So far I think programs would just call some function in OS that have set adress,[/quote]
Wait, you're not using virtual memory? I guess if you are making a very basic computer you don't strictly need any sort of physical constraints on things such as memory.
How does disk access work? I'm guessing that there is a simplified wiremod module that allows you to work with files directly in a directory, but if you are going to write that from scratch and have your own filesystem internal to the game, you are in for an adventure. How about thread scheduling? How are you making that happen? Do you have a C compiler writen for your cpu? Assemblers are easy enough to do, but writing an entire system in assembly is an excersize in bug wrangling. I would seriously suggest that you try to write an OS for something else, like an ARM or an ATmega or Z80.
I've not really looked into OS's but if it helps in wiremod you have ZC32, that compiles a subset of the C language in to ZASM (What the CPU in wiremod uses). Though I might be totally off target saying this.
The zCPU was just a hacked-together 32-bit clone of the z80, right? It's not as if it is exactly what Nikita has created. He created an entire CPU from basic logic and memory modules. The zCPU was just a lua-coded CPU (which is probably makes it way more responsive and less resource-hungry)
About virtual memory: The computer's RAM is stored in real RAM, either C arrays by DLL or lua arrays by in game entities. There will be two files on physical hard disk, one is page file and other is hard disk. Drivers and most of the OS will be copied to RAM. In the hardware version that is based on wiremod and not a dll, moving data between HDD, RAM, and pagefile will be done by a separate module that is simply controlled through few of CPU's outputs.
As thread scheduling, I suppose to use interrupts. I don't clearly understand the need to divide them into hardware and software interrupts, so there is simply an interrupt handler in RAM, and an instruction to copy state to CPU's own limited storage. Interrupt handler will be started when a signal at any of interrupt inputs change, or by simply jumping into the part of code in RAM that manifests the handler. By state I mean all registers and current execution position. However it only takes three to ten instructions to copy the state somewhere into RAM. Please tell me if there is anything wrong with this approach.
So you're not doing virtual addressing, but you still have a page file. What? One implies the other, you know.
Your approach to the thread scheduler is not well-formed. The entire point is to have concurrent processes and threads running at the same time, and your scheduler needs to figure out which one to run at a particular time. You [I]need[/I] software interrupts so your program can pass control back to the kernel at an appropriate moment, like locking a mutex or sleeping on a signal. The scheduling code can't be part of the same thread of execution, otherwise the scheduler could lock itself out, causing a double-fault. You need a separate priveledged thread of execution to run the scheduler in and the best way for passing info between threads is by way of the kernel thread, triggered by a software interrupt.
CPU has a special register that holds an offset applied to each adress in read or write instruction. It is supposed to be used when program is copied to dynamically allocated part of RAM. It doesn't get any closer to virtual adressing, because page file is simply a clone of HDD that is smaller and used for a different purpose. Maybe I named it wrong. But it is simply where blocks of RAM are placed if there is no room and they are the least used.
Scheduller does page switching when necessary. At equal ammount of time an interrupt comes from outside and scheduler rises a counter for current thread. When thread uses all the bits of time allowed for a thread of it's priority, scheduler makes the next thread in the list the current, and exits - changes state to that of current thread. If a thread is waiting for something, it checks if that happened and then calls the interrupt, which results in the scheduller. If a thread has nothing to do, it closes - calls kernel function to end a thread. That doesn't mean a program ended or is removed from memory - however if a program has no more threads that use it, it is a resource that noone uses, so it's garbage-collected.
[QUOTE]It has to be as fast as possible to get the most of the the computer, if the code is poorly optimised the software will run really slowly. [/QUOTE]
This is crucial. Specially if all your functions are called 1000+ times every second.
[QUOTE=Nikita;16946540]CPU has a special register that holds an offset applied to each adress in read or write instruction. It is supposed to be used when program is copied to dynamically allocated part of RAM. It doesn't get any closer to virtual adressing, because page file is simply a clone of HDD that is smaller and used for a different purpose. Maybe I named it wrong. But it is simply where blocks of RAM are placed if there is no room and they are the least used.
Scheduller does page switching when necessary. At equal ammount of time an interrupt comes from outside and scheduler rises a counter for current thread. When thread uses all the bits of time allowed for a thread of it's priority, scheduler makes the next thread in the list the current, and exits - changes state to that of current thread. If a thread is waiting for something, it checks if that happened and then calls the interrupt, which results in the scheduller. If a thread has nothing to do, it closes - calls kernel function to end a thread. That doesn't mean a program ended or is removed from memory - however if a program has no more threads that use it, it is a resource that noone uses, so it's garbage-collected.[/QUOTE]
So its a round-robin scheduling algorithm? Also, if you are thinking of cond-vars, the condition checking should be done by the user threads, not the scheduler. The scheduler simply wakes the threads when necessary. The user thread can call a function to put itself into a sleep state, at which point the scheduler should allow any other thread to pre-empt the sleeping thread. And don't forget that pre-empting, while inevitable, is still bad. You don't ever want to have a low-priority thread running while a high-priority thread must wait for access. That is called priority inversion and kind of defeats the purpose of having a priority scheduler in the first place. Of course, you still need to solve the problem of shared resources and critical sections in code that necessitates priority inversion. You just need to keep it as small as possible.
Yes, it is round-robin scheduling, yes, user threads check for conditions. I don't uderstand why is pre-empting bad. I think the system I made up is by all means a system of pre-emptive multitasking - At set periods of time, current thread gets interrupted (this does not damage the thread's data in any way), and scheduller either lets it continue running or puts it on hold and resumes another thread.
If there is a high-priority thread running together with a low-priority thread, there still have to be moments when low-priority thread is running and the high one is waiting - the high priority thread simply would have like 10 times more timeshare. But making some thread uninterruptable equals giving it all the CPU power, so if it does not wish to cooperate, there is no multitasking. Such power is only acceptable to the kernel thread.
Are there any other major modules of OS that I'm forgetting? Like the one that loads programs into RAM?
Sorry, you need to Log In to post a reply to this thread.