Kernel: Barebones implementation sessions and process groups
This commit is contained in:
parent
642929f071
commit
0f6c19a1b7
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue