mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Initial signal support. Please squash improvements into this commit.
This commit is contained in:
parent
7a9afd66fe
commit
2b032b0414
25 changed files with 972 additions and 23 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,3 +5,4 @@
|
|||
/*.so
|
||||
/*.a
|
||||
builds
|
||||
sysroot
|
||||
|
|
9
Makefile
9
Makefile
|
@ -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)
|
||||
|
|
|
@ -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
80
libmaxsi/c/hsrc/signal.h
Normal 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
|
|
@ -19,5 +19,6 @@
|
|||
#define EIO 27
|
||||
#define ENOEXEC 28
|
||||
#define EACCESS 29
|
||||
#define ESRCH 30
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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
42
libmaxsi/hsrc/signal.h
Normal 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
71
libmaxsi/hsrc/signalnum.h
Normal 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
|
||||
|
|
@ -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
127
libmaxsi/signal.cpp
Normal 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
38
libmaxsi/x64/signal.s
Normal 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
43
libmaxsi/x86/signal.s
Normal 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
|
||||
|
|
@ -11,3 +11,5 @@ all: $(BINARIES)
|
|||
clean:
|
||||
rm -f $(BINARIES)
|
||||
|
||||
install:
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -241,6 +241,9 @@ namespace Sortix
|
|||
// Initialize the process system.
|
||||
Process::Init();
|
||||
|
||||
// Initialize the thread system.
|
||||
Thread::Init();
|
||||
|
||||
// Initialize the IO system.
|
||||
IO::Init();
|
||||
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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
244
sortix/signal.cpp
Normal 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
99
sortix/signal.h
Normal 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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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(®isters, 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -106,4 +106,10 @@ namespace Sortix
|
|||
|
||||
thread->SaveRegisters(®s);
|
||||
}
|
||||
|
||||
void Thread::HandleSignalCPU(CPU::InterruptRegisters* regs)
|
||||
{
|
||||
regs->edi = currentsignal->signum;
|
||||
regs->eip = (size_t) sighandler;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ help \
|
|||
uname \
|
||||
idle \
|
||||
editor \
|
||||
kill \
|
||||
|
||||
BINARIES:=$(addprefix $(INITRDDIR)/,$(LOCALBINARIES))
|
||||
|
||||
|
|
38
utils/kill.cpp
Normal file
38
utils/kill.cpp
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue