summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/FileSystem/FileSystem.cpp8
-rw-r--r--Kernel/FileSystem/FileSystem.h1
-rw-r--r--Kernel/Syscall.cpp10
-rw-r--r--Kernel/Syscall.h3
-rw-r--r--Userland/shutdown.cpp17
5 files changed, 38 insertions, 1 deletions
diff --git a/Kernel/FileSystem/FileSystem.cpp b/Kernel/FileSystem/FileSystem.cpp
index 96728554bc..95a4f47093 100644
--- a/Kernel/FileSystem/FileSystem.cpp
+++ b/Kernel/FileSystem/FileSystem.cpp
@@ -68,3 +68,11 @@ void FS::sync()
for (auto fs : fses)
fs->flush_writes();
}
+
+void FS::lock_all()
+{
+ for (auto& it : all_fses()) {
+ it.value->m_lock.lock();
+ }
+}
+
diff --git a/Kernel/FileSystem/FileSystem.h b/Kernel/FileSystem/FileSystem.h
index 81d953c832..a41063c0a8 100644
--- a/Kernel/FileSystem/FileSystem.h
+++ b/Kernel/FileSystem/FileSystem.h
@@ -32,6 +32,7 @@ public:
unsigned fsid() const { return m_fsid; }
static FS* from_fsid(dword);
static void sync();
+ static void lock_all();
virtual bool initialize() = 0;
virtual const char* class_name() const = 0;
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index 95d14e44d7..0f6fb51404 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -1,6 +1,7 @@
#include <Kernel/Arch/i386/CPU.h>
#include <Kernel/Console.h>
#include <Kernel/Process.h>
+#include <Kernel/IO.h>
#include <Kernel/ProcessTracer.h>
#include <Kernel/Scheduler.h>
#include <Kernel/Syscall.h>
@@ -281,6 +282,15 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
return current->process().sys$sched_setparam((pid_t)arg1, (struct sched_param*)arg2);
case Syscall::SC_sched_getparam:
return current->process().sys$sched_setparam((pid_t)arg1, (struct sched_param*)arg2);
+ case Syscall::SC_halt: {
+ dbgprintf("<%u> halting! acquiring locks...\n");
+ FS::lock_all();
+ dbgprintf("<%u> halting! syncing...\n");
+ FS::sync();
+ dbgprintf("<%u> halting! bye, friends...\n");
+ IO::out16(0x604, 0x2000);
+ break;
+ }
default:
kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3);
return -ENOSYS;
diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h
index fd2f7fceef..033148a76f 100644
--- a/Kernel/Syscall.h
+++ b/Kernel/Syscall.h
@@ -112,7 +112,8 @@ struct timeval;
__ENUMERATE_SYSCALL(getpeername) \
__ENUMERATE_SYSCALL(sched_setparam) \
__ENUMERATE_SYSCALL(sched_getparam) \
- __ENUMERATE_SYSCALL(fchown)
+ __ENUMERATE_SYSCALL(fchown) \
+ __ENUMERATE_SYSCALL(halt)
namespace Syscall {
diff --git a/Userland/shutdown.cpp b/Userland/shutdown.cpp
new file mode 100644
index 0000000000..7884f12c15
--- /dev/null
+++ b/Userland/shutdown.cpp
@@ -0,0 +1,17 @@
+#include <Kernel/Syscall.h>
+#include <LibCore/CArgsParser.h>
+
+int main(int argc, char** argv)
+{
+ CArgsParser args_parser("shutdown");
+ args_parser.add_arg("n", "shut down now");
+ CArgsParserResult args = args_parser.parse(argc, (const char**)argv);
+
+ if (args.is_present("n")) {
+ syscall(SC_halt);
+ return 0;
+ } else {
+ args_parser.print_usage();
+ return 0;
+ }
+}