/* Copyright (C) 2008 Emmanuel Varoquaux
This file is part of XOS.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include "sys_proc.h"
#include "sys_io.h"
#include "current.h"
#include "get_proc.h"
#include "signal.h"
#include
#include
#include
#include
#include
#include
static inline int get_rpl(const struct interrupted_instruction_struct *interrupted_instruction)
{
struct sel_data_struct sel_data;
get_sel(&interrupted_instruction->cs, &sel_data);
return sel_data.rpl;
}
int is_orphaned_pg(int pgid)
{
struct proc_group_struct *proc_group;
if (!(proc_group = get_proc_group(pgid)))
return 0;
return is_orphaned_proc_group(proc_group);
}
void signal_pg(int pgid, int sig)
{
struct proc_group_struct *proc_group;
if (!(proc_group = get_proc_group(pgid)))
return;
signal_group(proc_group, sig);
}
void preempt(const struct interrupted_instruction_struct *interrupted_instruction)
{
if (is_idle() || get_rpl(interrupted_instruction)) /* l'interruption n'a pas interrompu un appel systeme */
yield();
}
int do_invalid_syscall()
{
return -ENOSYS;
}
void *const syscall_table[] = {
NULL,
do_exit,
do_fork,
do_exec,
do_getpid,
do_getpgid,
do_setpgid,
do_chdir,
do_sbrk,
do_sleep,
do_wait,
do_kill,
do_uname,
do_open,
do_close,
do_dup,
do_dup2,
do_pipe,
do_fcntl,
do_read,
do_write,
do_seek,
do_stat,
do_ioctl,
do_create,
do_remove,
do_mkdir,
do_rmdir,
do_rename,
do_mount,
do_umount,
do_reboot,
do_gettime,
do_mmap,
do_munmap,
do_mprotect
};
const unsigned int syscall_table_size = sizeof syscall_table / sizeof *syscall_table;
static void __attribute__ ((noreturn)) sh_terminate(int sig)
{
abort(sig);
}
static void __attribute__ ((noreturn)) sh_abort(int sig)
{
abort(sig);
}
static void sh_ignore(int sig) {}
static void sh_stop(int sig)
{
stop(sig);
}
static void sh_continue(int sig) {}
typedef void (*sighandler_t)(int);
static const sighandler_t signal_handler[] = {
NULL,
sh_terminate, /* SIGHUP */
sh_terminate, /* SIGINT */
sh_abort, /* SIGQUIT */
sh_abort, /* SIGILL */
sh_abort, /* SIGTRAP */
sh_abort, /* SIGABRT */
sh_abort, /* SIGBUS */
sh_abort, /* SIGFPE */
sh_terminate, /* SIGKILL */
sh_terminate, /* SIGUSR1 */
sh_abort, /* SIGSEGV */
sh_terminate, /* SIGUSR2 */
sh_terminate, /* SIGPIPE */
sh_terminate, /* SIGALRM */
sh_terminate, /* SIGTERM */
sh_terminate, /* SIGSTKFLT */
sh_ignore, /* SIGCHLD */
sh_continue, /* SIGCONT */
sh_stop, /* SIGSTOP */
sh_stop, /* SIGTSTP */
sh_stop, /* SIGTTIN */
sh_stop, /* SIGTTOU */
sh_ignore, /* SIGURG */
sh_abort, /* SIGXCPU */
sh_abort, /* SIGXFSZ */
sh_terminate, /* SIGVTALRM */
sh_terminate, /* SIGPROF */
sh_ignore, /* SIGWINCH */
sh_terminate, /* SIGPOLL */
sh_terminate, /* SIGPWR */
sh_abort /* SIGSYS */
};
static void handle_signals()
{
int sig;
while ((sig = deliver_signal()))
signal_handler[sig](sig);
}
void do_bottom_half_it(const struct interrupted_instruction_struct *interrupted_instruction)
{
int rpl;
rpl = get_rpl(interrupted_instruction);
if (rpl) /* pas de signaux pour idle */
handle_signals();
if (is_idle() || rpl) /* l'interruption n'a pas interrompu un appel systeme */
reap_orphan_zombies();
}
void do_bottom_half_syscall()
{
handle_signals();
reap_orphan_zombies();
}