Skip to content

Commit

Permalink
Merge pull request #117 from Galfurian/develop
Browse files Browse the repository at this point in the history
Process Overhaul, Memory Tweaks, and Bug Squashing
  • Loading branch information
Galfurian authored Dec 5, 2024
2 parents 4cd7ea9 + 5781e4d commit ddd88d1
Show file tree
Hide file tree
Showing 45 changed files with 1,748 additions and 1,177 deletions.
2 changes: 1 addition & 1 deletion doc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ if (DOXYGEN_FOUND)
${CMAKE_SOURCE_DIR}/mentos/inc/mem/slab.h
${CMAKE_SOURCE_DIR}/mentos/inc/mem/kheap.h
${CMAKE_SOURCE_DIR}/mentos/inc/mem/vmem_map.h
${CMAKE_SOURCE_DIR}/mentos/inc/mem/buddysystem.h
${CMAKE_SOURCE_DIR}/mentos/inc/mem/buddy_system.h
${CMAKE_SOURCE_DIR}/mentos/inc/hardware/timer.h
${CMAKE_SOURCE_DIR}/mentos/inc/hardware/cpuid.h
${CMAKE_SOURCE_DIR}/mentos/inc/hardware/pic8259.h
Expand Down
1 change: 1 addition & 0 deletions libc/inc/stdarg.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ typedef char *va_list;

/// @brief The start of a variadic list.
#define va_start(ap, last_arg) (ap = ((va_list)(&last_arg) + va_size(last_arg)))

/// @brief The end of a variadic list.
#define va_end(ap) ((void)0)

Expand Down
30 changes: 30 additions & 0 deletions libc/inc/stdint.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,33 @@ typedef signed intptr_t;

/// @brief Define the unsigned 32-bit pointer.
typedef unsigned uintptr_t;

/// @brief Minimum value of a signed 8-bit integer.
#define INT8_MIN (-128)

/// @brief Minimum value of a signed 16-bit integer.
#define INT16_MIN (-32768)

/// @brief Minimum value of a signed 32-bit integer.
#define INT32_MIN (-2147483648)

/// @brief Maximum value of a signed 8-bit integer.
#define INT8_MAX (+127)

/// @brief Maximum value of a signed 16-bit integer.
#define INT16_MAX (+32767)

/// @brief Maximum value of a signed 32-bit integer.
#define INT32_MAX (+2147483647)

/// @brief Maximum value of an unsigned 8-bit integer.
#define UINT8_MAX (+255)

/// @brief Maximum value of an unsigned 16-bit integer.
#define UINT16_MAX (+65535)

/// @brief Maximum value of an unsigned 32-bit integer.
#define UINT32_MAX (+4294967295U)

/// @brief Maximum value representable by size_t.
#define SIZE_MAX (+4294967295U)
23 changes: 15 additions & 8 deletions libc/inc/system/syscall_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,16 +376,23 @@
#define __NR_shmget 398 ///< System-call number for `shmget`
#define SYSCALL_NUMBER 399 ///< The total number of system-calls.

/// @brief Adjust the result of a system call and set errno if needed.
/// @param value The variable where the result of the system call is stored.
#define __syscall_set_errno(value) \
do { \
if ((unsigned int)(value) >= (unsigned int)(-125)) { \
errno = -(value); \
(value) = -1; \
} \
} while (0)

/// @brief Handle the value returned from a system call.
/// @param type Specifies the type of the returned value.
/// @param res The name of the variable where the result of the SC is stored.
#define __syscall_return(type, res) \
do { \
if ((unsigned int)(res) >= (unsigned int)(-125)) { \
errno = -(res); \
(res) = -1; \
} \
return (type)(res); \
/// @param value The variable where the result of the system call is stored.
#define __syscall_return(type, value) \
do { \
__syscall_set_errno(value); \
return (type)(value); \
} while (0)

// Few things about what follows:
Expand Down
88 changes: 57 additions & 31 deletions libc/src/stdlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "assert.h"
#include "stdlib.h"
#include "string.h"
#include "stdint.h"
#include "system/syscall_types.h"

/// @brief Number which identifies a memory area allocated through a call to
Expand All @@ -28,7 +29,10 @@ typedef struct {
/// @return a pointer to the allocated memory.
static inline void *malloc_header_to_ptr(malloc_header_t *header)
{
return (void *)((char *)header + sizeof(malloc_header_t));
if (header) {
return (void *)((char *)header + sizeof(malloc_header_t));
}
return NULL;
}

/// @brief Extract the malloc header, from the actual pointer to the allocated memory.
Expand All @@ -41,70 +45,92 @@ static inline malloc_header_t *ptr_to_malloc_header(void *ptr)

void *malloc(unsigned int size)
{
// Return NULL if size is zero, as no memory needs to be allocated.
if (size == 0) {
return NULL;
}
// Pointer for the allocated memory.
void *ptr;
// Allocate the memory.
// Attempt to allocate memory via a system call.
__inline_syscall_1(ptr, brk, size + sizeof(malloc_header_t));
// Check for errors from the brk.
if (ptr == 0) {
return NULL;
// Check if the system call failed (e.g., due to lack of memory).
if (ptr) {
// Initialize the malloc header at the start of the allocated block.
malloc_header_t *header = (malloc_header_t *)ptr;
// Set the magic number to verify validity.
header->magic = MALLOC_MAGIC_NUMBER;
// Store the requested size.
header->size = size;
// Return a pointer to the memory block after the header.
ptr = malloc_header_to_ptr(header);
}
// Initialize the malloc header.
malloc_header_t *header = (malloc_header_t *)ptr;
header->magic = MALLOC_MAGIC_NUMBER;
header->size = size;
// Return the allocated memory.
return malloc_header_to_ptr(header);
return ptr;
}

void *calloc(size_t num, size_t size)
{
// Check for overflow in multiplication (num * size)
if ((num != 0) && ((size * num) > SIZE_MAX)) {
return NULL;
}
// Allocate memory.
void *ptr = malloc(num * size);
if (ptr) {
// Zero-initialize the allocated memory.
memset(ptr, 0, num * size);
}
// Return the allocated and initialized memory.
return ptr;
}

void *realloc(void *ptr, size_t size)
{
// C standard implementation: When NULL is passed to realloc,
// simply malloc the requested size and return a pointer to that.
// C standard implementation: When NULL is passed to realloc, simply malloc
// the requested size and return a pointer to that.
if (__builtin_expect(ptr == NULL, 0)) {
return malloc(size);
}
// C standard implementation: For a size of zero, free the
// pointer and return NULL, allocating no new memory.
// C standard implementation: For a size of zero, free the pointer and
// return NULL, allocating no new memory.
if (__builtin_expect(size == 0, 0)) {
free(ptr);
return NULL;
}
// Get the malloc header.
// Get the malloc header for the pointer.
malloc_header_t *header = ptr_to_malloc_header(ptr);
// Check the header.
assert(header->magic == MALLOC_MAGIC_NUMBER && "This is not a valid pointer.");
// Get the old size.
// Validate the header.
if (!header || (header->magic != MALLOC_MAGIC_NUMBER)) {
return NULL;
}
// Get the old size from the header.
size_t old_size = header->size;
// Create the new pointer.
// Allocate new memory for the resized block.
void *newp = malloc(size);
memset(newp, 0, size);
memcpy(newp, ptr, old_size);
free(ptr);
if (newp) {
// Zero-initialize the new memory block.
memset(newp, 0, size);
// Copy the contents from the old memory block to the new one.
memcpy(newp, ptr, old_size < size ? old_size : size);
// Free the old memory block.
free(ptr);
}
// Return the pointer to the new memory block.
return newp;
}

void free(void *ptr)
{
// Get the malloc header.
malloc_header_t *header = ptr_to_malloc_header(ptr);
// Check the header.
assert(header->magic == MALLOC_MAGIC_NUMBER && "This is not a valid pointer.");
ptr = (char *)ptr - sizeof(malloc_header_t);
// Call the free.
int _res;
__inline_syscall_1(_res, brk, (char *)header);
if (ptr) {
// Get the malloc header.
malloc_header_t *header = ptr_to_malloc_header(ptr);
// Validate the malloc header.
if (!header || (header->magic != MALLOC_MAGIC_NUMBER)) {
return;
}
// Perform the system call to release memory.
int _res;
__inline_syscall_1(_res, brk, (char *)header);
}
}

/// Seed used to generate random numbers.
Expand Down
41 changes: 41 additions & 0 deletions libc/src/unistd/waitpid.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
#include "errno.h"
#include "unistd.h"
#include "system/syscall_types.h"
#include "syslog.h"
#include "strerror.h"

pid_t waitpid(pid_t pid, int *status, int options)
{
#if 1
pid_t __res;
int __status = 0;
do {
Expand All @@ -30,6 +33,44 @@ pid_t waitpid(pid_t pid, int *status, int options)
*status = __status;
}
__syscall_return(pid_t, __res);
#else

pid_t ret;

while (1) {
__inline_syscall_3(ret, waitpid, pid, status, options);

// Success: A child process state has changed.
if (ret > 0) {
break;
}

if (ret < 0) {
__syscall_set_errno(ret);

// Interrupted by a signal: Retry the syscall.
if (errno == EINTR) {
continue;
}

// No children to wait for, but WNOHANG allows non-blocking behavior.
if (errno == ECHILD) {
if (options & WNOHANG) {
// Return 0 to indicate no state change.
ret = 0;
break;
}
continue;
}

// Unrecoverable error: Return -1 and let the caller handle `errno`.
break;
}
}

// Return the PID of the child whose state has changed (or 0 for WNOHANG).
return ret;
#endif
}

pid_t wait(int *status)
Expand Down
19 changes: 7 additions & 12 deletions mentos/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@
# Set the target naming.
set(KERNEL_NAME kernel)
set(BOOTLOADER_NAME bootloader)
set(BUDDY_SYSTEM_FILE ${CMAKE_SOURCE_DIR}/mentos/src/mem/libbuddysystem.a)

# =============================================================================
# OPTIONS
# =============================================================================

# Add the memory option.
option(USE_BUDDY_SYSTEM "Build using the buddysystem written by the user." OFF)
# Enables memory allocation tracing.
option(ENABLE_ALLOC_TRACE "Enables memory allocation tracing." OFF)
# Enables scheduling feedback on terminal.
Expand Down Expand Up @@ -88,6 +85,7 @@ set(KERNEL_SOURCES
${CMAKE_SOURCE_DIR}/mentos/src/mem/slab.c
${CMAKE_SOURCE_DIR}/mentos/src/mem/vmem_map.c
${CMAKE_SOURCE_DIR}/mentos/src/mem/zone_allocator.c
${CMAKE_SOURCE_DIR}/mentos/src/mem/buddy_system.c
${CMAKE_SOURCE_DIR}/mentos/src/elf/elf.c
${CMAKE_SOURCE_DIR}/mentos/src/crypt/sha256.c
${CMAKE_SOURCE_DIR}/mentos/src/descriptor_tables/gdt.c
Expand All @@ -102,6 +100,7 @@ set(KERNEL_SOURCES
${CMAKE_SOURCE_DIR}/mentos/src/descriptor_tables/tss.S
${CMAKE_SOURCE_DIR}/mentos/src/process/scheduler_algorithm.c
${CMAKE_SOURCE_DIR}/mentos/src/process/scheduler_feedback.c
${CMAKE_SOURCE_DIR}/mentos/src/process/pid_manager.c
${CMAKE_SOURCE_DIR}/mentos/src/process/scheduler.c
${CMAKE_SOURCE_DIR}/mentos/src/process/process.c
${CMAKE_SOURCE_DIR}/mentos/src/process/wait.c
Expand All @@ -117,30 +116,26 @@ set(KERNEL_SOURCES

# =============================================================================
# Add kernel library.
if(USE_BUDDY_SYSTEM)
# Add the library with `buddysystem.c`.
add_library(${KERNEL_NAME} ${KERNEL_SOURCES} src/mem/buddysystem.c)
else(USE_BUDDY_SYSTEM)
# Add the library without `buddysystem.c`.
add_library(${KERNEL_NAME} ${KERNEL_SOURCES})
# Link the exercise libraries.
target_link_libraries(${KERNEL_NAME} ${BUDDY_SYSTEM_FILE})
endif(USE_BUDDY_SYSTEM)
add_library(${KERNEL_NAME} ${KERNEL_SOURCES})

# Add the includes.
target_include_directories(
${KERNEL_NAME} PUBLIC
${CMAKE_SOURCE_DIR}/mentos/inc
${CMAKE_SOURCE_DIR}/libc/inc
)

# Define that this code is kernel code.
target_compile_definitions(
${KERNEL_NAME} PUBLIC
__KERNEL__
)

target_compile_definitions(
${KERNEL_NAME} PUBLIC
MENTOS_ROOT="${CMAKE_SOURCE_DIR}"
)

# If the emulator is set to output on a log file, tell that to the C code.
if(${EMULATOR_OUTPUT_TYPE} STREQUAL OUTPUT_LOG)
target_compile_definitions(${KERNEL_NAME} PUBLIC EMULATOR_OUTPUT_LOG)
Expand Down
7 changes: 4 additions & 3 deletions mentos/inc/boot.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,12 @@ typedef struct boot_info_t {
unsigned int lowmem_phy_start;
/// lowmem physical addressable end
unsigned int lowmem_phy_end;

/// lowmem addressable start
unsigned int lowmem_start;
unsigned int lowmem_virt_start;
/// lowmem addressable end
unsigned int lowmem_end;
unsigned int lowmem_virt_end;
/// lowmem size
unsigned int lowmem_size;

/// stack end (comes after lowmem_end, and is the end of the low mapped memory)
unsigned int stack_end;
Expand Down
Loading

0 comments on commit ddd88d1

Please sign in to comment.