diff --git a/kernel/include/sortix/exit.h b/kernel/include/sortix/exit.h new file mode 100644 index 00000000..85ca5535 --- /dev/null +++ b/kernel/include/sortix/exit.h @@ -0,0 +1,55 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013, 2014. + + 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 . + + sortix/exit.h + Flags and constants related to process and thread exiting. + +*******************************************************************************/ + +#ifndef INCLUDE_SORTIX_EXIT_H +#define INCLUDE_SORTIX_EXIT_H + +#include + +#include + +__BEGIN_DECLS + +#ifndef __size_t_defined +#define __size_t_defined +#define __need_size_t +#include +#endif + +struct exit_thread +{ + void* unmap_from; + size_t unmap_size; + void* zero_from; + size_t zero_size; + unsigned long reserved[4]; +}; + +#define EXIT_THREAD_ONLY_IF_OTHERS (1<<0) +#define EXIT_THREAD_UNMAP (1<<1) +#define EXIT_THREAD_ZERO (1<<2) + +__END_DECLS + +#endif diff --git a/kernel/include/sortix/syscallnum.h b/kernel/include/sortix/syscallnum.h index c182a1cc..9fdcd86e 100644 --- a/kernel/include/sortix/syscallnum.h +++ b/kernel/include/sortix/syscallnum.h @@ -153,6 +153,7 @@ #define SYSCALL_RDMSR 129 #define SYSCALL_WRMSR 130 #define SYSCALL_SCHED_YIELD 131 -#define SYSCALL_MAX_NUM 132 /* index of highest constant + 1 */ +#define SYSCALL_EXIT_THREAD 132 +#define SYSCALL_MAX_NUM 133 /* index of highest constant + 1 */ #endif diff --git a/kernel/thread.cpp b/kernel/thread.cpp index a1abce0b..174cea62 100644 --- a/kernel/thread.cpp +++ b/kernel/thread.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014. This file is part of Sortix. @@ -26,9 +26,11 @@ #include #include +#include #include #include +#include #include #include #include @@ -279,6 +281,61 @@ bool Thread::DeliverSignal(int signum) return true; } +static int sys_exit_thread(int status, + int flags, + const struct exit_thread* user_extended) +{ + if ( flags & ~(EXIT_THREAD_ONLY_IF_OTHERS | + EXIT_THREAD_UNMAP | + EXIT_THREAD_ZERO) ) + return errno = EINVAL, -1; + + Thread* thread = CurrentThread(); + Process* process = CurrentProcess(); + + struct exit_thread extended; + if ( !user_extended ) + memset(&extended, 0, sizeof(extended)); + else if ( !CopyFromUser(&extended, user_extended, sizeof(extended)) ) + return -1; + + extended.unmap_size = Page::AlignUp(extended.unmap_size); + + kthread_mutex_lock(&thread->process->threadlock); + bool is_others = false; + for ( Thread* iter = thread->process->firstthread; + !is_others && iter; + iter = iter->nextsibling ) + { + if ( iter == thread ) + continue; + if ( iter->terminated ) + continue; + is_others = true; + } + kthread_mutex_unlock(&thread->process->threadlock); + + if ( (flags & EXIT_THREAD_ONLY_IF_OTHERS) && !is_others ) + return errno = ESRCH, -1; + + if ( flags & EXIT_THREAD_UNMAP && + Page::IsAligned((uintptr_t) extended.unmap_from) && + extended.unmap_size ) + { + ScopedLock lock(&process->segment_lock); + Memory::UnmapMemory(process, (uintptr_t) extended.unmap_from, + extended.unmap_size); + } + + if ( flags & EXIT_THREAD_ZERO ) + ZeroUser(extended.zero_from, extended.zero_size); + + if ( !is_others ) + thread->process->Exit(status); + + kthread_exit(); +} + static int sys_kill(pid_t pid, int signum) { // Protect the system idle process. @@ -320,6 +377,7 @@ static int sys_register_signal_handler(sighandler_t sighandler) void Thread::Init() { + Syscall::Register(SYSCALL_EXIT_THREAD, (void*) sys_exit_thread); Syscall::Register(SYSCALL_KILL, (void*) sys_kill); Syscall::Register(SYSCALL_RAISE, (void*) sys_raise); Syscall::Register(SYSCALL_REGISTER_SIGNAL_HANDLER, (void*) sys_register_signal_handler); diff --git a/libc/Makefile b/libc/Makefile index 323cb714..e9b4ac60 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -499,6 +499,7 @@ unistd/execv.o \ unistd/execvpe.o \ unistd/execvp.o \ unistd/_exit.o \ +unistd/exit_thread.o \ unistd/faccessat.o \ unistd/fchdirat.o \ unistd/fchdir.o \ diff --git a/libc/include/unistd.h b/libc/include/unistd.h index ebe357dd..ad667b0e 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -36,6 +36,7 @@ #if defined(_SORTIX_SOURCE) #include #include +#include #include __BEGIN_DECLS #ifndef __time_t_defined @@ -401,6 +402,7 @@ ssize_t write(int, const void*, size_t); #if defined(_SORTIX_SOURCE) int alarmns(const struct timespec* delay, struct timespec* odelay); int execvpe(const char*, char* const [], char* const []); +int exit_thread(int, int, const struct exit_thread*); int memstat(size_t* memused, size_t* memtotal); int mkpartition(int fd, off_t start, off_t length); pid_t sfork(int flags); diff --git a/libc/unistd/exit_thread.cpp b/libc/unistd/exit_thread.cpp new file mode 100644 index 00000000..ea73936a --- /dev/null +++ b/libc/unistd/exit_thread.cpp @@ -0,0 +1,35 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013, 2014. + + 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 . + + unistd/exit_thread.cpp + Destroys the current thread immediately with no clean up. + +*******************************************************************************/ + +#include + +#include + +DEFN_SYSCALL3(int, sys_exit_thread, SYSCALL_EXIT_THREAD, int, int, const struct exit_thread*); + +extern "C" +int exit_thread(int status, int flags, const struct exit_thread* extended) +{ + return sys_exit_thread(status, flags, extended); +}