diff options
| author | Amlal El Mahrouss <amlal@nekernel.org> | 2025-12-06 13:00:14 -0500 |
|---|---|---|
| committer | Amlal El Mahrouss <amlal@nekernel.org> | 2025-12-06 13:00:14 -0500 |
| commit | 64875ef4c38131cb8b728f96bad3eb255b99a655 (patch) | |
| tree | c2debc36054812d06bcb457e412a4b3cbd2876f2 /source | |
| parent | bbccd217b5e9ad1dec7664f7ae058d179768c9e0 (diff) | |
chore: updated draft of WG01 and WG02.
Signed-off-by: Amlal El Mahrouss <amlal@nekernel.org>
Diffstat (limited to 'source')
| -rw-r--r-- | source/INDEX.md | 9 | ||||
| -rw-r--r-- | source/wg01/wg01.tex | 195 | ||||
| -rw-r--r-- | source/wg02/wg02.tex | 166 | ||||
| -rw-r--r-- | source/wg03/.keep | 0 |
4 files changed, 370 insertions, 0 deletions
diff --git a/source/INDEX.md b/source/INDEX.md new file mode 100644 index 0000000..5ff9a1e --- /dev/null +++ b/source/INDEX.md @@ -0,0 +1,9 @@ +# Introduction + +This file indexes the different working groups and their purpose. + +## Working Groups + +- WG01: `Kernel Architecture Group.` +- WG02: `Multi-Tasking Group.` +- WG03: `Compiler Design Group.` diff --git a/source/wg01/wg01.tex b/source/wg01/wg01.tex new file mode 100644 index 0000000..f116cb8 --- /dev/null +++ b/source/wg01/wg01.tex @@ -0,0 +1,195 @@ +% AUTHOR: Amlal El Mahrouss +% PURPOSE: WG01: Kernel C++ + +\documentclass[11pt, a4paper]{article} +\usepackage{graphicx} +\usepackage{listings} +\usepackage{xcolor} +\usepackage{hyperref} + +\definecolor{codegray}{gray}{0.95} +\definecolor{codeblue}{rgb}{0.1,0.1,0.8} +\definecolor{codegreen}{rgb}{0,0.6,0} +\definecolor{codepurple}{rgb}{0.58,0,0.82} + +\title{WG01: Kernel C++} +\author{Amlal El Mahrouss\\NeKernel.org} +\date{\today} + +\lstset{ + language=C++, + backgroundcolor=\color{codegray}, + basicstyle=\footnotesize\ttfamily, + keywordstyle=\color{codeblue}\bfseries, + commentstyle=\color{codegreen}, + stringstyle=\color{codepurple}, + numbers=left, + numberstyle=\tiny\color{gray}, + stepnumber=1, + numbersep=5pt, + breaklines=true, + breakatwhitespace=false, + frame=single, + rulecolor=\color{black}, + captionpos=b, + keepspaces=true, + showspaces=false, + showstringspaces=false, + showtabs=false, + tabsize=2 +} + +\begin{document} + +\maketitle + +\section{Abstract} +{ +Many and most kernels have been shipped using the C programming language.\\ +And some of them like EKA2 uses the C++ programming language. Although notoriously difficult, one may still adapt to those constraints in order to deliver one such operating system kernel. \\ +That is the reason that most production-grade kernels (Linux, XNU, and NT) are mostly written in C. With a higher-level subset in C++. \\ +However, when correctly applying C++ principles to kernel development, one makes the development much more easier to pull off. +} + +\section{The Three Principles of Kernel C++} +\subsection{Part One: The C++ Runtime} +{ +The problem mostly lies in the C++ runtime. Which assumes an existing host. A host is the contrary of a freestanding target, that is a program which expects a runtime to be present and linked to the program. \\ +A C++ Kernel may instead make use of compile-time features of C++ alongside a tiny C++ runtime to make sure that no issues arise because of this host/freestanding difference. +} + +\subsection{Part Two: Constexpr and Friends} +{ +\textit{One may avoid V-tables or runtime dependent features when possible.} +While focusing instead on meta-programming and compile-time features offered by C++. For example one may use templates to implement a scheduling policy algorithm. \\ +One example of such implementation may be: \\ + +(Keep in mind that the code has not been tested on production systems, use it at your own risk!) + +\begin{lstlisting} +/// Reference Implementation: https://github.com +/// /nekernel-org/nekernel/blob/stable/src/kernel/ +/// KernelKit/CoreProcessScheduler.h#L51-L76 +/// AND: https://github.com/nekernel-org/nekernel/blob/stable/src/kernel +/// /KernelKit/CoreProcessScheduler.h#L78-L105 + +struct FileTree final { + static constexpr bool is_virtual_memory = false; + static constexpr bool is_memory = false; + static constexpr bool is_file = true; + /// ... +}; + +struct MemoryTree final { + static constexpr bool is_virtual_memory = false; + static constexpr bool is_memory = true; + static constexpr bool is_file = false; + /// ... +}; +\end{lstlisting} + +As you see, two structures leverages the `constexpr' keyword to make sure +no bugs or panic occur at runtime because of a misuse of a system resource. \\ + +Which is why the constexpr keyword is very powerful here, we avoid the many pitfalls of writing (and hoping) that the C version will be well-thought enough so that we can catch such bugs later. + +\subsection{Bonus: Using Concepts and the DDK.} +{ +This bonus subsection intends to show how properly applied C++\\ +Can solve issues related to driver validation. +The following example shows how powerful C++ can be when combining it with Device Driver development as well. + +\begin{lstlisting} +/// Reference implementation: +/// https://github.com/nekernel-org +/// /nekernel/blob/stable/src/libDDK/DriverKit +/// /c%2B%2B/driver_base.h +/// @brief This concept requires the driver +/// to be IDriverBase compliant. + +constexpr auto kInvalidType = 0; + +template <typename T> +concept IsValidDriver = requires(T a) { + { a.IsActive() && a.Type() > kInvalidType }; +}; + +/// @brief Consteval helper to detect +/// whether a template is truly based on IDriverBase. +/// @note This helper is consteval only. +template<IsValidDriver T> +consteval void ce_ddk_is_valid(T) {} +\end{lstlisting} +} +} + +\subsection{Part Three: Memory and C++ Classes} +{ +This last part treats about the final and most important part of this paper so far. Memory. As you may already have known, the C++ language uses a class lookup system (also called v-table) in order to refer to a base method in case if the instance has it missing. + +\begin{lstlisting} +/// Link: https://godbolt.org/z/q3Wceannr +/// /std:c++20 /Wall + +#include <iostream> + +class A +{ +public: + explicit A() = default; + virtual ~A() = default; + + virtual void doImpl() + { + std::cout << "doImpl\n"; + } +}; + +class B : public A +{ +public: + explicit B() = default; + ~B() override = default; +}; + +int main() { + B* callImpl = new B(); + callImpl->doImpl(); +} +\end{lstlisting} + +\section{Addressing V-Tables in a C++ Kernel.} + +Now the problem with kernel development is that we want to avoid such feature as much as possible, and we'd do that by following the Prong on Inheritance: + +\subsection{The Three Prongs on Inheritance:} + +Consider the following questions: + +\begin{itemize} +\item[A:] Is this a protocol/concept that can be extended to other similar protocols/concepts? +\item[B:] Can I do this without too much trade-off costs? +\item[C:] Can I do this without using V-Tables? +\end{itemize} +} + +When 2/3 of those questions fail, you should consider finding another solution to your problem, as it surely has an equivalent without V-Tables. + +\section{Conclusion} +{ +We can now conclude that C++ in Kernel Development is indeed possible under strict conditions of C++ Development. \\ +Breaking those conditions would lead to system quirks and instability. +A reference implementation of this paper exists, It's called NeKernel.org, available under the same internet address. \\ +I am looking forward to any questions or inquiries at: amlal@nekernel.org. +} + +\section{References} +{ +\begin{itemize} + \item[EKA2:] \href{https://en.wikipedia.org/wiki/EKA2}{Link} + \item[NeKernel.org:] \href{https://nekernel.org}{Link} + \item[Virtual Method Tables:] \href{https://en.wikipedia.org/wiki/Virtual_method_table}{Link} +\end{itemize} +} + +\end{document} diff --git a/source/wg02/wg02.tex b/source/wg02/wg02.tex new file mode 100644 index 0000000..b34f233 --- /dev/null +++ b/source/wg02/wg02.tex @@ -0,0 +1,166 @@ +% AUTHOR: Amlal El Mahrouss +% PURPOSE: WG02: CoreProcessScheduler + +\documentclass[11pt, a4paper]{article} +\usepackage{graphicx} +\usepackage{listings} +\usepackage{xcolor} +\usepackage{hyperref} + +\title{WG02: The CoreProcessScheduler} +\author{Amlal El Mahrouss\\NeKernel.org} +\date{\today} + +\definecolor{codegray}{gray}{0.95} +\definecolor{codeblue}{rgb}{0.1,0.1,0.8} +\definecolor{codegreen}{rgb}{0,0.6,0} +\definecolor{codepurple}{rgb}{0.58,0,0.82} + +\lstset{ + language=C++, + backgroundcolor=\color{codegray}, + basicstyle=\footnotesize\ttfamily, + keywordstyle=\color{codeblue}\bfseries, + commentstyle=\color{codegreen}, + stringstyle=\color{codepurple}, + numbers=left, + numberstyle=\tiny\color{gray}, + stepnumber=1, + numbersep=5pt, + breaklines=true, + breakatwhitespace=false, + frame=single, + rulecolor=\color{black}, + captionpos=b, + keepspaces=true, + showspaces=false, + showstringspaces=false, + showtabs=false, + tabsize=2 +} + +\begin{document} + +\maketitle + +\section{Abstract} + +{The CoreProcessScheduler governs how the scheduling backend and policy of the kernel works, It is the common gateway for schedulers inside NeKernel based systems.} + +\section{Overview} + +{The CoreProcessScheduler (now referred as CPS) serves as the foundation between the scheduler backend and kernel.} {It takes care of process life-cycle management, team-based process grouping, and affinity-based CPU based allocation to mention the least.} + +\section{The Affinity System} + +{Processes are given CPU time affinity hints using an affinity kind type, these hints help the scheduler run or adjust the current process.} + +\subsection{Sample Code \#1} + +{The following sample is C++ code.} {The smaller the value, the more critical the process.} + +\begin{lstlisting} +enum class AffinityKind : Int32 { + kRealTime = 100, + kVeryHigh = 150, + kHigh = 200, + kStandard = 1000, + kLowUsage = 1500, + kVeryLowUsage = 2000, +}; +\end{lstlisting} + +\section{The Team System} + +{The team system holds process metadata for the backend scheduler to run on. It holds methods and fields for backend specific operations.} {One implementation of such team is the UserProcessTeam object inside NeKernel.} + +\subsection{Sample Code \#2} + +{The following sample is used to hold team metadata.} {This is part of the NeKernel source tree.} + +\begin{lstlisting} +class UserProcessTeam final { + public: + explicit UserProcessTeam(); + ~UserProcessTeam() = default; + + NE_COPY_DEFAULT(UserProcessTeam) + + Array<USER_PROCESS, kSchedProcessLimitPerTeam>& AsArray(); + Ref<USER_PROCESS>& AsRef(); + ProcessID& Id() noexcept; + + public: + USER_PROCESS_ARRAY mProcessList; + USER_PROCESS_REF mCurrentProcess; + ProcessID mTeamId{0}; + ProcessID mProcessCur{0}; +}; +\end{lstlisting} + +\section{The Process Image System} + +{The process image container is a design pattern made to contain process data and metadata, its purpose comes from the lack of mainstream operating systems of such ability to hold metadata.} + +{This approach helps separate concerns and give modularity to the system, as the image and process structure are not mixed together.} + +\subsection{Sample Code \#3} + +{The following sample is a C++ container used to hold process data and metadata.} {This is part of the NeKernel source tree.} + +\begin{lstlisting} +using ImagePtr = void*; + +struct PROCESS_IMAGE final { + explicit PROCESS_IMAGE() = default; + + private: + friend USER_PROCESS; + friend KERNEL_TASK; + + friend class UserProcessScheduler; + + ImagePtr fCode; + ImagePtr fBlob; + + public: + Bool HasCode() const { return this->fCode != nullptr; } + + Bool HasImage() const { return this->fBlob != nullptr; } + + ErrorOr<ImagePtr> LeakImage() { + if (this->fCode) { + return ErrorOr<ImagePtr>{this->fCode}; + } + + return ErrorOr<ImagePtr>{kErrorInvalidData}; + } + + ErrorOr<ImagePtr> LeakBlob() { + if (this->fBlob) { + return ErrorOr<ImagePtr>{this->fBlob}; + } + + return ErrorOr<ImagePtr>{kErrorInvalidData}; + } +}; +\end{lstlisting} + +\section{Conclusion} + +{The CoreProcessScheduler is a piece of systems design with robust design and useful cases, although useful in desktop/server cases, It may not be suited for every other tasks.} + +{And while one scheduler backend (such as the UserProcessScheduler) takes care of user process scheduling and fairness, the CoreProcessScheduler takes care of the foundation for those systems.} + +\section{References} + +{ +\begin{itemize} + \item[CoreProcessScheduler:] \href{https://github.com/nekernel-org/nekernel/blob/develop/src/kernel/KernelKit/CoreProcessScheduler.h}{Link} + \item[NeKernel.org:] \href{https://nekernel.org/nekernel}{Link} + \item[Round Robin (OSTEP):] \href{https://pages.cs.wisc.edu/~remzi/OSTEP/cpu-sched.pdf}{Link} + \item[Processor Affinity:] \href{https://www.tmurgent.com/WhitePapers/ProcessorAffinity.pdf}{Link} +\end{itemize} +} + +\end{document}
\ No newline at end of file diff --git a/source/wg03/.keep b/source/wg03/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/wg03/.keep |
