ARCHITECTURE
This section explains the overall architecture of LSE/OS:
Item | Description |
---|---|
Context switcher (kernel) | Schedule tasks: it relies on the 'timer' service if automatic context switch is wanted (non cooperative) |
Tasks/drivers/services | Programs: Hardware drivers (PIC, timer, DMA, UART, Ethernet, etc), file systems, communication services, shells. All of these programs are tasks. |
Coresrv | The Core Service: this is the main service (in kernel address space) that manages memory, GDT (tasks), IDT (Interrupt Tables) |
Libarea | The memory management library that can be reused also for writing other programs (like file systems) |
pgflt | The service that wraps page faults interrupts (SIGSEGV) |
trap | The service that wraps various processor errors (SIGBUS) |
stray | The service that wraps the stray interrupt (interrupts are not treated fast enough) |
break | For debugging kernel with GDB |
NPX | The Floating Point Unit of the x86 |
Memory | The physical memory of the system |
GDT | The Global Descriptor Table that contains all the tasks of the system (x86) |
IDT | The Interrupt Descriptor Table that contains all the interrupts (taskgates) of the system |
Interrupts | Both NMI and External interrupts |
NMI | Non Maskable Interrupts: interrupts that cannot be ignored (Division by Zero, page faults, etc) |
PIC | Programmable Interrupt Controller: The controller that allows external interrupts to wake up the processor |
ioports | The ISA ports that are used with the inb() and outb() assembly instructions |
Peripherals | All the hardware peripherals that could be accessed by ioports or memory and trigger external interrupts. |
Drivers
In lseos, a driver is a 'thread group' or a 'team' composed of many
threads cooperating and sharing memory. Normally there are services (threads of class TCBC_SERVICE)
for handling interrupts (not interruptible) and schedulable threads (threads of class
TCBS_SCHED) for doing queued work.
When we launch the 'timer' driver, it creates the first process that create (implicitely) the process group:
Here, the timer drivers installs the timer interrupt handler (tick) and the system call entry point (timersrv):
Generally the master thread (the 'first' thread) dies when it has finished to launch all the functional threads:
In the following process view we see the sash process calling the delay(9) service, the timer interrupt handler "tick" receiving an hardware interrupt then directly sending a SIGALRM to the caller process.
In the following process view we see the same principle with the keyboard interrupts and Sash (Stand Alone Shell).
Process view of a minimal execution
In LSE/OS there aren't any drivers in the kernel address space except for some specific controllers like NPX (The floating point unit) that requires its registers to be saved and restored at each context switch.
The PIC (Programmable Interrupt Controller) does not need to be in the kernel address space any more! And not even the timer that drives the scheduler (see next sections).
Note that in the following view there is a specific task in kernel space called "Core". "Core" is the real kernel that manages memory and tasks through its dedicated services: coresrv0, coresrv1, ... (one for each cpu)
The only other services that need to be in the kernel address space are the fundamental NMI (Non Maskable Interrupts: "page faults", traps, breakpoints, etc), the idle threads (one for each cpu) and the main context switcher.
Context Switching
LSE/OS relies on the x86 specific instructions for context switching. It especially uses task gates for achieving this purpose. Unlike classic interrupt handlers that could be interrupted by other interrupts, task gates are not interruptible at all. Beeing interrupted while in an interrupt handler is not absolutely necessary.
The context switcher (the kernel) gets the next task to run through the runq() system call, then call the assembly instruction lcall():
When a tick (HZ) occurs the task that is currently executing is preempted by the tick interrupt handler. The latter performs a kind of yield() (actually this is a variant system call reparent()) that gives hands back to context switcher:
Finally the kernel calls runq() again and elects the next task to run:
Detailed sequence of context switcher: TODO
Services and their roles in the system
LSE/OS distributions comes with a set of services. The following table show basic description of their functionalities and dependencies:
Name | Description | Serviced by | Dependency | Status |
---|---|---|---|---|
coresrv | The Core Service: Used for allocating memory and creating tasks | kernel | - | Mandatory |
pic | The Programmable Interrupt Controller driver: Used to enable/disable external interrupts | pic | - | Optional |
timer | The 8253 Timer Controller driver: Used to generate the HZ tick interrupt but also for tasks to get current time and schedule events | timer | notify (if some tasks needs to register some timers) | Optional |
Here are the misceleanous hardware devices that are supported in LSE/OS:
Name | Description | Serviced by | Dependency | Status |
---|---|---|---|---|
dma | The 8237 DMA Controller driver: Used to transfer blocks of memory | dma | - | Optional |
ide | The IDE service: Used to access disks | ide | - | Optional |
pci | The PCI service: Used to create drivers for PCI based devices | pci | - | Optional |
Name | Description | Serviced by | Dependency | Status |
---|---|---|---|---|
npx | The Floating Point Unit: needed if you want to do floated point maths | kernel (because context switcher need to call it) | - | Optional |
prop | The Property Service (kind of a registry): A property is simply a key binded to a value. Tasks could store, update, fetch property values but can also attach and detach from properties. | prop | notify | Optional |
notify | The notification service: this service allow tasks to be notified with SIGNOTIFY when some another tasks die. | notify | - | Optional |
sec | The Security Service: this service, when enabled, wraps ioacquire() and srvreg() calls (not finished) | sec | - | Optional |
LSE/OS has a standard API for manipulating file descriptor based operations. Here is a list of service that are compliant to it:
Name | Description | Serviced by | Dependency | Status |
---|---|---|---|---|
pipe | The Pipe Service: Used to create communication endpoints | pipe | notify | Optional |
vfs | The File System Super Service: Used as a frontend to File System Services | vfs | notify, at least one file system, e.g. ramfs | Optional |
ramfs | The RAM File System | ramfs | notify, can work with or without vfs | Optional |
part | The Partition Service | part | ide | Optional |
fat | The FAT (MSDOS) File System | fat | part | Optional |
chiche | The Chiche File system: An example of filesystem using bpt (not yet finished) | chiche | part | Optional |
tty | The Terminal Service: allows to create unix style ttys to PC console, serial ports but also ptys (Pseudo-Terminals) | tty | notify | Optional |
Name | Description | Serviced by | Dependency | Status |
---|---|---|---|---|
rtl8139 | The Realtek 8139 Ethernet Driver | rtl8138 | pci, inet | Optional |
inet | The Network Super Service: Used as frontend to network services | inet | notify | Optional |
Name | Description | Serviced by | Dependency | Status |
---|---|---|---|---|
smp | The SMP service: Used to transmit information to other processors | smp | - | Need to compile the kernel explicitely for n cpus. |