summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-11-02 14:06:48 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-11-02 14:06:48 +0100
commit10b666f69a610c0bdc5bd60efd1d7d2bf499707d (patch)
tree3c552bce003cd7b9a95f161fa12b7d73f902c088 /Kernel
parent621217ffeb9bddec866ad8895bd01973977f2848 (diff)
downloadserenity-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.cpp30
-rw-r--r--Kernel/Keyboard.h27
-rw-r--r--Kernel/Process.cpp27
-rw-r--r--Kernel/Process.h5
-rw-r--r--Kernel/TTY.cpp14
-rw-r--r--Kernel/TTY.h2
-rw-r--r--Kernel/VirtualConsole.cpp10
-rw-r--r--Kernel/VirtualConsole.h2
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;