Skip to content

W4ilops/PTSS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Priority Task Scheduler System (PTSS)

Real-time task scheduler with deadline awareness, priority ordering, dependency resolution, and resource constraints. Written in C with POSIX threads.

Architecture

A single scheduler thread manages the ready queue on a 100ms tick. A fixed-size worker thread pool (default 4) executes tasks. The scheduler never executes tasks directly — it delegates to workers, keeping scheduling latency predictable regardless of task duration.

┌──────────────────┐     ┌──────────────┐
│ Scheduler Thread │────▶│  Ready Queue  │  (min-heap: deadline, then priority)
│   100ms tick     │     │  O(log n)     │
└──────────────────┘     └──────┬───────┘
                                │ assign
          ┌─────────────────────┼─────────────────────┐
          ▼                     ▼                     ▼
   ┌────────────┐       ┌────────────┐       ┌────────────┐
   │  Worker 0  │       │  Worker 1  │  ...  │  Worker N  │
   └────────────┘       └────────────┘       └────────────┘

State Machine

INITIALIZED ──▶ RUNNING ──▶ PAUSED
                   │
                   ▼
              SHUTTING_DOWN ──▶ STOPPED
  • Only RUNNING executes tasks
  • PAUSED queues tasks but does not run them
  • SHUTTING_DOWN finishes current tasks, then stops
  • STOPPED is terminal

Design Decisions

Decision Choice Rationale
Scheduling algorithm EDF (Earliest Deadline First) with priority tiebreaker Optimal for deadline-constrained single-processor scheduling. Priority alone risks missing deadlines for lower-priority but more urgent tasks.
Ready queue Binary min-heap O(log n) insert and extract. Simple, cache-friendly, no external dependencies.
Worker threads Fixed pool (default 4) Avoids dynamic thread creation overhead. Matches typical core count. Configurable via --workers.
Timing clock_gettime(CLOCK_MONOTONIC) Nanosecond precision, immune to wall-clock adjustments.
Synchronization Per-component mutexes with documented lock ordering Prevents deadlocks. Workers use per-worker condition variables to avoid thundering herd.
Memory Pre-allocated fixed pools No malloc/free during operation. Deterministic memory footprint.
Shutdown 3-phase graceful Soft stop → timeout wait → force kill. State persisted to disk for crash recovery.

Building

# Debug build (default)
make

# Release build (optimized)
make release

# Run tests
make test

# Memory leak check
make valgrind

# Clean
make clean

Requires: GCC, pthreads, POSIX. Compiles with -Wall -Wextra -Werror -pthread.

Usage

Standalone

./scheduler --workers 4 --max-tasks 1000 --log-level INFO

Options:

  • --workers N — Worker thread count (default: 4)
  • --max-tasks N — Maximum task pool size (default: 1000)
  • --log-level LEVEL — DEBUG, INFO, WARN, ERROR (default: INFO)
  • --save-state-dir DIR — Directory for state persistence
  • --log-file FILE — Log output file
  • --port N — Monitoring port (default: 9001)

Library

Compile with -DPTSS_NO_MAIN to exclude main(). Link against all .o files.

#include "protocol.h"

int my_task(void *arg) {
    // Task work here
    return 0;  // 0 = success, non-zero = failure
}

int main(void) {
    scheduler_config_t cfg = {0};
    cfg.num_workers = 4;

    scheduler_init(&cfg);
    scheduler_start();

    // Add tasks
    uint32_t id = scheduler_add_task("my-task", my_task, NULL,
                                      /*priority=*/5, /*timeout=*/30,
                                      /*deadline=*/60);

    // Add dependencies
    scheduler_add_dependency(id_b, id_a);

    // Query status
    task_status_report_t status = monitor_get_task_status(id);
    scheduler_metrics_t metrics = monitor_get_metrics();

    // Shutdown
    scheduler_shutdown();
    scheduler_destroy();
}

API

Task Management

Function Description
scheduler_add_task(name, func, arg, priority, timeout, deadline) Register a task. Returns task ID.
scheduler_add_dependency(task_id, depends_on) Add dependency: task_id runs after depends_on completes.
scheduler_cancel_task(task_id) Cancel a pending/running task.

Scheduler Control

Function Description
scheduler_init(config) Initialize with configuration.
scheduler_start() Begin scheduling (INITIALIZED → RUNNING).
scheduler_pause() Pause scheduling (RUNNING → PAUSED).
scheduler_resume() Resume scheduling (PAUSED → RUNNING).
scheduler_shutdown() Graceful shutdown with state persistence.
scheduler_destroy() Free all resources.

Monitoring

Function Description
monitor_get_state() Current scheduler state.
monitor_get_task_status(id) Status report for a specific task.
monitor_get_metrics() Aggregate performance metrics.
monitor_print_dashboard() Print human-readable status to stdout.

File Structure

File Lines Purpose
protocol.h ~300 Structures, constants, error codes, function declarations
scheduler.c ~790 Main scheduling loop, task management, signal handling, CLI
executor.c ~300 Worker thread pool, task execution, crash recovery
heap.c ~200 Min-heap priority queue (thread-safe)
log.c ~250 Structured logging, execution log, state persistence
monitor.c ~150 Status queries, metrics, dashboard
test_ptss.c ~610 7-test comprehensive test suite

Test Results

TEST 1: Basic Scheduling (Priority Order)     — PASS
TEST 2: Deadline Enforcement                  — PASS
TEST 3: Concurrent Execution (Thread Pool)    — PASS
TEST 4: Dependency Chain (A → B → C)          — PASS
TEST 5: Graceful Shutdown                     — PASS
TEST 6: Error Recovery (Failing Tasks)        — PASS
TEST 7: High Load (100 tasks, 4 workers)      — PASS

Throughput: ~40 tasks/sec (4 workers, 1ms tasks)
Peak queue depth: 96
Avg execution time: 1.1 ms

Limitations

  • Single machine only — no network distribution
  • No task migration — once assigned to a worker, runs to completion
  • Dependencies are direct only — no transitive resolution
  • CPU monitoring is best-effort (Linux /proc based, not guaranteed)
  • Maximum 1000 tasks and 16 workers (compile-time constants)
  • Task function pointers cannot be persisted — must be re-registered after restore

Lock Ordering

To prevent deadlocks, locks are always acquired in this order:

  1. task_pool_lock
  2. ready_queue.lock
  3. running_tasks_lock
  4. state_lock
  5. worker[i].lock
  6. task[i].lock
  7. log_lock

Never acquire a higher-numbered lock while holding a lower-numbered lock.

Error Codes

Code Name Meaning
0 PTSS_OK Success
-1 PTSS_ERR_INVALID_ARG Invalid argument
-2 PTSS_ERR_FULL Pool or queue is full
-3 PTSS_ERR_NOT_FOUND Task not found
-4 PTSS_ERR_INVALID_STATE Invalid state transition
-5 PTSS_ERR_DEPENDENCY Dependency not satisfied
-6 PTSS_ERR_TIMEOUT Operation timed out
-7 PTSS_ERR_RESOURCE Resource limit exceeded
-8 PTSS_ERR_IO File I/O error
-9 PTSS_ERR_THREAD Thread operation error
-10 PTSS_ERR_MEMORY Memory allocation error

License

This project is licensed under the MIT License.

Contact

PGP Public Key

-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEaX31qRYJKwYBBAHaRw8BAQdA4NAOMdNRqRdEl5VTzEDgWh9PbzWjMk/QZ7Do
htbIPtS0GHdhaWwgPHdhaWxAdHV0YW1haWwuY29tPoiZBBMWCgBBFiEE2hDNLVN+
cOGq0wcon7QDDWC8ApoFAml99akCGwMFCQWjmoAFCwkIBwICIgIGFQoJCAsCBBYC
AwECHgcCF4AACgkQn7QDDWC8AppwpgEApF5DddWsIJ0Q+rbp+DVax9mw/Bdnj1ip
qKWX5MGqeLMA/3pm620peWjlP113AwPcKrfgPB/BJcNwc8DoYUVAMDMMuDgEaX31
qRIKKwYBBAGXVQEFAQEHQDC5PkpGUHv1Pd0rObwaqHg2rzi6xGoZMTp35PqnPMJJ
AwEIB4h+BBgWCgAmFiEE2hDNLVN+cOGq0wcon7QDDWC8ApoFAml99akCGwwFCQWj
moAACgkQn7QDDWC8ApqXgQEA1eoTiQbFX17t3PeIL1Bxzz2jZfuMEHu0aAkQ+MOF
JCMBAMKcc4AfCxQgaj9nHoW4jYs7VCap4+F2R8nN/7JLbcAG
=Ln+f
-----END PGP PUBLIC KEY BLOCK-----

SSH Public Key

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJum3lcA0XQXBf93nSxYZAIOkfdqTmeAIeP4R6HWqfdw

About

Real-time task scheduler with deadline awareness, priority ordering, and dependency resolution in C

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors