From e90b72ec3082588b296956730bd2930cf8d5d671 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Fri, 10 Jul 2026 11:31:46 +0800 Subject: refactor: promote new architecture to repository root Archive the deprecated implementation under lume-legacy, make the new kernel the default root-level build, and update repository entry points without changing kernel behavior. --- kernel/pgrp.cc | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 kernel/pgrp.cc (limited to 'kernel/pgrp.cc') diff --git a/kernel/pgrp.cc b/kernel/pgrp.cc new file mode 100644 index 0000000..e5b382c --- /dev/null +++ b/kernel/pgrp.cc @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (C) 2026 Richard Qin */ + +/* + * Process Group / Session Implementation + * + * Hash table of signal_struct objects keyed by pgid. Lifecycle of + * signal_struct mirrors Linux: one per thread group, refcounted across + * CLONE_THREAD siblings, freed when the last task in the group exits. + * + * Reference: Linux kernel/pid.c, kernel/exit.c + */ + +#include +#include +#include +#include +#include + +/* ================================================================== */ +/* Hash table state */ +/* ================================================================== */ + +list_node g_pgrp_hash[kPgrpHashSize]; +Spinlock g_pgrp_lock; + +void pgrp_init() +{ + for (auto& bucket : g_pgrp_hash) bucket.init(); + g_pgrp_lock.init("pgrp"); +} + +/* ================================================================== */ +/* Internal helpers (must be called with g_pgrp_lock held) */ +/* ================================================================== */ + +static void pgrp_attach_locked(signal_struct* sig, int32 pgid) +{ + sig->pgid = pgid; + list_node* bucket = &g_pgrp_hash[pgrp_hash_idx(pgid)]; + sig->pgrp_link.prev = bucket->prev; + sig->pgrp_link.next = bucket; + bucket->prev->next = &sig->pgrp_link; + bucket->prev = &sig->pgrp_link; +} + +static void pgrp_detach_locked(signal_struct* sig) +{ + /* Unlink only if currently on a list — init() makes prev/next point + * to self, which we treat as "not linked". */ + if (sig->pgrp_link.next == &sig->pgrp_link) return; + sig->pgrp_link.prev->next = sig->pgrp_link.next; + sig->pgrp_link.next->prev = sig->pgrp_link.prev; + sig->pgrp_link.init(); +} + +/* ================================================================== */ +/* signal_struct allocation / refcount */ +/* ================================================================== */ + +signal_struct* alloc_signal_struct(int32 leader_pid, TaskControlBlock* leader) +{ + auto* sig = new signal_struct; + if (!sig) return nullptr; + sig->init(leader_pid, leader); + + LockGuard guard(g_pgrp_lock); + pgrp_attach_locked(sig, leader_pid); + return sig; +} + +signal_struct* fork_signal_struct(signal_struct* parent, + TaskControlBlock* child_leader) +{ + if (!parent) return nullptr; + + auto* sig = new signal_struct; + if (!sig) return nullptr; + + /* Copy identity from parent, then override leader and attach. */ + sig->lock.init("signal"); + sig->refcount = 1; + sig->leader = child_leader; + sig->tty_old_pgrp = 0; + sig->pgrp_link.init(); + + { + LockGuard pg(parent->lock); + sig->pgid = parent->pgid; + sig->sid = parent->sid; + sig->tty = parent->tty; + } + + LockGuard guard(g_pgrp_lock); + pgrp_attach_locked(sig, sig->pgid); + return sig; +} + +void get_signal_struct(signal_struct* sig) +{ + if (!sig) return; + LockGuard guard(sig->lock); + sig->refcount++; +} + +void put_signal_struct(signal_struct* sig) +{ + if (!sig) return; + + uint32 remaining; + { + LockGuard guard(sig->lock); + remaining = --sig->refcount; + } + if (remaining != 0) return; + + /* Last reference — detach from pgrp hash and free. */ + { + LockGuard guard(g_pgrp_lock); + pgrp_detach_locked(sig); + } + delete sig; +} + +/* ================================================================== */ +/* Pgrp membership change */ +/* ================================================================== */ + +void change_pgid(signal_struct* sig, int32 new_pgid) +{ + if (!sig) return; + LockGuard guard(g_pgrp_lock); + if (sig->pgid == new_pgid) return; + pgrp_detach_locked(sig); + pgrp_attach_locked(sig, new_pgid); +} + +int pgrp_member_count(int32 pgid) +{ + LockGuard guard(g_pgrp_lock); + int n = 0; + list_node* bucket = &g_pgrp_hash[pgrp_hash_idx(pgid)]; + for (list_node* node = bucket->next; node != bucket; node = node->next) { + auto* sig = list_entry(node); + if (sig->pgid == pgid) n++; + } + return n; +} -- cgit v1.2.3