diff options
author | Andreas Kling <awesomekling@gmail.com> | 2018-11-02 14:06:48 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2018-11-02 14:06:48 +0100 |
commit | 10b666f69a610c0bdc5bd60efd1d7d2bf499707d (patch) | |
tree | 3c552bce003cd7b9a95f161fa12b7d73f902c088 /Kernel | |
parent | 621217ffeb9bddec866ad8895bd01973977f2848 (diff) | |
download | serenity-10b666f69a610c0bdc5bd60efd1d7d2bf499707d.zip |
Basic ^C interrupt implementation.
For testing, I made cat put itself into a new process group.
This should eventually be done by sh between fork() and exec().
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Keyboard.cpp | 30 | ||||
-rw-r--r-- | Kernel/Keyboard.h | 27 | ||||
-rw-r--r-- | Kernel/Process.cpp | 27 | ||||
-rw-r--r-- | Kernel/Process.h | 5 | ||||
-rw-r--r-- | Kernel/TTY.cpp | 14 | ||||
-rw-r--r-- | Kernel/TTY.h | 2 | ||||
-rw-r--r-- | Kernel/VirtualConsole.cpp | 10 | ||||
-rw-r--r-- | Kernel/VirtualConsole.h | 2 |
8 files changed, 80 insertions, 37 deletions
diff --git a/Kernel/Keyboard.cpp b/Kernel/Keyboard.cpp index fad3164a0b..7251ead12d 100644 --- a/Kernel/Keyboard.cpp +++ b/Kernel/Keyboard.cpp @@ -40,9 +40,12 @@ static char shift_map[0x100] = void Keyboard::emit(byte ch) { + Key key; + key.character = ch; + key.modifiers = m_modifiers; if (m_client) - m_client->onKeyPress(ch); - m_queue.enqueue(ch); + m_client->onKeyPress(key); + m_queue.enqueue(key); } void Keyboard::handleIRQ() @@ -50,12 +53,12 @@ void Keyboard::handleIRQ() while (IO::in8(0x64) & 1) { BYTE ch = IO::in8(0x60); switch (ch) { - case 0x38: m_modifiers |= MOD_ALT; break; - case 0xB8: m_modifiers &= ~MOD_ALT; break; - case 0x1D: m_modifiers |= MOD_CTRL; break; - case 0x9D: m_modifiers &= ~MOD_CTRL; break; - case 0x2A: m_modifiers |= MOD_SHIFT; break; - case 0xAA: m_modifiers &= ~MOD_SHIFT; break; + case 0x38: m_modifiers |= Mod_Alt; break; + case 0xB8: m_modifiers &= ~Mod_Alt; break; + case 0x1D: m_modifiers |= Mod_Ctrl; break; + case 0x9D: m_modifiers &= ~Mod_Ctrl; break; + case 0x2A: m_modifiers |= Mod_Shift; break; + case 0xAA: m_modifiers &= ~Mod_Shift; break; case 0x1C: /* enter */ emit('\n'); break; case 0xFA: /* i8042 ack */ break; default: @@ -75,16 +78,13 @@ void Keyboard::handleIRQ() break; } } - if (!m_modifiers) { + if (!m_modifiers) emit(map[ch]); - } else if (m_modifiers & MOD_SHIFT) { + else if (m_modifiers & Mod_Shift) emit(shift_map[ch]); - } else if (m_modifiers & MOD_CTRL) { - // FIXME: This is obviously not a good enough way to process ctrl+whatever. - emit('^'); + else if (m_modifiers & Mod_Ctrl) emit(shift_map[ch]); } - } //break; } } @@ -127,7 +127,7 @@ ssize_t Keyboard::read(byte* buffer, size_t size) while (nread < size) { if (m_queue.isEmpty()) break; - buffer[nread++] = m_queue.dequeue(); + buffer[nread++] = m_queue.dequeue().character; } return nread; } diff --git a/Kernel/Keyboard.h b/Kernel/Keyboard.h index 7f374b840a..923c3ab9aa 100644 --- a/Kernel/Keyboard.h +++ b/Kernel/Keyboard.h @@ -6,15 +6,25 @@ #include <VirtualFileSystem/CharacterDevice.h> #include "IRQHandler.h" -class KeyboardClient { -public: - virtual ~KeyboardClient(); - virtual void onKeyPress(byte) = 0; -}; +class KeyboardClient; class Keyboard final : public IRQHandler, public CharacterDevice { AK_MAKE_ETERNAL public: + enum Modifier { + Mod_Alt = 0x01, + Mod_Ctrl = 0x02, + Mod_Shift = 0x04, + }; + + struct Key { + byte character { 0 }; + byte modifiers { 0 }; + bool alt() { return modifiers & Mod_Alt; } + bool ctrl() { return modifiers & Mod_Ctrl; } + bool shift() { return modifiers & Mod_Shift; } + }; + static Keyboard& the() PURE; virtual ~Keyboard() override; @@ -34,7 +44,12 @@ private: void emit(byte); KeyboardClient* m_client { nullptr }; - CircularQueue<byte, 16> m_queue; + CircularQueue<Key, 16> m_queue; byte m_modifiers { 0 }; }; +class KeyboardClient { +public: + virtual ~KeyboardClient(); + virtual void onKeyPress(Keyboard::Key) = 0; +}; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 24d0bdc16c..96df47c99f 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -139,6 +139,15 @@ static void forEachProcess(Callback callback) } } +void Process::for_each_in_pgrp(pid_t pgid, Function<void(Process&)> callback) +{ + ASSERT_INTERRUPTS_DISABLED(); + for (auto* process = s_processes->head(); process; process = process->next()) { + if (process->pgid() == pgid) + callback(*process); + } +} + Vector<Process*> Process::allProcesses() { InterruptDisabler disabler; @@ -575,10 +584,10 @@ void Process::sys$exit(int status) switchNow(); } -void Process::murder(int signal) +void Process::send_signal(int signal, Process* sender) { ASSERT_INTERRUPTS_DISABLED(); - bool wasCurrent = current == this; + bool wasCurrent = current == sender; set_state(Exiting); s_processes->remove(this); @@ -587,7 +596,7 @@ void Process::murder(int signal) if (wasCurrent) { kprintf("Current process committing suicide!\n"); if (!scheduleNewProcess()) { - kprintf("Process::murder: Failed to schedule a new process :(\n"); + kprintf("Process::send_signal: Failed to schedule a new process :(\n"); HANG; } } @@ -1014,9 +1023,8 @@ int Process::sys$uname(utsname* buf) return 0; } -int Process::sys$kill(pid_t pid, int sig) +int Process::sys$kill(pid_t pid, int signal) { - (void) sig; if (pid == 0) { // FIXME: Send to same-group processes. ASSERT(pid != 0); @@ -1030,13 +1038,8 @@ int Process::sys$kill(pid_t pid, int sig) auto* peer = Process::fromPID(pid); if (!peer) return -ESRCH; - if (sig == SIGKILL) { - peer->murder(SIGKILL); - return 0; - } else { - ASSERT_NOT_REACHED(); - } - return -1; + peer->send_signal(signal, this); + return 0; } int Process::sys$sleep(unsigned seconds) diff --git a/Kernel/Process.h b/Kernel/Process.h index dbec761466..7ac558e7d2 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -73,6 +73,8 @@ public: void setWakeupTime(DWORD t) { m_wakeupTime = t; } DWORD wakeupTime() const { return m_wakeupTime; } + static void for_each_in_pgrp(pid_t pgid, Function<void(Process&)>); + static void prepForIRETToNewProcess(); bool tick() { ++m_ticks; return --m_ticksLeft; } @@ -151,6 +153,8 @@ public: FileHandle* file_descriptor(size_t i) { return m_file_descriptors[i].ptr(); } const FileHandle* file_descriptor(size_t i) const { return m_file_descriptors[i].ptr(); } + void send_signal(int signal, Process* sender); + private: friend class MemoryManager; friend bool scheduleNewProcess(); @@ -211,7 +215,6 @@ private: pid_t m_parentPID { 0 }; static void notify_waiters(pid_t waitee, int exit_status, int signal); - void murder(int signal); Vector<String> m_arguments; Vector<String> m_initialEnvironment; diff --git a/Kernel/TTY.cpp b/Kernel/TTY.cpp index c2f4c10ec6..9661ce9353 100644 --- a/Kernel/TTY.cpp +++ b/Kernel/TTY.cpp @@ -1,4 +1,5 @@ #include "TTY.h" +#include "Process.h" TTY::TTY(unsigned major, unsigned minor) : CharacterDevice(major, minor) @@ -38,3 +39,16 @@ void TTY::emit(byte ch) { m_buffer.append(ch); } + +void TTY::interrupt() +{ + dbgprintf("%s: Interrupt ^C pressed!\n", ttyName().characters()); + if (pgid()) { + dbgprintf("%s: Send SIGINT to everyone in pgrp %d\n", ttyName().characters(), pgid()); + InterruptDisabler disabler; + Process::for_each_in_pgrp(pgid(), [this] (auto& process) { + dbgprintf("%s: Send SIGINT to %d\n", ttyName().characters(), process.pid()); + process.send_signal(SIGINT, nullptr); + }); + } +} diff --git a/Kernel/TTY.h b/Kernel/TTY.h index e352efa1eb..1770e53a3c 100644 --- a/Kernel/TTY.h +++ b/Kernel/TTY.h @@ -23,6 +23,8 @@ protected: virtual void onTTYWrite(byte) = 0; + void interrupt(); + private: Vector<byte> m_buffer; pid_t m_pgid { 0 }; diff --git a/Kernel/VirtualConsole.cpp b/Kernel/VirtualConsole.cpp index f4537fd766..6512758c92 100644 --- a/Kernel/VirtualConsole.cpp +++ b/Kernel/VirtualConsole.cpp @@ -384,9 +384,15 @@ void VirtualConsole::on_char(byte ch, bool shouldEmit) set_cursor(m_cursor_row, m_cursor_column); } -void VirtualConsole::onKeyPress(byte ch) +void VirtualConsole::onKeyPress(Keyboard::Key key) { - emit(ch); + if (key.ctrl() && key.character == 'C') { + interrupt(); + return; + } + if (key.ctrl()) + emit('^'); + emit(key.character); } void VirtualConsole::onConsoleReceive(byte ch) diff --git a/Kernel/VirtualConsole.h b/Kernel/VirtualConsole.h index 6fd7e28552..205e567f3e 100644 --- a/Kernel/VirtualConsole.h +++ b/Kernel/VirtualConsole.h @@ -17,7 +17,7 @@ public: private: // ^KeyboardClient - virtual void onKeyPress(byte) override; + virtual void onKeyPress(Keyboard::Key) override; // ^ConsoleImplementation virtual void onConsoleReceive(byte) override; |