diff --git a/core/panic/user.cpp b/core/panic/user.cpp index 3f525fb..5f9251b 100644 --- a/core/panic/user.cpp +++ b/core/panic/user.cpp @@ -169,15 +169,15 @@ nsa bool UserModeExceptionHandler(CPU::ExceptionFrame *Frame) return true; } - proc->Signals->SendSignal(SIGSEGV, - {Tasking::KILL_CRASH}); + proc->Signals.SendSignal(SIGSEGV, + {Tasking::KILL_CRASH}); break; } case CPU::x86::Debug: case CPU::x86::Breakpoint: { - proc->Signals->SendSignal(SIGTRAP, - {Tasking::KILL_CRASH}); + proc->Signals.SendSignal(SIGTRAP, + {Tasking::KILL_CRASH}); break; } case CPU::x86::DivideByZero: @@ -186,21 +186,21 @@ nsa bool UserModeExceptionHandler(CPU::ExceptionFrame *Frame) case CPU::x86::x87FloatingPoint: case CPU::x86::SIMDFloatingPoint: { - proc->Signals->SendSignal(SIGFPE, - {Tasking::KILL_CRASH}); + proc->Signals.SendSignal(SIGFPE, + {Tasking::KILL_CRASH}); break; } case CPU::x86::InvalidOpcode: case CPU::x86::GeneralProtectionFault: { - proc->Signals->SendSignal(SIGILL, - {Tasking::KILL_CRASH}); + proc->Signals.SendSignal(SIGILL, + {Tasking::KILL_CRASH}); break; } case CPU::x86::DeviceNotAvailable: { - proc->Signals->SendSignal(SIGBUS, - {Tasking::KILL_CRASH}); + proc->Signals.SendSignal(SIGBUS, + {Tasking::KILL_CRASH}); break; } case CPU::x86::NonMaskableInterrupt: diff --git a/include/signal.hpp b/include/signal.hpp index 1e2a810..eecbfd1 100644 --- a/include/signal.hpp +++ b/include/signal.hpp @@ -18,171 +18,121 @@ #ifndef __FENNIX_KERNEL_SIGNAL_H__ #define __FENNIX_KERNEL_SIGNAL_H__ +#include #include #include #include +#include #include -#include enum Signals : int { SIG_NULL = 0, - - /** - * Process abort signal. - */ - SIGABRT, - - /** - * Alarm clock. - */ - SIGALRM, - - /** - * Access to an undefined portion of a memory object. - */ - SIGBUS, - - /** - * Child process terminated, stopped, or continued. - */ - SIGCHLD, - - /** - * Continue executing, if stopped. - */ - SIGCONT, - - /** - * Erroneous arithmetic operation. - */ - SIGFPE, - - /** - * Hangup. - */ - SIGHUP, - - /** - * Illegal instruction. - */ - SIGILL, - - /** - * Terminal interrupt signal. - */ - SIGINT, - - /** - * Kill (cannot be caught or ignored). - */ - SIGKILL, - - /** - * Write on a pipe with no one to read it. - */ - SIGPIPE, - - /** - * Terminal quit signal. - */ - SIGQUIT, - - /** - * Invalid memory reference. - */ - SIGSEGV, - - /** - * Stop executing (cannot be caught or ignored). - */ - SIGSTOP, - - /** - * Termination signal. - */ - SIGTERM, - - /** - * Terminal stop signal. - */ - SIGTSTP, - - /** - * Background process attempting read. - */ - SIGTTIN, - - /** - * Background process attempting write. - */ - SIGTTOU, - - /** - * User-defined signal 1. - */ - SIGUSR1, - - /** - * User-defined signal 2. - */ - SIGUSR2, - - /** - * Pollable event. - */ - SIGPOLL, - - /** - * Profiling timer expired. - */ - SIGPROF, - - /** - * Bad system call. - */ - SIGSYS, - - /** - * Trace/breakpoint trap. - */ - SIGTRAP, - - /** - * High bandwidth data is available at a socket. - */ - SIGURG, - - /** - * Virtual timer expired. - */ - SIGVTALRM, - - /** - * CPU time limit exceeded. - */ - SIGXCPU, - - /** - * File size limit exceeded. - */ - SIGXFSZ, + /* Process abort signal. */ + SIGABRT = 1, + /* Alarm clock. */ + SIGALRM = 2, + /* Access to an undefined portion of a memory object. */ + SIGBUS = 3, + /* Child process terminated, stopped, or continued. */ + SIGCHLD = 4, + /* Continue executing, if stopped. */ + SIGCONT = 5, + /* Erroneous arithmetic operation. */ + SIGFPE = 6, + /* Hangup. */ + SIGHUP = 7, + /* Illegal instruction. */ + SIGILL = 8, + /* Terminal interrupt signal. */ + SIGINT = 9, + /* Kill (cannot be caught or ignored). */ + SIGKILL = 10, + /* Write on a pipe with no one to read it. */ + SIGPIPE = 11, + /* Terminal quit signal. */ + SIGQUIT = 12, + /* Invalid memory reference. */ + SIGSEGV = 13, + /* Stop executing (cannot be caught or ignored). */ + SIGSTOP = 14, + /* Termination signal. */ + SIGTERM = 15, + /* Terminal stop signal. */ + SIGTSTP = 16, + /* Background process attempting read. */ + SIGTTIN = 17, + /* Background process attempting write. */ + SIGTTOU = 18, + /* User-defined signal 1. */ + SIGUSR1 = 19, + /* User-defined signal 2. */ + SIGUSR2 = 20, + /* Pollable event. */ + SIGPOLL = 21, + /* Profiling timer expired. */ + SIGPROF = 22, + /* Bad system call. */ + SIGSYS = 23, + /* Trace/breakpoint trap. */ + SIGTRAP = 24, + /* High bandwidth data is available at a socket. */ + SIGURG = 25, + /* Virtual timer expired. */ + SIGVTALRM = 26, + /* CPU time limit exceeded. */ + SIGXCPU = 27, + /* File size limit exceeded. */ + SIGXFSZ = 28, /** * Reserved - * * These are just to match Linux's signal numbers. */ - SIGRSV1, - SIGRSV2, + SIGCOMP1 = 29, + SIGCOMP2 = 30, + SIGCOMP3 = 31, - /** - * Maximum signal number. - */ - SIGNAL_MAX + /* Real-time signals. */ + SIGRTMIN = 32, + SIGRT_1 = 33, + SIGRT_2 = 34, + SIGRT_3 = 35, + SIGRT_4 = 36, + SIGRT_5 = 37, + SIGRT_6 = 38, + SIGRT_7 = 39, + SIGRT_8 = 40, + SIGRT_9 = 41, + SIGRT_10 = 42, + SIGRT_11 = 43, + SIGRT_12 = 44, + SIGRT_13 = 45, + SIGRT_14 = 46, + SIGRT_15 = 47, + SIGRT_16 = 48, + SIGRT_17 = 49, + SIGRT_18 = 50, + SIGRT_19 = 51, + SIGRT_20 = 52, + SIGRT_21 = 53, + SIGRT_22 = 54, + SIGRT_23 = 55, + SIGRT_24 = 56, + SIGRT_25 = 57, + SIGRT_26 = 58, + SIGRT_27 = 59, + SIGRT_28 = 60, + SIGRT_29 = 61, + SIGRT_30 = 62, + SIGRT_31 = 63, + SIGRTMAX = 64, + + /* Maximum signal number. */ + SIGNAL_MAX = SIGRTMAX }; -enum SignalDisposition +enum SignalDispositions { /** * Terminate the process. @@ -210,21 +160,28 @@ enum SignalDisposition SIG_CONT }; -enum SignalAction +enum SignalActions { SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK }; +enum SignalActionDisposition : long +{ + SAD_ERR = -1, + SAD_DFL = 0, + SAD_IGN = 1, +}; + #define SA_NOCLDSTOP 1 #define SA_NOCLDWAIT 2 #define SA_SIGINFO 4 +#define SA_RESTORER 0x04000000 #define SA_ONSTACK 0x08000000 #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #define __SI_PAD_SIZE \ (128 - 2 * sizeof(int) - sizeof(long)) @@ -323,41 +280,32 @@ typedef struct } __si_fields; } siginfo_t; -struct sigaction +struct SignalAction { union { - void (*sa_handler)(int); - void (*sa_sigaction)(int, siginfo_t *, void *); - } __sa_handler; - sigset_t sa_mask; - int sa_flags; - void (*sa_restorer)(void); + void (*Handler)(int); + void (*Action)(int, siginfo_t *, void *); + sigset_t Disposition; + } sa_handler; + std::bitset<64> Mask; + unsigned long Flags; + void (*Restorer)(void); }; namespace Tasking { - __no_sanitize("shift") inline __always_inline - sigset_t - ToFlag(sigset_t sig) - { - return 1 << (sig - 1); - } - - inline __always_inline - sigset_t - ToSig(sigset_t flag) - { - return __builtin_ctzl(flag) + 1; - } - class Signal { private: struct SignalInfo { - int sig; - union sigval val; + int sig = SIG_NULL; + union sigval val + { + 0 + }; + pid_t tid = -1; }; struct StackInfo @@ -388,109 +336,97 @@ namespace Tasking void *TrampAddr = nullptr; size_t TrampSz = 0; - std::list SignalQueue; - std::atomic SignalMask = 0; - sigaction SignalAction[SIGNAL_MAX]{}; - SignalDisposition sigDisp[SIGNAL_MAX]; + std::list Queue; + SignalAction sa[64 + 1]{}; + // std::bitset GlobalMask; + // SignalDispositions Disposition[SIGNAL_MAX]; std::list Watchers; + std::unordered_map Disposition = { + {SIGHUP, SIG_TERM}, + {SIGINT, SIG_TERM}, + {SIGQUIT, SIG_TERM}, + {SIGILL, SIG_CORE}, + {SIGTRAP, SIG_CORE}, + {SIGABRT, SIG_CORE}, + {SIGBUS, SIG_CORE}, + {SIGFPE, SIG_CORE}, + {SIGKILL, SIG_TERM}, + {SIGUSR1, SIG_TERM}, + {SIGSEGV, SIG_CORE}, + {SIGUSR2, SIG_TERM}, + {SIGPIPE, SIG_TERM}, + {SIGALRM, SIG_TERM}, + {SIGTERM, SIG_TERM}, + {SIGCOMP1, SIG_IGN}, + {SIGCHLD, SIG_IGN}, + {SIGCONT, SIG_CONT}, + {SIGSTOP, SIG_STOP}, + {SIGTSTP, SIG_STOP}, + {SIGTTIN, SIG_STOP}, + {SIGTTOU, SIG_STOP}, + {SIGURG, SIG_IGN}, + {SIGXCPU, SIG_CORE}, + {SIGXFSZ, SIG_CORE}, + {SIGVTALRM, SIG_TERM}, + {SIGPROF, SIG_TERM}, + {SIGCOMP2, SIG_IGN}, + {SIGPOLL, SIG_TERM}, + {SIGCOMP3, SIG_IGN}, + {SIGSYS, SIG_CORE}, + {SIGRTMIN, SIG_IGN}, + {SIGRT_1, SIG_IGN}, + {SIGRT_2, SIG_IGN}, + {SIGRT_3, SIG_IGN}, + {SIGRT_4, SIG_IGN}, + {SIGRT_5, SIG_IGN}, + {SIGRT_6, SIG_IGN}, + {SIGRT_7, SIG_IGN}, + {SIGRT_8, SIG_IGN}, + {SIGRT_9, SIG_IGN}, + {SIGRT_10, SIG_IGN}, + {SIGRT_11, SIG_IGN}, + {SIGRT_12, SIG_IGN}, + {SIGRT_13, SIG_IGN}, + {SIGRT_14, SIG_IGN}, + {SIGRT_15, SIG_IGN}, + {SIGRT_16, SIG_IGN}, + {SIGRT_17, SIG_IGN}, + {SIGRT_18, SIG_IGN}, + {SIGRT_19, SIG_IGN}, + {SIGRT_20, SIG_IGN}, + {SIGRT_21, SIG_IGN}, + {SIGRT_22, SIG_IGN}, + {SIGRT_23, SIG_IGN}, + {SIGRT_24, SIG_IGN}, + {SIGRT_25, SIG_IGN}, + {SIGRT_26, SIG_IGN}, + {SIGRT_27, SIG_IGN}, + {SIGRT_28, SIG_IGN}, + {SIGRT_29, SIG_IGN}, + {SIGRT_30, SIG_IGN}, + {SIGRT_31, SIG_IGN}, + {SIGRTMAX, SIG_IGN}}; bool LinuxSig(); - - int ConvertToLinuxIfNecessary(int sig); - int ConvertToNativeIfNecessary(int sig); - - sigset_t ConvertSigsetToLinuxIfNecessary(sigset_t sig); - sigset_t ConvertSigsetToNativeIfNecessary(sigset_t sig); - - int MakeExitCode(int sig); - + int MakeExitCode(Signals sig); void InitTrampoline(); - - const sigset_t nMasks = ToFlag(SIGKILL) | - ToFlag(SIGSTOP) | - ToFlag(SIGCONT) | - ToFlag(SIGSEGV) | - ToFlag(SIGBUS) | - ToFlag(SIGILL) | - ToFlag(SIGFPE); - - const sigset_t lMasks = ToFlag(linux_SIGKILL) | - ToFlag(linux_SIGSTOP) | - ToFlag(linux_SIGCONT) | - ToFlag(linux_SIGSEGV) | - ToFlag(linux_SIGBUS) | - ToFlag(linux_SIGILL) | - ToFlag(linux_SIGFPE); - - void RemoveUnmaskable(sigset_t *sig) - { - if (LinuxSig()) - *sig &= ~lMasks; - else - *sig &= ~nMasks; - } - - bool CanHaveHandler(sigset_t sig) - { - switch (sig) - { - case SIGKILL: - case SIGSTOP: - case SIGCONT: - return false; - default: - return true; - } - } + SignalInfo GetAvailableSignal(void *thread); public: void *GetContext() { return ctx; } Signals GetLastSignal() { return LastSignal; } - int AddWatcher(Signal *who, int sig); - int RemoveWatcher(Signal *who, int sig); + int AddWatcher(Signal *who, Signals sig); + int RemoveWatcher(Signal *who, Signals sig); - int AddSignal(int sig, union sigval val); - int RemoveSignal(int sig); + int AddSignal(Signals sig, union sigval val = {0}, pid_t tid = -1); + int RemoveSignal(Signals sig); - /** - * For scheduler use only - * @return True if there is a signal to handle - */ - bool HandleSignal(CPU::TrapFrame *tf); - void RestoreHandleSignal(SyscallsFrame *tf); + bool HandleSignal(CPU::TrapFrame *tf, void *thread); + void RestoreHandleSignal(SyscallsFrame *tf, void *thread); - /** - * Mask a signal - * - * @param sig The signal to set - * - * @return Old mask - */ - sigset_t Block(sigset_t sig); - - /** - * Unmask a signal - * - * @param sig The signal to set - * - * @return Old mask - */ - sigset_t Unblock(sigset_t sig); - - /** - * Set the signal mask - * - * @param sig The signal to set - * - * @return Old mask - */ - sigset_t SetMask(sigset_t sig); - - sigset_t GetMask() { return SignalMask.load(); } - - int SetAction(int sig, const sigaction act); - int GetAction(int sig, sigaction *act); + int SetAction(Signals sig, const SignalAction *act); + int GetAction(Signals sig, SignalAction *act); /** * Send a signal to the process @@ -498,39 +434,56 @@ namespace Tasking * @param sig The signal to send * (compatibility specific) * @param val The value to send + * @param tid The thread ID to send the signal to * * @return 0 on success, -errno on error */ - int SendSignal(int sig, union sigval val = {0}); + int SendSignal(Signals sig, sigval val = {0}, pid_t tid = -1); int WaitAnySignal(); - bool HasPendingSignal(); + bool HasPendingSignal() { return !Queue.empty(); } /** * Wait for a signal * * @param sig The signal to wait for - * (compatibility specific) * @param val The value to wait for * * @return 0 on success, -errno on error */ - int WaitSignal(int sig, union sigval *val); + int WaitSignal(Signals sig, union sigval *val); /** * Wait for a signal with a timeout * * @param sig The signal to wait for - * (compatibility specific) * @param val The value to wait for * @param timeout The timeout to wait for * * @return 0 on success, -errno on error */ - int WaitSignalTimeout(int sig, union sigval *val, uint64_t timeout); + int WaitSignalTimeout(Signals sig, union sigval *val, uint64_t timeout); Signal(void *ctx); ~Signal(); + + friend class ThreadSignal; + }; + + class ThreadSignal + { + private: + Signal &pSig; + + public: + std::bitset<64> Mask = 0; + + sigset_t Block(sigset_t sig); + sigset_t Unblock(sigset_t sig); + sigset_t SetMask(sigset_t sig); + sigset_t GetMask(); + + ThreadSignal(Signal &sig) : pSig(sig) {} }; } diff --git a/include/syscall/linux/defs.hpp b/include/syscall/linux/defs.hpp index fe00fb2..220b5fd 100644 --- a/include/syscall/linux/defs.hpp +++ b/include/syscall/linux/defs.hpp @@ -170,6 +170,8 @@ #define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2 #define LINUX_REBOOT_CMD_KEXEC 0x45584543 +#define SA_IMMUTABLE 0x00800000 + typedef long __kernel_old_time_t; typedef long __kernel_suseconds_t; typedef int clockid_t; diff --git a/include/syscall/linux/signals.hpp b/include/syscall/linux/signals.hpp index 2c08462..623f004 100644 --- a/include/syscall/linux/signals.hpp +++ b/include/syscall/linux/signals.hpp @@ -20,6 +20,8 @@ #include +#define linux_NSIG 64 + #define linux_SIGHUP 1 #define linux_SIGINT 2 #define linux_SIGQUIT 3 @@ -53,4 +55,14 @@ #define linux_SIGSYS 31 #define linux_SIGUNUSED linux_SIGSYS +#define linux_SIGRTMIN 32 +#define linux_SIGRTMAX linux_NSIG +struct k_sigaction +{ + void (*handler)(int); + unsigned long flags; + void (*restorer)(void); + unsigned mask[2]; +}; + #endif // !__FENNIX_KERNEL_LINUX_SIGNALS_H__ diff --git a/include/task.hpp b/include/task.hpp index 806a91e..e28704d 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -333,6 +333,9 @@ namespace Tasking Memory::VirtualMemoryArea *vma; Memory::StackGuard *Stack; + /* Signal */ + ThreadSignal Signals; + /* CPU state */ #if defined(a64) CPU::x64::TrapFrame Registers{}; @@ -361,6 +364,7 @@ namespace Tasking { int *set_child_tid{}; int *clear_child_tid{}; + pid_t tgid = 0; } Linux{}; int SendSignal(int sig); @@ -437,6 +441,8 @@ namespace Tasking uint16_t UserID = UINT16_MAX; uint16_t GroupID = UINT16_MAX; } Real, Effective; + pid_t ProcessGroupID = 0; + pid_t SessionID = 0; } Security{}; TaskInfo Info{}; ThreadLocalStorage TLS{}; @@ -457,7 +463,7 @@ namespace Tasking Memory::ProgramBreak *ProgramBreak; /* Other */ - Signal *Signals; + Signal Signals; /* Threads & Children */ std::list Threads; diff --git a/syscalls/linux.cpp b/syscalls/linux.cpp index 09dcf5b..1092d1c 100644 --- a/syscalls/linux.cpp +++ b/syscalls/linux.cpp @@ -39,13 +39,288 @@ using Tasking::PCB; using Tasking::TCB; +static_assert(linux_SIGRTMIN == SIGRTMIN); +static_assert(linux_SIGRTMAX == SIGRTMAX); + struct SyscallData { const char *Name; void *Handler; }; -void linux_fork_return(void *tableAddr) +#ifdef DEBUG +const char *lSigStr[] = { + "INVALID", + "SIGHUP", + "SIGINT", + "SIGQUIT", + "SIGILL", + "SIGTRAP", + "SIGABRT", + "SIGBUS", + "SIGFPE", + "SIGKILL", + "SIGUSR1", + "SIGSEGV", + "SIGUSR2", + "SIGPIPE", + "SIGALRM", + "SIGTERM", + "SIGSTKFLT", + "SIGCHLD", + "SIGCONT", + "SIGSTOP", + "SIGTSTP", + "SIGTTIN", + "SIGTTOU", + "SIGURG", + "SIGXCPU", + "SIGXFSZ", + "SIGVTALRM", + "SIGPROF", + "SIGWINCH", + "SIGPOLL", + "SIGPWR", + "SIGSYS", + "SIGRTMIN", + "SIGRT_1", + "SIGRT_2", + "SIGRT_3", + "SIGRT_4", + "SIGRT_5", + "SIGRT_6", + "SIGRT_7", + "SIGRT_8", + "SIGRT_9", + "SIGRT_10", + "SIGRT_11", + "SIGRT_12", + "SIGRT_13", + "SIGRT_14", + "SIGRT_15", + "SIGRT_16", + "SIGRT_17", + "SIGRT_18", + "SIGRT_19", + "SIGRT_20", + "SIGRT_21", + "SIGRT_22", + "SIGRT_23", + "SIGRT_24", + "SIGRT_25", + "SIGRT_26", + "SIGRT_27", + "SIGRT_28", + "SIGRT_29", + "SIGRT_30", + "SIGRT_31", + "SIGRTMAX", +}; +#endif + +const char *rlimitStr[] = { + "RLIMIT_CPU", + "RLIMIT_FSIZE", + "RLIMIT_DATA", + "RLIMIT_STACK", + "RLIMIT_CORE", + "RLIMIT_RSS", + "RLIMIT_NPROC", + "RLIMIT_NOFILE", + "RLIMIT_MEMLOCK", + "RLIMIT_AS", + "RLIMIT_LOCKS", + "RLIMIT_SIGPENDING", + "RLIMIT_MSGQUEUE", + "RLIMIT_NICE", + "RLIMIT_RTPRIO", + "RLIMIT_RTTIME", + "RLIMIT_NLIMITS", +}; + +static const struct +{ + int linuxSignal; + Signals nativeSignal; + SignalDispositions nativeDisposition; +} signalMapping[] = { + {linux_SIGHUP, SIGHUP, SIG_TERM}, + {linux_SIGINT, SIGINT, SIG_TERM}, + {linux_SIGQUIT, SIGQUIT, SIG_TERM}, + {linux_SIGILL, SIGILL, SIG_CORE}, + {linux_SIGTRAP, SIGTRAP, SIG_CORE}, + {linux_SIGABRT, SIGABRT, SIG_CORE}, + {linux_SIGBUS, SIGBUS, SIG_CORE}, + {linux_SIGFPE, SIGFPE, SIG_CORE}, + {linux_SIGKILL, SIGKILL, SIG_TERM}, + {linux_SIGUSR1, SIGUSR1, SIG_TERM}, + {linux_SIGSEGV, SIGSEGV, SIG_CORE}, + {linux_SIGUSR2, SIGUSR2, SIG_TERM}, + {linux_SIGPIPE, SIGPIPE, SIG_TERM}, + {linux_SIGALRM, SIGALRM, SIG_TERM}, + {linux_SIGTERM, SIGTERM, SIG_TERM}, + {linux_SIGSTKFLT, SIGCOMP1, SIG_IGN}, + {linux_SIGCHLD, SIGCHLD, SIG_IGN}, + {linux_SIGCONT, SIGCONT, SIG_CONT}, + {linux_SIGSTOP, SIGSTOP, SIG_STOP}, + {linux_SIGTSTP, SIGTSTP, SIG_STOP}, + {linux_SIGTTIN, SIGTTIN, SIG_STOP}, + {linux_SIGTTOU, SIGTTOU, SIG_STOP}, + {linux_SIGURG, SIGURG, SIG_IGN}, + {linux_SIGXCPU, SIGXCPU, SIG_CORE}, + {linux_SIGXFSZ, SIGXFSZ, SIG_CORE}, + {linux_SIGVTALRM, SIGVTALRM, SIG_TERM}, + {linux_SIGPROF, SIGPROF, SIG_TERM}, + {linux_SIGWINCH, SIGCOMP2, SIG_IGN}, + {linux_SIGPOLL, SIGPOLL, SIG_TERM}, + {linux_SIGPWR, SIGCOMP3, SIG_IGN}, + {linux_SIGSYS, SIGSYS, SIG_CORE}, + {linux_SIGRTMIN, SIGRTMIN, SIG_IGN}, + {linux_SIGRTMIN + 1, SIGRT_1, SIG_IGN}, + {linux_SIGRTMIN + 2, SIGRT_2, SIG_IGN}, + {linux_SIGRTMIN + 3, SIGRT_3, SIG_IGN}, + {linux_SIGRTMIN + 4, SIGRT_4, SIG_IGN}, + {linux_SIGRTMIN + 5, SIGRT_5, SIG_IGN}, + {linux_SIGRTMIN + 6, SIGRT_6, SIG_IGN}, + {linux_SIGRTMIN + 7, SIGRT_7, SIG_IGN}, + {linux_SIGRTMIN + 8, SIGRT_8, SIG_IGN}, + {linux_SIGRTMIN + 9, SIGRT_9, SIG_IGN}, + {linux_SIGRTMIN + 10, SIGRT_10, SIG_IGN}, + {linux_SIGRTMIN + 11, SIGRT_11, SIG_IGN}, + {linux_SIGRTMIN + 12, SIGRT_12, SIG_IGN}, + {linux_SIGRTMIN + 13, SIGRT_13, SIG_IGN}, + {linux_SIGRTMIN + 14, SIGRT_14, SIG_IGN}, + {linux_SIGRTMIN + 15, SIGRT_15, SIG_IGN}, + {linux_SIGRTMIN + 16, SIGRT_16, SIG_IGN}, + {linux_SIGRTMIN + 17, SIGRT_17, SIG_IGN}, + {linux_SIGRTMIN + 18, SIGRT_18, SIG_IGN}, + {linux_SIGRTMIN + 19, SIGRT_19, SIG_IGN}, + {linux_SIGRTMIN + 20, SIGRT_20, SIG_IGN}, + {linux_SIGRTMIN + 21, SIGRT_21, SIG_IGN}, + {linux_SIGRTMIN + 22, SIGRT_22, SIG_IGN}, + {linux_SIGRTMIN + 23, SIGRT_23, SIG_IGN}, + {linux_SIGRTMIN + 24, SIGRT_24, SIG_IGN}, + {linux_SIGRTMIN + 25, SIGRT_25, SIG_IGN}, + {linux_SIGRTMIN + 26, SIGRT_26, SIG_IGN}, + {linux_SIGRTMIN + 27, SIGRT_27, SIG_IGN}, + {linux_SIGRTMIN + 28, SIGRT_28, SIG_IGN}, + {linux_SIGRTMIN + 29, SIGRT_29, SIG_IGN}, + {linux_SIGRTMIN + 30, SIGRT_30, SIG_IGN}, + {linux_SIGRTMIN + 31, SIGRT_31, SIG_IGN}, + {linux_SIGRTMAX, SIGRTMAX, SIG_IGN}}; + +int ConvertSignalToLinux(Signals sig) +{ + if (sig >= SIGRTMIN && sig <= SIGRTMAX) + return sig; /* We ignore for now */ + + foreach (auto &mapping in signalMapping) + { + if (mapping.nativeSignal == sig) + { + // debug("Converted \"%s\"(%d) to \"%s\"(%d)", + // sigStr[mapping.nativeSignal], sig, + // lSigStr[mapping.linuxSignal], mapping.linuxSignal); + return mapping.linuxSignal; + } + } + debug("Unknown signal %d", sig); + // assert(!"Unknown signal"); + return SIG_NULL; +} + +Signals ConvertSignalToNative(int sig) +{ + if (sig >= linux_SIGRTMIN && sig <= linux_SIGRTMAX) + return (Signals)sig; /* We ignore for now */ + + foreach (auto &mapping in signalMapping) + { + if (mapping.linuxSignal == sig) + { + // debug("Converted \"%s\"(%d) to \"%s\"(%d)", + // lSigStr[mapping.linuxSignal], sig, + // sigStr[mapping.nativeSignal], mapping.nativeSignal); + return mapping.nativeSignal; + } + } + debug("Unknown signal %d", sig); + // assert(!"Unknown signal"); + return SIG_NULL; +} + +unsigned long ConvertMaskToNative(unsigned long mask) +{ + unsigned long ret = 0; + for (int i = 0; i < 64; i++) + { + if (mask & (1ul << i)) + { + int sig = ConvertSignalToNative(i + 1); + if (unlikely(sig == SIG_NULL)) + continue; + ret |= 1ul << (sig - 1); + } + } + return ret; + + // std::bitset bitMask(mask); + // for (int i = 0; i < SIGNAL_MAX + 1; i++) + // { + // if (bitMask.test(i)) + // ret |= 1 << (ConvertSignalToNative(i + 1) - 1); + // } +} + +unsigned long ConvertMaskToLinux(unsigned long mask) +{ + unsigned long ret = 0; + for (int i = 0; i < 64; i++) + { + if (mask & (1ul << i)) + { + int sig = ConvertSignalToLinux((Signals)(i + 1)); + if (unlikely(sig == SIG_NULL)) + continue; + ret |= 1ul << (sig - 1); + } + } + return ret; + + // std::bitset bitMask(mask); + // for (int i = 0; i < linux_SIGUNUSED + 1; i++) + // { + // if (bitMask.test(i)) + // ret |= 1 << (ConvertSignalToLinux(i + 1) - 1); + // } +} + +void SetSigActToNative(const k_sigaction *linux, SignalAction *native) +{ + native->sa_handler.Handler = linux->handler; + native->Flags = linux->flags; + native->Restorer = linux->restorer; + + unsigned long mask = ((unsigned long)linux->mask[1] << 32) | linux->mask[0]; + native->Mask = std::bitset<64>(ConvertMaskToNative(mask)); + debug("m0:%#lx m1:%#lx | n:%#lx", linux->mask[0], linux->mask[1], native->Mask); +} + +void SetSigActToLinux(const SignalAction *native, k_sigaction *linux) +{ + linux->handler = native->sa_handler.Handler; + linux->flags = native->Flags; + linux->restorer = native->Restorer; + + unsigned long mask = native->Mask.to_ulong(); + mask = ConvertMaskToLinux(mask); + + linux->mask[0] = mask & 0xFFFFFFFF; + linux->mask[1] = (mask >> 32) & 0xFFFFFFFF; + debug("m0:%#lx m1:%#lx | n:%#lx", linux->mask[0], linux->mask[1], native->Mask); +} + +void __LinuxForkReturn(void *tableAddr) { #if defined(a64) asmv("movq %0, %%cr3" ::"r"(tableAddr)); /* Load process page table */ @@ -56,7 +331,7 @@ void linux_fork_return(void *tableAddr) asmv("sti\n"); /* Enable interrupts */ asmv("sysretq\n"); /* Return to rcx address in user mode */ #elif defined(a32) -#warning "linux_fork_return not implemented for i386" +#warning "__LinuxForkReturn not implemented for i386" #endif __builtin_unreachable(); } @@ -648,7 +923,7 @@ static int linux_dup2(SysFrm *, int oldfd, int newfd) static int linux_pause(SysFrm *) { PCB *pcb = thisProcess; - return pcb->Signals->WaitAnySignal(); + return pcb->Signals.WaitAnySignal(); } /* https://man7.org/linux/man-pages/man2/nanosleep.2.html */ @@ -690,7 +965,7 @@ static int linux_nanosleep(SysFrm *, while (time < sleepTime) { - if (pcb->Signals->HasPendingSignal()) + if (pcb->Signals.HasPendingSignal()) { debug("sleep interrupted by signal"); return -EINTR; @@ -739,6 +1014,9 @@ static pid_t linux_fork(SysFrm *sf) return -EAGAIN; } + NewProcess->Security.ProcessGroupID = Parent->Security.ProcessGroupID; + NewProcess->Security.SessionID = Parent->Security.SessionID; + NewProcess->PageTable = Parent->PageTable->Fork(); NewProcess->vma->Table = NewProcess->PageTable; NewProcess->vma->Fork(Parent->vma); @@ -773,7 +1051,7 @@ static pid_t linux_fork(SysFrm *sf) NewThread->Security.IsCritical = Thread->Security.IsCritical; NewThread->Registers = Thread->Registers; #if defined(a64) - NewThread->Registers.rip = (uintptr_t)linux_fork_return; + NewThread->Registers.rip = (uintptr_t)__LinuxForkReturn; /* For sysretq */ NewThread->Registers.rdi = (uintptr_t)NewProcess->PageTable; NewThread->Registers.rcx = sf->ReturnAddress; @@ -789,7 +1067,7 @@ static pid_t linux_fork(SysFrm *sf) #endif debug("ret addr: %#lx, stack: %#lx ip: %#lx", sf->ReturnAddress, - sf->StackPointer, (uintptr_t)linux_fork_return); + sf->StackPointer, (uintptr_t)__LinuxForkReturn); debug("Forked thread \"%s\"(%d) to \"%s\"(%d)", Thread->Name, Thread->ID, NewThread->Name, NewThread->ID); @@ -1077,7 +1355,9 @@ static pid_t linux_wait4(SysFrm *, pid_t pid, int *wstatus, int ExitStatus = child->ExitCode.load(); bool ProcessSignaled = true; bool CoreDumped = true; - int TermSignal = child->Signals->GetLastSignal(); + int TermSignal = child->Signals.GetLastSignal(); + TermSignal = ConvertSignalToLinux((Signals)TermSignal); + assert(TermSignal != SIG_NULL); debug("Process returned %d", ExitStatus); @@ -1234,8 +1514,8 @@ static pid_t linux_wait4(SysFrm *, pid_t pid, int *wstatus, /* https://man7.org/linux/man-pages/man2/kill.2.html */ static int linux_kill(SysFrm *, pid_t pid, int sig) { - PCB *target = thisProcess->GetContext()->GetProcessByID(pid); - if (!target) + PCB *pcb = thisProcess->GetContext()->GetProcessByID(pid); + if (!pcb) return -ESRCH; /* TODO: Check permissions */ @@ -1245,8 +1525,21 @@ static int linux_kill(SysFrm *, pid_t pid, int sig) if (pid == 0) { - fixme("Sending signal %d to all processes", sig); - return -ENOSYS; + bool found = false; + Signals nSig = ConvertSignalToNative(sig); + assert(nSig != SIG_NULL); + foreach (auto proc in pcb->GetContext()->GetProcessList()) + { + if (proc->Security.ProcessGroupID == thisProcess->Security.ProcessGroupID) + { + debug("Sending signal %s to %s(%d)", lSigStr[sig], proc->Name, proc->ID); + proc->SendSignal(nSig); + found = true; + } + } + if (!found) + return -ESRCH; + return 0; } if (pid == -1) @@ -1261,7 +1554,9 @@ static int linux_kill(SysFrm *, pid_t pid, int sig) return -ENOSYS; } - return target->Signals->SendSignal(sig); + Signals nSig = ConvertSignalToNative(sig); + assert(nSig != SIG_NULL); + return pcb->SendSignal(nSig); } /* https://man7.org/linux/man-pages/man2/uname.2.html */ @@ -1510,17 +1805,13 @@ static pid_t linux_getpgid(SysFrm *, pid_t pid) { PCB *pcb = thisProcess; if (pid == 0) - { - fixme("pid=0 is stub!"); - return 0; - } + return pcb->Security.ProcessGroupID; PCB *target = pcb->GetContext()->GetProcessByID(pid); if (!target) return -ESRCH; - stub; - return 0; + return target->Security.ProcessGroupID; } /* https://man7.org/linux/man-pages/man2/setpgid.2.html */ @@ -1529,7 +1820,7 @@ static int linux_setpgid(SysFrm *, pid_t pid, pid_t pgid) PCB *pcb = thisProcess; if (pid == 0) { - fixme("pid=0 is stub!"); + pcb->Security.ProcessGroupID = pgid; return 0; } @@ -1537,10 +1828,13 @@ static int linux_setpgid(SysFrm *, pid_t pid, pid_t pgid) if (!target) return -ESRCH; - if (pgid < 0) - return -EINVAL; + if (pgid == 0) + { + target->Security.ProcessGroupID = target->ID; + return 0; + } - fixme("setpgid(%d, %d) is stub!", pid, pgid); + target->Security.ProcessGroupID = pgid; return 0; } @@ -1702,16 +1996,22 @@ static int linux_reboot(SysFrm *, int magic, int magic2, int cmd, void *arg) } /* https://man7.org/linux/man-pages/man2/sigaction.2.html */ -static int linux_sigaction(SysFrm *, int signum, - const struct sigaction *act, - struct sigaction *oldact) +static int linux_sigaction(SysFrm *, int signum, const k_sigaction *act, + k_sigaction *oldact, size_t sigsetsize) { - if (signum == linux_SIGKILL || signum == linux_SIGSTOP) + if (signum < 1 || signum > linux_SIGRTMAX || + signum == linux_SIGKILL || signum == linux_SIGSTOP) { debug("Invalid signal %d", signum); return -EINVAL; } + if (sigsetsize != sizeof(sigset_t)) + { + warn("Unsupported sigsetsize %d!", sigsetsize); + return -EINVAL; + } + PCB *pcb = thisProcess; Memory::VirtualMemoryArea *vma = pcb->vma; @@ -1727,13 +2027,35 @@ static int linux_sigaction(SysFrm *, int signum, int ret = 0; if (pOldact) - ret = pcb->Signals->GetAction(signum, pOldact); + { + Signals nSig = ConvertSignalToNative(signum); + assert(nSig != SIG_NULL); + + SignalAction nSA{}; + SetSigActToNative(pOldact, &nSA); + ret = pcb->Signals.GetAction(nSig, &nSA); + SetSigActToLinux(&nSA, pOldact); + } if (unlikely(ret < 0)) return ret; if (pAct) - ret = pcb->Signals->SetAction(signum, *pAct); + { + if (pAct->flags & SA_IMMUTABLE) + { + warn("Immutable signal %d", signum); + return -EINVAL; + } + + Signals nSig = ConvertSignalToNative(signum); + assert(nSig != SIG_NULL); + + SignalAction nSA{}; + SetSigActToNative(pAct, &nSA); + ret = pcb->Signals.SetAction(nSig, &nSA); + SetSigActToLinux(&nSA, (k_sigaction *)pAct); + } return ret; } @@ -1750,7 +2072,8 @@ static int linux_sigprocmask(SysFrm *, int how, const sigset_t *set, return -EINVAL; } - PCB *pcb = thisProcess; + TCB *tcb = thisThread; + PCB *pcb = tcb->Parent; Memory::VirtualMemoryArea *vma = pcb->vma; if (vma->UserCheck(set) < 0 && set != nullptr) @@ -1765,21 +2088,25 @@ static int linux_sigprocmask(SysFrm *, int how, const sigset_t *set, how, pSet ? *pSet : 0, pOldset ? *pOldset : 0); if (pOldset) - *pOldset = pcb->Signals->GetMask(); + { + *pOldset = tcb->Signals.GetMask(); + *pOldset = ConvertMaskToLinux(*pOldset); + } if (!pSet) return 0; + sigset_t nativeSet = ConvertMaskToNative(*pSet); switch (how) { case SIG_BLOCK: - pcb->Signals->Block(*pSet); + tcb->Signals.Block(nativeSet); break; case SIG_UNBLOCK: - pcb->Signals->Unblock(*pSet); + tcb->Signals.Unblock(nativeSet); break; case SIG_SETMASK: - pcb->Signals->SetMask(*pSet); + tcb->Signals.SetMask(nativeSet); break; default: warn("Invalid how %#x", how); @@ -1791,7 +2118,7 @@ static int linux_sigprocmask(SysFrm *, int how, const sigset_t *set, /* https://man7.org/linux/man-pages/man2/sigreturn.2.html */ static void linux_sigreturn(SysFrm *sf) { - thisProcess->Signals->RestoreHandleSignal(sf); + thisProcess->Signals.RestoreHandleSignal(sf, thisThread); } /* https://man7.org/linux/man-pages/man2/gettid.2.html */ @@ -1803,14 +2130,13 @@ static pid_t linux_gettid(SysFrm *) /* https://man7.org/linux/man-pages/man2/tkill.2.html */ static int linux_tkill(SysFrm *, int tid, int sig) { - Tasking::PCB *pcb = thisProcess; - Tasking::TCB *tcb = pcb->GetThread(tid); + Tasking::TCB *tcb = thisProcess->GetThread(tid); if (!tcb) return -ESRCH; Signals nSig = ConvertSignalToNative(sig); assert(nSig != SIG_NULL); - return pcb->Signals.SendSignal(nSig); + return tcb->SendSignal(nSig); } /* https://man7.org/linux/man-pages/man2/set_tid_address.2.html */ @@ -1919,6 +2245,7 @@ static int linux_clock_gettime(SysFrm *, clockid_t clockid, struct timespec *tp) return 0; } +/* https://man7.org/linux/man-pages/man2/clock_nanosleep.2.html */ static int linux_clock_nanosleep(SysFrm *, clockid_t clockid, int flags, const struct timespec *request, struct timespec *remain) @@ -1981,12 +2308,29 @@ static __noreturn void linux_exit_group(SysFrm *sf, int status) /* https://man7.org/linux/man-pages/man2/tgkill.2.html */ static int linux_tgkill(SysFrm *sf, pid_t tgid, pid_t tid, int sig) { - Tasking::TCB *target = thisProcess->GetContext()->GetThreadByID(tid, thisProcess); - if (!target) - return -ESRCH; + Tasking::TCB *tcb = thisProcess->GetThread(tid); + if (!tcb || tcb->Linux.tgid != tgid) + { + debug("Invalid tgid %d tid %d", tgid, tid); - fixme("semi-stub: %d %d %d", tgid, tid, sig); - return target->Parent->Signals->SendSignal(sig); + tcb = nullptr; + foreach (auto t in thisProcess->Threads) + { + if (t->Linux.tgid == tgid) + { + debug("Found tgid %d tid %d", tgid, t->ID); + tcb = t; + break; + } + } + + if (!tcb) + return -ESRCH; + } + + Signals nSig = ConvertSignalToNative(sig); + assert(nSig != SIG_NULL); + return tcb->SendSignal(nSig); } /* https://man7.org/linux/man-pages/man2/open.2.html */ @@ -2098,36 +2442,20 @@ static int linux_prlimit64(SysFrm *, pid_t pid, int resource, UNUSED(pNewLimit); if (new_limit) - debug("new limit: rlim_cur:%ld rlim_max:%ld", pNewLimit->rlim_cur, pNewLimit->rlim_max); + debug("new limit: rlim_cur:%#lx rlim_max:%#lx", pNewLimit->rlim_cur, pNewLimit->rlim_max); if (old_limit) - debug("old limit: rlim_cur:%ld rlim_max:%ld", pOldLimit->rlim_cur, pOldLimit->rlim_max); + debug("old limit: rlim_cur:%#lx rlim_max:%#lx", pOldLimit->rlim_cur, pOldLimit->rlim_max); switch (resource) { - case RLIMIT_NOFILE: - { - fixme("Setting RLIMIT_NOFILE is stub"); - return 0; - } - case RLIMIT_STACK: - { - fixme("Setting RLIMIT_STACK is stub"); - return 0; - } - case RLIMIT_NPROC: - { - fixme("Setting RLIMIT_NPROC is stub"); - return 0; - } - case RLIMIT_FSIZE: - { - fixme("Setting RLIMIT_FSIZE is stub"); - return 0; - } case RLIMIT_CPU: + case RLIMIT_FSIZE: case RLIMIT_DATA: + case RLIMIT_STACK: case RLIMIT_CORE: case RLIMIT_RSS: + case RLIMIT_NPROC: + case RLIMIT_NOFILE: case RLIMIT_MEMLOCK: case RLIMIT_AS: case RLIMIT_LOCKS: @@ -2138,8 +2466,8 @@ static int linux_prlimit64(SysFrm *, pid_t pid, int resource, case RLIMIT_RTTIME: case RLIMIT_NLIMITS: { - fixme("resource %d is stub", resource); - return -ENOSYS; + fixme("resource %s(%d) is stub", rlimitStr[resource], resource); + return 0; /* just return 0 */ } default: { diff --git a/tasking/process.cpp b/tasking/process.cpp index 692aff1..22a288e 100644 --- a/tasking/process.cpp +++ b/tasking/process.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -58,7 +59,7 @@ namespace Tasking int PCB::SendSignal(int sig) { - return this->Signals->SendSignal(sig); + return this->Signals.SendSignal((enum Signals)sig); } void PCB::SetState(TaskState state) @@ -138,7 +139,8 @@ namespace Tasking TaskExecutionMode ExecutionMode, bool UseKernelPageTable, uint16_t UserID, uint16_t GroupID) - : Node(ProcFS, std::to_string(ctx->NextPID), NodeType::DIRECTORY) + : Node(ProcFS, std::to_string(ctx->NextPID), NodeType::DIRECTORY), + Signals(this) { debug("+ %#lx", this); @@ -214,7 +216,6 @@ namespace Tasking this->vma = new Memory::VirtualMemoryArea(this->PageTable); this->ProgramBreak = new Memory::ProgramBreak(this->PageTable, this->vma); - this->Signals = new Signal(this); debug("Process page table: %#lx", this->PageTable); debug("Created %s process \"%s\"(%d). Parent \"%s\"(%d)", @@ -230,7 +231,6 @@ namespace Tasking this->AllocatedMemory += sizeof(Memory::VirtualMemoryArea); this->AllocatedMemory += sizeof(Memory::ProgramBreak); this->AllocatedMemory += sizeof(SymbolResolver::Symbols); - this->AllocatedMemory += sizeof(Signal); this->Info.SpawnTime = TimeManager->GetCounter(); @@ -250,9 +250,6 @@ namespace Tasking don't get scheduled anymore */ ctx->PopProcess(this); - debug("Freeing signals"); - delete this->Signals; - debug("Freeing allocated memory"); delete this->ProgramBreak; delete this->vma; diff --git a/tasking/scheduler/custom.cpp b/tasking/scheduler/custom.cpp index 8e93b12..956fe50 100644 --- a/tasking/scheduler/custom.cpp +++ b/tasking/scheduler/custom.cpp @@ -678,7 +678,7 @@ namespace Tasking::Scheduler CPU::x32::wrmsr(CPU::x32::MSR_FS_BASE, CurrentCPU->CurrentThread->FSBase); #endif - CurrentCPU->CurrentProcess->Signals->HandleSignal(Frame); + CurrentCPU->CurrentProcess->Signals.HandleSignal(Frame, CurrentCPU->CurrentThread.load()); if (!ProcessNotChanged) (&CurrentCPU->CurrentProcess->Info)->LastUpdateTime = TimeManager->GetCounter(); diff --git a/tasking/signal.cpp b/tasking/signal.cpp index 9b1daeb..71575ed 100644 --- a/tasking/signal.cpp +++ b/tasking/signal.cpp @@ -30,73 +30,72 @@ #include "../kernel.h" #ifdef DEBUG -const char *lSigStr[] = { - "SIGHUP", - "SIGINT", - "SIGQUIT", - "SIGILL", - "SIGTRAP", - "SIGABRT", - "SIGBUS", - "SIGFPE", - "SIGKILL", - "SIGUSR1", - "SIGSEGV", - "SIGUSR2", - "SIGPIPE", - "SIGALRM", - "SIGTERM", - "SIGSTKFLT", - "SIGCHLD", - "SIGCONT", - "SIGSTOP", - "SIGTSTP", - "SIGTTIN", - "SIGTTOU", - "SIGURG", - "SIGXCPU", - "SIGXFSZ", - "SIGVTALRM", - "SIGPROF", - "SIGWINCH", - "SIGPOLL", - "SIGPWR", - "SIGSYS", - "SIGUNUSED", -}; - const char *sigStr[] = { - "INVALID ", - "SIGABRT ", - "SIGALRM ", - "SIGBUS ", - "SIGCHLD ", - "SIGCONT ", - "SIGFPE ", - "SIGHUP ", - "SIGILL ", - "SIGINT ", - "SIGKILL ", - "SIGPIPE ", - "SIGQUIT ", - "SIGSEGV ", - "SIGSTOP ", - "SIGTERM ", - "SIGTSTP ", - "SIGTTIN ", - "SIGTTOU ", - "SIGUSR1 ", - "SIGUSR2 ", - "SIGPOLL ", - "SIGPROF ", - "SIGSYS ", - "SIGTRAP ", - "SIGURG ", - "SIGVTALRM", - "SIGXCPU ", - "SIGXFSZ ", - "SIGRSV1 ", - "SIGRSV2 ", + /* 0 */ "INVALID", + /* 1 */ "SIGABRT", + /* 2 */ "SIGALRM", + /* 3 */ "SIGBUS", + /* 4 */ "SIGCHLD", + /* 5 */ "SIGCONT", + /* 6 */ "SIGFPE", + /* 7 */ "SIGHUP", + /* 8 */ "SIGILL", + /* 9 */ "SIGINT", + /* 10 */ "SIGKILL", + /* 11 */ "SIGPIPE", + /* 12 */ "SIGQUIT", + /* 13 */ "SIGSEGV", + /* 14 */ "SIGSTOP", + /* 15 */ "SIGTERM", + /* 16 */ "SIGTSTP", + /* 17 */ "SIGTTIN", + /* 18 */ "SIGTTOU", + /* 19 */ "SIGUSR1", + /* 20 */ "SIGUSR2", + /* 21 */ "SIGPOLL", + /* 22 */ "SIGPROF", + /* 23 */ "SIGSYS", + /* 24 */ "SIGTRAP", + /* 25 */ "SIGURG", + /* 26 */ "SIGVTALRM", + /* 27 */ "SIGXCPU", + /* 28 */ "SIGXFSZ", + /* 29 */ "SIGCOMP1", + /* 30 */ "SIGCOMP2", + /* 31 */ "SIGCOMP3", + /* 32 */ "SIGRTMIN", + /* 33 */ "SIGRT_1", + /* 34 */ "SIGRT_2", + /* 35 */ "SIGRT_3", + /* 36 */ "SIGRT_4", + /* 37 */ "SIGRT_5", + /* 38 */ "SIGRT_6", + /* 39 */ "SIGRT_7", + /* 40 */ "SIGRT_8", + /* 41 */ "SIGRT_9", + /* 42 */ "SIGRT_10", + /* 43 */ "SIGRT_11", + /* 44 */ "SIGRT_12", + /* 45 */ "SIGRT_13", + /* 46 */ "SIGRT_14", + /* 47 */ "SIGRT_15", + /* 48 */ "SIGRT_16", + /* 49 */ "SIGRT_17", + /* 50 */ "SIGRT_18", + /* 51 */ "SIGRT_19", + /* 52 */ "SIGRT_20", + /* 53 */ "SIGRT_21", + /* 54 */ "SIGRT_22", + /* 55 */ "SIGRT_23", + /* 56 */ "SIGRT_24", + /* 57 */ "SIGRT_25", + /* 58 */ "SIGRT_26", + /* 59 */ "SIGRT_27", + /* 60 */ "SIGRT_28", + /* 61 */ "SIGRT_29", + /* 62 */ "SIGRT_30", + /* 63 */ "SIGRT_31", + /* 64 */ "SIGRTMAX", }; const char *dispStr[] = { @@ -113,50 +112,89 @@ extern "C" uintptr_t _sig_linux_trampoline_start, _sig_linux_trampoline_end; static const struct { - int linuxSignal; - int nativeSignal; -} signalMapping[] = { - {linux_SIGHUP, SIGHUP}, - {linux_SIGINT, SIGINT}, - {linux_SIGQUIT, SIGQUIT}, - {linux_SIGILL, SIGILL}, - {linux_SIGTRAP, SIGTRAP}, - {linux_SIGABRT, SIGABRT}, - {linux_SIGBUS, SIGBUS}, - {linux_SIGFPE, SIGFPE}, - {linux_SIGKILL, SIGKILL}, - {linux_SIGUSR1, SIGUSR1}, - {linux_SIGSEGV, SIGSEGV}, - {linux_SIGUSR2, SIGUSR2}, - {linux_SIGPIPE, SIGPIPE}, - {linux_SIGALRM, SIGALRM}, - {linux_SIGTERM, SIGTERM}, - {linux_SIGSTKFLT, SIGRSV1}, - {linux_SIGCHLD, SIGCHLD}, - {linux_SIGCONT, SIGCONT}, - {linux_SIGSTOP, SIGSTOP}, - {linux_SIGTSTP, SIGTSTP}, - {linux_SIGTTIN, SIGTTIN}, - {linux_SIGTTOU, SIGTTOU}, - {linux_SIGURG, SIGURG}, - {linux_SIGXCPU, SIGXCPU}, - {linux_SIGXFSZ, SIGXFSZ}, - {linux_SIGVTALRM, SIGVTALRM}, - {linux_SIGPROF, SIGPROF}, - {linux_SIGPOLL, SIGPOLL}, - {linux_SIGPWR, SIGRSV2}, - {linux_SIGSYS, SIGSYS}, - {linux_SIGUNUSED, SIGSYS}, + Signals Signal; + SignalDispositions Disposition; +} SignalDisposition[] = { + {SIGHUP, SIG_TERM}, + {SIGINT, SIG_TERM}, + {SIGQUIT, SIG_TERM}, + {SIGILL, SIG_CORE}, + {SIGTRAP, SIG_CORE}, + {SIGABRT, SIG_CORE}, + {SIGBUS, SIG_CORE}, + {SIGFPE, SIG_CORE}, + {SIGKILL, SIG_TERM}, + {SIGUSR1, SIG_TERM}, + {SIGSEGV, SIG_CORE}, + {SIGUSR2, SIG_TERM}, + {SIGPIPE, SIG_TERM}, + {SIGALRM, SIG_TERM}, + {SIGTERM, SIG_TERM}, + {SIGCOMP1, SIG_IGN}, + {SIGCHLD, SIG_IGN}, + {SIGCONT, SIG_CONT}, + {SIGSTOP, SIG_STOP}, + {SIGTSTP, SIG_STOP}, + {SIGTTIN, SIG_STOP}, + {SIGTTOU, SIG_STOP}, + {SIGURG, SIG_IGN}, + {SIGXCPU, SIG_CORE}, + {SIGXFSZ, SIG_CORE}, + {SIGVTALRM, SIG_TERM}, + {SIGPROF, SIG_TERM}, + {SIGCOMP2, SIG_IGN}, + {SIGPOLL, SIG_TERM}, + {SIGCOMP3, SIG_IGN}, + {SIGSYS, SIG_CORE}, + {SIGRTMIN, SIG_IGN}, + {SIGRT_1, SIG_IGN}, + {SIGRT_2, SIG_IGN}, + {SIGRT_3, SIG_IGN}, + {SIGRT_4, SIG_IGN}, + {SIGRT_5, SIG_IGN}, + {SIGRT_6, SIG_IGN}, + {SIGRT_7, SIG_IGN}, + {SIGRT_8, SIG_IGN}, + {SIGRT_9, SIG_IGN}, + {SIGRT_10, SIG_IGN}, + {SIGRT_11, SIG_IGN}, + {SIGRT_12, SIG_IGN}, + {SIGRT_13, SIG_IGN}, + {SIGRT_14, SIG_IGN}, + {SIGRT_15, SIG_IGN}, + {SIGRT_16, SIG_IGN}, + {SIGRT_17, SIG_IGN}, + {SIGRT_18, SIG_IGN}, + {SIGRT_19, SIG_IGN}, + {SIGRT_20, SIG_IGN}, + {SIGRT_21, SIG_IGN}, + {SIGRT_22, SIG_IGN}, + {SIGRT_23, SIG_IGN}, + {SIGRT_24, SIG_IGN}, + {SIGRT_25, SIG_IGN}, + {SIGRT_26, SIG_IGN}, + {SIGRT_27, SIG_IGN}, + {SIGRT_28, SIG_IGN}, + {SIGRT_29, SIG_IGN}, + {SIGRT_30, SIG_IGN}, + {SIGRT_31, SIG_IGN}, + {SIGRTMAX, SIG_IGN}, }; -static_assert(linux_SIGUNUSED == SIGNAL_MAX); +SignalDispositions GetDefaultSignalDisposition(Signals sig) +{ + foreach (auto var in SignalDisposition) + { + if (var.Signal == sig) + return var.Disposition; + } -#define CTLif(x) ConvertToLinuxIfNecessary(x) -#define CTNif(x) ConvertToNativeIfNecessary(x) -#define CSigTLif(x) ConvertSigsetToLinuxIfNecessary(x) -#define CSigTNif(x) ConvertSigsetToNativeIfNecessary(x) + error("Invalid signal: %d", sig); + return SIG_TERM; +} -/* TODO: CTLif & CTNif may need optimization */ +/* syscalls/linux.cpp */ +extern int ConvertSignalToLinux(Signals sig); namespace Tasking { @@ -165,86 +203,10 @@ namespace Tasking return ((PCB *)ctx)->Info.Compatibility == Linux; } - int Signal::ConvertToLinuxIfNecessary(int sig) - { - if (!LinuxSig()) - { - debug("Not linux sig: %d", sig); - return sig; - } - - foreach (auto &mapping in signalMapping) - { - if (mapping.nativeSignal == sig) - { - // debug("Converted %d to %d", sig, mapping.linuxSignal); - return mapping.linuxSignal; - } - } - - return -1; - } - - int Signal::ConvertToNativeIfNecessary(int sig) - { - if (!LinuxSig()) - { - debug("Not native sig: %d", sig); - return sig; - } - - foreach (auto &mapping in signalMapping) - { - if (mapping.linuxSignal == sig) - { - // debug("Converted %d to %d", sig, mapping.nativeSignal); - return mapping.nativeSignal; - } - } - - return -1; - } - - sigset_t Signal::ConvertSigsetToLinuxIfNecessary(sigset_t sig) - { - if (!LinuxSig()) - { - debug("Not linux sigset: %#lx", sig); - return 0; - } - - sigset_t ret = 0; - for (int i = 0; i < SIGNAL_MAX; i++) - { - if (sig & ToFlag(i)) - ret |= ToFlag(CTLif(i)); - } - - return ret; - } - - sigset_t Signal::ConvertSigsetToNativeIfNecessary(sigset_t sig) - { - if (!LinuxSig()) - { - debug("Not native sigset: %#lx", sig); - return 0; - } - - sigset_t ret = 0; - for (int i = 0; i < linux_SIGUNUSED; i++) - { - if (sig & ToFlag(i)) - ret |= ToFlag(CTNif(i)); - } - - return ret; - } - - int Signal::MakeExitCode(int sig) + int Signal::MakeExitCode(Signals sig) { if (this->LinuxSig()) - return 128 + sig; + return 128 + ConvertSignalToLinux(sig); else return 100 + sig; } @@ -293,7 +255,7 @@ namespace Tasking } case Windows: { - fixme("Windows compatibility"); + assert(!"Windows compatibility not implemented"); break; } default: @@ -304,18 +266,18 @@ namespace Tasking /* ------------------------------------------------------ */ - int Signal::AddWatcher(Signal *who, int sig) + int Signal::AddWatcher(Signal *who, Signals sig) { - SmartLock(SignalLock); SignalInfo info; info.sig = sig; info.val.sival_ptr = who; + SmartLock(SignalLock); Watchers.push_back(info); return 0; } - int Signal::RemoveWatcher(Signal *who, int sig) + int Signal::RemoveWatcher(Signal *who, Signals sig) { SmartLock(SignalLock); forItr(itr, Watchers) @@ -330,42 +292,73 @@ namespace Tasking return -ENOENT; } - int Signal::AddSignal(int sig, union sigval val) + int Signal::AddSignal(Signals sig, union sigval val, pid_t tid) { - SmartLock(SignalLock); - SignalInfo info{.sig = sig, .val = val}; - SignalQueue.push_back(info); + SignalInfo info{.sig = sig, .val = val, .tid = tid}; + Queue.push_back(info); return 0; } - int Signal::RemoveSignal(int sig) + int Signal::RemoveSignal(Signals sig) { - SmartLock(SignalLock); - forItr(itr, SignalQueue) - { - if (itr->sig == sig) - { - SignalQueue.erase(itr); - return 0; - } - } - return -ENOENT; + size_t n = Queue.remove_if([sig](SignalInfo &info) + { return info.sig == sig; }); + debug("Removed %d signals", n); + return n ? 0 : -ENOENT; } - bool Signal::HandleSignal(CPU::TrapFrame *tf) + Signal::SignalInfo Signal::GetAvailableSignal(void *thread) { - SmartLock(SignalLock); - if (SignalQueue.empty()) - return false; + forItr(itr, Queue) + { + // if (GlobalMask.test(itr->sig - 1)) + // { + // debug("Signal %s is blocked by global mask", + // sigStr[itr->sig]); + // continue; + // } + if (((TCB *)thread)->Signals.Mask.test(itr->sig - 1)) + { + debug("Signal %s is blocked by thread mask", + sigStr[itr->sig]); + continue; + } + + if (((TCB *)thread)->ID != itr->tid && itr->tid != -1) + { + debug("Signal %s is not for this thread", + sigStr[itr->sig]); + continue; + } + + assert(sa[itr->sig].sa_handler.Disposition != SAD_IGN); + assert(sa[itr->sig].sa_handler.Disposition != SAD_DFL); + + Queue.erase(itr); + debug("Signal %s is available", sigStr[itr->sig]); + return *itr; + } + + debug("No signal available"); + return {}; + } + + bool Signal::HandleSignal(CPU::TrapFrame *tf, void *thread) + { /* We don't want to do this in kernel mode */ - if (unlikely(tf->cs != GDT_USER_CODE)) + if (tf->cs != GDT_USER_CODE) return false; - debug("We have %d signals to handle", SignalQueue.size()); + if (Queue.empty()) + return false; - SignalInfo sigI = SignalQueue.front(); - SignalQueue.erase(SignalQueue.begin()); + debug("We have %d signals to handle", Queue.size()); + + SmartLock(SignalLock); + SignalInfo sigI = GetAvailableSignal(thread); + if (sigI.sig == SIG_NULL) + return false; uintptr_t _p_rsp = ((PCB *)ctx)->PageTable->Get(tf->rsp); uint64_t paRsp = _p_rsp; @@ -388,10 +381,11 @@ namespace Tasking si.GSBase = CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE); si.FSBase = CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE); si.ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSR_SHADOW_GS_BASE); + si.SignalMask = ((TCB *)thread)->Signals.Mask.to_ulong(); + si.Compatibility = ((PCB *)ctx)->Info.Compatibility; + debug("gs: %#lx fs: %#lx shadow: %#lx", si.GSBase, si.FSBase, si.ShadowGSBase); - si.SignalMask = SignalMask.load(); - si.Compatibility = ((PCB *)ctx)->Info.Compatibility; /* Copy the stack info */ uint64_t *pRsp = (uint64_t *)(paRsp - sizeof(StackInfo)); @@ -400,31 +394,56 @@ namespace Tasking /* Set the handler address */ pRsp--; /* Alignment */ pRsp--; - *pRsp = uint64_t(SignalAction[sigI.sig].__sa_handler.sa_handler); + *pRsp = uint64_t(sa[sigI.sig].sa_handler.Handler); assert(!((uintptr_t)pRsp & 0xF)); + int cSig = LinuxSig() ? ConvertSignalToLinux((Signals)sigI.sig) : sigI.sig; + #ifdef DEBUG DumpData("Stack Data", (void *)pRsp, paRsp - uint64_t(pRsp)); debug("initial stack tf->rsp: %#lx after: %#lx", tf->rsp, uint64_t(vRsp)); - debug("sig: %d -> %d", sigI.sig, CTLif(sigI.sig)); + debug("sig: %d -> %d", sigI.sig, cSig); #endif tf->rsp = uint64_t(vRsp); tf->rip = uint64_t(TrampAddr); - tf->rdi = CTLif(sigI.sig); - tf->rsi = uint64_t(sigI.val.sival_ptr); + /* void func(int signo); */ + /* void func(int signo, siginfo_t *info, void *context); */ + tf->rdi = cSig; + if (sa[sigI.sig].Flags & SA_SIGINFO) + { + fixme("SA_SIGINFO not implemented"); + siginfo_t *info = 0; + void *context = 0; + tf->rsi = uint64_t(info); + tf->rdx = uint64_t(context); + tf->rcx = 0; + tf->r8 = 0; + tf->r9 = 0; + } + else + { + tf->rsi = 0; + tf->rdx = 0; + tf->rcx = 0; + tf->r8 = 0; + tf->r9 = 0; + } + + ((TCB *)thread)->Signals.Mask = sa[sigI.sig].Mask; assert(TrampAddr != nullptr); return true; } - void Signal::RestoreHandleSignal(SyscallsFrame *sf) + void Signal::RestoreHandleSignal(SyscallsFrame *sf, void *thread) { - SmartLock(SignalLock); debug("Restoring signal handler"); + SmartLock(SignalLock); + gsTCB *gs = (gsTCB *)CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE); uint64_t *sp = (uint64_t *)((PCB *)ctx)->PageTable->Get(gs->TempStack); sp++; /* Alignment */ @@ -454,7 +473,7 @@ namespace Tasking sf->ReturnAddress = si->tf.rip; gs->TempStack = (void *)si->tf.rsp; - SignalMask.store(si->SignalMask); + ((TCB *)thread)->Signals.Mask = si->SignalMask; CPU::x64::fxrstor(&si->fx); CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, si->ShadowGSBase); @@ -468,86 +487,83 @@ namespace Tasking /* Return because we will restore at sysretq */ } - sigset_t Signal::Block(sigset_t sig) + int Signal::SetAction(Signals sig, const SignalAction *act) { SmartLock(SignalLock); - sig = CSigTNif(sig); - sigset_t oldMask = SignalMask.fetch_or(sig); - debug("%#lx -> %#lx", oldMask, SignalMask); - return CSigTLif(oldMask); - } - - sigset_t Signal::Unblock(sigset_t sig) - { - SmartLock(SignalLock); - sig = CSigTNif(sig); - sigset_t oldMask = SignalMask.fetch_and(~sig); - debug("%#lx -> %#lx", oldMask, SignalMask); - return CSigTLif(oldMask); - } - - sigset_t Signal::SetMask(sigset_t sig) - { - SmartLock(SignalLock); - sig = CSigTNif(sig); - sigset_t oldMask = SignalMask.exchange(sig); - debug("%#lx -> %#lx", oldMask, SignalMask); - return CSigTLif(oldMask); - } - - int Signal::SetAction(int sig, const sigaction act) - { - SmartLock(SignalLock); - int nSig = CTNif(sig); - if ((size_t)nSig > sizeof(SignalAction) / sizeof(SignalAction[0])) + if ((size_t)sig > sizeof(sa) / sizeof(sa[0])) { - debug("Invalid signal: %d (req %d)", nSig, sig); + debug("Invalid signal: %d", sig); return -EINVAL; } - SignalAction[nSig].__sa_handler.sa_handler = act.__sa_handler.sa_handler; - SignalAction[nSig].sa_mask = act.sa_mask; - SignalAction[nSig].sa_flags = act.sa_flags; + if ((long)act->sa_handler.Disposition == SAD_IGN) + { + Disposition[sig] = SIG_IGN; + debug("Set disposition for %s to SIG_IGN", sigStr[sig]); + debug("Discarding pending signals %s", sigStr[sig]); + + bool found = false; + forItr(itr, Queue) + { + if (itr->sig == sig) + { + Queue.erase(itr); + found = true; + break; + } + } + + if (!found) + { + debug("No pending signal %s", sigStr[sig]); + } + } + + if ((long)act->sa_handler.Disposition == SAD_DFL) + { + Disposition[sig] = GetDefaultSignalDisposition(sig); + debug("Set disposition for %s to %s (default)", sigStr[sig], + dispStr[Disposition[sig]]); + } + + sa[sig].sa_handler.Handler = act->sa_handler.Handler; + sa[sig].Mask = act->Mask; + sa[sig].Flags = act->Flags; + sa[sig].Restorer = act->Restorer; + debug("Set action for %s with handler %#lx, mask %#lx and flags %#lx", - LinuxSig() ? lSigStr[nSig] : sigStr[nSig], - SignalAction[nSig].__sa_handler.sa_handler, - SignalAction[nSig].sa_mask, - SignalAction[nSig].sa_flags); + sigStr[sig], sa[sig].sa_handler.Handler, sa[sig].Mask, sa[sig].Flags); return 0; } - int Signal::GetAction(int sig, sigaction *act) + int Signal::GetAction(Signals sig, SignalAction *act) { SmartLock(SignalLock); - - int nSig = CTNif(sig); - if ((size_t)nSig > sizeof(SignalAction) / sizeof(SignalAction[0])) + if ((size_t)sig > sizeof(sa) / sizeof(sa[0])) { - debug("Invalid signal: %d (req %d)", nSig, sig); + debug("Invalid signal: %d", sig); return -EINVAL; } - act->__sa_handler.sa_handler = SignalAction[nSig].__sa_handler.sa_handler; - act->sa_mask = SignalAction[nSig].sa_mask; - act->sa_flags = SignalAction[nSig].sa_flags; + act->sa_handler.Handler = sa[sig].sa_handler.Handler; + act->Mask = sa[sig].Mask; + act->Flags = sa[sig].Flags; + act->Restorer = sa[sig].Restorer; debug("Got action for %s with handler %#lx, mask %#lx and flags %#lx", - LinuxSig() ? lSigStr[nSig] : sigStr[nSig], - SignalAction[nSig].__sa_handler.sa_handler, - SignalAction[nSig].sa_mask, - SignalAction[nSig].sa_flags); + sigStr[sig], sa[sig].sa_handler.Handler, sa[sig].Mask, sa[sig].Flags); return 0; } - int Signal::SendSignal(int sig, union sigval val) + int Signal::SendSignal(Signals sig, sigval val, pid_t tid) { + SmartLock(SignalLock); PCB *pcb = (PCB *)ctx; - int nSig = CTNif(sig); - LastSignal = (Signals)nSig; + LastSignal = sig; debug("Sending signal %s to %s(%d)", - sigStr[nSig], pcb->Name, pcb->ID); + sigStr[sig], pcb->Name, pcb->ID); - if (SignalAction[nSig].__sa_handler.sa_handler) + if (sa[sig].sa_handler.Handler) { if (pcb->Security.ExecutionMode == Kernel) { @@ -555,35 +571,51 @@ namespace Tasking return -EINVAL; } - debug("sa_handler: %#lx", - SignalAction[nSig].__sa_handler.sa_handler); - debug("Adding signal %s to queue", sigStr[nSig]); + if (sa[sig].sa_handler.Disposition == SAD_IGN) + { + debug("Ignoring signal %s", sigStr[sig]); + return 0; + } + + debug("sa_handler: %#lx", sa[sig].sa_handler.Handler); + debug("Adding signal %s to queue", sigStr[sig]); goto CompleteSignal; } + else + { + debug("No handler for signal %s", sigStr[sig]); + } - debug("Signal disposition: %s", dispStr[sigDisp[nSig]]); - switch (sigDisp[nSig]) + if (thisThread->Signals.Mask.test(sig - 1)) + { + debug("Signal %s is blocked by thread mask", + sigStr[sig]); + return 0; + } + + debug("Signal disposition: %s", dispStr[Disposition[sig]]); + switch (Disposition[sig]) { case SIG_TERM: { if (unlikely(pcb->Security.IsCritical)) { debug("Critical process %s received signal %s(%d): Terminated", - pcb->Name, sigStr[nSig], nSig); + pcb->Name, sigStr[sig], sig); // int3; } - pcb->SetExitCode(MakeExitCode(nSig)); + pcb->SetExitCode(MakeExitCode(sig)); debug("We have %d watchers", this->Watchers.size()); if (this->Watchers.size() > 0) pcb->SetState(Zombie); else pcb->SetState(Terminated); - break; + return 0; } case SIG_IGN: { - debug("Ignoring signal %d", nSig); + debug("Ignoring signal %d", sig); return 0; } case SIG_CORE: @@ -593,27 +625,31 @@ namespace Tasking if (unlikely(pcb->Security.IsCritical)) { debug("Critical process %s received signal %s(%d): Core dumped", - pcb->Name, sigStr[nSig], nSig); + pcb->Name, sigStr[sig], sig); // int3; } - pcb->SetExitCode(MakeExitCode(nSig)); + pcb->SetExitCode(MakeExitCode(sig)); debug("We have %d watchers", this->Watchers.size()); if (this->Watchers.size() > 0) pcb->SetState(CoreDump); else pcb->SetState(Terminated); - break; + return 0; } case SIG_STOP: { + debug("Stopping process %s(%d) with signal %s(%d)", + pcb->Name, pcb->ID, sigStr[sig], sig); pcb->SetState(Stopped); - break; + return 0; } case SIG_CONT: { + debug("Continuing process %s(%d) with signal %s(%d)", + pcb->Name, pcb->ID, sigStr[sig], sig); pcb->SetState(Ready); - break; + return 0; } default: assert(!"Invalid signal disposition"); @@ -624,14 +660,14 @@ namespace Tasking if (pcb->Security.ExecutionMode == Kernel) { debug("Kernel process %s received signal %s(%d)! Ignoring... (with exceptions)", - pcb->Name, sigStr[nSig], nSig); + pcb->Name, sigStr[sig], sig); return 0; } this->InitTrampoline(); - debug("Signal %s(%d) completed", sigStr[nSig], nSig); - if (sigDisp[nSig] != SIG_IGN) + debug("Signal %s(%d) completed", sigStr[sig], sig); + if (Disposition[sig] != SIG_IGN) { foreach (auto info in Watchers) { @@ -645,27 +681,24 @@ namespace Tasking } debug("Adding signal to queue"); - SignalQueue.push_back({.sig = nSig, .val = val}); + Queue.push_back({.sig = sig, .val = val, .tid = tid}); return 0; } int Signal::WaitAnySignal() { - /* Sleep until a signal that terminated or invokes - the signal catch function */ - debug("Waiting for any signal"); - size_t oldSize = SignalQueue.size(); + size_t oldSize = Queue.size(); Reset: - while (SignalQueue.size() == oldSize) + while (Queue.size() == oldSize) TaskManager->Yield(); - if (SignalQueue.size() > oldSize) + if (Queue.size() > oldSize) { debug("Added signal to queue %d > %d", - SignalQueue.size(), oldSize); - oldSize = SignalQueue.size(); + Queue.size(), oldSize); + oldSize = Queue.size(); goto Reset; } @@ -673,77 +706,66 @@ namespace Tasking return -EINTR; } - bool Signal::HasPendingSignal() - { - return !SignalQueue.empty(); - } - - int Signal::WaitSignal(int sig, union sigval *val) + int Signal::WaitSignal(Signals sig, union sigval *val) { + assert(!"WaitSignal not implemented"); return 0; } - int Signal::WaitSignalTimeout(int sig, union sigval *val, uint64_t timeout) + int Signal::WaitSignalTimeout(Signals sig, union sigval *val, uint64_t timeout) { + assert(!"WaitSignalTimeout not implemented"); return 0; } - Signal::Signal(void *ctx) + Signal::Signal(void *_ctx) { - assert(ctx != nullptr); - this->ctx = ctx; + assert(_ctx != nullptr); + this->ctx = _ctx; - sigDisp[SIG_NULL] = SIG_IGN; - sigDisp[SIGABRT] = SIG_CORE; - sigDisp[SIGALRM] = SIG_TERM; - sigDisp[SIGBUS] = SIG_CORE; - sigDisp[SIGCHLD] = SIG_IGN; - sigDisp[SIGCONT] = SIG_CONT; - sigDisp[SIGFPE] = SIG_CORE; - sigDisp[SIGHUP] = SIG_TERM; - sigDisp[SIGILL] = SIG_CORE; - sigDisp[SIGINT] = SIG_TERM; - sigDisp[SIGKILL] = SIG_TERM; - sigDisp[SIGPIPE] = SIG_TERM; - sigDisp[SIGQUIT] = SIG_TERM; - sigDisp[SIGSEGV] = SIG_CORE; - sigDisp[SIGSTOP] = SIG_STOP; - sigDisp[SIGTERM] = SIG_TERM; - sigDisp[SIGTSTP] = SIG_STOP; - sigDisp[SIGTTIN] = SIG_STOP; - sigDisp[SIGTTOU] = SIG_STOP; - sigDisp[SIGUSR1] = SIG_TERM; - sigDisp[SIGUSR2] = SIG_TERM; - sigDisp[SIGPOLL] = SIG_TERM; - sigDisp[SIGPROF] = SIG_TERM; - sigDisp[SIGSYS] = SIG_CORE; - sigDisp[SIGTRAP] = SIG_CORE; - sigDisp[SIGURG] = SIG_IGN; - sigDisp[SIGVTALRM] = SIG_TERM; - sigDisp[SIGXCPU] = SIG_CORE; - sigDisp[SIGXFSZ] = SIG_CORE; + // for (int i = 1; i < SIGNAL_MAX; i++) + // Disposition[i] = GetDefaultSignalDisposition(i); #ifdef DEBUG static int once = 0; if (!once++) { - if (LinuxSig()) - { - for (int i = 0; i <= linux_SIGUNUSED; i++) - debug("%s: %s", - lSigStr[i], - dispStr[sigDisp[i]]); - } - else - { - for (int i = 0; i < SIGNAL_MAX; i++) - debug("%s: %s", - sigStr[i], - dispStr[sigDisp[i]]); - } + for (int i = 1; i < SIGNAL_MAX; i++) + debug("%s: %s", + sigStr[i], + dispStr[Disposition[(Signals)i]]); } #endif } Signal::~Signal() {} + + sigset_t ThreadSignal::Block(sigset_t sig) + { + sigset_t oldMask = Mask.to_ulong(); + Mask |= sig; + debug("%#lx -> %#lx", oldMask, Mask); + return oldMask; + } + + sigset_t ThreadSignal::Unblock(sigset_t sig) + { + sigset_t oldMask = Mask.to_ulong(); + Mask &= ~sig; + debug("%#lx -> %#lx", oldMask, Mask); + return oldMask; + } + + sigset_t ThreadSignal::SetMask(sigset_t sig) + { + sigset_t oldMask = Mask.to_ulong(); + Mask = sig; + debug("%#lx -> %#lx", oldMask, Mask); + return oldMask; + } + + sigset_t ThreadSignal::GetMask() + { + return Mask.to_ulong(); + } } diff --git a/tasking/thread.cpp b/tasking/thread.cpp index eda9944..f939695 100644 --- a/tasking/thread.cpp +++ b/tasking/thread.cpp @@ -64,7 +64,7 @@ namespace Tasking { int TCB::SendSignal(int sig) { - return this->Parent->Signals->SendSignal(sig); + return this->Parent->Signals.SendSignal((enum Signals)sig, {0}, this->ID); } void TCB::SetState(TaskState state) @@ -420,6 +420,7 @@ namespace Tasking TaskArchitecture Architecture, TaskCompatibility Compatibility, bool ThreadNotReady) + : Signals(Parent->Signals) { debug("+ %#lx", this); @@ -440,6 +441,14 @@ namespace Tasking this->ctx = ctx; this->ID = (TID)this->Parent->ID + (TID)this->Parent->Threads.size(); + if (Compatibility == TaskCompatibility::Linux) + { + if (Parent->Threads.size() == 0) + this->Linux.tgid = Parent->ID; + else + this->Linux.tgid = Parent->Threads.front()->Linux.tgid; + } + if (this->Name) delete[] this->Name;