Merge branch 'develop' into feature/remove_nasm

This commit is contained in:
Enrico Fraccaroli
2024-01-15 15:26:56 +01:00
52 changed files with 339 additions and 733 deletions
-39
View File
@@ -1,39 +0,0 @@
name: MacOS
on:
push:
branches-ignore:
- "releases/**"
paths-ignore:
- "**.md"
- ".gitignore"
- "**/ubuntu.yml"
- "**/windows.yml"
pull_request:
paths-ignore:
- "**.md"
- ".gitignore"
- "**/ubuntu.yml"
- "**/windows.yml"
jobs:
build:
name: Build
runs-on: macos-latest
steps:
- name: Clone repository
uses: actions/checkout@v3
- name: Install dependencies
run: |
brew install x86_64-elf-gcc nasm
- name: Build
run: |
cmake \
-DCMAKE_C_COMPILER=x86_64-elf-gcc \
-DCMAKE_AR=x86_64-elf-gas \
-DCMAKE_LINKER=x86_64-elf-ld \
-DCMAKE_OBJCOPY=x86_64-elf-objcopy \
-DCMAKE_OBJDUMP=x86_64-elf-objdump \
-DCMAKE_RANLIB=x86_64-elf-ranlib \
-DCMAKE_ASM_COMPILER=/usr/local/bin/nasm \
-DCMAKE_SYSTEM_NAME=Linux \
-B build
cmake --build build --parallel 2 --verbose
-36
View File
@@ -1,36 +0,0 @@
name: Windows
on:
push:
branches-ignore:
- "releases/**"
paths-ignore:
- "**.md"
- ".gitignore"
- "**/macos.yml"
- "**/ubuntu.yml"
pull_request:
paths-ignore:
- "**.md"
- ".gitignore"
- "**/macos.yml"
- "**/ubuntu.yml"
jobs:
test:
name: Build
runs-on: windows-latest
steps:
- name: Clone repo
uses: actions/checkout@v3
- name: Install dependencies
run: |
choco install nasm
echo "C:\Program Files\NASM" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Set up MinGW
uses: egor-tensin/setup-mingw@v2
with:
version: latest
platform: x32
- name: Build
run: |
cmake -B build
cmake --build build --parallel 2
-6
View File
@@ -1,6 +0,0 @@
{
"files.associations": {
"string.h": "c",
"debug.h": "c"
}
}
+5 -3
View File
@@ -30,7 +30,7 @@ message(STATUS "System name : ${CMAKE_HOST_SYSTEM_NAME}")
message(STATUS "Kernel version : ${CMAKE_SYSTEM_VERSION}")
if((${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Darwin") OR APPLE)
# Specify the linker flags.
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nostdlib")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nostdlib")
elseif((${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows") OR WIN32)
# Windows set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -sdl)
else()
@@ -58,7 +58,7 @@ else()
# set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -sdl)
endif()
# Speicfy the linker.
# set(CMAKE_LINKER ld)
set(CMAKE_LINKER ld)
endif()
# Enable the assembly language.
@@ -97,6 +97,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-pic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding")
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcommon")
endif()
@@ -201,7 +202,8 @@ add_custom_target(
COMMAND bash ${CMAKE_SOURCE_DIR}/scripts/get_text_address.sh ${CMAKE_BINARY_DIR}/programs/prog_* >> ${CMAKE_BINARY_DIR}/.gdbinit
COMMAND echo "break boot.c: boot_main" >> ${CMAKE_BINARY_DIR}/.gdbinit
COMMAND echo "break kernel.c: kmain" >> ${CMAKE_BINARY_DIR}/.gdbinit
COMMAND echo "target remote localhost:1234" >> ${CMAKE_BINARY_DIR}/.gdbinit
# Create the GDB connection file.
COMMAND echo "target remote localhost:1234" > ${CMAKE_BINARY_DIR}/gdb.run
DEPENDS ${CMAKE_BINARY_DIR}/mentos/kernel_bootloader.bin
DEPENDS ${CMAKE_BINARY_DIR}/mentos/kernel.bin
DEPENDS all_programs
+47 -55
View File
@@ -5,24 +5,29 @@
[![forthebadge](https://forthebadge.com/images/badges/for-you.svg)](https://forthebadge.com)
[![Ubuntu](https://github.com/mentos-team/MentOS/actions/workflows/ubuntu.yml/badge.svg)](https://github.com/mentos-team/MentOS/actions/workflows/ubuntu.yml)
[![MacOS](https://github.com/mentos-team/MentOS/actions/workflows/macos.yml/badge.svg)](https://github.com/mentos-team/MentOS/actions/workflows/macos.yml)
## Table of Contents
1. [What is MentOS](#1-what-is-mentos)
2. [Implemented features](#2-implemented-features)
3. [Prerequisites](#3-prerequisites)
4. [Compiling MentOS](#4-compiling-mentos)
5. [Generating the EXT2 filesystem](#5-generating-the-ext2-filesystem)
6. [Running MentOS](#6-running-mentos)
7. [Running MentOS from GRUB](#7-running-mentos-from-grub)
8. [Running and adding new programs to MentOS](#8-running-and-adding-new-programs-to-mentos)
9. [Kernel logging](#9-kernel-logging)
10. [Change the scheduling algorithm](#10-change-the-scheduling-algorithm)
11. [Debugging the kernel](#11-debugging-the-kernel)
12. [Contributors](#12-contributors)
- [MentOS (Mentoring Operating System)](#mentos-mentoring-operating-system)
- [Table of Contents](#table-of-contents)
- [What is MentOS](#what-is-mentos)
- [Implemented features](#implemented-features)
- [Prerequisites](#prerequisites)
- [Installing the prerequisites](#installing-the-prerequisites)
- [Compiling MentOS](#compiling-mentos)
- [Generating the EXT2 filesystem](#generating-the-ext2-filesystem)
- [Running MentOS](#running-mentos)
- [Running MentOS from GRUB](#running-mentos-from-grub)
- [Running and adding new programs to MentOS](#running-and-adding-new-programs-to-mentos)
- [Create a new program](#create-a-new-program)
- [Add the new program to the list of compiled sources](#add-the-new-program-to-the-list-of-compiled-sources)
- [Running a program or a test](#running-a-program-or-a-test)
- [Kernel logging](#kernel-logging)
- [Change the scheduling algorithm](#change-the-scheduling-algorithm)
- [Debugging the kernel](#debugging-the-kernel)
- [Contributors](#contributors)
## 1. What is MentOS
## What is MentOS
MentOS (Mentoring Operating System) is an open source educational operating
system. The goal of MentOS is to provide a project environment that is realistic
@@ -46,7 +51,8 @@ Gualandri.
*[Back to the Table of Contents](#table-of-contents)*
## 2. Implemented features
## Implemented features
Follows the list of implemented features:
**Processes and Events**
@@ -91,22 +97,18 @@ I will try to keep it updated...
*[Back to the Table of Contents](#table-of-contents)*
## 3. Prerequisites
## Prerequisites
MentOS is compatible with the main **unix-based** operating systems. It has been
tested with *Ubuntu*, *WSL1*, *WSL2*, and *MacOS*.
tested with *Ubuntu*, and under Windows with *WSL1* and *WSL2*.
### 3.1. Generic Prerequisites
For **compiling** the system we need:
#### 3.1.1. Compile
For compiling the system:
- nasm
- git
- gcc
- nasm
- make
- cmake
- git
- ccmake (suggested)
- e2fsprogs (should be already installed)
@@ -115,43 +117,29 @@ Under **MacOS**, for compiling, you have additional dependencies:
- i386-elf-binutils
- i386-elf-gcc
#### 3.1.2. Execute
To execute the operating system, you need to install:
For **executing** the operating system we need:
- qemu-system-i386 (or qemu-system-x86)
#### 3.1.3. Debug
For debugging we suggest using:
For **debugging** we suggest using:
- gdb or cgdb
### 3.2. installation Prerequisites
### Installing the prerequisites
Under **Ubuntu**, you can type the following commands:
```bash
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y build-essential git cmake qemu-system-x86 nasm e2fsprogs
sudo apt-get install -y git build-essential nasm make cmake cmake-curses-gui e2fsprogs
sudo apt-get install -y qemu-system-x86
sudo apt-get install -y gdb cgdb
```
Note: Older versions might have `qemu-system-i386` instead of `qemu-system-x86`.
Under **MacOS** you also need to install the i386-elf cross-compiler. The
simplest installation method is through Homebrew package manager.
Install [Homebrew](https://brew.sh) if you don't already have it, and
then type the following commands:
```bash
brew update && brew upgrade
brew install i386-elf-binutils i386-elf-gcc git cmake qemu nasm e2fsprogs
brew install gdb cgdb #<- for debug only
```
*[Back to the Table of Contents](#table-of-contents)*
## 4. Compiling MentOS
## Compiling MentOS
Compile MentOS with:
@@ -165,7 +153,7 @@ make
*[Back to the Table of Contents](#table-of-contents)*
## 5. Generating the EXT2 filesystem
## Generating the EXT2 filesystem
Generate the EXT2 filesystem with:
@@ -176,7 +164,7 @@ you just need to generate the filesystem once. If you change a `program` you nee
*[Back to the Table of Contents](#table-of-contents)*
## 6. Running MentOS
## Running MentOS
Boot MentOS with qemu:
@@ -188,7 +176,7 @@ To login, use one of the usernames listed in `files/etc/passwd`.
*[Back to the Table of Contents](#table-of-contents)*
## 7. Running MentOS from GRUB
## Running MentOS from GRUB
For booting MentOS from GRUB in QEMU we need the following tools:
@@ -211,11 +199,11 @@ make qemu-grub
*[Back to the Table of Contents](#table-of-contents)*
## 8. Running and adding new programs to MentOS
## Running and adding new programs to MentOS
This section explains how to add a new program to MentOS, and also how to run programs in mentos. It also explains how to add new tests, which are located in the `programs/tests` folder.
### 8.1. Create a new program
### Create a new program
Head to the `programs` (or the `programs/tests`) folder. Create and open a new program, for instance a file called `hello_world.c`, with your preferred editor, and add this content to the file:
```C
@@ -228,7 +216,7 @@ int main(int argc, char *argv[])
}
```
### 8.2. Add the new program to the list of compiled sources
### Add the new program to the list of compiled sources
Now we can add the program to the list of files which are compiled and placed inside MentOS filesystem.
The following procedure is the same for both `programs` and `programs/tests`, what changes is which `CMakeLists.txt` file we modify.
@@ -253,7 +241,7 @@ set(TESTS
That's it, the `hello_world.c` file will be compiled and will appear inside the `/bin` or `/bin/tests` folder of MentOS.
### 8.3. Running a program or a test
### Running a program or a test
Once you login into MentOS, if you placed your source code in `programs`, you can execute the program by simply typing:
```bash
hello_world
@@ -268,7 +256,7 @@ However, the `/bin/tests` folder is not listed in `PATH`, so, if you want to exe
*[Back to the Table of Contents](#table-of-contents)*
## 9. Kernel logging
## Kernel logging
The kernel provides ways of printing logging messages *from* inside the kernel code *to* the bash where you executed the `make qemu`.
These *logging* functions are:
@@ -322,7 +310,7 @@ This example sets the `__DEBUG_LEVEL__`, so that all the messages from `INFO` an
*[Back to the Table of Contents](#table-of-contents)*
## 10. Change the scheduling algorithm
## Change the scheduling algorithm
MentOS supports scheduling algorithms for aperiodic:
@@ -390,7 +378,7 @@ make qemu
*[Back to the Table of Contents](#table-of-contents)*
## 11. Debugging the kernel
## Debugging the kernel
If you want to use GDB to debug MentOS, first you need to compile everything:
@@ -450,7 +438,7 @@ to connect to the running process.
*[Back to the Table of Contents](#table-of-contents)*
## 12. Contributors
## Contributors
Project Manager:
@@ -472,5 +460,9 @@ Developers:
- Soft IRQs
- Timer
- Signals
* And many other valuable contributors
* [rouseabout](https://github.com/rouseabout)
* [seekbytes](https://github.com/seekbytes)
* [fischerling](https://github.com/fischerling)
*[Back to the Table of Contents](#table-of-contents)*
+6 -8
View File
@@ -1,6 +1,6 @@
/// @file waitpid.c
/// @brief
/// @copyright (c) 2014-2023 This file is distributed under the MIT License.
/// @copyright (c) 2014-2024 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include "sys/unistd.h"
@@ -18,19 +18,17 @@ pid_t waitpid(pid_t pid, int *status, int options)
int __status = 0;
do {
__inline_syscall3(__res, waitpid, pid, &__status, options);
if (__res < 0) {
if (__res != 0) {
break;
}
if (__status == EXIT_ZOMBIE) {
break;
}
}
if (options && WNOHANG) {
break;
}
}
} while (1);
if (status) {
*status = __status;
}
}
__syscall_return(pid_t, __res);
}
+2
View File
@@ -15,6 +15,8 @@ option(USE_BUDDY_SYSTEM "Build using the buddysystem written by the user." OFF)
option(ENABLE_CACHE_TRACE "Enables cache tracing." OFF)
# Enables memory allocation tracing.
option(ENABLE_ALLOC_TRACE "Enables memory allocation tracing." OFF)
# Enables scheduling feedback on terminal.
option(ENABLE_SCHEDULER_FEEDBACK "Enables scheduling feedback on terminal." OFF)
# =============================================================================
# SOURCES
+5 -13
View File
@@ -9,45 +9,37 @@ MEMORY {
SECTIONS
{
. = 0x00100000;
_bootloader_start = .;
_bootloader_start = .;
.multiboot . : AT(ADDR(.multiboot))
{
. = ALIGN(4);
_multiboot_header_start = .;
*(.multiboot_header)
_multiboot_header_end = .;
} > BOOTLOADER_MEM
/* Put the .text section. */
.text . : AT(ADDR(.text))
{
_text_start = .;
*(.text)
_text_end = .;
} > BOOTLOADER_MEM
/* Read-only data. */
.rodata ALIGN(4K) : AT(ADDR(.rodata))
{
_rodata_start = .;
*(.rodata)
_rodata_end = .;
} > BOOTLOADER_MEM
/* Read-write data (initialized) */
.data ALIGN(4K) : AT(ADDR(.data))
.data ALIGN(4K) : AT(ADDR(.data))
{
_data_start = .;
*(.data)
_data_end = .;
} > BOOTLOADER_MEM
/* Read-write data (uninitialized) and stack */
.bss ALIGN(4K) : AT(ADDR(.bss))
.bss ALIGN(4K) : AT(ADDR(.bss))
{
_bss_start = .;
*(.bss*)
_bss_end = .;
} > BOOTLOADER_MEM
/* Put a symbol end here, it tells us where all the kernel code/data ends,
+4
View File
@@ -112,3 +112,7 @@ int sys_waitperiod(void);
/// @param gid ID of the group
/// @return 1 if the group is orphan, 0 otherwise.
int is_orphaned_pgrp(pid_t gid);
/// @brief Exit the current process with status
/// @param status The exit status of the current process
void do_exit(int status);
-8
View File
@@ -15,33 +15,25 @@ SECTIONS
/* Put the .text section. */
.text . : AT(ADDR(.text))
{
_text_start = .;
EXCLUDE_FILE(*boot.*.o) *(.text)
_text_end = .;
} > KERNEL_LOWMEM
/* Read-only data. */
.rodata ALIGN(4K) : AT(ADDR(.rodata))
{
_rodata_start = .;
EXCLUDE_FILE(*boot.*.o) *(.rodata)
_rodata_end = .;
} > KERNEL_LOWMEM
/* Read-write data (initialized) */
.data ALIGN(4K) : AT(ADDR(.data))
{
_data_start = .;
EXCLUDE_FILE(*boot.*.o) *(.data)
_data_end = .;
} > KERNEL_LOWMEM
/* Read-write data (uninitialized) and stack */
.bss ALIGN(4K) : AT(ADDR(.bss))
{
_bss_start = .;
*(.bss*)
_bss_end = .;
} > KERNEL_LOWMEM
/* Put a symbol end here, it tells us where all the kernel code/data ends,
-103
View File
@@ -1,103 +0,0 @@
; MentOS, The Mentoring Operating system project
; @file boot.asm
; @brief Kernel start location, multiboot header
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
bits 32 ; All instructions should be 32-bit.
extern boot_main ; The start point of our C code
; The magic field should contain this.
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
; This should be in %eax.
MULTIBOOT_BOOTLOADER_MAGIC equ 0x2BADB002
; = Specify what GRUB should PROVIDE =========================================
; Align the kernel and kernel modules on i386 page (4KB) boundaries.
MULTIBOOT_PAGE_ALIGN equ 0x00000001
; Provide the kernel with memory information.
MULTIBOOT_MEMORY_INFO equ 0x00000002
; Must pass video information to OS.
MULTIBOOT_VIDEO_MODE equ 0x00000004
; -----------------------------------------------------------------------------
; This is the flag combination that we prepare for Grub
; to read at kernel load time.
MULTIBOOT_HEADER_FLAGS equ (MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO)
; Grub reads this value to make sure it loads a kernel
; and not just garbage.
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
LOAD_MEMORY_ADDRESS equ 0x00000000
; reserve (1024*1024) for the stack on a doubleword boundary
KERNEL_STACK_SIZE equ 0x100000
; -----------------------------------------------------------------------------
; SECTION (multiboot_header)
; -----------------------------------------------------------------------------
section .multiboot_header
align 4
; This is the GRUB Multiboot header.
multiboot_header:
; magic
dd MULTIBOOT_HEADER_MAGIC
; flags
dd MULTIBOOT_HEADER_FLAGS
; checksum
dd MULTIBOOT_CHECKSUM
; -----------------------------------------------------------------------------
; SECTION (data)
; -----------------------------------------------------------------------------
; section .data nobits
; align 4096
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
global boot_entry
boot_entry:
; Clear interrupt flag [IF = 0]; 0xFA
cli
; To set up a stack, we simply set the esp register to point to the top of
; our stack (as it grows downwards).
mov esp, stack_top
; pass the initial ESP
push esp
; pass Multiboot info structure
push ebx
; pass Multiboot magic number
push eax
; Call the boot_main() function inside boot.c
call boot_main
; Set interrupt flag [IF = 1]; 0xFA
; Clear interrupts and hang if we return from boot_main
cli
hang:
hlt
jmp hang
global boot_kernel
boot_kernel:
mov edx, [esp + 4] ; stack_pointer
mov ebx, [esp + 8] ; entry
mov eax, [esp + 12] ; boot info
mov esp, edx ; set stack pointer
push eax ; push the boot info
call ebx ; call the kernel main
; -----------------------------------------------------------------------------
; SECTION (bss)
; -----------------------------------------------------------------------------
section .bss
align 16
global stack_bottom
stack_bottom:
resb KERNEL_STACK_SIZE
global stack_top
stack_top:
; the top of the stack is the bottom because the stack counts down
+16 -3
View File
@@ -32,6 +32,19 @@
# reserve (1024*1024) for the stack on a doubleword boundary
.equ KERNEL_STACK_SIZE, 0x100000
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
.pushsection .note.name, "a", @note
.align 4
.long 2f - 1f /* namesz */
.long 4f - 3f /* descsz */
.long 18 /* type */
1:.asciz "MentOS" /* name */
2:.align 4
3:.long boot_entry /* desc */
4:.align 4
.popsection
# -----------------------------------------------------------------------------
# SECTION (multiboot_header)
# -----------------------------------------------------------------------------
@@ -40,11 +53,11 @@
# This is the GRUB Multiboot header.
multiboot_header:
# magic
.quad MULTIBOOT_HEADER_MAGIC
.long MULTIBOOT_HEADER_MAGIC
# flags
.quad MULTIBOOT_HEADER_FLAGS
.long MULTIBOOT_HEADER_FLAGS
# checksum
.quad MULTIBOOT_CHECKSUM
.long MULTIBOOT_CHECKSUM
# -----------------------------------------------------------------------------
# SECTION (data)
-116
View File
@@ -1,116 +0,0 @@
; MentOS, The Mentoring Operating system project
; @file exception.asm
; @brief
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
extern isr_handler
; Macro used to define a ISR which does not push an error code.
%macro ISR_NOERR 1
global INT_%1
INT_%1:
cli
; A normal ISR stub that pops a dummy error code to keep a
; uniform stack frame
push 0
push %1
jmp isr_common
%endmacro
; Macro used to define a ISR which pushes an error code.
%macro ISR_ERR 1
global INT_%1
INT_%1:
cli
push %1
jmp isr_common
%endmacro
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
; Standard X86 interrupt service routines
ISR_NOERR 0
ISR_NOERR 1
ISR_NOERR 2
ISR_NOERR 3
ISR_NOERR 4
ISR_NOERR 5
ISR_NOERR 6
ISR_NOERR 7
ISR_ERR 8
ISR_NOERR 9
ISR_ERR 10
ISR_ERR 11
ISR_ERR 12
ISR_ERR 13
ISR_ERR 14
ISR_NOERR 15
ISR_NOERR 16
ISR_NOERR 17
ISR_NOERR 18
ISR_NOERR 19
ISR_NOERR 20
ISR_NOERR 21
ISR_NOERR 22
ISR_NOERR 23
ISR_NOERR 24
ISR_NOERR 25
ISR_NOERR 26
ISR_NOERR 27
ISR_NOERR 28
ISR_NOERR 29
ISR_NOERR 30
ISR_NOERR 31
ISR_NOERR 80
isr_common:
; Save all registers (eax, ecx, edx, ebx, esp, ebp, esi, edi)
pusha
; Save segment registers
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; CLD - Azzera la flag di Direzione
; Questa istruzione forza semplicemente a zero la flag di Direzione.
; Quando la flag di direzione vale 0 tutte le istruzioni per la
; manipolazione delle stringhe agiscono in avanti, cioè dagli indirizzi più
; bassi a quelli più alti.
; L'istruzione agisce dunque sui puntatori SI e DI producendo su essi un
; autoincremento proporzionale alla dimensione degli operandi trattati.
; Le sue caratteristiche sono riassunte nella seguente tabella (leggi le
; istruzioni Legenda della Tabella):
cld
; Call the interrupt handler.
push esp
call isr_handler
add esp, 0x4
; Restore segment registers.
pop gs
pop fs
pop es
pop ds
; Restore all registers (eax, ecx, edx, ebx, esp, ebp, esi, edi).
popa
; Cleanup error code and IRQ #
add esp, 0x8
iret ; pops 5 things at once:
; CS, EIP, EFLAGS, SS, and ESP
-30
View File
@@ -1,30 +0,0 @@
; MentOS, The Mentoring Operating system project
; @file gdt.asm
; @brief
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
global gdt_flush ; Allows the C code to call gdt_flush().
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
gdt_flush:
mov eax, [esp+4] ; Get the pointer to the GDT, passed as a parameter.
lgdt [eax] ; Load the new GDT pointer
; The data segments selectors (registers), can be easily modified using
; simple mov instruction, but the cs can't be used with mov, so you use:
jmp 0x08:flush
; to load the segment configurations into the the code segment selector.
flush:
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
mov ds, ax ; Load all data segment selectors
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret
-17
View File
@@ -1,17 +0,0 @@
; MentOS, The Mentoring Operating system project
; @file idt.asm
; @brief
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
global idt_flush ; Allows the C code to call idt_flush().
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
idt_flush:
mov eax, [esp+4] ; Get the pointer to the IDT, passed as a parameter.
lidt [eax] ; Load the IDT pointer.
ret
+55 -57
View File
@@ -1,28 +1,26 @@
; MentOS, The Mentoring Operating system project
; @file interrupt.asm
; @brief
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
# MentOS, The Mentoring Operating system project
# @file interrupt.asm
# @brief
# @copyright (c) 2014-2021 This file is distributed under the MIT License.
# See LICENSE.md for details.
extern irq_handler
.extern irq_handler
%macro IRQ 2
global IRQ_%1
IRQ_%1:
cli ; disable interrupt line
; A normal ISR stub that pops a dummy error code to keep a
; uniform stack frame
push 0
push %2 ; irq number
.macro IRQ ARG1, ARG2
.globl IRQ_&ARG1
IRQ_&ARG1:
cli # disable interrupt line
push $0
push &ARG2
jmp irq_common
%endmacro
.endm
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
# -----------------------------------------------------------------------------
# SECTION (text)
# -----------------------------------------------------------------------------
.text
; 32 is the first irq, 47 is the last one. DO NOT CHANGE THESE NUMBERS.
# 32 is the first irq, 47 is the last one. DO NOT CHANGE THESE NUMBERS.
IRQ 0, 32
IRQ 1, 33
IRQ 2, 34
@@ -40,52 +38,52 @@ IRQ 13, 45
IRQ 14, 46
IRQ 15, 47
irq_common:
;==== Save CPU registers ===================================================
; when an irq occurs, the following registers are already pushed on stack:
; eip, cs, eflags, useresp, ss
irq_common:
# ==== Save CPU registers ===================================================
# when an irq occurs, the following registers are already pushed on stack:
# eip, cs, eflags, useresp, ss
; Save registers: eax, ecx, edx, ebx, esp, ebp, esi, edi
# Save registers: eax, ecx, edx, ebx, esp, ebp, esi, edi
pusha
; Save segment registers
push ds
push es
push fs
push gs
;---------------------------------------------------------------------------
# Save segment registers
push %ds
push %es
push %fs
push %gs
# ---------------------------------------------------------------------------
;==== ensure we are using kernel data segment ==============================
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
# ==== ensure we are using kernel data segment ==============================
mov $0x10,%ax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
mov %ax,%gs
cld
;---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
;==== Call the interrupt handler ===========================================
; The argument passed is a pointer to an Interrupt_State struct,
; which describes the stack layout for all interrupts.
push esp
# ==== Call the interrupt handler ===========================================
# The argument passed is a pointer to an Interrupt_State struct,
# which describes the stack layout for all interrupts.
push %esp
call irq_handler
add esp, $4 ; remove esp from stack
;---------------------------------------------------------------------------
add $0x04, %esp # remove esp from stack
# ---------------------------------------------------------------------------
;==== Restore registers ====================================================
; restore segment registers
pop gs
pop fs
pop es
pop ds
# ==== Restore registers ====================================================
# restore segment registers
pop %gs
pop %fs
pop %es
pop %ds
; restore registers: eax, ecx, edx, ebx, esp, ebp, esi, edi
# restore registers: eax, ecx, edx, ebx, esp, ebp, esi, edi
popa
;---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
; Cleanup error code and IRQ #
add esp, $8
# Cleanup error code and IRQ #
add $0x08, %esp
; return to process
iret ; pops 5 things at once:
; CS, EIP, EFLAGS, SS, and ESP
# return to process
iret # pops 5 things at once:
# CS, EIP, EFLAGS, SS, and ESP
-17
View File
@@ -1,17 +0,0 @@
; MentOS, The Mentoring Operating system project
; @file tss.asm
; @brief
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
global tss_flush
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
tss_flush:
mov ax, 0x28
ltr ax
ret
+1 -1
View File
@@ -6,7 +6,7 @@
// Setup the logging for this file (do this before any other include).
#include "sys/kernel_levels.h" // Include kernel log levels.
#define __DEBUG_HEADER__ "[ELF ]" ///< Change header.
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE ///< Set log level.
#define __DEBUG_LEVEL__ LOGLEVEL_DEBUG ///< Set log level.
#include "io/debug.h" // Include debugging functions.
#include "assert.h"
+23 -45
View File
@@ -43,28 +43,6 @@ char *module_start[MAX_MODULES];
/// Describe end address of grub multiboot modules.
char *module_end[MAX_MODULES];
// Everything is defined in kernel.ld.
/// Points at the multiheader grub info, starting address.
extern uint32_t _multiboot_header_start;
/// Points at the multiheader grub info, ending address.
extern uint32_t _multiboot_header_end;
/// Points at the kernel code, starting address.
extern uint32_t _text_start;
/// Points at the kernel code, ending address.
extern uint32_t _text_end;
/// Points at the read-only kernel data, starting address.
extern uint32_t _rodata_start;
/// Points at the read-only kernel data, ending address.
extern uint32_t _rodata_end;
/// Points at the read-write kernel data initialized, starting address.
extern uint32_t _data_start;
/// Points at the read-write kernel data initialized, ending address.
extern uint32_t _data_end;
/// Points at the read-write kernel data uninitialized an kernel stack, starting address.
extern uint32_t _bss_start;
/// Points at the read-write kernel data uninitialized an kernel stack, ending address.
extern uint32_t _bss_end;
/// Points at the top of the kernel stack.
extern uint32_t stack_top;
/// Points at the bottom of the kernel stack.
@@ -107,8 +85,8 @@ int kmain(boot_info_t *boot_informations)
boot_info = *boot_informations;
// Am I booted by a Multiboot-compliant boot loader?
if (boot_info.magic != MULTIBOOT_BOOTLOADER_MAGIC) {
printf("Invalid magic number: 0x%x\n", boot_info.magic);
return 1;
pr_emerg("Invalid magic number: 0x%x\n", boot_info.magic);
while (1) {}
}
// Set the initial esp.
initial_esp = boot_info.stack_base;
@@ -131,7 +109,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize modules...");
if (!init_modules(boot_info.multiboot_header)) {
print_fail();
return 1;
while (1) {}
}
print_ok();
@@ -140,7 +118,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize physical memory manager...");
if (!pmmngr_init(&boot_info)) {
print_fail();
return 1;
while (1) {}
}
print_ok();
@@ -216,7 +194,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize ATA devices...");
if (ata_initialize()) {
pr_emerg("Failed to initialize ATA devices!\n");
return 1;
while (1) {}
}
print_ok();
@@ -225,7 +203,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize EXT2 filesystem...");
if (ext2_initialize()) {
pr_emerg("Failed to initialize EXT2 filesystem!\n");
return 1;
while (1) {}
}
print_ok();
@@ -234,7 +212,7 @@ int kmain(boot_info_t *boot_informations)
printf("Mount EXT2 filesystem...");
if (do_mount("ext2", "/", "/dev/hda")) {
pr_emerg("Failed to mount EXT2 filesystem...\n");
return 1;
while (1) {}
}
print_ok();
@@ -244,7 +222,7 @@ int kmain(boot_info_t *boot_informations)
if (procfs_module_init()) {
print_fail();
pr_emerg("Failed to register `procfs`!\n");
return 1;
while (1) {}
}
print_ok();
@@ -253,7 +231,7 @@ int kmain(boot_info_t *boot_informations)
printf(" Mounting 'procfs'...");
if (do_mount("procfs", "/proc", NULL)) {
pr_emerg("Failed to mount procfs at `/proc`!\n");
return 1;
while (1) {}
}
print_ok();
@@ -263,7 +241,7 @@ int kmain(boot_info_t *boot_informations)
if (procv_module_init()) {
print_fail();
pr_emerg("Failed to initialize `/proc/video`!\n");
return 1;
while (1) {}
}
print_ok();
@@ -273,7 +251,7 @@ int kmain(boot_info_t *boot_informations)
if (procs_module_init()) {
print_fail();
pr_emerg("Failed to initialize proc system entries!\n");
return 1;
while (1) {}
}
print_ok();
@@ -283,7 +261,7 @@ int kmain(boot_info_t *boot_informations)
if (procipc_module_init()) {
print_fail();
pr_emerg("Failed to initialize the IPC information system!\n");
return 1;
while (1) {}
}
print_ok();
@@ -293,7 +271,7 @@ int kmain(boot_info_t *boot_informations)
if (sem_init()) {
print_fail();
pr_emerg("Failed to initialize the IPC/SEM system!\n");
return 1;
while (1) {}
}
print_ok();
@@ -303,7 +281,7 @@ int kmain(boot_info_t *boot_informations)
if (msq_init()) {
print_fail();
pr_emerg("Failed to initialize the IPC/MSQ system!\n");
return 1;
while (1) {}
}
print_ok();
@@ -313,7 +291,7 @@ int kmain(boot_info_t *boot_informations)
if (shm_init()) {
print_fail();
pr_emerg("Failed to initialize the IPC/SHM system!\n");
return 1;
while (1) {}
}
print_ok();
@@ -328,7 +306,7 @@ int kmain(boot_info_t *boot_informations)
if (ps2_initialize()) {
print_fail();
pr_emerg("Failed to initialize proc system entries!\n");
return 1;
while (1) {}
}
print_ok();
@@ -365,7 +343,7 @@ int kmain(boot_info_t *boot_informations)
printf("Init process management...");
if (!init_tasking()) {
print_fail();
return 1;
while (1) {}
}
print_ok();
@@ -375,7 +353,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize scheduler feedback system...");
if (!scheduler_feedback_init()) {
print_fail();
return 1;
while (1) {}
}
print_ok();
#endif
@@ -385,7 +363,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize scheduler feedback system (2)...");
if (procfb_module_init()) {
print_fail();
return 1;
while (1) {}
}
print_ok();
@@ -395,7 +373,7 @@ int kmain(boot_info_t *boot_informations)
task_struct *init_p = process_create_init("/bin/init");
if (!init_p) {
print_fail();
return 1;
while (1) {}
}
print_ok();
@@ -404,7 +382,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize floating point unit...");
if (!fpu_install()) {
print_fail();
return 1;
while (1) {}
}
print_ok();
@@ -413,7 +391,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize signals...");
if (!signals_init()) {
print_fail();
return 1;
while (1) {}
}
print_ok();
@@ -432,5 +410,5 @@ int kmain(boot_info_t *boot_informations)
for (;;) {}
// We should not be here.
pr_emerg("Dear developer, we have to talk...\n");
return 1;
while (1) {}
}
+10 -4
View File
@@ -4,10 +4,10 @@
/// See LICENSE.md for details.
// Setup the logging for this file (do this before any other include).
#include "sys/kernel_levels.h" // Include kernel log levels.
#define __DEBUG_HEADER__ "[PROC ]" ///< Change header.
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE ///< Set log level.
#include "io/debug.h" // Include debugging functions.
#include "sys/kernel_levels.h" // Include kernel log levels.
#define __DEBUG_HEADER__ "[PROC ]" ///< Change header.
#define __DEBUG_LEVEL__ LOGLEVEL_DEBUG ///< Set log level.
#include "io/debug.h" // Include debugging functions.
#include "assert.h"
#include "elf/elf.h"
@@ -91,11 +91,15 @@ static int __reset_process(task_struct *task)
return 0;
}
pr_debug("Switching to task page directory.\n");
// Save the current page directory.
page_directory_t *crtdir = paging_get_current_directory();
// FIXME: Now to clear the stack a pgdir switch is made, it should be a kernel mmapping.
paging_switch_directory_va(task->mm->pgd);
pr_debug("Clean stack (%p).\n", task->mm->start_stack);
// Clean stack space.
memset((char *)task->mm->start_stack, 0, DEFAULT_STACK_SIZE);
// Set the base address of the stack.
@@ -105,6 +109,8 @@ static int __reset_process(task_struct *task)
// Enable the interrupts.
task->thread.regs.eflags = task->thread.regs.eflags | EFLAG_IF;
pr_debug("Switching to previous page directory.\n");
// Restore previous pgdir
paging_switch_directory(crtdir);
+6 -1
View File
@@ -517,7 +517,7 @@ pid_t sys_waitpid(pid_t pid, int *status, int options)
return 0;
}
void sys_exit(int exit_code)
void do_exit(int exit_code)
{
// Get the current task.
if (runqueue.curr == NULL) {
@@ -573,6 +573,11 @@ void sys_exit(int exit_code)
pr_debug("Process %d exited with value %d\n", runqueue.curr->pid, exit_code);
}
void sys_exit(int exit_code)
{
do_exit(exit_code << 8);
}
int sys_sched_setparam(pid_t pid, const sched_param_t *param)
{
list_head *it;
-78
View File
@@ -1,78 +0,0 @@
; MentOS, The Mentoring Operating system project
; @file user.asm
; @brief
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
; Enter userspace (ring3) (from Ring 0, namely Kernel)
; Usage: enter_userspace(uintptr_t location, uintptr_t stack);
; On stack
; | stack | [ebp + 0x0C] ARG1
; | location | [ebp + 0x08] ARG0
; | return address | [ebp + 0x04]
; | EBP | [ebp + 0x00]
; | SS |
; | ESP |
; | EFLAGS |
; | CS |
; | EIP |
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
global enter_userspace ; Allows the C code to call enter_userspace(...).
enter_userspace:
push ebp ; Save current ebp
mov ebp, esp ; open a new stack frame
;==== Segment selector =====================================================
mov ax, 0x23
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; we don't need to worry about SS. it's handled by iret
;---------------------------------------------------------------------------
; We have to prepare the following stack before executing iret
; SS --> Segment selector
; ESP --> Stack address
; EFLAGS --> CPU state flgas
; CS --> Code segment
; EIP --> Entry point
;
;==== User data segmenet with bottom 2 bits set for ring3 ?=================
push 0x23 ; push SS on Kernel's stack
;---------------------------------------------------------------------------
;==== (ESP) Stack address ==================================================
mov eax, [ebp + 0x0C] ; get uintptr_t stack
push eax ; push process's stack address on Kernel's stack
;---------------------------------------------------------------------------
;==== (EFLAGS) =============================================================
pushf ; push EFLAGS into Kernel's stack
pop eax ; pop EFLAGS into eax
or eax, 0x200 ; enable interrupt
push eax ; push new EFLAGS on Kernel's stack
;---------------------------------------------------------------------------
;==== (CS) Code Segment ====================================================
push 0x1b ;
;---------------------------------------------------------------------------
;==== (EIP) Entry point ====================================================
mov eax, [ebp + 0x08] ; get uintptr_t location
push eax ; push uintptr_t location on Kernel's stack
;---------------------------------------------------------------------------
iret ; interrupt return
pop ebp
ret
; WE SHOULD NOT STILL BE HERE! :(p
+10 -10
View File
@@ -495,38 +495,38 @@ int do_signal(struct pt_regs *f)
continue;
case SIGQUIT:
sys_exit(GET_EXIT_STATUS(1));
do_exit(GET_EXIT_STATUS(1));
continue;
case SIGILL:
sys_exit(GET_EXIT_STATUS(132));
do_exit(GET_EXIT_STATUS(132));
continue;
case SIGTRAP:
sys_exit(GET_EXIT_STATUS(133));
do_exit(GET_EXIT_STATUS(133));
continue;
case SIGABRT:
sys_exit(GET_EXIT_STATUS(134));
do_exit(GET_EXIT_STATUS(134));
continue;
case SIGFPE:
sys_exit(GET_EXIT_STATUS(136) | signr);
do_exit(GET_EXIT_STATUS(136) | signr);
__unlock_task_sighand(current_process);
return 1;
case SIGBUS:
sys_exit(GET_EXIT_STATUS(138) | signr);
do_exit(GET_EXIT_STATUS(138) | signr);
__unlock_task_sighand(current_process);
return 1;
case SIGSEGV:
sys_exit(GET_EXIT_STATUS(139) | signr);
do_exit(GET_EXIT_STATUS(139) | signr);
__unlock_task_sighand(current_process);
return 1;
case SIGXCPU:
sys_exit(GET_EXIT_STATUS(158) | signr);
do_exit(GET_EXIT_STATUS(158) | signr);
__unlock_task_sighand(current_process);
case SIGXFSZ:
sys_exit(GET_EXIT_STATUS(159) | signr);
do_exit(GET_EXIT_STATUS(159) | signr);
__unlock_task_sighand(current_process);
case SIGSYS:
default:
sys_exit(GET_EXIT_STATUS(exit_code) | signr);
do_exit(GET_EXIT_STATUS(exit_code) | signr);
__unlock_task_sighand(current_process);
return 1;
}
+58
View File
@@ -1,6 +1,37 @@
# =============================================================================
# BUILD
# =============================================================================
# Add the executables (manually).
set(PROGRAMS
nice.c
ls.c
mkdir.c
ipcrm.c
login.c
man.c
logo.c
shell.c
cpuid.c
clear.c
rmdir.c
poweroff.c
rm.c
cat.c
init.c
ps.c
kill.c
edit.c
sleep.c
date.c
echo.c
showpid.c
uname.c
ipcs.c
touch.c
uptime.c
pwd.c
env.c
)
# Set the directory where the compiled binaries will be placed.
set(MENTOS_BIN_DIR ${CMAKE_SOURCE_DIR}/files/bin)
# Create the directory.
@@ -56,6 +87,23 @@ foreach(FILE_NAME ${PROGRAMS})
string(RANDOM LENGTH 1 ALPHABET 0123456789AB RANDOM_SEED ${RAND_HASH} TEXADDR_FIRST)
set(TEXT_ADDR 0x${TEXADDR_FIRST}${TEXADDR_INFIX}0000)
# =========================================================================
# EXECUTABLE
# =========================================================================
set(TARGET_NAME prog_${EXECUTABLE_NAME})
# =========================================================================
# TEXT ADDRESS
# =========================================================================
# Randomize .text section address so when debugging symbols don't clash.
# The allowed range is from 256MB to 2.75GB
# Minimum allowed address: 0x10000000
# Max allowed address: 0xB0000000
string(MD5 RAND_HASH ${FILE_NAME})
string(SUBSTRING ${RAND_HASH} 1 3 TEXADDR_INFIX)
string(RANDOM LENGTH 1 ALPHABET 0123456789AB RANDOM_SEED ${RAND_HASH} TEXADDR_FIRST)
set(TEXT_ADDR 0x${TEXADDR_FIRST}${TEXADDR_INFIX}0000)
# =========================================================================
# EXECUTABLE
# =========================================================================
@@ -76,6 +124,16 @@ foreach(FILE_NAME ${PROGRAMS})
# Set the output name.
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "${EXECUTABLE_NAME}")
target_link_libraries(${TARGET_NAME} libc)
# We need to specify the name of the entry function.
target_compile_options(${TARGET_NAME} PRIVATE -u_start)
# Add the linking properties.
set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "-Wl,-Ttext=${TEXT_ADDR},-e_start,-melf_i386")
# Set the output directory.
set_target_properties(${TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${MENTOS_BIN_DIR}")
# Set the output name.
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "${EXECUTABLE_NAME}")
# Append the program name to the list of all the executables.
list(APPEND ALL_EXECUTABLES ${TARGET_NAME})
endforeach()
+1 -1
View File
@@ -59,7 +59,7 @@ foreach(FILE_NAME ${TESTS})
# EXECUTABLE
# =========================================================================
# Create the target.
add_executable(${TARGET_NAME} ${FILE_NAME})
add_executable(${TARGET_NAME} ${CMAKE_SOURCE_DIR}/programs/tests/${FILE_NAME})
# Add the dependency to libc.
add_dependencies(${TARGET_NAME} libc)
# Add the includes.
+3 -2
View File
@@ -16,7 +16,6 @@ void sig_handler(int sig)
{
printf("handler(%d) : Starting handler.\n", sig);
if (sig == SIGABRT) {
static int counter = 0;
counter += 1;
@@ -38,8 +37,10 @@ int main(int argc, char *argv[])
if (sigaction(SIGABRT, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGABRT, strerror(errno));
return 1;
return EXIT_FAILURE;
}
abort();
return EXIT_SUCCESS;
}
+3 -4
View File
@@ -39,12 +39,11 @@ int main(int argc, char *argv[])
action.sa_handler = alarm_handler;
if (sigaction(SIGALRM, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGALRM, strerror(errno));
return 1;
return EXIT_FAILURE;
}
alarm(5);
while(1) { }
while (1) {}
return 0;
return EXIT_SUCCESS;
}
+5 -5
View File
@@ -22,12 +22,12 @@ int main(int argc, char *argv[])
int status;
if (argc != 2) {
__print_usage(argc, argv);
return 1;
return EXIT_FAILURE;
}
if (setenv("ENV_VAR", "pwd0", 0) == -1) {
printf("Failed to set env: `ENV_VAR`\n");
return 1;
return EXIT_FAILURE;
}
char *file = "echo";
@@ -54,11 +54,11 @@ int main(int argc, char *argv[])
execvpe(file, exec_argv, exec_envp);
} else {
__print_usage(argc, argv);
return 1;
return EXIT_FAILURE;
}
printf("Exec failed.\n");
return 1;
return EXIT_FAILURE;
}
wait(&status);
return 0;
return EXIT_SUCCESS;
}
+2 -2
View File
@@ -11,8 +11,8 @@ int main(int argc, char *argv[])
char *ENV_VAR = getenv("ENV_VAR");
if (ENV_VAR == NULL) {
printf("Failed to get env: `ENV_VAR`\n");
return 1;
return EXIT_FAILURE;
}
printf("ENV_VAR = %s\n", ENV_VAR);
return 0;
return EXIT_SUCCESS;
}
+2 -2
View File
@@ -12,7 +12,7 @@
int main(int argc, char *argv[])
{
if (argc != 2) {
return 1;
return EXIT_FAILURE;
}
char *ptr;
int N;
@@ -61,5 +61,5 @@ int main(int argc, char *argv[])
break;
}
#endif
return 0;
return EXIT_SUCCESS;
}
+2 -2
View File
@@ -13,8 +13,8 @@ int main(int argc, char *argv[])
char *ENV_VAR = getenv("ENV_VAR");
if (ENV_VAR == NULL) {
printf("Failed to get env: `ENV_VAR`\n");
return 1;
return EXIT_FAILURE;
}
printf("ENV_VAR = %s\n", ENV_VAR);
return 0;
return EXIT_SUCCESS;
}
+3 -3
View File
@@ -39,14 +39,14 @@ int main(int argc, char **argv)
group_t *root_group = getgrgid(0);
if (strcmp(root_group->gr_name, "root") != 0) {
printf("Error in getgrgid function.");
return 1;
return EXIT_FAILURE;
}
root_group = getgrnam("root");
if (root_group->gr_gid != 0) {
printf("Error in getgrnam function.");
return 1;
return EXIT_FAILURE;
}
return 0;
return EXIT_SUCCESS;
}
+2 -2
View File
@@ -27,12 +27,12 @@ int main(int argc, char **argv)
printf("%d) pid_child: %d, gid_child: %d, ppid_child: %d, sid_child: %d\n",
i, pid_child, gid_child, ppid_child, sid_child);
sleep(5);
exit(0);
return EXIT_SUCCESS;
}
}
//int status;
//while (wait(&status) > 0)
// ;
return 0;
return EXIT_SUCCESS;
}
+2 -2
View File
@@ -49,7 +49,7 @@ int main(int argc, char *argv[])
action.sa_handler = alarm_handler;
if (sigaction(SIGALRM, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGALRM, strerror(errno));
return 1;
return EXIT_FAILURE;
}
itimerval interval = { 0 };
@@ -57,5 +57,5 @@ int main(int argc, char *argv[])
setitimer(ITIMER_REAL, &interval, NULL);
while(1) { }
return 0;
return EXIT_SUCCESS;
}
+2 -2
View File
@@ -48,7 +48,7 @@ int main(int argc, char *argv[])
action.sa_handler = child_sigusr1_handler;
if (sigaction(SIGUSR1, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGUSR1, strerror(errno));
return 1;
return EXIT_FAILURE;
}
child_process();
} else {
@@ -61,5 +61,5 @@ int main(int argc, char *argv[])
int status;
wait(&status);
printf("main : end (%d)\n", status);
return 0;
return EXIT_SUCCESS;
}
+2 -2
View File
@@ -14,7 +14,7 @@ int main(int argc, char *argv[])
{
if (argc != 3) {
printf("%s: You must provide 2 dimensions.\n", argv[0]);
return 1;
return EXIT_FAILURE;
}
char *ptr;
int rows = strtol(argv[1], &ptr, 10);
@@ -48,5 +48,5 @@ int main(int argc, char *argv[])
sleep(5);
pr_warning("Exiting!\n");
return 0;
return EXIT_SUCCESS;
}
+4 -4
View File
@@ -58,7 +58,7 @@ int main(int argc, char *argv[])
key = ftok("/home/user/test7.txt", 5);
if (key < 0) {
perror("Failed to generate key using ftok");
return 1;
return EXIT_FAILURE;
}
printf("Generated key using ftok (key = %d)\n", key);
@@ -67,7 +67,7 @@ int main(int argc, char *argv[])
msqid = msgget(key, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (msqid < 0) {
perror("Failed to create message queue");
return 1;
return EXIT_FAILURE;
}
printf("Created message queue (id : %d)\n", msqid);
@@ -81,7 +81,7 @@ int main(int argc, char *argv[])
sleep(3);
// Send the message.
__send_message(msqid, 1, &message, "General Kenobi...");
return 0;
return EXIT_SUCCESS;
}
// Receive the message.
__receive_message(msqid, 1, &message);
@@ -106,5 +106,5 @@ int main(int argc, char *argv[])
perror("Failed to remove message queue.");
}
printf("Correctly removed message queue.\n");
return 0;
return EXIT_SUCCESS;
}
+4 -3
View File
@@ -3,10 +3,11 @@
/// @copyright (c) 2014-2023 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include <stdio.h>
#include <sched.h>
#include <sys/unistd.h>
#include <strerror.h>
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
int main(int argc, char *argv[])
{
@@ -42,5 +43,5 @@ int main(int argc, char *argv[])
break;
}
}
return 0;
return EXIT_SUCCESS;
}
+4 -3
View File
@@ -3,10 +3,11 @@
/// @copyright (c) 2014-2023 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include <stdio.h>
#include <sched.h>
#include <sys/unistd.h>
#include <strerror.h>
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
int main(int argc, char *argv[])
{
@@ -30,5 +31,5 @@ int main(int argc, char *argv[])
break;
}
}
return 0;
return EXIT_SUCCESS;
}
+4 -3
View File
@@ -3,10 +3,11 @@
/// @copyright (c) 2014-2023 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include <stdio.h>
#include <sched.h>
#include <sys/unistd.h>
#include <strerror.h>
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
int main(int argc, char *argv[])
{
@@ -30,5 +31,5 @@ int main(int argc, char *argv[])
break;
}
}
return 0;
return EXIT_SUCCESS;
}
+3 -2
View File
@@ -5,6 +5,7 @@
#include <sys/unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
@@ -14,9 +15,9 @@ int main(int argc, char *argv[])
for (int i = 0; i < 10; ++i) {
if ((cpid = fork()) == 0) {
execl("/bin/tests/t_alarm", "t_alarm", NULL);
return 0;
return EXIT_SUCCESS;
}
}
while (wait(NULL) != -1) continue;
return 0;
return EXIT_SUCCESS;
}
+9 -9
View File
@@ -26,7 +26,7 @@ int main(int argc, char *argv[])
semid = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (semid < 0) {
perror("Failed to create semaphore set");
return 1;
return EXIT_FAILURE;
}
printf("[father] Created semaphore set (semid : %d)\n", semid);
@@ -37,7 +37,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, SETVAL, &arg);
if (ret < 0) {
perror("Failed to set value of semaphore");
return 1;
return EXIT_FAILURE;
}
printf("[father] Set semaphore value (id : %d, value : %d == 1)\n", semid, arg.val);
@@ -46,7 +46,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) {
perror("Failed to get the value of semaphore set");
return 1;
return EXIT_FAILURE;
}
printf("[father] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret);
@@ -65,7 +65,7 @@ int main(int argc, char *argv[])
// Increment semaphore value.
if (semop(semid, &op_child, 1) < 0) {
perror("Failed to perform first child operation");
return 1;
return EXIT_FAILURE;
}
printf("[child] Succesfully performed opeation (id : %d)\n", semid);
@@ -74,7 +74,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) {
perror("Failed to get the value of semaphore set");
return 1;
return EXIT_FAILURE;
}
printf("[child] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret);
printf("[child] Exit, now.\n", semid, ret);
@@ -87,14 +87,14 @@ int main(int argc, char *argv[])
}
printf("[child] Correctly removed semaphore set.\n");
return 0;
return EXIT_SUCCESS;
}
// ========================================================================
// Perform the operations.
if (semop(semid, op, 2) < 0) {
perror("Failed to perform operation");
return 1;
return EXIT_FAILURE;
}
printf("[father] Performed semaphore operations (id : %d)\n", semid);
@@ -103,7 +103,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) {
perror("Failed to get the value of semaphore set");
return 1;
return EXIT_FAILURE;
}
printf("[father] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret);
@@ -115,5 +115,5 @@ int main(int argc, char *argv[])
}
printf("[father] Correctly removed semaphore set.\n");
return 0;
return EXIT_SUCCESS;
}
+12 -12
View File
@@ -26,7 +26,7 @@ int main(int argc, char *argv[])
key = ftok("/home/user/test7.txt", 5);
if (key < 0) {
perror("Failed to generate key using ftok.");
return 1;
return EXIT_FAILURE;
}
printf("Generated key using ftok (key = %d)\n", key);
@@ -35,7 +35,7 @@ int main(int argc, char *argv[])
semid = semget(key, 1, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (semid < 0) {
perror("Failed to create semaphore set.");
return 1;
return EXIT_FAILURE;
}
printf("[father] Created semaphore set (id : %d)\n", semid);
@@ -46,7 +46,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, SETVAL, &arg);
if (ret < 0) {
perror("Failed to set value of semaphore.");
return 1;
return EXIT_FAILURE;
}
printf("[father] Set semaphore value (id : %d, value : %d == 1)\n", semid, arg.val);
@@ -55,7 +55,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) {
perror("Failed to get the value of semaphore set.");
return 1;
return EXIT_FAILURE;
}
printf("[father] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret);
@@ -71,7 +71,7 @@ int main(int argc, char *argv[])
sleep(3);
if (semop(semid, &op_child, 1) < 0) {
perror("Failed to perform first child operation.");
return 1;
return EXIT_FAILURE;
}
printf("[child] Succesfully performed opeation (id : %d)\n", semid);
@@ -79,7 +79,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) {
perror("Failed to get the value of semaphore set.");
return 1;
return EXIT_FAILURE;
}
printf("[child] Get semaphore value (id : %d, value : %d == 0)\n", semid, ret);
@@ -87,7 +87,7 @@ int main(int argc, char *argv[])
sleep(3);
if (semop(semid, &op_child, 1) < 0) {
perror("Failed to perform second child operation.");
return 1;
return EXIT_FAILURE;
}
printf("[child] Succesfully performed opeation (id : %d)\n", semid);
@@ -95,14 +95,14 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) {
perror("Failed to get the value of semaphore set.");
return 1;
return EXIT_FAILURE;
}
printf("[child] Get semaphore value (id : %d, value : %d == 0)\n", semid, ret);
printf("[child] Exit, now.\n", semid, ret);
// Exit with the child process.
return 0;
return EXIT_SUCCESS;
}
// ========================================================================
@@ -121,7 +121,7 @@ int main(int argc, char *argv[])
// Perform the operations.
if (semop(semid, op_father, 3) < 0) {
perror("Failed to perform father operation.");
return 1;
return EXIT_FAILURE;
}
sleep(2);
@@ -132,7 +132,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) {
perror("Failed to get the value of semaphore set.");
return 1;
return EXIT_FAILURE;
}
printf("[father] Get semaphore value (id : %d, value : %d == 0)\n", semid, ret);
@@ -143,5 +143,5 @@ int main(int argc, char *argv[])
}
printf("[father] Correctly removed semaphore set.\n");
return 0;
return EXIT_SUCCESS;
}
+3 -3
View File
@@ -52,7 +52,7 @@ int main(int argc, char *argv[])
if (semctl(semid, 0, SETALL, &arg) == -1) {
perror("Failed to set semaphores");
return 1;
return EXIT_FAILURE;
}
if (!fork()) {
@@ -82,7 +82,7 @@ int main(int argc, char *argv[])
}
if (semctl(semid, 0, IPC_RMID, 0) == -1) {
perror("Failed to remove IPC");
return 1;
return EXIT_FAILURE;
}
return 0;
return EXIT_SUCCESS;
}
+2 -2
View File
@@ -15,7 +15,7 @@ int main(int argc, char *argv[])
if (setenv("ENV_VAR", "pwd0", 0) == -1) {
printf("Failed to set env: `PWD`\n");
return 1;
return EXIT_FAILURE;
}
if (fork() == 0) {
@@ -24,5 +24,5 @@ int main(int argc, char *argv[])
}
wait(&status);
return 0;
return EXIT_SUCCESS;
}
+4 -3
View File
@@ -33,7 +33,7 @@ int main(int argc, char *argv[])
action.sa_handler = sigusr1_handler;
if (sigaction(SIGUSR1, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGUSR1, strerror(errno));
return 1;
return EXIT_FAILURE;
}
printf("main : Calling handler (%d).\n", SIGUSR1);
@@ -41,8 +41,9 @@ int main(int argc, char *argv[])
int ret = kill(getpid(), SIGUSR1);
printf("main : Returning from handler (%d): %d.\n", SIGUSR1, ret);
printf("main : value : %d\n", values);
for (int i = 0; i < 4; ++i)
for (int i = 0; i < 4; ++i) {
printf("values[%d] : `%d`\n", i, values[i]);
}
free(values);
return 0;
return EXIT_SUCCESS;
}
+2 -1
View File
@@ -45,7 +45,7 @@ int main(int argc, char *argv[])
if (sigaction(SIGFPE, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGFPE, strerror(errno));
return 1;
return EXIT_FAILURE;
}
printf("Diving by zero (unrecoverable)...\n");
@@ -57,4 +57,5 @@ int main(int argc, char *argv[])
d /= e;
e -= 1;
printf("d: %d, e: %d\n", d, e);
return EXIT_SUCCESS;
}
+2 -1
View File
@@ -36,7 +36,7 @@ int main(int argc, char *argv[])
if (sigaction(SIGFPE, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGFPE, strerror(errno));
return 1;
return EXIT_FAILURE;
}
printf("Diving by zero (unrecoverable)...\n");
@@ -48,4 +48,5 @@ int main(int argc, char *argv[])
e -= 1;
}
printf("d: %d, e: %d\n", d, e);
return EXIT_SUCCESS;
}
+2 -2
View File
@@ -25,7 +25,7 @@ int main(int argc, char *argv[])
action.sa_handler = sigusr1_handler;
if (sigaction(SIGUSR1, &action, NULL) == -1) {
printf("Failed to set signal handler (%d, %s).\n", SIGUSR1, strerror(errno));
return 1;
return EXIT_FAILURE;
}
printf("main : Blocking signal (%d).\n", SIGUSR1);
@@ -45,5 +45,5 @@ int main(int argc, char *argv[])
ret = kill(getpid(), SIGUSR1);
printf("main : Returning from handler (%d): %d.\n", SIGUSR1, ret);
return 0;
return EXIT_SUCCESS;
}
+4 -3
View File
@@ -38,12 +38,12 @@ int main(int argc, char *argv[])
if (sigaction(SIGUSR1, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGUSR1, strerror(errno));
return 1;
return EXIT_FAILURE;
}
if (sigaction(SIGUSR2, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGUSR2, strerror(errno));
return 1;
return EXIT_FAILURE;
}
kill(getpid(), SIGUSR1);
@@ -51,5 +51,6 @@ int main(int argc, char *argv[])
kill(getpid(), SIGUSR2);
while(1) { };
return 0;
return EXIT_SUCCESS;
}
+1 -1
View File
@@ -17,5 +17,5 @@ int main(int argc, char *argv[])
sleep(4);
printf("COMPLETED.\n");
return 0;
return EXIT_SUCCESS;
}
+2 -2
View File
@@ -31,7 +31,7 @@ int main(int argc, char *argv[])
action.sa_handler = wait_for_child;
if (sigaction(SIGCHLD, &action, NULL) == -1) {
printf("Failed to set signal handler. %d\n", SIGCHLD);
return 1;
return EXIT_FAILURE;
}
child_pid = fork();
@@ -55,5 +55,5 @@ int main(int argc, char *argv[])
}
}
return 0;
return EXIT_SUCCESS;
}