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
3 changes: 3 additions & 0 deletions drivers/serial/interrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@

#define DR_MASK 1

struct signal_wait_t* com1_signal;
struct signal_wait_t* com2_signal;

void serial_init_interrupts(void) {
uint8_t com1_v = idt_get_vector();
uint8_t com2_v = idt_get_vector();
Expand Down
8 changes: 0 additions & 8 deletions kernel/core/kentry.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,6 @@
#include <drivers/pcie/pcie_init.h>
#include <drivers/disk/disk.h>

#ifdef SERIAL
#include <drivers/serial/interrupts.h>
#endif /* SERIAL */

#define RFL_MASK 0xD5

#define CR4_FSGSBASE (1 << 16)
Expand Down Expand Up @@ -129,10 +125,6 @@ void kentry(void) {

proc_data_get()->sts |= PROC_STS_INT_READY;

#ifdef SERIAL
serial_init_interrupts();
#endif /* SERIAL */

logging_log_debug("Early PCIE init");
disk_init();
fs_init();
Expand Down
29 changes: 23 additions & 6 deletions kernel/core/mm.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <core/process.h>
#include <core/scheduler.h>
#include <core/time.h>
#include <core/signal.h>

#include <lib/mergesort.h>

Expand Down Expand Up @@ -73,6 +74,8 @@ static struct free_transaction_list_t* transaction_list;
uint8_t pending_free_lock;
static struct disarm_list_t* disarm_list;

static struct signal_wait_t* free_pending_wait;

static struct mm_tree_node_t* alloc_node(void) {
struct mm_tree_node_t* next;
lock_acquire(&n_lock);
Expand Down Expand Up @@ -269,11 +272,13 @@ static uint64_t mm_alloc_max(size_t size, uint64_t align, uint64_t max, struct m
return ret + adj;
}

extern void mm_init(
void mm_init(
void (*first_segment)(uint64_t* handle),
void (*next_segment)(uint64_t* handle, struct mem_segment_t* seg)) {
kernel_limit = (uint64_t)&_kernel_pend;

free_pending_wait = 0;

lock_init(&p_lock);
lock_init(&v_lock);
lock_init(&n_lock);
Expand Down Expand Up @@ -433,6 +438,10 @@ void mm_free_v(uint64_t base, size_t size) {
pending->next = pending_free;
pending_free = (struct free_transaction_list_t* volatile)pending;
lock_release(&pending_free_lock);

if (free_pending_wait) {
signal_awake(free_pending_wait);
}
}

static void free_all_pending(void* _ign) {
Expand All @@ -442,10 +451,14 @@ static void free_all_pending(void* _ign) {
struct disarm_list_t* disarm;
uint8_t cntrl;

free_pending_wait = signal_wait_alloc();

while (1) {
do {
time_sleep(SHOOTDOWN_DELAY_MS);
} while (!pending_free);
time_sleep(SHOOTDOWN_DELAY_MS);

while (!pending_free) {
signal_wait(free_pending_wait);
}

lock_acquire(&pending_free_lock);

Expand All @@ -465,8 +478,6 @@ static void free_all_pending(void* _ign) {
lock_release(&pending_free_lock);

do {
cpu_pause();

cntrl = 0;
lock_acquire(&pending_free_lock);
for (disarm = disarm_list; disarm; disarm = disarm->next) {
Expand All @@ -476,6 +487,10 @@ static void free_all_pending(void* _ign) {
}
}
lock_release(&pending_free_lock);

if (cntrl) {
signal_wait(free_pending_wait);
}
} while(cntrl);

while (transaction_list) {
Expand Down Expand Up @@ -515,4 +530,6 @@ void mm_barrier_disarm(uint8_t id) {
break;
}
}

signal_awake(free_pending_wait);
}
7 changes: 7 additions & 0 deletions kernel/core/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,10 @@ void process_sleep(uint64_t wake_time) {
cpu_hlt();
}
}

void process_set_callback(void (*callback)(struct pcb_t*)) {
struct pcb_t* current = proc_data_get()->current_process;

current->sleep_state.callback = callback;
current->sched_cntr = SCHED_CALLBACK;
}
8 changes: 8 additions & 0 deletions kernel/core/scheduler.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <core/proc_data.h>
#include <core/gdt.h>
#include <core/time.h>
#include <core/logging.h>

#include <apic/apic_regs.h>

Expand Down Expand Up @@ -89,7 +90,14 @@ void scheduler_run(void) {

lock_release(&lock_sched);
break;
case SCHED_CALLBACK:
current_pcb->sleep_state.callback(current_pcb);
break;
default:
logging_log_error("Invalid scheduler code %u", current_pcb->sched_cntr);
__attribute__((fallthrough));
case SCHED_READY:
case SCHED_SIGNAL_READY:
scheduler_schedule(current_pcb);
break;
}
Expand Down
77 changes: 77 additions & 0 deletions kernel/core/signal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* signal.c - kernel signal implementation */
/* Copyright (C) 2026 Ebrahim Aleem
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>
*/

#include <stdint.h>

#include <core/signal.h>
#include <core/lock.h>
#include <core/process.h>
#include <core/scheduler.h>
#include <core/alloc.h>
#include <core/proc_data.h>
#include <core/cpu_instr.h>

struct signal_wait_t {
struct pcb_t* queue;
uint8_t lock;
};

static void signal_wait_callback(struct pcb_t* pcb) {
struct signal_wait_t* wait = pcb->meta[0];

lock_acquire(&wait->lock);
pcb->next = wait->queue;
wait->queue = pcb;
lock_release(&wait->lock);
}

struct signal_wait_t* signal_wait_alloc(void) {
struct signal_wait_t* ret = kmalloc(sizeof(struct signal_wait_t));

lock_init(&ret->lock);
ret->queue = 0;

return ret;
}

void signal_wait(struct signal_wait_t* wait) {
volatile struct pcb_t* current = proc_data_get()->current_process;

current->meta[0] = wait;
process_set_callback(signal_wait_callback);

while (current->sched_cntr != SCHED_SIGNAL_READY) {
cpu_wait_loop();
}

current->sched_cntr = SCHED_READY;
}

void signal_awake(struct signal_wait_t* wait) {
struct pcb_t* i, * next;
lock_acquire(&wait->lock);
i = wait->queue;
wait->queue = 0;
lock_release(&wait->lock);

for (; i; i = next) {
next = i->next;

i->sched_cntr = SCHED_SIGNAL_READY;
scheduler_schedule(i);
}
}
14 changes: 13 additions & 1 deletion kernel/devfs/tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@
#include <core/cpu_instr.h>
#include <core/mm.h>
#include <core/paging.h>
#include <core/signal.h>

#include <lib/kstrcmp.h>
#include <lib/kmemcpy.h>
#include <lib/kstrlen.h>

#ifdef SERIAL
#include <drivers/serial/interrupts.h>
#endif /* SERIAL */

#define TTY_RING_MASK 0x3FFF

#define MASK(i) ((i) & TTY_RING_MASK)
Expand All @@ -47,6 +52,7 @@ struct tty_handle_t {
uint8_t* read_buffer;
volatile uint16_t write_index;
volatile uint16_t read_index;
struct signal_wait_t* signal;
enum {
TTY_MODE_COOKED,
TTY_MODE_RAW
Expand All @@ -67,13 +73,17 @@ void tty_init(void) {
com1.read_buffer = (uint8_t*)paging_ident(mm_alloc_p(TTY_READ_BUFFER_SIZE));
com1.write_index = 0;
com1.read_index = 0;
com1.signal = signal_wait_alloc();
lock_init(&com1.lock);

com2.writer = serial_write_com2;
com2.read_buffer = (uint8_t*)paging_ident(mm_alloc_p(TTY_READ_BUFFER_SIZE));
com2.write_index = 0;
com2.read_index = 0;
com2.signal = signal_wait_alloc();
lock_init(&com2.lock);

serial_init_interrupts();
#endif /* SERIAL */
}

Expand Down Expand Up @@ -108,7 +118,7 @@ size_t tty_read(struct tty_handle_t* tty, void* buffer, size_t count) {

while (count) {
while (EMPTY(tty->read_index, tty->write_index)) {
cpu_pause(); //TODO futex wait
signal_wait(tty->signal);
}

lock_acquire(&tty->lock);
Expand Down Expand Up @@ -176,5 +186,7 @@ uint8_t tty_queue_read(struct tty_handle_t* tty, uint8_t byte) {
}
}

signal_awake(tty->signal);

return 1;
}
22 changes: 16 additions & 6 deletions kernel/include/core/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@

#include <kernel/core/exception_dispatch.h>
#include <kernel/core/fs.h>
#include <kernel/core/signal.h>

#define MAX_FD 256
#define MAX_META 1

struct pcb_t;

struct pcb_t {
// order is important
Expand Down Expand Up @@ -68,17 +72,21 @@ struct pcb_t {

uint8_t fxdata[512] __attribute__((aligned(16)));

union {
uint64_t wake_time;
void (*callback)(struct pcb_t*);
} sleep_state;

void* meta[MAX_META];

enum {
SCHED_READY,
SCHED_KILL,
SCHED_SKIP,
SCHED_SLEEP
SCHED_SLEEP,
SCHED_CALLBACK,
SCHED_SIGNAL_READY
} sched_cntr;

union {
uint64_t wake_time;
} sleep_state;

};

struct preempt_frame_t {
Expand Down Expand Up @@ -131,4 +139,6 @@ extern uint8_t process_create_guarded_stack(uint64_t* init_vaddr, uint64_t* init

extern void process_sleep(uint64_t wake_time);

extern void process_set_callback(void (*callback)(struct pcb_t*));

#endif /* KERNEL_CORE_PROCESS_H */
24 changes: 24 additions & 0 deletions kernel/include/core/signal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* signal.h - kernel signal interface */
/* Copyright (C) 2026 Ebrahim Aleem
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>
*/

#include <stdint.h>

struct signal_wait_t;

extern struct signal_wait_t* signal_wait_alloc(void);
extern void signal_wait(struct signal_wait_t* wait);
extern void signal_awake(struct signal_wait_t* wait);
Loading