From bbccd217b5e9ad1dec7664f7ae058d179768c9e0 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Sat, 6 Dec 2025 11:25:13 -0500 Subject: chore: new version of papers WG01 and WG02. Signed-off-by: Amlal El Mahrouss --- draft/wg01/cpp_kernel_dev.tex | 165 ----------------------------------- draft/wg01/wg01.tex | 195 ++++++++++++++++++++++++++++++++++++++++++ draft/wg02/cpp_cps.tex | 130 ---------------------------- draft/wg02/wg02.tex | 166 +++++++++++++++++++++++++++++++++++ 4 files changed, 361 insertions(+), 295 deletions(-) delete mode 100644 draft/wg01/cpp_kernel_dev.tex create mode 100644 draft/wg01/wg01.tex delete mode 100644 draft/wg02/cpp_cps.tex create mode 100644 draft/wg02/wg02.tex (limited to 'draft') diff --git a/draft/wg01/cpp_kernel_dev.tex b/draft/wg01/cpp_kernel_dev.tex deleted file mode 100644 index 71afb7d..0000000 --- a/draft/wg01/cpp_kernel_dev.tex +++ /dev/null @@ -1,165 +0,0 @@ -\documentclass{article} -\usepackage{graphicx} -\usepackage{listings} - -\lstset { % - language=C++ -} - -\title{WG01: C++ for Kernel Development} -\author{Amlal El Mahrouss\\NeKernel.org} -\date{\today} - -\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} -{ -One may avoid v-tables and runtime dependent features as much as 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 can see these 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. - -template -concept IsValidDriver = requires(T a) { - { a.IsActive() && a.Type() > 0 }; -}; - -/// @brief Consteval helper to detect -/// whether a template is truly based on IDriverBase. -/// @note This helper is consteval only. -template -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 - -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} - -\subsection{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{Final Words and 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 \\\\Yours truly, \\ -Amlal El Mahrouss -} - -\section{References} -{ -\begin{itemize} - \item[EKA2:] https://en.wikipedia.org/wiki/EKA2 - \item[NeKernel.org:] https://nekernel.org -\end{itemize} -} - -\end{document} diff --git a/draft/wg01/wg01.tex b/draft/wg01/wg01.tex new file mode 100644 index 0000000..f116cb8 --- /dev/null +++ b/draft/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 +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 +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 + +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/draft/wg02/cpp_cps.tex b/draft/wg02/cpp_cps.tex deleted file mode 100644 index ad55331..0000000 --- a/draft/wg02/cpp_cps.tex +++ /dev/null @@ -1,130 +0,0 @@ -\documentclass{article} -\usepackage{graphicx} -\usepackage{hyperref} - -\title{WG02: The CoreProcessScheduler} -\author{Amlal El Mahrouss\\NeKernel.org} -\date{\today} - -\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 intermediate foundal 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{verbatim} -enum class AffinityKind : Int32 { - kRealTime = 100, - kVeryHigh = 150, - kHigh = 200, - kStandard = 1000, - kLowUsage = 1500, - kVeryLowUsage = 2000, -}; -\end{verbatim} - -\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{verbatim} -class UserProcessTeam final { - public: - explicit UserProcessTeam(); - ~UserProcessTeam() = default; - - NE_COPY_DEFAULT(UserProcessTeam) - - Array& AsArray(); - Ref& AsRef(); - ProcessID& Id() noexcept; - - public: - USER_PROCESS_ARRAY mProcessList; - USER_PROCESS_REF mCurrentProcess; - ProcessID mTeamId{0}; - ProcessID mProcessCur{0}; -}; - -\end{verbatim} - -\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{verbatim} -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 LeakImage() { - if (this->fCode) { - return ErrorOr{this->fCode}; - } - - return ErrorOr{kErrorInvalidData}; - } - - ErrorOr LeakBlob() { - if (this->fBlob) { - return ErrorOr{this->fBlob}; - } - - return ErrorOr{kErrorInvalidData}; - } -}; - -\end{verbatim} - -\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} - -{NeKernel}: \href{https://github.com/nekernel-org/nekernel}{NeKernel} - -{CoreProcessScheduler}: \href{https://github.com/nekernel-org/nekernel/blob/develop/src/kernel/KernelKit/CoreProcessScheduler.h}{CoreProcessScheduler} - -\end{document} \ No newline at end of file diff --git a/draft/wg02/wg02.tex b/draft/wg02/wg02.tex new file mode 100644 index 0000000..b34f233 --- /dev/null +++ b/draft/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& AsArray(); + Ref& 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 LeakImage() { + if (this->fCode) { + return ErrorOr{this->fCode}; + } + + return ErrorOr{kErrorInvalidData}; + } + + ErrorOr LeakBlob() { + if (this->fBlob) { + return ErrorOr{this->fBlob}; + } + + return ErrorOr{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 -- cgit v1.2.3