Initial signal support. Please squash improvements into this commit.

This commit is contained in:
Jonas 'Sortie' Termansen 2011-09-15 22:38:40 +02:00
parent 7a9afd66fe
commit 2b032b0414
25 changed files with 972 additions and 23 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@
/*.so
/*.a
builds
sysroot

View File

@ -1,5 +1,11 @@
ifndef CPU
CPU=x86
MFLAGS:=CPU=$(CPU)
endif
ifndef SYSROOT
SYSROOT:=$(shell pwd)/sysroot
MFLAGS:=SYSROOT=$(SYSROOT)
endif
REMOTE=192.168.2.6
@ -22,9 +28,10 @@ INITRD=sortix/sortix.initrd
all: $(INITRD)
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:
rm -rf $(SYSROOT)
rm -f $(INITRD)
rm -f initrd/*
(for D in $(MODULES); do $(MAKE) clean $(MFLAGS) --directory $$D || exit $?; done)

View File

@ -45,6 +45,7 @@ c/h/sys/stat.h \
c/h/sys/types.h \
c/h/sys/wait.h \
c/h/stdio.h \
c/h/signal.h \
COMMONOBJS=c++.o memory.o string.o error.o format.o
SORTIXOBJS:=$(addprefix sortix/,$(COMMONOBJS))
@ -56,10 +57,12 @@ process.o \
thread.o \
io.o \
init.o \
signal.o \
$(CPU)/signal.o \
start.o \
random.o \
HEADERS=\
MAXSIHEADERS=\
error.h \
io.h \
memory.h \
@ -72,6 +75,8 @@ types.h \
format.h \
keyboard.h \
sortedlist.h \
signal.h \
signalnum.h \
sortix-vga.h \
sortix-keyboard.h \
sortix-sound.h \
@ -100,7 +105,7 @@ ifndef LIBMAXSI_NO_LIBC
BINS:=$(BINS) libc.a
endif
HEADERS:=$(HEADERS) $(CHEADERS)
HEADERS:=$(MAXSIHEADERS) $(CHEADERS)
else
DEFINES:=$(DEFINES) -DLIBMAXSI_NO_LIBC
@ -173,3 +178,18 @@ sortix/%.o: sortix/%.cpp
clean:
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

80
libmaxsi/c/hsrc/signal.h Normal file
View File

@ -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

View File

@ -19,5 +19,6 @@
#define EIO 27
#define ENOEXEC 28
#define EACCESS 29
#define ESRCH 30
#endif

View File

@ -62,6 +62,7 @@ namespace Maxsi
case EIO: return (char*) "Input/output error";
case ENOEXEC: return (char*) "Not executable";
case EACCESS: return (char*) "Permission denied";
case ESRCH: return (char*) "No such process";
default: return (char*) "Unknown error condition";
}
}

42
libmaxsi/hsrc/signal.h Normal file
View File

@ -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

71
libmaxsi/hsrc/signalnum.h Normal file
View File

@ -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

View File

@ -24,6 +24,7 @@
******************************************************************************/
#include "platform.h"
#include "signal.h"
namespace Maxsi
{
@ -31,6 +32,10 @@ namespace Maxsi
extern "C" void initialize_standard_library()
{
// Initialize stuff such as errno.
init_error_functions();
// It's probably best to initialize the Unix signals early on.
Signal::Init();
}
}

127
libmaxsi/signal.cpp Normal file
View File

@ -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);
}
}
}

38
libmaxsi/x64/signal.s Normal file
View File

@ -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

43
libmaxsi/x86/signal.s Normal file
View File

@ -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

View File

@ -11,3 +11,5 @@ all: $(BINARIES)
clean:
rm -f $(BINARIES)
install:

View File

@ -74,10 +74,11 @@ pipe.o \
filesystem.o \
directory.o \
mount.o \
signal.o \
fs/devfs.o \
fs/initfs.o \
fs/ramfs.o \
../libmaxsi/libmaxsi-sortix.a
../libmaxsi/libmaxsi-sortix.a \
JSOBJS:=$(subst .o,-js.o,$(OBJS))
@ -127,20 +128,8 @@ sortix.bin: sortix-$(BUILDID).tmp
clean:
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"

View File

@ -241,6 +241,9 @@ namespace Sortix
// Initialize the process system.
Process::Init();
// Initialize the thread system.
Thread::Init();
// Initialize the IO system.
IO::Init();

View File

@ -153,7 +153,7 @@ namespace Sortix
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();
if ( !clone->addrspace )
{

View File

@ -132,6 +132,8 @@ namespace Sortix
Memory::SwitchAddressSpace(newaddrspace);
currentthread = nextthread;
nextthread->HandleSignal(regs);
LogEndContextSwitch(currentthread, regs);
if ( currentthread->scfunc ) { Syscall::Resume(regs); }

244
sortix/signal.cpp Normal file
View File

@ -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;
}
}

99
sortix/signal.h Normal file
View File

@ -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

View File

@ -54,7 +54,10 @@
#define SYSCALL_GETCWD 26
#define SYSCALL_UNLINK 27
#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

View File

@ -23,12 +23,16 @@
******************************************************************************/
#include "platform.h"
#include <libmaxsi/error.h>
#include <libmaxsi/memory.h>
#include "process.h"
#include "thread.h"
#include "scheduler.h"
#include "memorymanagement.h"
#include "time.h"
#include "syscall.h"
using namespace Maxsi;
namespace Sortix
{
@ -46,6 +50,8 @@ namespace Sortix
Maxsi::Memory::Set(&registers, 0, sizeof(registers));
ready = false;
scfunc = NULL;
currentsignal = NULL;
sighandler = NULL;
ResetCallbacks();
}
@ -65,6 +71,7 @@ namespace Sortix
schedulerlistprev = NULL;
schedulerlistnext = NULL;
scfunc = NULL;
sighandler = forkfrom->sighandler;
ResetCallbacks();
}
@ -78,6 +85,14 @@ namespace Sortix
ASSERT(CurrentProcess() == process);
ASSERT(nextsleepingthread == NULL);
// Delete information about signals being processed.
while ( currentsignal )
{
Signal* todelete = currentsignal;
currentsignal = currentsignal->nextsignal;
delete todelete;
}
Memory::UnmapRangeUser(stackpos, stacksize);
}
@ -85,8 +100,26 @@ namespace Sortix
{
ASSERT(ready);
Signal* clonesignal = NULL;
if ( currentsignal )
{
clonesignal = currentsignal->Fork();
if ( !clonesignal ) { return NULL; }
}
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;
}
@ -154,4 +187,83 @@ namespace Sortix
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);
}
}

View File

@ -25,6 +25,8 @@
#ifndef SORTIX_THREAD_H
#define SORTIX_THREAD_H
#include "signal.h"
namespace Sortix
{
class Process;
@ -34,6 +36,8 @@ namespace Sortix
Thread* CreateThread(addr_t entry, size_t stacksize = 0);
Thread* CurrentThread();
typedef void (*sighandler_t)(int);
class Thread
{
friend Thread* CreateThread(addr_t entry, size_t stacksize);
@ -41,6 +45,9 @@ namespace Sortix
public:
enum State { NONE, RUNNABLE, BLOCKING };
public:
static void Init();
private:
Thread();
Thread(const Thread* forkfrom);
@ -67,6 +74,9 @@ namespace Sortix
public:
addr_t stackpos;
size_t stacksize;
Signal* currentsignal;
SignalQueue signalqueue;
sighandler_t sighandler;
// After being created/forked, a thread is not inserted into the scheduler.
// Whenever the thread has been safely established within a process, then
@ -84,6 +94,10 @@ namespace Sortix
Thread* Fork();
void SaveRegisters(const CPU::InterruptRegisters* src);
void LoadRegisters(CPU::InterruptRegisters* dest);
void HandleSignal(CPU::InterruptRegisters* regs);
private:
void HandleSignalCPU(CPU::InterruptRegisters* regs);
public:
void* scfunc;

View File

@ -106,4 +106,10 @@ namespace Sortix
thread->SaveRegisters(&regs);
}
void Thread::HandleSignalCPU(CPU::InterruptRegisters* regs)
{
regs->edi = currentsignal->signum;
regs->eip = (size_t) sighandler;
}
}

View File

@ -16,6 +16,7 @@ help \
uname \
idle \
editor \
kill \
BINARIES:=$(addprefix $(INITRDDIR)/,$(LOCALBINARIES))

38
utils/kill.cpp Normal file
View File

@ -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;
}