View of xos/kernel/syscall.c


XOS | Parent Directory | View | Download

/* 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 <http://www.gnu.org/licenses/>. */
 
#include "sys_proc.h"
#include "sys_io.h"
#include "current.h"
#include "get_proc.h"
#include "signal.h"
 
#include <stop.h>
#include <system.h>
#include <system_data_structs.h>
#include <it_stack_structs.h>
#include <errno.h>
#include <stddef.h>
 
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();
}