Kernel: Barebones implementation sessions and process groups

This commit is contained in:
Bananymous 2023-08-22 11:35:40 +03:00
parent 642929f071
commit 0f6c19a1b7
5 changed files with 140 additions and 69 deletions

View File

@ -1,5 +1,6 @@
#pragma once
#include <BAN/Iteration.h>
#include <BAN/String.h>
#include <BAN/StringView.h>
#include <BAN/Vector.h>
@ -45,11 +46,17 @@ namespace Kernel
void exit(int status, int signal);
static void for_each_process(const BAN::Function<BAN::Iteration(Process&)>& callback);
void add_thread(Thread*);
void on_thread_exit(Thread&);
pid_t sid() const { return m_sid; }
pid_t pgrp() const { return m_pgrp; }
pid_t pid() const { return m_pid; }
bool is_session_leader() const { return pid() == sid(); }
BAN::ErrorOr<long> sys_exit(int status);
BAN::ErrorOr<long> sys_gettermios(::termios*);
@ -111,7 +118,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_clock_gettime(clockid_t, timespec*) const;
TTY& tty() { ASSERT(m_tty); return *m_tty; }
TTY& tty() { ASSERT(m_controlling_terminal); return *m_controlling_terminal; }
static Process& current() { return Thread::current().process(); }
@ -121,8 +128,8 @@ namespace Kernel
const userspace_info_t& userspace_info() const { return m_userspace_info; }
private:
Process(const Credentials&, pid_t);
static Process* create_process(const Credentials&);
Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp);
static Process* create_process(const Credentials&, pid_t parent, pid_t sid = 0, pid_t pgrp = 0);
static void register_process(Process*);
// Load an elf file to virtual address space of the current page table
@ -150,9 +157,13 @@ namespace Kernel
BAN::Vector<BAN::UniqPtr<VirtualRange>> m_mapped_ranges;
pid_t m_sid;
pid_t m_pgrp;
const pid_t m_pid;
const pid_t m_parent;
mutable RecursiveSpinLock m_lock;
const pid_t m_pid = 0;
BAN::String m_working_directory;
BAN::Vector<Thread*> m_threads;
@ -167,7 +178,7 @@ namespace Kernel
ExitStatus m_exit_status;
BAN::UniqPtr<PageTable> m_page_table;
BAN::RefPtr<TTY> m_tty;
BAN::RefPtr<TTY> m_controlling_terminal;
friend class Thread;
};

View File

@ -23,8 +23,8 @@ namespace Kernel
uint32_t height() const { return m_height; }
uint32_t width() const { return m_width; }
void set_foreground_process(pid_t pgid) { m_foreground_process = pgid; }
pid_t foreground_process() const { return m_foreground_process; }
void set_foreground_pgrp(pid_t pgrp) { m_foreground_pgrp = pgrp; }
pid_t foreground_pgrp() const { return m_foreground_pgrp; }
// for kprint
static void putchar_current(uint8_t ch);
@ -97,7 +97,7 @@ namespace Kernel
TerminalDriver::Color m_foreground { TerminalColor::BRIGHT_WHITE };
TerminalDriver::Color m_background { TerminalColor::BLACK };
pid_t m_foreground_process { 0 };
pid_t m_foreground_pgrp { 0 };
termios m_termios;

View File

@ -56,7 +56,7 @@ namespace Kernel
BAN::ErrorOr<int> OpenFileDescriptorSet::open(BAN::StringView absolute_path, int flags)
{
if (flags & ~(O_RDONLY | O_WRONLY | O_NOFOLLOW | O_SEARCH | O_APPEND | O_TRUNC | O_CLOEXEC))
if (flags & ~(O_RDONLY | O_WRONLY | O_NOFOLLOW | O_SEARCH | O_APPEND | O_TRUNC | O_CLOEXEC | O_TTY_INIT))
return BAN::Error::from_errno(ENOTSUP);
int access_mask = O_EXEC | O_RDONLY | O_WRONLY | O_SEARCH;

View File

@ -21,13 +21,43 @@ namespace Kernel
{
static BAN::Vector<Process*> s_processes;
static SpinLock s_process_lock;
static RecursiveSpinLock s_process_lock;
Process* Process::create_process(const Credentials& credentials)
void Process::for_each_process(const BAN::Function<BAN::Iteration(Process&)>& callback)
{
static pid_t s_next_pid = 1;
auto* process = new Process(credentials, s_next_pid++);
LockGuard _(s_process_lock);
for (auto* process : s_processes)
{
auto ret = callback(*process);
if (ret == BAN::Iteration::Break)
return;
ASSERT(ret == BAN::Iteration::Continue);
}
}
Process* Process::create_process(const Credentials& credentials, pid_t parent, pid_t sid, pid_t pgrp)
{
static pid_t s_next_id = 1;
pid_t pid;
{
CriticalScope _;
pid = s_next_id;
if (sid == 0 && pgrp == 0)
{
sid = s_next_id;
pgrp = s_next_id;
}
s_next_id++;
}
ASSERT(sid > 0);
ASSERT(pgrp > 0);
auto* process = new Process(credentials, pid, parent, sid, pgrp);
ASSERT(process);
return process;
}
@ -42,7 +72,7 @@ namespace Kernel
Process* Process::create_kernel(entry_t entry, void* data)
{
auto* process = create_process({ 0, 0, 0, 0 });
auto* process = create_process({ 0, 0, 0, 0 }, 0);
MUST(process->m_working_directory.push_back('/'));
auto* thread = MUST(Thread::create_kernel(entry, data, process));
process->add_thread(thread);
@ -54,7 +84,7 @@ namespace Kernel
{
auto elf = TRY(load_elf_for_exec(credentials, path, "/"sv, {}));
auto* process = create_process(credentials);
auto* process = create_process(credentials, 0);
MUST(process->m_working_directory.push_back('/'));
process->m_page_table = BAN::UniqPtr<PageTable>::adopt(MUST(PageTable::create_userspace()));;
@ -95,11 +125,13 @@ namespace Kernel
return process;
}
Process::Process(const Credentials& credentials, pid_t pid)
Process::Process(const Credentials& credentials, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp)
: m_credentials(credentials)
, m_open_file_descriptors(m_credentials)
, m_sid(sid)
, m_pgrp(pgrp)
, m_pid(pid)
, m_tty(TTY::current())
, m_parent(parent)
{
for (size_t i = 0; i < sizeof(m_signal_handlers) / sizeof(*m_signal_handlers); i++)
m_signal_handlers[i] = (vaddr_t)SIG_DFL;
@ -148,9 +180,6 @@ namespace Kernel
// NOTE: We must clear allocators while the page table is still alive
m_fixed_width_allocators.clear();
m_general_allocator.clear();
if (m_tty && m_tty->foreground_process() == pid())
m_tty->set_foreground_process(0);
}
void Process::on_thread_exit(Thread& thread)
@ -198,10 +227,11 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_gettermios(::termios* termios)
{
LockGuard _(m_lock);
if (!m_tty)
if (!m_controlling_terminal)
return BAN::Error::from_errno(ENOTTY);
Kernel::termios ktermios = m_tty->get_termios();
Kernel::termios ktermios = m_controlling_terminal->get_termios();
termios->c_lflag = 0;
if (ktermios.canonical)
termios->c_lflag |= ICANON;
@ -214,14 +244,15 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_settermios(const ::termios* termios)
{
LockGuard _(m_lock);
if (!m_tty)
if (!m_controlling_terminal)
return BAN::Error::from_errno(ENOTTY);
Kernel::termios ktermios;
ktermios.echo = termios->c_lflag & ECHO;
ktermios.canonical = termios->c_lflag & ICANON;
m_tty->set_termios(ktermios);
m_controlling_terminal->set_termios(ktermios);
return 0;
}
@ -325,8 +356,8 @@ namespace Kernel
if (m_general_allocator)
general_allocator = TRY(m_general_allocator->clone(*page_table));
Process* forked = create_process(m_credentials);
forked->m_tty = m_tty;
Process* forked = create_process(m_credentials, m_pid, m_sid, m_pgrp);
forked->m_controlling_terminal = m_controlling_terminal;
forked->m_working_directory = BAN::move(working_directory);
forked->m_page_table = BAN::move(page_table);
forked->m_open_file_descriptors = BAN::move(open_file_descriptors);
@ -455,12 +486,17 @@ namespace Kernel
if (options)
return BAN::Error::from_errno(EINVAL);
{
LockGuard _(s_process_lock);
for (auto* process : s_processes)
if (process->pid() == pid)
target = process;
}
for_each_process(
[&](Process& process)
{
if (process.pid() == pid)
{
target = &process;
return BAN::Iteration::Break;
}
return BAN::Iteration::Continue;
}
);
if (target == nullptr)
return BAN::Error::from_errno(ECHILD);
@ -555,7 +591,14 @@ namespace Kernel
flags &= ~O_CREAT;
}
return TRY(m_open_file_descriptors.open(absolute_path, flags));
int fd = TRY(m_open_file_descriptors.open(absolute_path, flags));
auto inode = MUST(m_open_file_descriptors.inode_of(fd));
// Open controlling terminal
if ((flags & O_TTY_INIT) && !(flags & O_NOCTTY) && inode->is_tty() && is_session_leader() && !m_controlling_terminal)
m_controlling_terminal = (TTY*)inode.ptr();
return fd;
}
BAN::ErrorOr<long> Process::sys_openat(int fd, BAN::StringView path, int flags, mode_t mode)
@ -791,14 +834,18 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_termid(char* buffer) const
{
LockGuard _(m_lock);
if (!m_tty)
auto& tty = m_controlling_terminal;
if (!tty)
buffer[0] = '\0';
else
{
ASSERT(minor(m_tty->rdev()) < 10);
ASSERT(minor(tty->rdev()) < 10);
strcpy(buffer, "/dev/tty0");
buffer[8] += minor(m_tty->rdev());
buffer[8] += minor(tty->rdev());
}
return 0;
}
@ -834,7 +881,7 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_kill(pid_t pid, int signal)
{
if (pid <= 0)
if (pid == 0 || pid == -1)
return BAN::Error::from_errno(ENOTSUP);
if (signal != 0 && (signal < _SIGMIN || signal > _SIGMAX))
return BAN::Error::from_errno(EINVAL);
@ -842,19 +889,26 @@ namespace Kernel
if (pid == Process::current().pid())
return Process::current().sys_raise(signal);
LockGuard process_guard(s_process_lock);
for (auto* process : s_processes)
{
if (process->pid() == pid)
bool found = false;
for_each_process(
[&](Process& process)
{
if (signal == 0)
return 0;
CriticalScope _;
process->m_signal_pending_mask |= 1ull << signal;
return 0;
if (pid == process.pid() || -pid == process.pid())
{
found = true;
if (signal)
{
CriticalScope _;
process.m_signal_pending_mask |= 1 << signal;
}
return (pid > 0) ? BAN::Iteration::Break : BAN::Iteration::Continue;
}
return BAN::Iteration::Continue;
}
}
);
if (found)
return 0;
return BAN::Error::from_errno(ESRCH);
}
@ -869,31 +923,37 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_tcsetpgrp(int fd, pid_t pgid)
BAN::ErrorOr<long> Process::sys_tcsetpgrp(int fd, pid_t pgrp)
{
LockGuard _(m_lock);
// FIXME: validate the inode
if (!m_controlling_terminal)
return BAN::Error::from_errno(ENOTTY);
bool valid_pgrp = false;
for_each_process(
[&](Process& process)
{
if (process.sid() == sid() && process.pgrp() == pgrp)
{
valid_pgrp = true;
return BAN::Iteration::Break;
}
return BAN::Iteration::Continue;
}
);
if (!valid_pgrp)
return BAN::Error::from_errno(EPERM);
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
if (!inode->is_tty())
return BAN::Error::from_errno(ENOTTY);
if ((TTY*)inode.ptr() != m_controlling_terminal.ptr())
return BAN::Error::from_errno(ENOTTY);
// FIXME: use process groups instead of process ids
// FIXME: return values
LockGuard process_guard(s_process_lock);
for (auto* process : s_processes)
{
if (process->pid() == pgid)
{
if (!process->is_userspace())
return BAN::Error::from_errno(EINVAL);
((TTY*)inode.ptr())->set_foreground_process(pgid);
return 0;
}
}
return BAN::Error::from_errno(EPERM);
((TTY*)inode.ptr())->set_foreground_pgrp(pgrp);
return 0;
}
BAN::ErrorOr<long> Process::sys_setuid(uid_t uid)

View File

@ -29,7 +29,7 @@ namespace Kernel
static dev_t next_tty_rdev()
{
static dev_t major = DevFileSystem::get().get_next_rdev();
static dev_t minor = 1;
static dev_t minor = 0;
return makedev(major, minor++);
}
@ -75,17 +75,17 @@ namespace Kernel
ASSERT(MUST(Process::current().sys_read(fd, &event, sizeof(event))) == sizeof(event));
TTY& current_tty = *TTY::current();
if (current_tty.m_foreground_process &&
if (current_tty.m_foreground_pgrp &&
event.pressed() &&
event.ctrl() &&
!event.shift()
&& event.key == Input::Key::C
)
{
if (auto ret = Process::sys_kill(current_tty.m_foreground_process, SIGINT); ret.is_error())
if (auto ret = Process::sys_kill(-current_tty.m_foreground_pgrp, SIGINT); ret.is_error())
dwarnln("TTY: {}", ret.error());
}
else
else
current_tty.on_key(event);
}
}, nullptr