The Pedigree Project 0.1
job-control-syscalls.cc
1/* Copyright (c) 2026, Pedigree Developers. */
2#include "job-control-syscalls.h"
3#include "pedigree/kernel/process/Scheduler.h"
4#include "pedigree/kernel/process/TerminationDeferral.h"
5#include "pedigree/kernel/process/Thread.h"
6#include "pedigree/kernel/processor/Processor.h"
7#include "pedigree/kernel/processor/ProcessorInformation.h"
8#include "pedigree/kernel/syscallError.h"
9
10#include "PosixProcess.h"
11
12namespace {
13PosixProcess* caller() {
14 Process* process = Processor::information().getCurrentThread()->getParent();
15 return process->getType() == Process::Posix ? static_cast<PosixProcess*>(process) : nullptr;
16}
17
18int identity(int pid, bool session) {
19 int result = -1;
20 {
21 TerminationDeferral lifetime;
24 PosixProcess* target = nullptr;
25 if (!pid)
26 target = caller();
27 else if (pid > 0 && Scheduler::instance().acquireProcessByUserspaceId(lease, pid) &&
28 lease->getType() == Process::Posix)
29 target = static_cast<PosixProcess*>(lease.get());
30 else if (pid > 0 && Scheduler::instance().acquireThreadByUserspaceId(task, pid) &&
31 task->getParent()->getType() == Process::Posix) {
32 target = static_cast<PosixProcess*>(task->getParent());
33 }
34 if (target) {
35 size_t id = 0;
36 if (session)
37 id = target->getSessionId(caller()->pidNamespace().get());
38 else
39 target->getProcessGroupId(id, caller()->pidNamespace().get());
40 if (id)
41 result = id;
42 }
43 }
44 syscallError(result < 0 ? Error::NoSuchProcess : 0);
45 return result;
46}
47} // namespace
48
49int posix_getsid(int pid) {
50 return identity(pid, true);
51}
52int posix_getpgid(int pid) {
53 return identity(pid, false);
54}
55int posix_getpgrp() {
56 return identity(0, false);
57}
58
59int posix_setsid() {
60 SC_NOTICE("setsid");
61
62 TerminationDeferral lifetime;
63 PosixProcess* process = caller();
64 if (!process) {
65 SYSCALL_ERROR(NoSuchProcess);
66 return -1;
67 }
68 return process->createSession();
69}
70
71int posix_setpgid(int pid, int pgid) {
72 int result = -1;
73 int error = 0;
74 {
75 TerminationDeferral lifetime;
76 PosixProcess* current = caller();
79 PosixProcess* target = current;
80 if (pid < 0 || !current)
81 error = Error::NoSuchProcess;
82 else if (pgid < 0)
83 error = Error::InvalidArgument;
84 else {
85 if (pid && static_cast<size_t>(pid) != current->getUserspaceId()) {
86 if (!Scheduler::instance().acquireProcessByUserspaceId(lease, pid) ||
87 lease->getType() != Process::Posix) {
88 error = Scheduler::instance().acquireThreadByUserspaceId(task, pid)
89 ? Error::InvalidArgument
90 : Error::NoSuchProcess;
91 target = nullptr;
92 } else
93 target = static_cast<PosixProcess*>(lease.get());
94 }
95 if (target) {
96 result = target->changeProcessGroup(
97 *current, pgid ? pgid : target->getUserspaceId(current->pidNamespace().get()));
98 error = result < 0 ? Processor::information().getCurrentThread()->getErrno() : 0;
99 }
100 }
101 }
102 syscallError(error);
103 return result;
104}
size_t getUserspaceId() const
Definition Process.h:504
Process * getParent()
Definition Process.h:620
static ProcessorInformation & information()
static Scheduler & instance()
Definition Scheduler.h:96
Process * getParent() const
Definition Thread.h:340