mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 15:08:21 +00:00
job control: sessions and process groups
This commit is contained in:
@@ -52,6 +52,11 @@ extern syscall_newthread
|
|||||||
extern syscall_threadexit
|
extern syscall_threadexit
|
||||||
extern syscall_futex
|
extern syscall_futex
|
||||||
extern syscall_gettid
|
extern syscall_gettid
|
||||||
|
extern syscall_getppid
|
||||||
|
extern syscall_getpgid
|
||||||
|
extern syscall_getsid
|
||||||
|
extern syscall_setsid
|
||||||
|
extern syscall_setpgid
|
||||||
syscalltab:
|
syscalltab:
|
||||||
dq syscall_print
|
dq syscall_print
|
||||||
dq syscall_mmap
|
dq syscall_mmap
|
||||||
@@ -106,7 +111,12 @@ dq syscall_newthread
|
|||||||
dq syscall_threadexit
|
dq syscall_threadexit
|
||||||
dq syscall_futex
|
dq syscall_futex
|
||||||
dq syscall_gettid
|
dq syscall_gettid
|
||||||
syscallcount equ 53
|
dq syscall_getppid
|
||||||
|
dq syscall_getpgid
|
||||||
|
dq syscall_getsid
|
||||||
|
dq syscall_setsid
|
||||||
|
dq syscall_setpgid
|
||||||
|
syscallcount equ 58
|
||||||
section .text
|
section .text
|
||||||
global arch_syscall_entry
|
global arch_syscall_entry
|
||||||
; on entry:
|
; on entry:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#ifdef SYSCALL_LOGGING
|
#ifdef SYSCALL_LOGGING
|
||||||
|
|
||||||
#define SYSCALL_COUNT 53
|
#define SYSCALL_COUNT 58
|
||||||
#define LOGSTR(x) arch_e9_puts(x)
|
#define LOGSTR(x) arch_e9_puts(x)
|
||||||
|
|
||||||
static char *name[] = {
|
static char *name[] = {
|
||||||
@@ -60,7 +60,12 @@ static char *name[] = {
|
|||||||
"newthread",
|
"newthread",
|
||||||
"threadexit",
|
"threadexit",
|
||||||
"futex",
|
"futex",
|
||||||
"gettid"
|
"gettid",
|
||||||
|
"getppid",
|
||||||
|
"getpgid",
|
||||||
|
"getsid",
|
||||||
|
"setsid",
|
||||||
|
"setpgid"
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *args[] = {
|
static char *args[] = {
|
||||||
@@ -116,7 +121,12 @@ static char *args[] = {
|
|||||||
"entry %p stack %p", // newthread
|
"entry %p stack %p", // newthread
|
||||||
"N/A", // threadexit
|
"N/A", // threadexit
|
||||||
"futex %p op %d value %d timespec %p", // futex
|
"futex %p op %d value %d timespec %p", // futex
|
||||||
"N/A" // gettid
|
"N/A", // gettid
|
||||||
|
"N/A", // getppid
|
||||||
|
"pid %d", // getpgid
|
||||||
|
"pid %d", // getsid
|
||||||
|
"N/A", // setsid
|
||||||
|
"pid %d pgid %d", // setpgid
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -129,7 +139,6 @@ __attribute__((no_caller_saved_registers)) void arch_syscall_log(int syscall, ui
|
|||||||
|
|
||||||
thread_t *thread = _cpu()->thread;
|
thread_t *thread = _cpu()->thread;
|
||||||
proc_t *proc = thread->proc;
|
proc_t *proc = thread->proc;
|
||||||
|
|
||||||
snprintf(argbuff, 768, syscall < SYSCALL_COUNT ? args[syscall] : "N/A", a1, a2, a3, a4, a5, a6);
|
snprintf(argbuff, 768, syscall < SYSCALL_COUNT ? args[syscall] : "N/A", a1, a2, a3, a4, a5, a6);
|
||||||
snprintf(printbuff, 1024, "\e[92msyscall: pid %d tid %d: %s: %s (%lu free pages)\n\e[0m", proc->pid, thread->tid, syscall < SYSCALL_COUNT ? name[syscall] : "invalid syscall", argbuff, freepagecount);
|
snprintf(printbuff, 1024, "\e[92msyscall: pid %d tid %d: %s: %s (%lu free pages)\n\e[0m", proc->pid, thread->tid, syscall < SYSCALL_COUNT ? name[syscall] : "invalid syscall", argbuff, freepagecount);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef _JOBCTL_H
|
||||||
|
#define _JOBCTL_H
|
||||||
|
|
||||||
|
#include <kernel/scheduler.h>
|
||||||
|
|
||||||
|
int jobctl_newsession(proc_t *proc);
|
||||||
|
int jobctl_newgroup(proc_t *proc);
|
||||||
|
int jobctl_changegroup(proc_t *proc, proc_t *group);
|
||||||
|
void jobctl_detach(proc_t *);
|
||||||
|
void jobctl_addproc(proc_t *parent, proc_t *proc);
|
||||||
|
void jobctl_procremove(proc_t *proc);
|
||||||
|
pid_t jobctl_getpgid(proc_t *proc);
|
||||||
|
pid_t jobctl_getsid(proc_t *proc);
|
||||||
|
void jobctl_setctty(proc_t *proc, void *ctty);
|
||||||
|
void *jobctl_getctty(proc_t *proc);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -74,6 +74,29 @@ typedef struct proc_t {
|
|||||||
semaphore_t waitsem;
|
semaphore_t waitsem;
|
||||||
spinlock_t exiting;
|
spinlock_t exiting;
|
||||||
bool nomorethreads;
|
bool nomorethreads;
|
||||||
|
|
||||||
|
spinlock_t jobctllock;
|
||||||
|
struct {
|
||||||
|
// NULL if this process is leader
|
||||||
|
struct proc_t *leader;
|
||||||
|
|
||||||
|
// these are only applicable if the process is leader
|
||||||
|
struct proc_t *foreground; // process group leader, NULL if self
|
||||||
|
void *controllingtty;
|
||||||
|
int processcount; // refcount
|
||||||
|
} session;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
// NULL if this process is leader
|
||||||
|
struct proc_t *leader;
|
||||||
|
// linked list
|
||||||
|
struct proc_t *nextmember;
|
||||||
|
struct proc_t *previousmember;
|
||||||
|
|
||||||
|
// these are only applicable if the process is leader
|
||||||
|
spinlock_t lock; // protects the linked list
|
||||||
|
int processcount; // refcount
|
||||||
|
} pgrp;
|
||||||
} proc_t;
|
} proc_t;
|
||||||
|
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <kernel/poll.h>
|
#include <kernel/poll.h>
|
||||||
#include <ringbuffer.h>
|
#include <ringbuffer.h>
|
||||||
|
#include <kernel/vfs.h>
|
||||||
|
|
||||||
#define DEVICE_BUFFER_SIZE 512
|
#define DEVICE_BUFFER_SIZE 512
|
||||||
#define READ_BUFFER_SIZE 4096
|
#define READ_BUFFER_SIZE 4096
|
||||||
@@ -23,6 +24,7 @@ typedef struct {
|
|||||||
ttydevicewritefn_t writetodevice;
|
ttydevicewritefn_t writetodevice;
|
||||||
int minor;
|
int minor;
|
||||||
winsize_t winsize;
|
winsize_t winsize;
|
||||||
|
vnode_t *mastervnode;
|
||||||
} tty_t;
|
} tty_t;
|
||||||
|
|
||||||
void tty_init();
|
void tty_init();
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ typedef struct vfs_t {
|
|||||||
#define V_FFLAGS_NONBLOCKING 4
|
#define V_FFLAGS_NONBLOCKING 4
|
||||||
#define V_FFLAGS_SHARED 8
|
#define V_FFLAGS_SHARED 8
|
||||||
#define V_FFLAGS_EXEC 16
|
#define V_FFLAGS_EXEC 16
|
||||||
|
#define V_FFLAGS_NOCTTY 32
|
||||||
|
|
||||||
typedef struct vnode_t {
|
typedef struct vnode_t {
|
||||||
struct vops_t *ops;
|
struct vops_t *ops;
|
||||||
|
|||||||
+38
-1
@@ -2,6 +2,7 @@
|
|||||||
#include <kernel/devfs.h>
|
#include <kernel/devfs.h>
|
||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
#include <kernel/alloc.h>
|
#include <kernel/alloc.h>
|
||||||
|
#include <kernel/jobctl.h>
|
||||||
|
|
||||||
#define TTY_MAX_COUNT 4096
|
#define TTY_MAX_COUNT 4096
|
||||||
#define CONTROLLING_TTY_MINOR TTY_MAX_COUNT
|
#define CONTROLLING_TTY_MINOR TTY_MAX_COUNT
|
||||||
@@ -237,6 +238,29 @@ static int isatty(int minor) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int open(int minor, vnode_t **vnode, int flags) {
|
||||||
|
tty_t *tty = ttyget(minor);
|
||||||
|
|
||||||
|
if (minor == CONTROLLING_TTY_MINOR) {
|
||||||
|
// return controlling tty
|
||||||
|
tty_t *ctty = jobctl_getctty(_cpu()->thread->proc);
|
||||||
|
|
||||||
|
if (ctty == NULL) {
|
||||||
|
return ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOP_RELEASE(*vnode);
|
||||||
|
*vnode = (vnode_t *)(ctty->mastervnode);
|
||||||
|
} else if (tty == NULL) {
|
||||||
|
return ENODEV;
|
||||||
|
} else if ((flags & V_FFLAGS_NOCTTY) == 0) {
|
||||||
|
// set as controlling tty
|
||||||
|
jobctl_setctty(_cpu()->thread->proc, tty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int allocminor(tty_t *tty) {
|
static int allocminor(tty_t *tty) {
|
||||||
MUTEX_ACQUIRE(&listmutex, false);
|
MUTEX_ACQUIRE(&listmutex, false);
|
||||||
|
|
||||||
@@ -264,7 +288,8 @@ static devops_t devops = {
|
|||||||
.poll = poll,
|
.poll = poll,
|
||||||
.read = read,
|
.read = read,
|
||||||
.ioctl = ioctl,
|
.ioctl = ioctl,
|
||||||
.isatty = isatty
|
.isatty = isatty,
|
||||||
|
.open = open
|
||||||
};
|
};
|
||||||
|
|
||||||
tty_t *tty_create(char *name, ttydevicewritefn_t fn) {
|
tty_t *tty_create(char *name, ttydevicewritefn_t fn) {
|
||||||
@@ -310,6 +335,14 @@ tty_t *tty_create(char *name, ttydevicewritefn_t fn) {
|
|||||||
tty->writetodevice = fn;
|
tty->writetodevice = fn;
|
||||||
tty->minor = minor;
|
tty->minor = minor;
|
||||||
|
|
||||||
|
vnode_t *newnode;
|
||||||
|
__assert(devfs_getnode(NULL, DEV_MAJOR_TTY, minor, &newnode) == 0);
|
||||||
|
|
||||||
|
tty->mastervnode = (vnode_t *)((devnode_t *)newnode)->master;
|
||||||
|
VOP_HOLD(tty->mastervnode);
|
||||||
|
|
||||||
|
VOP_RELEASE(newnode);
|
||||||
|
|
||||||
return tty;
|
return tty;
|
||||||
error:
|
error:
|
||||||
if (tty->name)
|
if (tty->name)
|
||||||
@@ -322,6 +355,10 @@ tty_t *tty_create(char *name, ttydevicewritefn_t fn) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tty_unregister(char *name, tty_t *tty) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void tty_destroy(char *name, tty_t *tty) {
|
void tty_destroy(char *name, tty_t *tty) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,286 @@
|
|||||||
|
#include <kernel/jobctl.h>
|
||||||
|
#include <kernel/interrupt.h>
|
||||||
|
#include <kernel/tty.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <logging.h>
|
||||||
|
|
||||||
|
// assumes interrupts are disabled
|
||||||
|
static void addtolist(proc_t *pgrp, proc_t *proc) {
|
||||||
|
spinlock_acquire(&pgrp->pgrp.lock);
|
||||||
|
|
||||||
|
proc->pgrp.nextmember = pgrp->pgrp.nextmember;
|
||||||
|
proc->pgrp.previousmember = NULL;
|
||||||
|
pgrp->pgrp.nextmember = proc;
|
||||||
|
|
||||||
|
if (proc->pgrp.nextmember)
|
||||||
|
proc->pgrp.nextmember->pgrp.previousmember = proc;
|
||||||
|
|
||||||
|
spinlock_release(&pgrp->pgrp.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
// assumes interrupts are disabled
|
||||||
|
static void removefromlist(proc_t *pgrp, proc_t *proc) {
|
||||||
|
spinlock_acquire(&pgrp->pgrp.lock);
|
||||||
|
|
||||||
|
if (proc->pgrp.previousmember)
|
||||||
|
proc->pgrp.previousmember->pgrp.nextmember = proc->pgrp.nextmember;
|
||||||
|
|
||||||
|
if (proc->pgrp.nextmember)
|
||||||
|
proc->pgrp.nextmember->pgrp.previousmember = proc->pgrp.previousmember;
|
||||||
|
|
||||||
|
spinlock_release(&pgrp->pgrp.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jobctl_setctty(proc_t *proc, void *_ctty) {
|
||||||
|
tty_t *tty = _ctty;
|
||||||
|
__assert(tty);
|
||||||
|
|
||||||
|
bool intstatus = interrupt_set(false);
|
||||||
|
spinlock_acquire(&proc->jobctllock);
|
||||||
|
|
||||||
|
tty_t *unholdtty = NULL;
|
||||||
|
|
||||||
|
// if not the session leader
|
||||||
|
if (proc->session.leader)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
if (tty == NULL && proc->session.controllingtty) {
|
||||||
|
unholdtty = proc->session.controllingtty;
|
||||||
|
proc->session.controllingtty = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tty && proc->session.controllingtty == NULL) {
|
||||||
|
VOP_HOLD(tty->mastervnode);
|
||||||
|
proc->session.controllingtty = tty;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
spinlock_release(&proc->jobctllock);
|
||||||
|
interrupt_set(intstatus);
|
||||||
|
|
||||||
|
if (unholdtty) {
|
||||||
|
VOP_RELEASE(unholdtty->mastervnode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *jobctl_getctty(proc_t *proc) {
|
||||||
|
tty_t *tty = NULL;
|
||||||
|
|
||||||
|
bool intstatus = interrupt_set(false);
|
||||||
|
spinlock_acquire(&proc->jobctllock);
|
||||||
|
|
||||||
|
if (proc->session.leader) {
|
||||||
|
proc_t *session = proc->session.leader;
|
||||||
|
spinlock_acquire(&session->jobctllock);
|
||||||
|
|
||||||
|
tty = session->session.controllingtty;
|
||||||
|
if (tty) {
|
||||||
|
VOP_HOLD(tty->mastervnode);
|
||||||
|
}
|
||||||
|
|
||||||
|
spinlock_release(&session->jobctllock);
|
||||||
|
} else if (proc->session.controllingtty){
|
||||||
|
// is the session leader
|
||||||
|
tty = proc->session.controllingtty;
|
||||||
|
VOP_HOLD(tty->mastervnode);
|
||||||
|
}
|
||||||
|
|
||||||
|
spinlock_release(&proc->jobctllock);
|
||||||
|
interrupt_set(intstatus);
|
||||||
|
return tty;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t jobctl_getpgid(proc_t *proc) {
|
||||||
|
bool intstatus = interrupt_set(false);
|
||||||
|
spinlock_acquire(&proc->jobctllock);
|
||||||
|
|
||||||
|
pid_t pid = proc->pgrp.leader ? proc->pgrp.leader->pid : proc->pid;
|
||||||
|
|
||||||
|
spinlock_release(&proc->jobctllock);
|
||||||
|
interrupt_set(intstatus);
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t jobctl_getsid(proc_t *proc) {
|
||||||
|
bool intstatus = interrupt_set(false);
|
||||||
|
spinlock_acquire(&proc->jobctllock);
|
||||||
|
|
||||||
|
pid_t pid = proc->session.leader ? proc->session.leader->pid : proc->pid;
|
||||||
|
|
||||||
|
spinlock_release(&proc->jobctllock);
|
||||||
|
interrupt_set(intstatus);
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jobctl_newsession(proc_t *proc) {
|
||||||
|
// keep those saved so we don't unhold them with interrupts disabled,
|
||||||
|
// which would possibly call into the allocators without interrupts
|
||||||
|
proc_t *unholdpgrp = NULL;
|
||||||
|
proc_t *unholdsession = NULL;
|
||||||
|
|
||||||
|
int error = 0;
|
||||||
|
bool intstatus = interrupt_set(false);
|
||||||
|
spinlock_acquire(&proc->jobctllock);
|
||||||
|
|
||||||
|
// check if session/group leader
|
||||||
|
if (proc->pgrp.leader == NULL) {
|
||||||
|
error = EPERM;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
unholdpgrp = proc->pgrp.leader;
|
||||||
|
unholdsession = proc->session.leader;
|
||||||
|
|
||||||
|
removefromlist(proc->pgrp.leader, proc);
|
||||||
|
|
||||||
|
proc->session.leader = NULL;
|
||||||
|
proc->session.foreground = NULL;
|
||||||
|
proc->session.controllingtty = NULL;
|
||||||
|
|
||||||
|
proc->pgrp.leader = NULL;
|
||||||
|
proc->pgrp.nextmember = NULL;
|
||||||
|
proc->pgrp.previousmember = NULL;
|
||||||
|
|
||||||
|
leave:
|
||||||
|
spinlock_release(&proc->jobctllock);
|
||||||
|
interrupt_set(intstatus);
|
||||||
|
|
||||||
|
if (unholdpgrp) {
|
||||||
|
PROC_RELEASE(unholdpgrp);
|
||||||
|
PROC_RELEASE(unholdsession);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jobctl_newgroup(proc_t *proc) {
|
||||||
|
// keep it saved so we don't unhold it with interrupts disabled,
|
||||||
|
// which would possibly call into the allocators without interrupts
|
||||||
|
proc_t *unholdpgrp = NULL;
|
||||||
|
|
||||||
|
int error = 0;
|
||||||
|
bool intstatus = interrupt_set(false);
|
||||||
|
spinlock_acquire(&proc->jobctllock);
|
||||||
|
|
||||||
|
// check if session/group leader
|
||||||
|
if (proc->pgrp.leader == NULL) {
|
||||||
|
error = EPERM;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
unholdpgrp = proc->pgrp.leader;
|
||||||
|
|
||||||
|
removefromlist(proc->pgrp.leader, proc);
|
||||||
|
|
||||||
|
proc->pgrp.leader = NULL;
|
||||||
|
proc->pgrp.nextmember = NULL;
|
||||||
|
proc->pgrp.previousmember = NULL;
|
||||||
|
|
||||||
|
leave:
|
||||||
|
spinlock_release(&proc->jobctllock);
|
||||||
|
interrupt_set(intstatus);
|
||||||
|
|
||||||
|
if (unholdpgrp) {
|
||||||
|
PROC_RELEASE(unholdpgrp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jobctl_changegroup(proc_t *proc, proc_t *group) {
|
||||||
|
// keep it saved so we don't unhold it with interrupts disabled,
|
||||||
|
// which would possibly call into the allocators without interrupts
|
||||||
|
proc_t *unholdpgrp = NULL;
|
||||||
|
|
||||||
|
int error = 0;
|
||||||
|
bool intstatus = interrupt_set(false);
|
||||||
|
spinlock_acquire(&proc->jobctllock);
|
||||||
|
|
||||||
|
// check if session/group leader
|
||||||
|
if (proc->pgrp.leader == NULL) {
|
||||||
|
error = EPERM;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
removefromlist(proc->pgrp.leader, proc);
|
||||||
|
unholdpgrp = proc->pgrp.leader;
|
||||||
|
proc->pgrp.leader = group;
|
||||||
|
addtolist(group, proc);
|
||||||
|
|
||||||
|
leave:
|
||||||
|
spinlock_release(&proc->jobctllock);
|
||||||
|
interrupt_set(intstatus);
|
||||||
|
|
||||||
|
if (unholdpgrp) {
|
||||||
|
PROC_RELEASE(unholdpgrp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jobctl_detach(proc_t *proc) {
|
||||||
|
// called on process exit (when the last userland thread is exiting)
|
||||||
|
proc_t *unholdpgrp = NULL;
|
||||||
|
proc_t *unholdsession = NULL;
|
||||||
|
bool intstatus = interrupt_set(false);
|
||||||
|
spinlock_acquire(&proc->jobctllock);
|
||||||
|
|
||||||
|
if (proc->pgrp.leader) {
|
||||||
|
unholdpgrp = proc->pgrp.leader;
|
||||||
|
removefromlist(proc->pgrp.leader, proc);
|
||||||
|
proc->pgrp.leader = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proc->session.leader) {
|
||||||
|
unholdsession = proc->session.leader;
|
||||||
|
proc->session.leader = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
spinlock_release(&proc->jobctllock);
|
||||||
|
interrupt_set(intstatus);
|
||||||
|
|
||||||
|
if (unholdpgrp) {
|
||||||
|
PROC_RELEASE(unholdpgrp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unholdsession) {
|
||||||
|
PROC_RELEASE(unholdsession);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jobctl_addproc(proc_t *parent, proc_t *proc) {
|
||||||
|
// called when a new process is being created (such as by fork)
|
||||||
|
|
||||||
|
bool intstatus = interrupt_set(false);
|
||||||
|
spinlock_acquire(&parent->jobctllock);
|
||||||
|
spinlock_acquire(&proc->jobctllock);
|
||||||
|
|
||||||
|
proc->session.leader = parent->session.leader ? parent->session.leader : parent;
|
||||||
|
proc->pgrp.leader = parent->pgrp.leader ? parent->pgrp.leader : parent;
|
||||||
|
|
||||||
|
PROC_HOLD(proc->session.leader);
|
||||||
|
PROC_HOLD(proc->pgrp.leader);
|
||||||
|
|
||||||
|
addtolist(proc->pgrp.leader, proc);
|
||||||
|
|
||||||
|
spinlock_release(&proc->jobctllock);
|
||||||
|
spinlock_release(&parent->jobctllock);
|
||||||
|
interrupt_set(intstatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jobctl_procremove(proc_t *proc) {
|
||||||
|
// called after all refcounts to a proc are released
|
||||||
|
// cleans up session stuff
|
||||||
|
|
||||||
|
if (proc->session.leader != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (proc->session.foreground) {
|
||||||
|
PROC_RELEASE(proc->session.foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_t *tty = proc->session.controllingtty;
|
||||||
|
VOP_RELEASE(tty->mastervnode);
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <kernel/file.h>
|
#include <kernel/file.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <kernel/devfs.h>
|
#include <kernel/devfs.h>
|
||||||
|
#include <kernel/jobctl.h>
|
||||||
|
|
||||||
#define QUANTUM_US 100000
|
#define QUANTUM_US 100000
|
||||||
#define SCHEDULER_STACK_SIZE PAGE_SIZE
|
#define SCHEDULER_STACK_SIZE PAGE_SIZE
|
||||||
@@ -55,6 +56,8 @@ proc_t *sched_newproc() {
|
|||||||
proc->fdfirst = 3;
|
proc->fdfirst = 3;
|
||||||
SPINLOCK_INIT(proc->fdlock);
|
SPINLOCK_INIT(proc->fdlock);
|
||||||
SEMAPHORE_INIT(&proc->waitsem, 0);
|
SEMAPHORE_INIT(&proc->waitsem, 0);
|
||||||
|
SPINLOCK_INIT(proc->jobctllock);
|
||||||
|
SPINLOCK_INIT(proc->pgrp.lock);
|
||||||
|
|
||||||
proc->fd = alloc(sizeof(fd_t) * 3);
|
proc->fd = alloc(sizeof(fd_t) * 3);
|
||||||
if (proc->fd == NULL) {
|
if (proc->fd == NULL) {
|
||||||
@@ -242,6 +245,8 @@ void sched_procexit() {
|
|||||||
// which hold a reference. it won't now since its a zombie, which is why it will be held
|
// which hold a reference. it won't now since its a zombie, which is why it will be held
|
||||||
PROC_HOLD(proc);
|
PROC_HOLD(proc);
|
||||||
|
|
||||||
|
jobctl_detach(proc);
|
||||||
|
|
||||||
// close fds
|
// close fds
|
||||||
for (int fd = 0; fd < proc->fdcount; ++fd)
|
for (int fd = 0; fd < proc->fdcount; ++fd)
|
||||||
fd_close(fd);
|
fd_close(fd);
|
||||||
@@ -606,11 +611,11 @@ void sched_runinit() {
|
|||||||
|
|
||||||
vnode_t *consolenode;
|
vnode_t *consolenode;
|
||||||
__assert(devfs_getbyname("console", &consolenode) == 0);
|
__assert(devfs_getbyname("console", &consolenode) == 0);
|
||||||
__assert(VOP_OPEN(&consolenode, V_FFLAGS_READ, &proc->cred) == 0)
|
__assert(VOP_OPEN(&consolenode, V_FFLAGS_READ | V_FFLAGS_NOCTTY, &proc->cred) == 0)
|
||||||
VOP_HOLD(consolenode);
|
VOP_HOLD(consolenode);
|
||||||
__assert(VOP_OPEN(&consolenode, V_FFLAGS_WRITE, &proc->cred) == 0)
|
__assert(VOP_OPEN(&consolenode, V_FFLAGS_WRITE | V_FFLAGS_NOCTTY, &proc->cred) == 0)
|
||||||
VOP_HOLD(consolenode);
|
VOP_HOLD(consolenode);
|
||||||
__assert(VOP_OPEN(&consolenode, V_FFLAGS_WRITE, &proc->cred) == 0)
|
__assert(VOP_OPEN(&consolenode, V_FFLAGS_WRITE | V_FFLAGS_NOCTTY, &proc->cred) == 0)
|
||||||
|
|
||||||
file_t *stdin = fd_allocate();
|
file_t *stdin = fd_allocate();
|
||||||
file_t *stdout = fd_allocate();
|
file_t *stdout = fd_allocate();
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <kernel/file.h>
|
#include <kernel/file.h>
|
||||||
#include <kernel/interrupt.h>
|
#include <kernel/interrupt.h>
|
||||||
|
#include <kernel/jobctl.h>
|
||||||
|
|
||||||
#include <logging.h>
|
|
||||||
syscallret_t syscall_fork(context_t *ctx) {
|
syscallret_t syscall_fork(context_t *ctx) {
|
||||||
syscallret_t ret = {
|
syscallret_t ret = {
|
||||||
.ret = -1,
|
.ret = -1,
|
||||||
@@ -53,6 +53,7 @@ syscallret_t syscall_fork(context_t *ctx) {
|
|||||||
|
|
||||||
CTX_RET(&nthread->context) = 0;
|
CTX_RET(&nthread->context) = 0;
|
||||||
CTX_ERRNO(&nthread->context) = 0;
|
CTX_ERRNO(&nthread->context) = 0;
|
||||||
|
jobctl_addproc(proc, nproc);
|
||||||
|
|
||||||
ret.ret = nproc->pid;
|
ret.ret = nproc->pid;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include <kernel/syscalls.h>
|
#include <kernel/syscalls.h>
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
|
#include <kernel/jobctl.h>
|
||||||
|
#include <logging.h>
|
||||||
|
|
||||||
syscallret_t syscall_getpid(context_t *ctx) {
|
syscallret_t syscall_getpid(context_t *ctx) {
|
||||||
syscallret_t ret = {
|
syscallret_t ret = {
|
||||||
@@ -8,3 +10,31 @@ syscallret_t syscall_getpid(context_t *ctx) {
|
|||||||
};
|
};
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syscallret_t syscall_getppid(context_t *ctx) {
|
||||||
|
syscallret_t ret = {
|
||||||
|
.ret = _cpu()->thread->proc->parent ? _cpu()->thread->proc->parent->pid : 1,
|
||||||
|
.errno = 0
|
||||||
|
};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
syscallret_t syscall_getpgid(context_t *ctx, pid_t pid) {
|
||||||
|
syscallret_t ret = {
|
||||||
|
.errno = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__assert(pid == 0);
|
||||||
|
ret.ret = jobctl_getpgid(_cpu()->thread->proc);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
syscallret_t syscall_getsid(context_t *ctx, pid_t pid) {
|
||||||
|
syscallret_t ret = {
|
||||||
|
.errno = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__assert(pid == 0);
|
||||||
|
ret.ret = jobctl_getsid(_cpu()->thread->proc);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#include <kernel/syscalls.h>
|
||||||
|
#include <kernel/jobctl.h>
|
||||||
|
#include <logging.h>
|
||||||
|
|
||||||
|
syscallret_t syscall_setsid(context_t *) {
|
||||||
|
syscallret_t ret;
|
||||||
|
|
||||||
|
ret.errno = jobctl_newsession(_cpu()->thread->proc);
|
||||||
|
ret.ret = ret.errno ? -1 : _cpu()->thread->proc->pid;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
syscallret_t syscall_setpgid(context_t *, pid_t pid, pid_t pgid) {
|
||||||
|
syscallret_t ret;
|
||||||
|
__assert(pid == 0 || pid == _cpu()->thread->proc->pid);
|
||||||
|
__assert(pgid == 0 || pgid == _cpu()->thread->proc->pid);
|
||||||
|
|
||||||
|
ret.errno = jobctl_newgroup(_cpu()->thread->proc);
|
||||||
|
ret.ret = ret.errno ? -1 : _cpu()->thread->proc->pid;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -188,10 +188,10 @@ index 0000000..e5b087a
|
|||||||
+
|
+
|
||||||
diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..00537fa
|
index 0000000..d2ec1c5
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
+++ mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
||||||
@@ -0,0 +1,599 @@
|
@@ -0,0 +1,618 @@
|
||||||
+#include <bits/ensure.h>
|
+#include <bits/ensure.h>
|
||||||
+#include <mlibc/debug.hpp>
|
+#include <mlibc/debug.hpp>
|
||||||
+#include <mlibc/all-sysdeps.hpp>
|
+#include <mlibc/all-sysdeps.hpp>
|
||||||
@@ -276,13 +276,20 @@ index 0000000..00537fa
|
|||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ pid_t sys_getppid() {
|
+ pid_t sys_getppid() {
|
||||||
+ // TODO UNSTUB
|
+ long ret;
|
||||||
+ return 1;
|
+ syscall(SYSCALL_GETPPID, &ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ int sys_getsid(pid_t pid, pid_t *pgid) {
|
||||||
|
+ long ret;
|
||||||
|
+ long error = syscall(SYSCALL_GETSID, &ret, pid);
|
||||||
|
+ return 0;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ int sys_getpgid(pid_t pid, pid_t *pgid) {
|
+ int sys_getpgid(pid_t pid, pid_t *pgid) {
|
||||||
+ // TODO UNSTUB
|
+ long ret;
|
||||||
+ *pgid = 1;
|
+ long error = syscall(SYSCALL_GETPGID, &ret, pid);
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
@@ -327,6 +334,18 @@ index 0000000..00537fa
|
|||||||
+ return 0;
|
+ return 0;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
+ int sys_setpgid(pid_t pid, pid_t pgid) {
|
||||||
|
+ long ret;
|
||||||
|
+ return syscall(SYSCALL_SETPGID, &ret, pid, pgid);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ int sys_setsid(pid_t *out) {
|
||||||
|
+ long ret;
|
||||||
|
+ long error = syscall(SYSCALL_SETSID, &ret);
|
||||||
|
+ *out = ret;
|
||||||
|
+ return error;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ int sys_futex_tid() {
|
+ int sys_futex_tid() {
|
||||||
+ long ret;
|
+ long ret;
|
||||||
+ syscall(SYSCALL_GETTID, &ret);
|
+ syscall(SYSCALL_GETTID, &ret);
|
||||||
@@ -810,10 +829,10 @@ index 0000000..990eca0
|
|||||||
+#endif
|
+#endif
|
||||||
diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..c57a0fa
|
index 0000000..859c459
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
+++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
||||||
@@ -0,0 +1,76 @@
|
@@ -0,0 +1,81 @@
|
||||||
+#ifndef _SYSCALL_H_INCLUDE
|
+#ifndef _SYSCALL_H_INCLUDE
|
||||||
+#define _SYSCALL_H_INCLUDE
|
+#define _SYSCALL_H_INCLUDE
|
||||||
+
|
+
|
||||||
@@ -870,6 +889,11 @@ index 0000000..c57a0fa
|
|||||||
+#define SYSCALL_THREADEXIT 50
|
+#define SYSCALL_THREADEXIT 50
|
||||||
+#define SYSCALL_FUTEX 51
|
+#define SYSCALL_FUTEX 51
|
||||||
+#define SYSCALL_GETTID 52
|
+#define SYSCALL_GETTID 52
|
||||||
|
+#define SYSCALL_GETPPID 53
|
||||||
|
+#define SYSCALL_GETPGID 54
|
||||||
|
+#define SYSCALL_GETSID 55
|
||||||
|
+#define SYSCALL_SETSID 56
|
||||||
|
+#define SYSCALL_SETPGID 57
|
||||||
+
|
+
|
||||||
+#include <stddef.h>
|
+#include <stddef.h>
|
||||||
+#include <stdint.h>
|
+#include <stdint.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user