Initial signal support. Please squash improvements into this commit.
This commit is contained in:
parent
7a9afd66fe
commit
2b032b0414
|
@ -5,3 +5,4 @@
|
||||||
/*.so
|
/*.so
|
||||||
/*.a
|
/*.a
|
||||||
builds
|
builds
|
||||||
|
sysroot
|
||||||
|
|
9
Makefile
9
Makefile
|
@ -1,5 +1,11 @@
|
||||||
ifndef CPU
|
ifndef CPU
|
||||||
CPU=x86
|
CPU=x86
|
||||||
|
MFLAGS:=CPU=$(CPU)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef SYSROOT
|
||||||
|
SYSROOT:=$(shell pwd)/sysroot
|
||||||
|
MFLAGS:=SYSROOT=$(SYSROOT)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
REMOTE=192.168.2.6
|
REMOTE=192.168.2.6
|
||||||
|
@ -22,9 +28,10 @@ INITRD=sortix/sortix.initrd
|
||||||
all: $(INITRD)
|
all: $(INITRD)
|
||||||
|
|
||||||
suball:
|
suball:
|
||||||
(for D in $(MODULES); do $(MAKE) all $(MFLAGS) --directory $$D || exit $?; done)
|
(for D in $(MODULES); do ($(MAKE) all $(MFLAGS) --directory $$D && $(MAKE) install $(MFLAGS) --directory $$D) || exit $?; done)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
rm -rf $(SYSROOT)
|
||||||
rm -f $(INITRD)
|
rm -f $(INITRD)
|
||||||
rm -f initrd/*
|
rm -f initrd/*
|
||||||
(for D in $(MODULES); do $(MAKE) clean $(MFLAGS) --directory $$D || exit $?; done)
|
(for D in $(MODULES); do $(MAKE) clean $(MFLAGS) --directory $$D || exit $?; done)
|
||||||
|
|
|
@ -45,6 +45,7 @@ c/h/sys/stat.h \
|
||||||
c/h/sys/types.h \
|
c/h/sys/types.h \
|
||||||
c/h/sys/wait.h \
|
c/h/sys/wait.h \
|
||||||
c/h/stdio.h \
|
c/h/stdio.h \
|
||||||
|
c/h/signal.h \
|
||||||
|
|
||||||
COMMONOBJS=c++.o memory.o string.o error.o format.o
|
COMMONOBJS=c++.o memory.o string.o error.o format.o
|
||||||
SORTIXOBJS:=$(addprefix sortix/,$(COMMONOBJS))
|
SORTIXOBJS:=$(addprefix sortix/,$(COMMONOBJS))
|
||||||
|
@ -56,10 +57,12 @@ process.o \
|
||||||
thread.o \
|
thread.o \
|
||||||
io.o \
|
io.o \
|
||||||
init.o \
|
init.o \
|
||||||
|
signal.o \
|
||||||
|
$(CPU)/signal.o \
|
||||||
start.o \
|
start.o \
|
||||||
random.o \
|
random.o \
|
||||||
|
|
||||||
HEADERS=\
|
MAXSIHEADERS=\
|
||||||
error.h \
|
error.h \
|
||||||
io.h \
|
io.h \
|
||||||
memory.h \
|
memory.h \
|
||||||
|
@ -72,6 +75,8 @@ types.h \
|
||||||
format.h \
|
format.h \
|
||||||
keyboard.h \
|
keyboard.h \
|
||||||
sortedlist.h \
|
sortedlist.h \
|
||||||
|
signal.h \
|
||||||
|
signalnum.h \
|
||||||
sortix-vga.h \
|
sortix-vga.h \
|
||||||
sortix-keyboard.h \
|
sortix-keyboard.h \
|
||||||
sortix-sound.h \
|
sortix-sound.h \
|
||||||
|
@ -100,7 +105,7 @@ ifndef LIBMAXSI_NO_LIBC
|
||||||
BINS:=$(BINS) libc.a
|
BINS:=$(BINS) libc.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
HEADERS:=$(HEADERS) $(CHEADERS)
|
HEADERS:=$(MAXSIHEADERS) $(CHEADERS)
|
||||||
|
|
||||||
else
|
else
|
||||||
DEFINES:=$(DEFINES) -DLIBMAXSI_NO_LIBC
|
DEFINES:=$(DEFINES) -DLIBMAXSI_NO_LIBC
|
||||||
|
@ -173,3 +178,18 @@ sortix/%.o: sortix/%.cpp
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o sortix/*.o c/*.o x86/*.o x64/*.o *.a *.so $(CHEADERS) $(HEADERS)
|
rm -f *.o sortix/*.o c/*.o x86/*.o x64/*.o *.a *.so $(CHEADERS) $(HEADERS)
|
||||||
|
|
||||||
|
# Installation into sysroot
|
||||||
|
install:
|
||||||
|
mkdir -p $(SYSROOT)/usr/lib
|
||||||
|
for F in $(BINS); do cp --preserve=links $$F $(SYSROOT)/usr/lib || exit $?; done
|
||||||
|
mkdir -p $(SYSROOT)/usr/include
|
||||||
|
for F in $(CHEADERS); do F=`echo $$F | sed 's/c\/h\///g'`; mkdir -p $(SYSROOT)/usr/include/`dirname $$F`; cp c/h/$$F $(SYSROOT)/usr/include/$$F || exit $?; done
|
||||||
|
mkdir -p $(SYSROOT)/usr/include/libmaxsi
|
||||||
|
for F in $(MAXSIHEADERS); do cp $$F $(SYSROOT)/usr/include/libmaxsi || exit $?; done
|
||||||
|
cp start.o $(SYSROOT)/usr/lib/crt1.o
|
||||||
|
touch deleteme.cpp
|
||||||
|
g++ $(CPUFLAGS) -c deleteme.cpp -o deleteme.o
|
||||||
|
for F in crt0.o crtn.o crtbegin.o crtend.o crtbeginT.o crti.o; do cp deleteme.o $(SYSROOT)/usr/lib/$$F; done
|
||||||
|
for F in libgcc.so libm.so libstdc++.so; do ld $(CPULDFLAGS) -shared deleteme.o -o $(SYSROOT)/usr/lib/$$F; done
|
||||||
|
rm -f deleteme.o deleteme.cpp
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi 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 Lesser General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
signal.h
|
||||||
|
Signals.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* TODO: This does not fully implement POSIX 2008-1 yet! */
|
||||||
|
|
||||||
|
#ifndef _SIGNAL_H
|
||||||
|
#define _SIGNAL_H 1
|
||||||
|
|
||||||
|
#include <features.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#define SIGHUP 1 /* Hangup */
|
||||||
|
#define SIGINT 2 /* Interrupt */
|
||||||
|
#define SIGQUIT 3 /* Quit */
|
||||||
|
#define SIGILL 4 /* Illegal Instruction */
|
||||||
|
#define SIGTRAP 5 /* Trace/Breakpoint Trap */
|
||||||
|
#define SIGABRT 6 /* Abort */
|
||||||
|
#define SIGEMT 7 /* Emulation Trap */
|
||||||
|
#define SIGFPE 8 /* Arithmetic Exception */
|
||||||
|
#define SIGKILL 9 /* Killed */
|
||||||
|
#define SIGBUS 10 /* Bus Error */
|
||||||
|
#define SIGSEGV 11 /* Segmentation Fault */
|
||||||
|
#define SIGSYS 12 /* Bad System Call */
|
||||||
|
#define SIGPIPE 13 /* Broken Pipe */
|
||||||
|
#define SIGALRM 14 /* Alarm Clock */
|
||||||
|
#define SIGTERM 15 /* Terminated */
|
||||||
|
#define SIGUSR1 16 /* User Signal 1 */
|
||||||
|
#define SIGUSR2 17 /* User Signal 2 */
|
||||||
|
#define SIGCHLD 18 /* Child Status */
|
||||||
|
#define SIGPWR 19 /* Power Fail/Restart */
|
||||||
|
#define SIGWINCH 20 /* Window Size Change */
|
||||||
|
#define SIGURG 21 /* Urgent Socket Condition */
|
||||||
|
#define SIGSTOP 23 /* Stopped (signal) */
|
||||||
|
#define SIGTSTP 24 /* Stopped (user) */
|
||||||
|
#define SIGCONT 25 /* Continued */
|
||||||
|
#define SIGTTIN 26 /* Stopped (tty input) */
|
||||||
|
#define SIGTTOU 27 /* Stopped (tty output) */
|
||||||
|
#define SIGVTALRM 28 /* Virtual Timer Expired */
|
||||||
|
#define SIGXCPU 30 /* CPU time limit exceeded */
|
||||||
|
#define SIGXFSZ 31 /* File size limit exceeded */
|
||||||
|
#define SIGWAITING 32 /* All LWPs blocked */
|
||||||
|
#define SIGLWP 33 /* Virtual Interprocessor Interrupt for Threads Library */
|
||||||
|
#define SIGAIO 34 /* Asynchronous I/O */
|
||||||
|
|
||||||
|
@include(pid_t.h);
|
||||||
|
|
||||||
|
typedef void (*sighandler_t)(int);
|
||||||
|
|
||||||
|
void SIG_DFL(int signum);
|
||||||
|
void SIG_IGN(int signum);
|
||||||
|
void SIG_ERR(int signum);
|
||||||
|
|
||||||
|
sighandler_t signal(int signum, sighandler_t handler);
|
||||||
|
int kill(pid_t pid, int sig);
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -19,5 +19,6 @@
|
||||||
#define EIO 27
|
#define EIO 27
|
||||||
#define ENOEXEC 28
|
#define ENOEXEC 28
|
||||||
#define EACCESS 29
|
#define EACCESS 29
|
||||||
|
#define ESRCH 30
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -62,6 +62,7 @@ namespace Maxsi
|
||||||
case EIO: return (char*) "Input/output error";
|
case EIO: return (char*) "Input/output error";
|
||||||
case ENOEXEC: return (char*) "Not executable";
|
case ENOEXEC: return (char*) "Not executable";
|
||||||
case EACCESS: return (char*) "Permission denied";
|
case EACCESS: return (char*) "Permission denied";
|
||||||
|
case ESRCH: return (char*) "No such process";
|
||||||
default: return (char*) "Unknown error condition";
|
default: return (char*) "Unknown error condition";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi 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 Lesser General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
signal.h
|
||||||
|
Handles the good old unix signals.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LIBMAXSI_SIGNAL_H
|
||||||
|
#define LIBMAXSI_SIGNAL_H
|
||||||
|
|
||||||
|
#include "signalnum.h"
|
||||||
|
|
||||||
|
namespace Maxsi
|
||||||
|
{
|
||||||
|
namespace Signal
|
||||||
|
{
|
||||||
|
typedef void (*Handler)(int);
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
Handler RegisterHandler(int signum, Handler handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi 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 Lesser General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
signalnum.h
|
||||||
|
Declares the signal-related constants.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LIBMAXSI_SIGNALNUM_H
|
||||||
|
#define LIBMAXSI_SIGNALNUM_H
|
||||||
|
|
||||||
|
namespace Maxsi
|
||||||
|
{
|
||||||
|
namespace Signal
|
||||||
|
{
|
||||||
|
const int HUP = 1; /* Hangup */
|
||||||
|
const int INT = 2; /* Interrupt */
|
||||||
|
const int QUIT = 3; /* Quit */
|
||||||
|
const int ILL = 4; /* Illegal Instruction */
|
||||||
|
const int TRAP = 5; /* Trace/Breakpoint Trap */
|
||||||
|
const int ABRT = 6; /* Abort */
|
||||||
|
const int EMT = 7; /* Emulation Trap */
|
||||||
|
const int FPE = 8; /* Arithmetic Exception */
|
||||||
|
const int KILL = 9; /* Killed */
|
||||||
|
const int BUS = 10; /* Bus Error */
|
||||||
|
const int SEGV = 11; /* Segmentation Fault */
|
||||||
|
const int SYS = 12; /* Bad System Call */
|
||||||
|
const int PIPE = 13; /* Broken Pipe */
|
||||||
|
const int ALRM = 14; /* Alarm Clock */
|
||||||
|
const int TERM = 15; /* Terminated */
|
||||||
|
const int USR1 = 16; /* User Signal 1 */
|
||||||
|
const int USR2 = 17; /* User Signal 2 */
|
||||||
|
const int CHLD = 18; /* Child Status */
|
||||||
|
const int PWR = 19; /* Power Fail/Restart */
|
||||||
|
const int WINCH = 20; /* Window Size Change */
|
||||||
|
const int URG = 21; /* Urgent Socket Condition */
|
||||||
|
const int STOP = 23; /* Stopped (signal) */
|
||||||
|
const int TSTP = 24; /* Stopped (user) */
|
||||||
|
const int CONT = 25; /* Continued */
|
||||||
|
const int TTIN = 26; /* Stopped (tty input) */
|
||||||
|
const int TTOU = 27; /* Stopped (tty output) */
|
||||||
|
const int VTALRM = 28; /* Virtual Timer Expired */
|
||||||
|
const int XCPU = 30; /* CPU time limit exceeded */
|
||||||
|
const int XFSZ = 31; /* File size limit exceeded */
|
||||||
|
const int WAITING = 32; /* All LWPs blocked */
|
||||||
|
const int LWP = 33; /* Virtual Interprocessor Interrupt for Threads Library */
|
||||||
|
const int AIO = 34; /* Asynchronous I/O */
|
||||||
|
const int NUMSIGNALS = 35;
|
||||||
|
|
||||||
|
typedef void (*Handler)(int);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
#include "signal.h"
|
||||||
|
|
||||||
namespace Maxsi
|
namespace Maxsi
|
||||||
{
|
{
|
||||||
|
@ -31,6 +32,10 @@ namespace Maxsi
|
||||||
|
|
||||||
extern "C" void initialize_standard_library()
|
extern "C" void initialize_standard_library()
|
||||||
{
|
{
|
||||||
|
// Initialize stuff such as errno.
|
||||||
init_error_functions();
|
init_error_functions();
|
||||||
|
|
||||||
|
// It's probably best to initialize the Unix signals early on.
|
||||||
|
Signal::Init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi 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 Lesser General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
signal.cpp
|
||||||
|
Handles the good old unix signals.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
#include "process.h"
|
||||||
|
#include "signal.h"
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
namespace Maxsi
|
||||||
|
{
|
||||||
|
namespace Signal
|
||||||
|
{
|
||||||
|
void Core(int signum)
|
||||||
|
{
|
||||||
|
Process::Exit(128 + signum);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void SIG_DFL(int signum)
|
||||||
|
{
|
||||||
|
if ( signum == Signal::HUP ) { Process::Exit(128 + signum); } else
|
||||||
|
if ( signum == Signal::INT ) { Process::Exit(128 + signum); } else
|
||||||
|
if ( signum == Signal::QUIT ) { Core(signum); } else
|
||||||
|
if ( signum == Signal::TRAP ) { Core(signum); } else
|
||||||
|
if ( signum == Signal::ABRT ) { Core(signum); } else
|
||||||
|
if ( signum == Signal::EMT ) { Core(signum); } else
|
||||||
|
if ( signum == Signal::FPE ) { Core(signum); } else
|
||||||
|
if ( signum == Signal::KILL ) { Process::Exit(128 + signum); } else
|
||||||
|
if ( signum == Signal::BUS ) { Core(signum); } else
|
||||||
|
if ( signum == Signal::SEGV ) { Core(signum); } else
|
||||||
|
if ( signum == Signal::SYS ) { Core(signum); } else
|
||||||
|
if ( signum == Signal::PIPE ) { Process::Exit(128 + signum); } else
|
||||||
|
if ( signum == Signal::ALRM ) { Process::Exit(128 + signum); } else
|
||||||
|
if ( signum == Signal::TERM ) { Process::Exit(128 + signum); } else
|
||||||
|
if ( signum == Signal::USR1 ) { Process::Exit(128 + signum); } else
|
||||||
|
if ( signum == Signal::USR2 ) { Process::Exit(128 + signum); } else
|
||||||
|
if ( signum == Signal::CHLD ) { /* Ignore this signal. */ } else
|
||||||
|
if ( signum == Signal::PWR ) { /* Ignore this signal. */ } else
|
||||||
|
if ( signum == Signal::WINCH ) { /* Ignore this signal. */ } else
|
||||||
|
if ( signum == Signal::URG ) { /* Ignore this signal. */ } else
|
||||||
|
if ( signum == Signal::CONT ) { /* Ignore this signal. */ } else
|
||||||
|
if ( signum == Signal::VTALRM ) { /* Ignore this signal. */ } else
|
||||||
|
if ( signum == Signal::XCPU ) { Core(signum); } else
|
||||||
|
if ( signum == Signal::XFSZ ) { Core(signum); } else
|
||||||
|
if ( signum == Signal::WAITING ) { /* Ignore this signal. */ } else
|
||||||
|
if ( signum == Signal::LWP ) { /* Ignore this signal. */ } else
|
||||||
|
if ( signum == Signal::AIO ) { /* Ignore this signal. */ } else
|
||||||
|
{ /* Ignore this signal. */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void SIG_IGN(int /*signum*/)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void SIG_ERR(int /*signum*/)
|
||||||
|
{
|
||||||
|
Process::Abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
const int MAX_SIGNALS = 128;
|
||||||
|
sighandler_t handlers[MAX_SIGNALS];
|
||||||
|
|
||||||
|
extern "C" void SignalHandlerAssembly(int signum);
|
||||||
|
extern "C" void SignalHandler(int signum)
|
||||||
|
{
|
||||||
|
if ( 0 <= signum && signum < (int) MAX_SIGNALS )
|
||||||
|
{
|
||||||
|
handlers[signum](signum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFN_SYSCALL1_VOID(SysRegisterSignalHandler, 29, sighandler_t);
|
||||||
|
DEFN_SYSCALL0_VOID(SysSigReturn, 30);
|
||||||
|
DEFN_SYSCALL2(int, SysKill, 31, pid_t, int);
|
||||||
|
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < MAX_SIGNALS; i++ )
|
||||||
|
{
|
||||||
|
handlers[i] = SIG_DFL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell the kernel which function we want called upon signals.
|
||||||
|
SysRegisterSignalHandler(&SignalHandlerAssembly);
|
||||||
|
}
|
||||||
|
|
||||||
|
Handler RegisterHandler(int signum, Handler handler)
|
||||||
|
{
|
||||||
|
if ( signum < 0 || MAX_SIGNALS <= signum ) { return SIG_ERR; }
|
||||||
|
return handlers[signum] = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" sighandler_t signal(int signum, sighandler_t handler)
|
||||||
|
{
|
||||||
|
return RegisterHandler(signum, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int kill(pid_t pid, int signum)
|
||||||
|
{
|
||||||
|
return SysKill(pid, signum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi 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 Lesser General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
signal.s
|
||||||
|
An assembly stub that for handling unix signals.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
.globl SignalHandlerAssembly
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
|
||||||
|
.type SignalHandlerAssembly, @function
|
||||||
|
SignalHandlerAssembly:
|
||||||
|
|
||||||
|
# The kernel put the signal id in edi.
|
||||||
|
call SignalHandler
|
||||||
|
|
||||||
|
# Return control to the kernel, so normal computation can resume normally.
|
||||||
|
movl $3, %eax
|
||||||
|
int $0x80
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi 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 Lesser General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
signal.s
|
||||||
|
An assembly stub that for handling unix signals.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
.globl SignalHandlerAssembly
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
|
||||||
|
.type SignalHandlerAssembly, @function
|
||||||
|
SignalHandlerAssembly:
|
||||||
|
|
||||||
|
# The kernel put the signal id in edi.
|
||||||
|
pushl %edi
|
||||||
|
call SignalHandler
|
||||||
|
|
||||||
|
# Restore the stack as it was.
|
||||||
|
addl $4, %esp
|
||||||
|
|
||||||
|
# Now that the stack is intact, return control to the kernel, so normal
|
||||||
|
# computation can resume normally.
|
||||||
|
movl $30, %eax # SysSigReturn
|
||||||
|
int $0x80
|
||||||
|
|
|
@ -11,3 +11,5 @@ all: $(BINARIES)
|
||||||
clean:
|
clean:
|
||||||
rm -f $(BINARIES)
|
rm -f $(BINARIES)
|
||||||
|
|
||||||
|
install:
|
||||||
|
|
||||||
|
|
|
@ -74,10 +74,11 @@ pipe.o \
|
||||||
filesystem.o \
|
filesystem.o \
|
||||||
directory.o \
|
directory.o \
|
||||||
mount.o \
|
mount.o \
|
||||||
|
signal.o \
|
||||||
fs/devfs.o \
|
fs/devfs.o \
|
||||||
fs/initfs.o \
|
fs/initfs.o \
|
||||||
fs/ramfs.o \
|
fs/ramfs.o \
|
||||||
../libmaxsi/libmaxsi-sortix.a
|
../libmaxsi/libmaxsi-sortix.a \
|
||||||
|
|
||||||
JSOBJS:=$(subst .o,-js.o,$(OBJS))
|
JSOBJS:=$(subst .o,-js.o,$(OBJS))
|
||||||
|
|
||||||
|
@ -127,20 +128,8 @@ sortix.bin: sortix-$(BUILDID).tmp
|
||||||
clean:
|
clean:
|
||||||
for D in $(DIRS); do rm -fv $$D/*.o $$D/*.bin $$D/*.out $$D/*.tmp; done
|
for D in $(DIRS); do rm -fv $$D/*.o $$D/*.bin $$D/*.out $$D/*.tmp; done
|
||||||
|
|
||||||
# Local machine
|
# Installation into sysroot
|
||||||
|
install:
|
||||||
|
mkdir -p $(SYSROOT)/usr/include/sortix
|
||||||
|
cp $(CPU)/bits.h $(SYSROOT)/usr/include/sortix/bits.h
|
||||||
|
|
||||||
install: sortix.bin
|
|
||||||
cp sortix.bin /boot
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
rm -f /boot/sortix.bin
|
|
||||||
|
|
||||||
# Remote machine
|
|
||||||
|
|
||||||
install-remote: sortix.bin
|
|
||||||
scp -r ./ 192.168.2.6:/home/sortie/Desktop/sortix
|
|
||||||
scp sortix.bin root@192.168.2.6:/boot
|
|
||||||
ssh root@192.168.2.6 "init 6"
|
|
||||||
|
|
||||||
uninstall-remote:
|
|
||||||
ssh root@192.168.2.6 "rm /boot/sortix.bin"
|
|
||||||
|
|
|
@ -241,6 +241,9 @@ namespace Sortix
|
||||||
// Initialize the process system.
|
// Initialize the process system.
|
||||||
Process::Init();
|
Process::Init();
|
||||||
|
|
||||||
|
// Initialize the thread system.
|
||||||
|
Thread::Init();
|
||||||
|
|
||||||
// Initialize the IO system.
|
// Initialize the IO system.
|
||||||
IO::Init();
|
IO::Init();
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,7 @@ namespace Sortix
|
||||||
if ( clonesegments == NULL ) { delete clone; return NULL; }
|
if ( clonesegments == NULL ) { delete clone; return NULL; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fork address-space here and copy memory somehow.
|
// Fork address-space here and copy memory.
|
||||||
clone->addrspace = Memory::Fork();
|
clone->addrspace = Memory::Fork();
|
||||||
if ( !clone->addrspace )
|
if ( !clone->addrspace )
|
||||||
{
|
{
|
||||||
|
|
|
@ -132,6 +132,8 @@ namespace Sortix
|
||||||
Memory::SwitchAddressSpace(newaddrspace);
|
Memory::SwitchAddressSpace(newaddrspace);
|
||||||
currentthread = nextthread;
|
currentthread = nextthread;
|
||||||
|
|
||||||
|
nextthread->HandleSignal(regs);
|
||||||
|
|
||||||
LogEndContextSwitch(currentthread, regs);
|
LogEndContextSwitch(currentthread, regs);
|
||||||
|
|
||||||
if ( currentthread->scfunc ) { Syscall::Resume(regs); }
|
if ( currentthread->scfunc ) { Syscall::Resume(regs); }
|
||||||
|
|
|
@ -0,0 +1,244 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||||
|
|
||||||
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
Sortix 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.
|
||||||
|
|
||||||
|
Sortix 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 Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
signal.cpp
|
||||||
|
Classes and functions making it easier to handle Unix signals.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include <libmaxsi/memory.h>
|
||||||
|
#include "panic.h"
|
||||||
|
#include "signal.h"
|
||||||
|
|
||||||
|
using namespace Maxsi;
|
||||||
|
|
||||||
|
namespace Sortix
|
||||||
|
{
|
||||||
|
const int PRIORITY_NORMAL = 0;
|
||||||
|
const int PRIORITY_HIGH = 1;
|
||||||
|
const int PRIORITY_STOP = 2;
|
||||||
|
const int PRIORITY_CORE = 3;
|
||||||
|
const int PRIORITY_KILL = 4;
|
||||||
|
|
||||||
|
const int PRIORITIES[Maxsi::Signal::NUMSIGNALS] =
|
||||||
|
{
|
||||||
|
PRIORITY_NORMAL, // unused
|
||||||
|
PRIORITY_NORMAL, // SIGHUP
|
||||||
|
PRIORITY_NORMAL, // SIGINT
|
||||||
|
PRIORITY_NORMAL, // SIGQUIT
|
||||||
|
PRIORITY_CORE, // SIGILL
|
||||||
|
PRIORITY_CORE, // SIGTRAP
|
||||||
|
PRIORITY_CORE, // SIGABRT
|
||||||
|
PRIORITY_CORE, // SIGEMT
|
||||||
|
PRIORITY_CORE, // SIGFPE
|
||||||
|
PRIORITY_KILL, // SIGKILL
|
||||||
|
PRIORITY_CORE, // SIGBUS
|
||||||
|
PRIORITY_CORE, // SIGSEGV
|
||||||
|
PRIORITY_CORE, // SIGSYS
|
||||||
|
PRIORITY_NORMAL, // SIGPIPE
|
||||||
|
PRIORITY_NORMAL, // SIGALRM
|
||||||
|
PRIORITY_NORMAL, // SIGTERM
|
||||||
|
PRIORITY_NORMAL, // SIGUSR1
|
||||||
|
PRIORITY_NORMAL, // SIGUSR2
|
||||||
|
PRIORITY_NORMAL, // SIGCHLD
|
||||||
|
PRIORITY_HIGH, // SIGPWR
|
||||||
|
PRIORITY_NORMAL, // SIGWINCH
|
||||||
|
PRIORITY_NORMAL, // SIGURG
|
||||||
|
PRIORITY_NORMAL, // obsolete
|
||||||
|
PRIORITY_STOP, // SIGSTOP
|
||||||
|
PRIORITY_STOP, // SIGTSTP
|
||||||
|
PRIORITY_STOP, // SIGCONT
|
||||||
|
PRIORITY_STOP, // SIGTTIN
|
||||||
|
PRIORITY_STOP, // SIGTTOU
|
||||||
|
PRIORITY_NORMAL, // SIGVTALRM
|
||||||
|
PRIORITY_NORMAL, // obsolete
|
||||||
|
PRIORITY_CORE, // SIGXCPU
|
||||||
|
PRIORITY_CORE, // SIGXFSZ
|
||||||
|
PRIORITY_NORMAL, // SIGCORE
|
||||||
|
PRIORITY_NORMAL, // SIGLWP
|
||||||
|
PRIORITY_NORMAL, // SIGAIO
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns true of the exact ordering of this signal version others aren't
|
||||||
|
// important - if it returns false, then this signal will be put in the
|
||||||
|
// queue according to priority, instead of being merged into another signal
|
||||||
|
// with the same signum.
|
||||||
|
bool Unifiable(int /*signum*/)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns whether a specific signal is more important to deliver than
|
||||||
|
// another. This is used to schedule signals.
|
||||||
|
int CompareSignalPriority(int siga, int sigb)
|
||||||
|
{
|
||||||
|
int prioa = PRIORITY_NORMAL;
|
||||||
|
int priob = PRIORITY_NORMAL;
|
||||||
|
|
||||||
|
if ( siga < Maxsi::Signal::NUMSIGNALS ) { prioa = PRIORITIES[siga]; }
|
||||||
|
if ( sigb < Maxsi::Signal::NUMSIGNALS ) { priob = PRIORITIES[sigb]; }
|
||||||
|
|
||||||
|
if ( prioa < priob ) { return -1; } else
|
||||||
|
if ( prioa > priob ) { return 1; }
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SignalQueue::SignalQueue()
|
||||||
|
{
|
||||||
|
queue = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SignalQueue::~SignalQueue()
|
||||||
|
{
|
||||||
|
while ( queue )
|
||||||
|
{
|
||||||
|
Signal* todelete = queue;
|
||||||
|
queue = queue->nextsignal;
|
||||||
|
delete todelete;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queues the signal and schedules it for processing.
|
||||||
|
bool SignalQueue::Push(int signum)
|
||||||
|
{
|
||||||
|
ASSERT(0 <= signum && signum < 128);
|
||||||
|
|
||||||
|
if ( Unifiable(signum) )
|
||||||
|
{
|
||||||
|
for ( Signal* signal = queue; signal != NULL; signal = signal->nextsignal )
|
||||||
|
{
|
||||||
|
if ( signal->signum != signum ) { continue; }
|
||||||
|
|
||||||
|
signal->numpending++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Signal* signal = new Signal;
|
||||||
|
if ( !signal ) { return false; }
|
||||||
|
|
||||||
|
signal->signum = signum;
|
||||||
|
signal->numpending = 1;
|
||||||
|
signal->nextsignal = NULL;
|
||||||
|
signal->returncode = 128 + signum;
|
||||||
|
|
||||||
|
Insert(signal);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the signal in O(N), which is pretty fast for small Ns.
|
||||||
|
void SignalQueue::Insert(Signal* signal)
|
||||||
|
{
|
||||||
|
if ( !queue )
|
||||||
|
{
|
||||||
|
queue = signal;
|
||||||
|
last = signal;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the signal is to be inserted last, then just do it quickly.
|
||||||
|
if ( last != NULL && 0 <= CompareSignalPriority(last->signum, signal->signum) )
|
||||||
|
{
|
||||||
|
last->nextsignal = signal;
|
||||||
|
signal->nextsignal = NULL;
|
||||||
|
last = signal;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the signal should be inserted first.
|
||||||
|
if ( queue != NULL && CompareSignalPriority(queue->signum, signal->signum) < 0 )
|
||||||
|
{
|
||||||
|
signal->nextsignal = queue;
|
||||||
|
queue = signal;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find where the signal should be inserted.
|
||||||
|
for ( Signal* tmp = queue; tmp != NULL; tmp = tmp->nextsignal )
|
||||||
|
{
|
||||||
|
Signal* next = tmp->nextsignal;
|
||||||
|
|
||||||
|
if ( next != NULL && CompareSignalPriority(next->signum, signal->signum) < 0 )
|
||||||
|
{
|
||||||
|
tmp->nextsignal = signal;
|
||||||
|
signal->nextsignal = next;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( next == NULL )
|
||||||
|
{
|
||||||
|
tmp->nextsignal = signal;
|
||||||
|
signal->nextsignal = NULL;
|
||||||
|
last = signal;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given the stack of currently processing signals, return a new signal if
|
||||||
|
// it is more important to handle at this point.
|
||||||
|
Signal* SignalQueue::Pop(Signal* current)
|
||||||
|
{
|
||||||
|
if ( queue == NULL ) { return NULL; }
|
||||||
|
|
||||||
|
bool returnqueue = false;
|
||||||
|
|
||||||
|
// If we are currently handling no signal, then just return the first.
|
||||||
|
if ( current == NULL ) { returnqueue = true; }
|
||||||
|
|
||||||
|
// If we are handling a signal, only override it with another if it is
|
||||||
|
// more important.
|
||||||
|
else if ( CompareSignalPriority(current->signum, queue->signum) < 0 )
|
||||||
|
{
|
||||||
|
returnqueue = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( returnqueue )
|
||||||
|
{
|
||||||
|
Signal* result = queue;
|
||||||
|
queue = queue->nextsignal;
|
||||||
|
result->nextsignal = NULL;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Signal* Signal::Fork()
|
||||||
|
{
|
||||||
|
Signal* clone = new Signal();
|
||||||
|
if ( !clone ) { return NULL; }
|
||||||
|
|
||||||
|
Memory::Copy(clone, this, sizeof(Signal));
|
||||||
|
|
||||||
|
Signal* nextsignalclone = NULL;
|
||||||
|
if ( nextsignal )
|
||||||
|
{
|
||||||
|
nextsignalclone = nextsignal->Fork();
|
||||||
|
if ( !nextsignalclone ) { delete clone; return NULL; }
|
||||||
|
}
|
||||||
|
|
||||||
|
clone->nextsignal = nextsignalclone;
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||||
|
|
||||||
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
Sortix 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.
|
||||||
|
|
||||||
|
Sortix 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 Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
signal.h
|
||||||
|
Classes and functions making it easier to handle Unix signals.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef SORTIX_SIGNAL_H
|
||||||
|
#define SORTIX_SIGNAL_H
|
||||||
|
|
||||||
|
#include <libmaxsi/signalnum.h>
|
||||||
|
|
||||||
|
namespace Sortix
|
||||||
|
{
|
||||||
|
#define SIGHUP 1 /* Hangup */
|
||||||
|
#define SIGINT 2 /* Interrupt */
|
||||||
|
#define SIGQUIT 3 /* Quit */
|
||||||
|
#define SIGILL 4 /* Illegal Instruction */
|
||||||
|
#define SIGTRAP 5 /* Trace/Breakpoint Trap */
|
||||||
|
#define SIGABRT 6 /* Abort */
|
||||||
|
#define SIGEMT 7 /* Emulation Trap */
|
||||||
|
#define SIGFPE 8 /* Arithmetic Exception */
|
||||||
|
#define SIGKILL 9 /* Killed */
|
||||||
|
#define SIGBUS 10 /* Bus Error */
|
||||||
|
#define SIGSEGV 11 /* Segmentation Fault */
|
||||||
|
#define SIGSYS 12 /* Bad System Call */
|
||||||
|
#define SIGPIPE 13 /* Broken Pipe */
|
||||||
|
#define SIGALRM 14 /* Alarm Clock */
|
||||||
|
#define SIGTERM 15 /* Terminated */
|
||||||
|
#define SIGUSR1 16 /* User Signal 1 */
|
||||||
|
#define SIGUSR2 17 /* User Signal 2 */
|
||||||
|
#define SIGCHLD 18 /* Child Status */
|
||||||
|
#define SIGPWR 19 /* Power Fail/Restart */
|
||||||
|
#define SIGWINCH 20 /* Window Size Change */
|
||||||
|
#define SIGURG 21 /* Urgent Socket Condition */
|
||||||
|
#define SIGSTOP 23 /* Stopped (signal) */
|
||||||
|
#define SIGTSTP 24 /* Stopped (user) */
|
||||||
|
#define SIGCONT 25 /* Continued */
|
||||||
|
#define SIGTTIN 26 /* Stopped (tty input) */
|
||||||
|
#define SIGTTOU 27 /* Stopped (tty output) */
|
||||||
|
#define SIGVTALRM 28 /* Virtual Timer Expired */
|
||||||
|
#define SIGXCPU 30 /* CPU time limit exceeded */
|
||||||
|
#define SIGXFSZ 31 /* File size limit exceeded */
|
||||||
|
#define SIGWAITING 32 /* All LWPs blocked */
|
||||||
|
#define SIGLWP 33 /* Virtual Interprocessor Interrupt for Threads Library */
|
||||||
|
#define SIGAIO 34 /* Asynchronous I/O */
|
||||||
|
|
||||||
|
struct Signal
|
||||||
|
{
|
||||||
|
int signum;
|
||||||
|
int returncode;
|
||||||
|
unsigned numpending;
|
||||||
|
CPU::InterruptRegisters regs;
|
||||||
|
Signal* nextsignal;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Signal* Fork();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class SignalQueue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SignalQueue();
|
||||||
|
~SignalQueue();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Signal* queue;
|
||||||
|
Signal* last;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool Push(int signum);
|
||||||
|
Signal* Pop(Signal* current);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Insert(Signal* signal);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -54,7 +54,10 @@
|
||||||
#define SYSCALL_GETCWD 26
|
#define SYSCALL_GETCWD 26
|
||||||
#define SYSCALL_UNLINK 27
|
#define SYSCALL_UNLINK 27
|
||||||
#define SYSCALL_REGISTER_ERRNO 28
|
#define SYSCALL_REGISTER_ERRNO 28
|
||||||
#define SYSCALL_MAX_NUM 29 /* index of highest constant + 1 */
|
#define SYSCALL_REGISTER_SIGNAL_HANDLER 29
|
||||||
|
#define SYSCALL_SIGRETURN 30
|
||||||
|
#define SYSCALL_KILL 31
|
||||||
|
#define SYSCALL_MAX_NUM 32 /* index of highest constant + 1 */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,16 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
#include <libmaxsi/error.h>
|
||||||
#include <libmaxsi/memory.h>
|
#include <libmaxsi/memory.h>
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
#include "memorymanagement.h"
|
#include "memorymanagement.h"
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
|
using namespace Maxsi;
|
||||||
|
|
||||||
namespace Sortix
|
namespace Sortix
|
||||||
{
|
{
|
||||||
|
@ -46,6 +50,8 @@ namespace Sortix
|
||||||
Maxsi::Memory::Set(®isters, 0, sizeof(registers));
|
Maxsi::Memory::Set(®isters, 0, sizeof(registers));
|
||||||
ready = false;
|
ready = false;
|
||||||
scfunc = NULL;
|
scfunc = NULL;
|
||||||
|
currentsignal = NULL;
|
||||||
|
sighandler = NULL;
|
||||||
ResetCallbacks();
|
ResetCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +71,7 @@ namespace Sortix
|
||||||
schedulerlistprev = NULL;
|
schedulerlistprev = NULL;
|
||||||
schedulerlistnext = NULL;
|
schedulerlistnext = NULL;
|
||||||
scfunc = NULL;
|
scfunc = NULL;
|
||||||
|
sighandler = forkfrom->sighandler;
|
||||||
ResetCallbacks();
|
ResetCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +85,14 @@ namespace Sortix
|
||||||
ASSERT(CurrentProcess() == process);
|
ASSERT(CurrentProcess() == process);
|
||||||
ASSERT(nextsleepingthread == NULL);
|
ASSERT(nextsleepingthread == NULL);
|
||||||
|
|
||||||
|
// Delete information about signals being processed.
|
||||||
|
while ( currentsignal )
|
||||||
|
{
|
||||||
|
Signal* todelete = currentsignal;
|
||||||
|
currentsignal = currentsignal->nextsignal;
|
||||||
|
delete todelete;
|
||||||
|
}
|
||||||
|
|
||||||
Memory::UnmapRangeUser(stackpos, stacksize);
|
Memory::UnmapRangeUser(stackpos, stacksize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,8 +100,26 @@ namespace Sortix
|
||||||
{
|
{
|
||||||
ASSERT(ready);
|
ASSERT(ready);
|
||||||
|
|
||||||
|
Signal* clonesignal = NULL;
|
||||||
|
if ( currentsignal )
|
||||||
|
{
|
||||||
|
clonesignal = currentsignal->Fork();
|
||||||
|
if ( !clonesignal ) { return NULL; }
|
||||||
|
}
|
||||||
|
|
||||||
Thread* clone = new Thread(this);
|
Thread* clone = new Thread(this);
|
||||||
if ( !clone ) { return NULL; }
|
if ( !clone )
|
||||||
|
{
|
||||||
|
while ( clonesignal )
|
||||||
|
{
|
||||||
|
Signal* todelete = clonesignal;
|
||||||
|
clonesignal = clonesignal->nextsignal;
|
||||||
|
delete todelete;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
clone->currentsignal = clonesignal;
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
@ -154,4 +187,83 @@ namespace Sortix
|
||||||
Scheduler::SetThreadState(this, State::RUNNABLE);
|
Scheduler::SetThreadState(this, State::RUNNABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Thread::HandleSignal(CPU::InterruptRegisters* regs)
|
||||||
|
{
|
||||||
|
Signal* override = signalqueue.Pop(currentsignal);
|
||||||
|
if ( !override ) { return; }
|
||||||
|
if ( !sighandler ) { delete override; return; }
|
||||||
|
|
||||||
|
if ( override->signum == SIGKILL )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override->nextsignal = currentsignal;
|
||||||
|
Maxsi::Memory::Copy(&override->regs, regs, sizeof(override->regs));
|
||||||
|
currentsignal = override;
|
||||||
|
|
||||||
|
HandleSignalCPU(regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysSigReturn()
|
||||||
|
{
|
||||||
|
Thread* thread = CurrentThread();
|
||||||
|
if ( !thread->currentsignal ) { return; }
|
||||||
|
|
||||||
|
CPU::InterruptRegisters* dest = Syscall::InterruptRegs();
|
||||||
|
CPU::InterruptRegisters* src = &thread->currentsignal->regs;
|
||||||
|
|
||||||
|
Maxsi::Memory::Copy(dest, src, sizeof(CPU::InterruptRegisters));
|
||||||
|
thread->currentsignal = thread->currentsignal->nextsignal;
|
||||||
|
Syscall::AsIs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysRegisterSignalHandler(sighandler_t sighandler)
|
||||||
|
{
|
||||||
|
CurrentThread()->sighandler = sighandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SysKill(pid_t pid, int signum)
|
||||||
|
{
|
||||||
|
if ( signum < 0 || 128 <= signum ) { Error::Set(EINVAL); return -1; }
|
||||||
|
|
||||||
|
// Protect the system idle process.
|
||||||
|
if ( pid == 0 ) { Error::Set(EPERM); return -1; }
|
||||||
|
|
||||||
|
Process* process = Process::Get(pid);
|
||||||
|
if ( !process ) { Error::Set(ESRCH); return -1; }
|
||||||
|
|
||||||
|
// TODO: Protect init?
|
||||||
|
// TODO: Check for permission.
|
||||||
|
// TODO: Check for zombies.
|
||||||
|
|
||||||
|
Thread* currentthread = CurrentThread();
|
||||||
|
Thread* thread = NULL;
|
||||||
|
if ( currentthread->process->pid == pid ) { thread = currentthread; }
|
||||||
|
if ( !thread ) { thread = process->firstthread; }
|
||||||
|
if ( !thread ) { Error::Set(ESRCH); return -1; /* TODO: Zombie? */ }
|
||||||
|
|
||||||
|
// TODO: If thread is not runnable, wake it and runs its handler?
|
||||||
|
if ( !thread->signalqueue.Push(signum) )
|
||||||
|
{
|
||||||
|
// TODO: Possibly kill the process?
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( thread == currentthread )
|
||||||
|
{
|
||||||
|
Syscall::SyscallRegs()->result = 0;
|
||||||
|
thread->HandleSignal(Syscall::InterruptRegs());
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thread::Init()
|
||||||
|
{
|
||||||
|
Syscall::Register(SYSCALL_KILL, (void*) SysKill);
|
||||||
|
Syscall::Register(SYSCALL_REGISTER_SIGNAL_HANDLER, (void*) SysRegisterSignalHandler);
|
||||||
|
Syscall::Register(SYSCALL_SIGRETURN, (void*) SysSigReturn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#ifndef SORTIX_THREAD_H
|
#ifndef SORTIX_THREAD_H
|
||||||
#define SORTIX_THREAD_H
|
#define SORTIX_THREAD_H
|
||||||
|
|
||||||
|
#include "signal.h"
|
||||||
|
|
||||||
namespace Sortix
|
namespace Sortix
|
||||||
{
|
{
|
||||||
class Process;
|
class Process;
|
||||||
|
@ -34,6 +36,8 @@ namespace Sortix
|
||||||
Thread* CreateThread(addr_t entry, size_t stacksize = 0);
|
Thread* CreateThread(addr_t entry, size_t stacksize = 0);
|
||||||
Thread* CurrentThread();
|
Thread* CurrentThread();
|
||||||
|
|
||||||
|
typedef void (*sighandler_t)(int);
|
||||||
|
|
||||||
class Thread
|
class Thread
|
||||||
{
|
{
|
||||||
friend Thread* CreateThread(addr_t entry, size_t stacksize);
|
friend Thread* CreateThread(addr_t entry, size_t stacksize);
|
||||||
|
@ -41,6 +45,9 @@ namespace Sortix
|
||||||
public:
|
public:
|
||||||
enum State { NONE, RUNNABLE, BLOCKING };
|
enum State { NONE, RUNNABLE, BLOCKING };
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void Init();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Thread();
|
Thread();
|
||||||
Thread(const Thread* forkfrom);
|
Thread(const Thread* forkfrom);
|
||||||
|
@ -67,6 +74,9 @@ namespace Sortix
|
||||||
public:
|
public:
|
||||||
addr_t stackpos;
|
addr_t stackpos;
|
||||||
size_t stacksize;
|
size_t stacksize;
|
||||||
|
Signal* currentsignal;
|
||||||
|
SignalQueue signalqueue;
|
||||||
|
sighandler_t sighandler;
|
||||||
|
|
||||||
// After being created/forked, a thread is not inserted into the scheduler.
|
// After being created/forked, a thread is not inserted into the scheduler.
|
||||||
// Whenever the thread has been safely established within a process, then
|
// Whenever the thread has been safely established within a process, then
|
||||||
|
@ -84,6 +94,10 @@ namespace Sortix
|
||||||
Thread* Fork();
|
Thread* Fork();
|
||||||
void SaveRegisters(const CPU::InterruptRegisters* src);
|
void SaveRegisters(const CPU::InterruptRegisters* src);
|
||||||
void LoadRegisters(CPU::InterruptRegisters* dest);
|
void LoadRegisters(CPU::InterruptRegisters* dest);
|
||||||
|
void HandleSignal(CPU::InterruptRegisters* regs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void HandleSignalCPU(CPU::InterruptRegisters* regs);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void* scfunc;
|
void* scfunc;
|
||||||
|
|
|
@ -106,4 +106,10 @@ namespace Sortix
|
||||||
|
|
||||||
thread->SaveRegisters(®s);
|
thread->SaveRegisters(®s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Thread::HandleSignalCPU(CPU::InterruptRegisters* regs)
|
||||||
|
{
|
||||||
|
regs->edi = currentsignal->signum;
|
||||||
|
regs->eip = (size_t) sighandler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ help \
|
||||||
uname \
|
uname \
|
||||||
idle \
|
idle \
|
||||||
editor \
|
editor \
|
||||||
|
kill \
|
||||||
|
|
||||||
BINARIES:=$(addprefix $(INITRDDIR)/,$(LOCALBINARIES))
|
BINARIES:=$(addprefix $(INITRDDIR)/,$(LOCALBINARIES))
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int usage()
|
||||||
|
{
|
||||||
|
printf("usage: kill [-n] pid ...\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if ( argc < 2 ) { return usage(); }
|
||||||
|
|
||||||
|
int first = 1;
|
||||||
|
int signum = SIGTERM;
|
||||||
|
if ( argv[1][0] == '-' )
|
||||||
|
{
|
||||||
|
signum = atoi(argv[first++]);
|
||||||
|
if ( argc < 3 ) { return usage(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
for ( int i = first; i < argc; i++ )
|
||||||
|
{
|
||||||
|
pid_t pid = atoi(argv[i]);
|
||||||
|
if ( kill(pid, signum) )
|
||||||
|
{
|
||||||
|
printf("kill: (%u): %s\n", pid, strerror(errno));
|
||||||
|
result |= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
Loading…
Reference in New Issue