Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 38 additions & 16 deletions .github/workflows/make.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,37 +29,59 @@ jobs:

- name: Build Lab 2 (Signals & Libraries)
run: |
cd lab1
if [ -d "zad1" ]; then gcc -Wall zad1/main.c -o zad1/main.out; fi
if [ -d "zad2" ]; then gcc -Wall zad2/main.c -o zad1/main.out && gcc zad2/child.c -o child.out; fi
if [ -f "zad3/Makefile" ]; then cd zad3 && make && cd ..; fi
cd ..
# Fixed directory change (was cd lab1)
if [ -d "lab2" ]; then
cd lab2
if [ -d "zad1" ]; then gcc -Wall zad1/main.c -o zad1/main.out; fi
if [ -d "zad2" ]; then gcc -Wall zad2/main.c -o zad2/main.out && gcc -Wall zad2/child.c -o zad2/child.out; fi
if [ -f "zad3/Makefile" ]; then cd zad3 && make && cd ..; fi
cd ..
fi

- name: Build Lab 3 (Pipes & FIFOs)
run: |
cd lab3
make all
if [ -d "lab3" ]; then
cd lab3
make all
cd ..
fi

- name: Build Lab 4 (Message Queues)
run: |
cd lab4
make all
if [ -d "lab4" ]; then
cd lab4
make all
cd ..
fi

- name: Build Lab 5 (Semaphores & Shared Memory)
run: |
for d in lab5/zad*/; do
if [ -f "$d/Makefile" ]; then
echo "Building $d"
cd "$d" && make all && cd -
fi
done
if [ -d "lab5" ]; then
for d in lab5/zad*/; do
if [ -f "$d/Makefile" ]; then
echo "Building $d"
cd "$d" && make all && cd -
fi
done
fi

- name: Verify IPC Cleanup Utilities
run: |
if [ -f "lab5/zad3/bin/cleaner.out" ]; then
./lab5/zad3/bin/cleaner.out
fi

- name: Build Lab 6 (Pthreads, RTOS & Sync)
run: |
if [ -d "lab6" ]; then
cd lab6
# We call specific targets because our Makefile's 'all' just prints a message
make level1
make level2
make level3
cd ..
fi

- name: Success Notification
run: echo "All laboratories compiled successfully!"

3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Operating Systems - AGH UST 🐧
# Operating Systems @ AGH UST 🐧

[![C](https://img.shields.io/badge/C-00599C?style=for-the-badge&logo=c&logoColor=white)](https://en.wikipedia.org/wiki/C_(programming_language))
[![Linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black)](https://www.linux.org/)
Expand All @@ -18,6 +18,7 @@ The projects focus on low-level system programming in UNIX/Linux environments, u
| [`lab3/`](./lab3) | Pipes and FIFOs (IPC) | Inter-Process Communication using Unnamed Pipes (`pipe`) and Named Pipes/FIFOs (`mkfifo`), deadlock prevention, and client-server process synchronization. |
| [`lab4/`](./lab4) | POSIX Message Queues (IPC) | A "hub and spoke" communication system where multiple independent terminal clients exchange text messages in real-time using `/dev/mqueue`. Features asynchronous I/O managed by duplicating processes via `fork()`. |
| [`lab5/`](./lab5) | POSIX Semaphores & Shared Memory | Implementation of the classic Producer-Consumer problem within a multi-process architecture. Leverages POSIX shared memory for zero-copy data transfer and POSIX semaphores for strict access synchronization, complete with a Manager daemon mitigating starvation via an aging algorithm. |
| [`lab6/`](./lab6) | POSIX Threads, RTOS scheduling | A comprehensive, multithreaded simulation of a mobile robot's internal operating system. POSIX threads (pthreads), complex inter-thread communication, synchronization mechanisms, and Real-Time Operating System (RTOS) scheduling. |

## ⚙️ System Requirements

Expand Down
8 changes: 8 additions & 0 deletions lab6/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Object files
obj/

# Executables
bin/

# Generated output files (simulated images, logs, reports)
output/
48 changes: 48 additions & 0 deletions lab6/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
CC = gcc
CFLAGS = -Wall -Wextra -pthread -g -I$(INCDIR)

INCDIR = include
SRCDIR = src
OBJDIR = obj
BINDIR = bin
OUTDIR = output

# Create directories if they do not exist
$(shell mkdir -p $(OBJDIR) $(BINDIR) $(OUTDIR))

.PHONY: all clean level1 level2 level3

all:
@echo "Please specify a target to build: make level1, make level2, or make level3"

level1: $(BINDIR)/level1.out
level2: $(BINDIR)/level2.out
level3: $(BINDIR)/level3.out

# --- Object files compilation ---
$(OBJDIR)/common.o: $(SRCDIR)/common.c $(INCDIR)/common.h
$(CC) $(CFLAGS) -c $(SRCDIR)/common.c -o $(OBJDIR)/common.o

$(OBJDIR)/program1.o: $(SRCDIR)/program1.c $(INCDIR)/common.h
$(CC) $(CFLAGS) -DLEVEL1 -c $(SRCDIR)/program1.c -o $(OBJDIR)/program1.o

$(OBJDIR)/program2.o: $(SRCDIR)/program2.c $(INCDIR)/common.h
$(CC) $(CFLAGS) -DLEVEL2 -c $(SRCDIR)/program2.c -o $(OBJDIR)/program2.o

$(OBJDIR)/program3.o: $(SRCDIR)/program3.c $(INCDIR)/common.h
$(CC) $(CFLAGS) -DLEVEL3 -c $(SRCDIR)/program3.c -o $(OBJDIR)/program3.o

# --- Linking executables ---
$(BINDIR)/level1.out: $(OBJDIR)/common.o $(OBJDIR)/program1.o
$(CC) $(CFLAGS) $^ -o $@

$(BINDIR)/level2.out: $(OBJDIR)/common.o $(OBJDIR)/program2.o
$(CC) $(CFLAGS) $^ -o $@

$(BINDIR)/level3.out: $(OBJDIR)/common.o $(OBJDIR)/program3.o
$(CC) $(CFLAGS) $^ -o $@

# --- Cleanup ---
clean:
rm -rf $(OBJDIR)/* $(BINDIR)/* $(OUTDIR)/*

109 changes: 109 additions & 0 deletions lab6/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Real-Time Mobile Robot System Simulation

A comprehensive, multithreaded simulation of a mobile robot's internal operating system written in C. This project demonstrates advanced system programming concepts, including POSIX threads (pthreads), complex inter-thread communication, synchronization mechanisms, and Real-Time Operating System (RTOS) scheduling.

## 📌 Project Overview
In modern robotics (similar to the ROS architecture), various sensors operate at different frequencies. This project simulates a core system where two cameras generate image frames at 25 Hz, while the robot's odometry/state updates at 100 Hz. The system handles the asynchronous nature of these sensors, synchronizes stereo camera frames, and safely logs data to a simulated disk at 10 Hz—all without race conditions or data corruption.

## 🚀 Key Features & Technologies
- **Multithreading:** Concurrent execution of up to 7 independent threads (`pthread`).
- **Synchronization:** Utilization of Mutexes (`pthread_mutex_t`) and Semaphores (`sem_t`) to prevent race conditions.
- **Advanced IPC (Inter-Process Communication):**
- Implementation of **Circular Buffers (FIFO)** to queue sensory data and prevent data loss.
- **Condition Variables (`pthread_cond_t`)** to completely eliminate busy-waiting.
- **Real-Time Scheduling:** Implementation of `SCHED_FIFO` policy for critical threads.
- **Lock-Free Operations:** Usage of C11 Atomics (`stdatomic.h`) for high-performance, lock-free system monitoring.
- **Graceful Shutdown:** Interception of `SIGINT` (`CTRL+C`) for safe resource deallocation and memory cleanup (`pthread_join`, `pthread_mutex_destroy`).

## 🏗️ System Architecture
The system consists of the following concurrent threads:
1. **Left Camera Thread (25 Hz):** Generates image frames and timestamps.
2. **Right Camera Thread (25 Hz):** Generates image frames and timestamps.
3. **Synchronizer Thread:** Evaluates timestamps and pairs left/right frames if the time difference is `< 20 ms`.
4. **Image Writer Thread (10 Hz):** Pulls paired frames and simulates disk I/O by generating `.jpg` (text) files.
5. **Robot State Thread (100 Hz):** High-priority thread simulating the robot's spatial movement (X, Y, Theta).
6. **Logger Thread (10 Hz):** Periodically captures and logs the current robot state to `robot_state.txt`.
7. **Watchdog Thread (1 Hz):** Monitors the frequency of all threads using atomic variables to ensure strict Real-Time deadlines are met.

## 📁 Directory Structure
```text
projekt_os/
├── bin/ # Compiled executable binaries (.out)
├── include/ # Header files (common.h)
├── obj/ # Compiled object files (.o)
├── output/ # Generated logs, text files, and simulated .jpgs
├── scripts/ # Bash scripts for automated building and testing
├── src/ # Source code (.c files)
├── Makefile # Build automation
└── .gitignore
```

## 🛠️ Project Progression (Levels)

The project is built iteratively in three distinct levels, compiling different sets of features.

### Level 1: Basic Synchronization (`program1.c`)

* Establishes the 6 core threads.
* Implements basic synchronization using standard Mutexes and Semaphores.
* Runs for a fixed duration of 20 seconds before shutting down automatically.

### Level 2: Circular Buffers & Conditional Variables (`program2.c`)

* Introduces robust **64-element Circular Buffers (FIFO)** for frame handling.
* Replaces raw sleep routines in reader threads with **Condition Variables**, ensuring microsecond-level reaction times when data arrives.
* Introduces **Graceful Shutdown** via `SIGINT` (CTRL+C) handling.

### Level 3: RTOS & Lock-Free Monitoring (`program3.c`)

* Upgrades to **Real-Time Scheduling (`SCHED_FIFO`)** granting hardware-level priorities to critical threads (Robot State & Watchdog).
* Implements lock-free counters using `<stdatomic.h>`.
* Generates a final performance report upon shutdown.

## ⚙️ Compilation & Execution

### Prerequisites

* Linux / Windows Subsystem for Linux (WSL)
* GCC Compiler
* GNU Make

### Building the Project

You can build specific levels using the provided Makefile:

```bash
make clean
make level1 # Builds bin/level1.out
make level2 # Builds bin/level2.out
make level3 # Builds bin/level3.out
```

### Automated Testing via Bash Scripts

The easiest way to observe the system is by using the provided bash scripts. They automatically compile the code, run the simulation, simulate keyboard interruptions (`CTRL+C`), and print a summary of the output directory.

```bash
./scripts/run_level1.sh
./scripts/run_level2.sh
./scripts/run_level3.sh
```

### ⚠️ Note on Real-Time Execution (Level 3)

In Level 3, the program attempts to use the `SCHED_FIFO` real-time scheduling policy. On standard Linux configurations, unprivileged users are not allowed to set real-time priorities (to prevent system lockups).

If you run `./scripts/run_level3.sh` normally, the system will fall back to default scheduling and display a warning.
To observe true RTOS capabilities without dropped frames or missed deadlines, execute the script with `sudo`:

```bash
sudo ./scripts/run_level3.sh
```

## 🧹 Cleanup

To remove all compiled binaries, object files, and generated output logs, simply run:

```bash
make clean
```
72 changes: 72 additions & 0 deletions lab6/include/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#ifndef COMMON_H
#define COMMON_H

#define _POSIX_C_SOURCE 200809L

#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#include <stdbool.h>

// --- SYSTEM CONSTANTS ---
#define CAMERA_FREQ_HZ 25
#define ROBOT_FREQ_HZ 100
#define LOG_FREQ_HZ 10
#define SYNC_TOLERANCE_MS 20 // Max time difference for stereo matching (20 ms)
#define BUFFER_SIZE 64 // Circular buffer size

// --- DATA STRUCTURES ---

// Single camera frame structure
typedef struct {
int frame_id; // Sequential frame number
struct timespec timestamp; // Time of capture
} frame_t;

// Robot state structure
typedef struct {
double x;
double y;
double theta; // Orientation
struct timespec timestamp; // State generation time
} robot_state_t;

// Circular buffer structure (used from Task 2)
typedef struct {
frame_t buffer[BUFFER_SIZE];
int head; // Write index
int tail; // Read index
int count; // Current number of elements

// Synchronization mechanisms (Task 2)
pthread_mutex_t mutex;
pthread_cond_t not_empty;
pthread_cond_t not_full;
} frame_buffer_t;

// --- UTILITY FUNCTION DECLARATIONS ---

// Calculates time difference in milliseconds between two timestamps
double time_diff_ms(struct timespec start, struct timespec end);

// Gets current time using CLOCK_MONOTONIC
void get_current_time(struct timespec *ts);

// Precise thread sleep for a given frequency (e.g., 25 Hz)
void sleep_for_freq(int freq_hz);

// --- BUFFER OPERATIONS (Task 2) ---

// Initializes the circular buffer and its synchronization mechanisms
void buffer_init(frame_buffer_t* buf);

// Pushes a frame into the buffer. Overwrites the oldest frame if full.
void buffer_push(frame_buffer_t* buf, frame_t frame);

// Pops a frame from the buffer. Blocks if empty. Returns false if interrupted.
bool buffer_pop(frame_buffer_t* buf, frame_t* frame, volatile bool* is_running);

// Cleans up mutexes and condition variables
void buffer_destroy(frame_buffer_t* buf);

#endif // COMMON_H
46 changes: 46 additions & 0 deletions lab6/scripts/run_level1.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash

set -e

PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$PROJECT_ROOT"

echo "========================================"
echo " Building and Running LEVEL 1 "
echo "========================================"

make clean > /dev/null 2>&1
make level1

echo ""
echo "[INFO] Starting simulation (takes 20 seconds)..."
echo "----------------------------------------"

./bin/level1.out

echo "----------------------------------------"
echo "[INFO] Simulation finished. Analyzing outputs..."
echo ""

# Check outputs in the new directory
if [ -f "output/robot_state.txt" ]; then
echo "=> Robot State Log (first 5 entries):"
head -n 5 output/robot_state.txt
else
echo "=> [ERROR] output/robot_state.txt was not generated!"
fi

echo ""

IMAGE_COUNT=$(ls -1 output/*.jpg 2>/dev/null | wc -l)
if [ "$IMAGE_COUNT" -gt 0 ]; then
echo "=> Total simulated images generated: $IMAGE_COUNT"
echo "=> Sample generated image files:"
ls -1 output/left_*.jpg output/right_*.jpg 2>/dev/null | head -n 6
else
echo "=> [ERROR] No .jpg files were generated in output/!"
fi

echo "========================================"
echo " Script Execution Completed "
echo "========================================"
Loading
Loading