The PandOS+ project structure heavily relies on cmake sub-directory functionality, which allows for modular compilation based on target architecture and toggle flags. The root directory contains three major kind of sub-directories:
os: the major library providing all functionality required for the various phases and ultimately the proper operating system implementation. The library also contains utility procedures to aid debugging on the target machine;test: unit tests to be executed on the host's machine aimed at verifying the logic correctness of the functionality implemented in theossub-project. These unit tests should complement the providedphase{n}tests;phase{n}: the code for each phase of the project to be compiled into a MIPS kernel and tested on the uMPS3 emulator.
The identifier for a new born process (pid for short) is generated in a semi-unique way, which provides a good balance between raw performance and robustness. The 32 bits of the pid are initially subdivided into two sections:
- the lower
MAX_PROC_BITSbits identify the index of the underlyingpcb_tstructure in the table of allpcb_ts; - the remaining
WORD_BITS - MAX_PROC_BITSbits are set to the lower bits of therecycle_countcounter.
Finally, the resulting pid is incremented by one. This is done to reserve 0 as
the value of the conventional NULL_PID, which does not describe any valid pid
at all. The value of MAX_PROC_BITS is computed by hand based on the value of
MAX_PROC, preserving the following invariant:
This approach does not guarantee a complete uniqueness (which cannot be achieved
with any limited word length) but is nonetheless an improvement over the simpler
usage of indices/addresses. Compared to incremental pids the chosen implementation
lowers the address space significantly by halving possible pids by a factor of
2^MAX_PROC_BITS and using a shared recycle count for all processes. An
improvement (at the cost of some memory) could use an array of MAX_PROC
recycle counters, having one for each process. This latter approach could also
improve safety by making pid spoofing much harder.
This project uses cmake and make to compile and requires the host's C
compiler along with the MIPSel cross compilation toolchain even when targeting
the host machine. The following cmake options are available:
CROSS_COMPILE: defaults toON (1). Toggle the target of compilation between the host's system (OFF (0)) and the MIPS architecture (ON (1));DEBUG: defaults toOFF (0). Whether to attach gdb debug information to the compiled object, improving the debugging experience on the host machine;CMAKE_EXPORT_COMPILE_COMMANDS: defaults toOFF (0). Can be set to true to generate acompile_commands.jsonin the artifacts directory containing all compile flags for each file of the project. It's required by language servers likeclangdorcclsto offer meaningful advice.
The standard default cmake build will compile all project phases (i.e. the tests
in phase{n}) and generate a UMPS3 kernel for each. Provided you call the
artifact directory build the emulator configuration found in
machines/phase{n} should work out of the box.
mkdir build && cd build
cmake ..
makeIf you have any issues with machines/phase3, please try using
machines/phase3-bin instead.
The cmake build system allows us to easily swap C compilers and we can use that
to our advantage. Compiling for the host's system architecture allows us to run
the contents of the test directory locally and check for logic correctness. We
can therefore disable cross-compilation via the CROSS_COMPILE option and run
unit tests as shown below:
mkdir buildt && cd buildt
cmake -DCROSS_COMPILE=0 ..
make && make testThe project offline documentation can be generated via
Doxygen. The following commands will produce the
output TeX files in build/docs/latex.
mkdir build && cd build
cmake ..
make docsAny C Language Server needs to know how all source files will be compiled (namely the flags given to the compiler) to correctly work. Providing the flags for each file can be tedious, so using the cmake builtin functionality is preferred:
mkdir build && cd build
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..
mv compile_commands.json ..