summaryrefslogtreecommitdiff
path: root/kernel/source/syscall.cpp
diff options
context:
space:
mode:
authorBenji Dial <benji@benjidial.net>2024-05-20 17:40:47 -0400
committerBenji Dial <benji@benjidial.net>2024-05-20 17:40:47 -0400
commit9af5588c30c4126a2800aae1afcb0de2c373dc6c (patch)
treed2a48a97b1664f958b5f88a8b0c03ef8366b0f49 /kernel/source/syscall.cpp
parent5a54df93c4e9368c36e69d1e9c88cd2904e92308 (diff)
downloadhilbert-os-9af5588c30c4126a2800aae1afcb0de2c373dc6c.tar.gz
rewrite application stuff in the kernel to support multitasking
Diffstat (limited to 'kernel/source/syscall.cpp')
-rw-r--r--kernel/source/syscall.cpp682
1 files changed, 439 insertions, 243 deletions
diff --git a/kernel/source/syscall.cpp b/kernel/source/syscall.cpp
index 5d9714c..6b0f13f 100644
--- a/kernel/source/syscall.cpp
+++ b/kernel/source/syscall.cpp
@@ -1,5 +1,6 @@
#include <hilbert/kernel/application.hpp>
#include <hilbert/kernel/framebuffer.hpp>
+#include <hilbert/kernel/load-app.hpp>
#include <hilbert/kernel/paging.hpp>
#include <hilbert/kernel/input.hpp>
#include <hilbert/kernel/panic.hpp>
@@ -17,16 +18,6 @@ namespace hilbert::kernel::syscall {
file_result_directory
};
- bool is_range_owned_by_application(uint64_t start, uint64_t end) {
- auto *process = application::running_thread->the_process;
- uint64_t pstart = (start / 4096) * 4096;
- uint64_t pend = ((end - 1) / 4096 + 1) * 4096;
- for (uint64_t p = pstart; p < pend; p += 4096)
- if (!process->is_page_owned(p))
- return false;
- return true;
- }
-
void set_zero(uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
rax = 0;
rdi = 0;
@@ -35,26 +26,26 @@ namespace hilbert::kernel::syscall {
}
void encode_color_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
+
rax = (uint64_t)framebuffer::encode_color(
rdi & 0xff, (rdi >> 8) & 0xff, (rdi >> 16) & 0xff);
rdi = 0;
rsi = 0;
rdx = 0;
+
}
void get_framebuffer_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
- auto *process = application::running_thread->the_process;
+ auto *process = application::running_thread->owner;
if (process->framebuffer_vaddr == 0) {
uint64_t pages_needed =
(framebuffer::dword_pitch * framebuffer::height * 4 - 1) / 4096 + 1;
- uint64_t vaddr = process->get_free_vaddr_pages(pages_needed);
+ uint64_t vaddr = process->memory->get_free_vaddr_pages(pages_needed);
for (uint64_t i = 0; i < pages_needed; ++i)
- process->map_page(
+ process->memory->map_page(
vaddr + i * 4096, framebuffer::paddr + i * 4096, true, false, false);
process->framebuffer_vaddr = vaddr;
}
@@ -69,23 +60,26 @@ namespace hilbert::kernel::syscall {
}
void open_file_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
-
- if (!is_range_owned_by_application(rdi, rdi + rsi)) {
- set_zero(rax, rdi, rsi, rdx);
- return;
- }
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
- utility::string path_string((const char *)rdi, rsi);
+ const char *path = (const char *)rdi;
+ uint64_t path_length = rsi;
+ bool allow_creation = rdx & 1;
+ bool only_allow_creation = rdx & 2;
set_zero(rax, rdi, rsi, rdx);
+ auto *process = application::running_thread->owner;
+ if (!process->memory->valid_to_read(path, path + path_length, false))
+ return;
+
+ utility::string path_string(path, path_length);
+
vfile::canon_path cp;
vfile::vfile file;
vfile::canonize_path(path_string, cp);
- switch (vfile::lookup_path(cp, file, true)) {
+ switch (vfile::look_up_path(cp, file, true)) {
case storage::fs_result::device_error:
case storage::fs_result::fs_corrupt:
@@ -95,7 +89,7 @@ namespace hilbert::kernel::syscall {
case storage::fs_result::does_not_exist:
- if (!(rdx & 1)) {
+ if (!allow_creation) {
rax = (uint64_t)application::stream_result::does_not_exist;
return;
}
@@ -105,7 +99,7 @@ namespace hilbert::kernel::syscall {
case storage::fs_result::success:
- if (rdx & 2) {
+ if (only_allow_creation) {
rax = (uint64_t)application::stream_result::already_exists;
return;
}
@@ -115,33 +109,33 @@ namespace hilbert::kernel::syscall {
return;
}
+ rdi = process->add_file_stream(new application::file_stream {
+ .the_file = utility::move(file), .offset = 0 });
rax = (uint64_t)application::stream_result::success;
- rdi = application::running_thread->the_process->open_streams.add_new(
- new application::vfile_stream(utility::move(file)));
-
- return;
}
}
void end_this_thread_syscall(
- uint64_t &, uint64_t &rdi, uint64_t &, uint64_t &
- ) {
- application::running_thread->exit_code = (int)(uint32_t)rdi;
- delete application::running_thread;
- application::resume_next();
+ uint64_t &, uint64_t &rdi, uint64_t &, uint64_t &) {
+
+ int exit_code = (int)(uint32_t)rdi;
+ auto *t = application::running_thread;
+ t->on_end_thread();
+ t->owner->notify_thread_ended(t, exit_code);
+ delete t;
+ application::resume_next_thread();
}
void get_new_pages_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
uint64_t count = rdi;
set_zero(rax, rdi, rsi, rdx);
- auto *p = application::running_thread->the_process;
- uint64_t vaddr = p->get_free_vaddr_pages(count);
+ auto *p = application::running_thread->owner;
+ uint64_t vaddr = p->memory->get_free_vaddr_pages(count);
for (uint64_t i = 0; i < count; ++i) {
uint64_t kvaddr;
@@ -150,7 +144,7 @@ namespace hilbert::kernel::syscall {
for (int i = 0; i < 4096; ++i)
((uint8_t *)kvaddr)[i] = 0;
paging::unmap_kernel_page((uint64_t)kvaddr);
- p->map_page(vaddr + i * 4096, paddr, true, false, true);
+ p->memory->map_page(vaddr + i * 4096, paddr, true, false, true);
}
rax = vaddr;
@@ -158,229 +152,213 @@ namespace hilbert::kernel::syscall {
}
void get_input_packet_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
set_zero(rax, rdi, rsi, rdx);
- auto *t = application::running_thread;
- do
- if (input::input_queue->count > 0) {
- input::input_packet packet = input::input_queue->take();
- if (packet.is_mouse) {
- rax = packet.mouse.buttons | 0x80;
- rdi = (uint16_t)packet.mouse.x_change;
- rsi = (uint16_t)packet.mouse.y_change;
- }
- else {
- rax = 0;
- rdi = packet.keyboard;
- }
- return;
- }
- while (application::save_thread_state(t->cpu));
+ while (input::input_queue->count == 0)
+ application::running_thread->wait_for_input();
- t->state = application::thread_state::waiting;
- application::threads_waiting_for_input->insert(t);
- application::resume_next();
+ input::input_packet packet = input::input_queue->take();
+ if (packet.is_mouse) {
+ rax = packet.mouse.buttons | 0x80;
+ rdi = (uint16_t)packet.mouse.x_change;
+ rsi = (uint16_t)packet.mouse.y_change;
+ }
+ else {
+ rax = 0;
+ rdi = packet.keyboard;
+ }
+
+ }
+
+ void create_socket(
+ application::process *p1, application::process *p2,
+ application::socket_stream_end *&se1_out,
+ application::socket_stream_end *&se2_out) {
+
+ application::socket *s = new application::socket();
+ se1_out = new application::socket_stream_end {
+ .the_socket = s, .read_queue = s->queue_1, .write_queue = s->queue_2,
+ .waiting_to_read = utility::queue<application::thread *>(),
+ .is_other_side_open = true, .other_process = p2, .other_end = 0 };
+ se2_out = new application::socket_stream_end {
+ .the_socket = s, .read_queue = s->queue_2, .write_queue = s->queue_2,
+ .waiting_to_read = utility::queue<application::thread *>(),
+ .is_other_side_open = true, .other_process = p1, .other_end = se1_out };
+ se1_out->other_end = se2_out;
}
void create_private_socket_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
- auto *s = new application::socket;
- auto *ss1 = new application::socket_stream(s, false);
- auto *ss2 = new application::socket_stream(s, true);
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
+
set_zero(rax, rdi, rsi, rdx);
- auto *p = application::running_thread->the_process;
- rax = (uint64_t)p->open_streams.add_new(ss1);
- rdi = (uint64_t)p->open_streams.add_new(ss2);
+
+ auto *p = application::running_thread->owner;
+
+ application::socket_stream_end *se1, *se2;
+ create_socket(p, p, se1, se2);
+
+ rax = p->add_socket_stream(se1);
+ rdi = p->add_socket_stream(se2);
+
}
void create_socket_listener_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
- if (!is_range_owned_by_application(rdi, rdi + rsi)) {
- set_zero(rax, rdi, rsi, rdx);
- return;
- }
+ auto *p = application::running_thread->owner;
- utility::string id_string((const char *)rdi, rsi);
+ const char *id = (const char *)rdi;
+ uint64_t id_length = rsi;
set_zero(rax, rdi, rsi, rdx);
- for (auto *p = application::all_socket_listeners->first; p; p = p->next)
- if (p->value->id == id_string) {
- rax = (uint64_t)application::stream_result::socket_id_already_used;
- return;
- }
+ if (!p->memory->valid_to_read(id, id + id_length, false))
+ return;
- auto *sl = new application::socket_listener();
- sl->id = utility::move(id_string);
- sl->is_listening = true;
- rax = (uint64_t)application::stream_result::success;
- rdi = (uint64_t)application::running_thread->the_process
- ->socket_listeners.add_new(utility::move(sl));
+ auto *sl =
+ application::try_register_socket_listener(
+ utility::string(id, id_length));
+
+ if (sl) {
+ rdx = p->add_socket_listener(sl);
+ rax = (uint64_t)application::stream_result::success;
+ }
+
+ else
+ rax = (uint64_t)application::stream_result::socket_id_already_in_use;
}
void stop_socket_listener_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
unsigned handle = (unsigned)rdi;
set_zero(rax, rdi, rsi, rdx);
- auto *p = application::running_thread->the_process;
-
- if (p->socket_listeners.has_id(handle)) {
- auto *sl = p->socket_listeners.get(handle);
- p->socket_listeners.remove_id(handle);
- if (sl->waiting_to_accept_connection.count > 0 ||
- sl->waiting_to_connect.count > 0) {
- sl->is_listening = false;
- while (sl->waiting_to_accept_connection.count > 0) {
- auto *t = sl->waiting_to_accept_connection.take();
- t->state = application::thread_state::paused;
- application::paused_threads->insert(t);
- }
- while (sl->waiting_to_connect.count > 0) {
- auto *t = sl->waiting_to_connect.take();
- t->state = application::thread_state::paused;
- application::paused_threads->insert(t);
- }
- }
- else
- delete sl;
- }
+
+ auto *sl =
+ application::running_thread->owner->take_socket_listener(handle);
+
+ if (!sl)
+ return;
+
+ while (sl->waiting_to_accept.count > 0)
+ sl->waiting_to_accept.take()->notify_no_socket_stream();
+ while (sl->waiting_to_connect.count > 0)
+ sl->waiting_to_connect.take()->notify_no_socket_stream();
+
+ application::remove_socket_listener(sl);
}
void accept_socket_connection_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
unsigned handle = (unsigned)rdi;
set_zero(rax, rdi, rsi, rdx);
+
auto *t = application::running_thread;
- auto *p = t->the_process;
+ auto *sl = t->owner->get_socket_listener(handle);
- if (!p->socket_listeners.has_id(handle)) {
- rax = (uint64_t)application::stream_result::socket_id_not_in_use;
+ if (!sl) {
+ rax = (uint64_t)application::stream_result::bad_handle;
return;
}
- auto *sl = p->socket_listeners.get(handle);
-
if (sl->waiting_to_connect.count > 0) {
+
auto *ot = sl->waiting_to_connect.take();
- auto *sock = new application::socket();
- application::stream *s1 = new application::socket_stream(sock, false);
- application::stream *s2 = new application::socket_stream(sock, true);
- unsigned handle = p->open_streams.add_new(utility::move(s1));
- ot->just_connected_to = s2;
- ot->state = application::thread_state::paused;
- application::paused_threads->insert(ot);
+
+ application::socket_stream_end *our_end, *their_end;
+ create_socket(t->owner, ot->owner, our_end, their_end);
+
+ unsigned our_handle = t->owner->add_socket_stream(our_end);
+ unsigned their_handle = ot->owner->add_socket_stream(their_end);
+
+ ot->notify_new_socket_stream(their_handle);
+
rax = (uint64_t)application::stream_result::success;
- rdi = handle;
- return;
+ rdi = our_handle;
+
}
- if (application::save_thread_state(t->cpu)) {
- if (sl->is_listening) {
+ else {
+
+ auto result = t->wait_to_accept_from(sl);
+ if (result.has_value) {
rax = (uint64_t)application::stream_result::success;
- rdi = p->open_streams.add_new(utility::move(t->just_accepted));
+ rdi = result.value;
}
- else {
- if (sl->waiting_to_accept_connection.count == 0 &&
- sl->waiting_to_connect.count == 0)
- delete sl;
+ else
rax = (uint64_t)application::stream_result::socket_listener_closed;
- }
- return;
- }
- t->state = application::thread_state::waiting;
- sl->waiting_to_accept_connection.insert(t);
- application::resume_next();
+ }
}
void connect_to_socket_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
+
+ const char *id = (const char *)rdi;
+ uint64_t id_length = rsi;
+ set_zero(rax, rdi, rsi, rdx);
- if (!is_range_owned_by_application(rdi, rdi + rsi)) {
- set_zero(rax, rdi, rsi, rdx);
+ auto *t = application::running_thread;
+
+ if (!t->owner->memory->valid_to_read(id, id + id_length, false))
+ return;
+
+ utility::string id_string(id, id_length);
+ auto *sl = application::try_get_socket_listener(id_string);
+
+ if (!sl) {
+ rax = (uint64_t)application::stream_result::socket_id_not_in_use;
return;
}
- utility::string id_string((const char *)rdi, rsi);
- set_zero(rax, rdi, rsi, rdx);
+ if (sl->waiting_to_accept.count > 0) {
- for (auto *i = application::all_socket_listeners->first; i; i = i->next)
- if (i->value->id == id_string) {
- auto *sl = i->value;
- auto *t = application::running_thread;
- auto *p = t->the_process;
-
- if (sl->waiting_to_accept_connection.count > 0) {
- auto *ot = sl->waiting_to_accept_connection.take();
- auto *sock = new application::socket();
- auto *s1 = new application::socket_stream(sock, false);
- auto *s2 = new application::socket_stream(sock, true);
- unsigned handle = p->open_streams.add_new(utility::move(s1));
- ot->just_accepted = s2;
- ot->state = application::thread_state::paused;
- application::paused_threads->insert(ot);
- rax = (uint64_t)application::stream_result::success;
- rdi = handle;
- return;
- }
+ auto *ot = sl->waiting_to_accept.take();
- if (application::save_thread_state(t->cpu)) {
- if (sl->is_listening) {
- rax = (uint64_t)application::stream_result::success;
- rdi = p->open_streams.add_new(utility::move(t->just_connected_to));
- }
- else {
- if (sl->waiting_to_accept_connection.count == 0 &&
- sl->waiting_to_connect.count == 0)
- delete sl;
- rax = (uint64_t)application::stream_result::socket_id_not_in_use;
- }
- return;
- }
+ application::socket_stream_end *our_end, *their_end;
+ create_socket(t->owner, ot->owner, our_end, their_end);
+
+ unsigned our_handle = t->owner->add_socket_stream(our_end);
+ unsigned their_handle = ot->owner->add_socket_stream(their_end);
+
+ ot->notify_new_socket_stream(their_handle);
- t->state = application::thread_state::waiting;
- sl->waiting_to_connect.insert(t);
- application::resume_next();
+ rax = (uint64_t)application::stream_result::success;
+ rdi = our_handle;
+
+ }
+ else {
+
+ auto result = t->wait_to_connect_to(sl);
+ if (result.has_value) {
+ rax = (uint64_t)application::stream_result::success;
+ rdi = result.value;
}
+ else
+ rax = (uint64_t)application::stream_result::socket_listener_closed;
- rax = (uint64_t)application::stream_result::socket_id_not_in_use;
+ }
}
void close_stream_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
unsigned handle = (unsigned)rdi;
set_zero(rax, rdi, rsi, rdx);
- auto *p = application::running_thread->the_process;
-
- if (p->open_streams.has_id(handle)) {
- application::stream *s = p->open_streams.get(handle);
- p->open_streams.remove_id(handle);
- delete s;
- }
+ application::running_thread->owner->close_stream(handle);
}
void seek_stream_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
unsigned handle = (unsigned)rdi;
uint8_t origin = (uint8_t)rsi;
@@ -390,117 +368,335 @@ namespace hilbert::kernel::syscall {
if (origin >= 3)
return;
- auto *p = application::running_thread->the_process;
+ auto stream = application::running_thread->owner->get_stream(handle);
- if (!p->open_streams.has_id(handle)) {
+ if (stream.is_null()) {
rax = (uint64_t)application::stream_result::bad_handle;
return;
}
- rax = (uint64_t)p->open_streams.get(handle)
- ->seek((application::seek_origin)origin, offset);
+ if (stream.is_socket) {
+ rax = (uint64_t)application::stream_result::not_seekable;
+ return;
+ }
+
+ auto *fs = stream.as_file_stream;
+
+ switch (origin) {
+
+ case 0://beginning
+ if (offset < 0 || (uint64_t)offset > fs->the_file.dir_entry.length) {
+ rax = (uint64_t)application::stream_result::out_of_bounds;
+ return;
+ }
+ fs->offset = offset;
+ rax = (uint64_t)application::stream_result::success;
+ return;
+
+ case 1://end
+ if (offset > 0 || (uint64_t)-offset > fs->the_file.dir_entry.length) {
+ rax = (uint64_t)application::stream_result::out_of_bounds;
+ return;
+ }
+ fs->offset = fs->the_file.dir_entry.length + offset;
+ rax = (uint64_t)application::stream_result::success;
+ return;
+
+ case 2://current position
+ int64_t new_offset = offset + fs->offset;
+ if (new_offset < 0 || (uint64_t)new_offset > fs->the_file.dir_entry.length) {
+ rax = (uint64_t)application::stream_result::out_of_bounds;
+ return;
+ }
+ fs->offset = (uint64_t)new_offset;
+ rax = (uint64_t)application::stream_result::success;
+ return;
+
+ }
}
void read_from_stream_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
unsigned handle = (unsigned)rdi;
uint64_t count = (uint64_t)rsi;
- uint64_t buffer = (uint64_t)rdx;
+ uint8_t *buffer = (uint8_t *)rdx;
set_zero(rax, rdi, rsi, rdx);
- if (!is_range_owned_by_application(buffer, buffer + count))
+ auto *t = application::running_thread;
+
+ if (!t->owner->memory->valid_to_read(buffer, buffer + count, true))
return;
- auto *p = application::running_thread->the_process;
+ auto stream = t->owner->get_stream(handle);
- if (!p->open_streams.has_id(handle)) {
+ if (stream.is_null()) {
rax = (uint64_t)application::stream_result::bad_handle;
return;
}
- rax = (uint64_t)p->open_streams.get(handle)->read(count, (void *)buffer);
+ if (stream.is_socket) {
+ auto *ss = stream.as_socket_stream;
+ for (uint64_t i = 0; i < count; ++i) {
+ while (ss->read_queue.count == 0) {
+ if (!ss->is_other_side_open) {
+ rax = (uint64_t)application::stream_result::other_end_closed;
+ return;
+ }
+ t->wait_for_socket_stream(ss);
+ }
+ buffer[i] = ss->read_queue.take();
+ }
+ rax = (uint64_t)application::stream_result::success;
+ }
+
+ else {
+ auto *fs = stream.as_file_stream;
+ if (fs->offset + count > fs->the_file.dir_entry.length) {
+ rax = (uint64_t)application::stream_result::out_of_bounds;
+ return;
+ }
+ auto read_result = fs->the_file.read_file(fs->offset, count, buffer);
+ if (read_result != storage::fs_result::success) {
+ rax = (uint64_t)application::stream_result::io_error;
+ return;
+ }
+ fs->offset += count;
+ rax = (uint64_t)application::stream_result::success;
+ }
}
void write_to_stream_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
unsigned handle = (unsigned)rdi;
uint64_t count = (uint64_t)rsi;
- uint64_t buffer = (uint64_t)rdx;
+ const uint8_t *buffer = (uint8_t *)rdx;
set_zero(rax, rdi, rsi, rdx);
- if (!is_range_owned_by_application(buffer, buffer + count))
+ auto *t = application::running_thread;
+
+ if (!t->owner->memory->valid_to_read(buffer, buffer + count, false))
return;
- auto *p = application::running_thread->the_process;
+ auto stream = t->owner->get_stream(handle);
- if (!p->open_streams.has_id(handle)) {
+ if (stream.is_null()) {
rax = (uint64_t)application::stream_result::bad_handle;
return;
}
- rax = (uint64_t)p->open_streams.get(handle)
- ->write(count, (const void *)buffer);
+ if (stream.is_socket) {
+ auto *ss = stream.as_socket_stream;
+ if (!ss->is_other_side_open) {
+ rax = (uint64_t)application::stream_result::other_end_closed;
+ return;
+ }
+ for (uint64_t i = 0; i < count; ++i)
+ ss->write_queue.insert(buffer[i]);
+ rax = (uint64_t)application::stream_result::success;
+ }
+
+ else {
+ //TODO: write to file
+ panic(0x9af5e6);
+ }
}
void get_stream_length_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
unsigned handle = (unsigned)rdi;
set_zero(rax, rdi, rsi, rdx);
- auto *p = application::running_thread->the_process;
+ auto *t = application::running_thread;
- if (!p->open_streams.has_id(handle)) {
+ auto stream = t->owner->get_stream(handle);
+
+ if (stream.is_null())
rax = (uint64_t)application::stream_result::bad_handle;
- return;
- }
- rax = (uint64_t)p->open_streams.get(handle)->get_length(rdi);
+ else if (stream.is_socket)
+ rax = (uint64_t)application::stream_result::not_sized;
+
+ else {
+ rdi = stream.as_file_stream->the_file.dir_entry.length;
+ rax = (uint64_t)application::stream_result::success;
+ }
}
+ struct env_var_spec {
+ uint64_t name_len;
+ const char *name;
+ uint64_t value_len;
+ const char *value;
+ };
+
+ struct gstream_spec {
+ uint64_t parent_handle;
+ uint64_t child_handle;
+ };
+
+ struct psi_spec {
+ uint64_t path_len;
+ const char *path;
+ uint64_t env_var_count;
+ const env_var_spec *env_vars;
+ uint64_t gstream_count;
+ const gstream_spec *gstreams;
+ };
+
void start_process_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
- //TODO
- (void)rax;
- (void)rdi;
- (void)rsi;
- (void)rdx;
- panic(0x9af5e6);
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
+
+ const psi_spec *psi = (const psi_spec *)rdi;
+ set_zero(rax, rdi, rsi, rdx);
+
+ auto *owner = application::running_thread->owner;
+
+ if (!owner->memory->valid_to_read(psi, psi + 1, false) ||
+ !owner->memory->valid_to_read(
+ psi->path, psi->path + psi->path_len, false) ||
+ !owner->memory->valid_to_read(
+ psi->env_vars, psi->env_vars + psi->env_var_count, false) ||
+ !owner->memory->valid_to_read(
+ psi->gstreams, psi->gstreams + psi->gstream_count, false))
+ return;
+
+ for (uint64_t i = 0; i < psi->env_var_count; ++i)
+ if (!owner->memory->valid_to_read(psi->env_vars[i].name,
+ psi->env_vars[i].name + psi->env_vars[i].name_len, false) ||
+ !owner->memory->valid_to_read(psi->env_vars[i].value,
+ psi->env_vars[i].value + psi->env_vars[i].value_len, false))
+ return;
+
+ for (uint64_t i = 0; i < psi->gstream_count; ++i) {
+ auto owner_stream = owner->get_stream(psi->gstreams[i].parent_handle);
+ if (owner_stream.is_null() || (owner_stream.is_socket &&
+ owner_stream.as_socket_stream->waiting_to_read.count != 0) ||
+ psi->gstreams[i].child_handle >= 65536)
+ return;
+ }
+
+ utility::string path_string(psi->path, psi->path_len);
+ vfile::canon_path cpath;
+ vfile::canonize_path(path_string, cpath);
+
+ vfile::vfile file;
+ auto lookup_result = vfile::look_up_path(cpath, file, true);
+ switch (lookup_result) {
+ case storage::fs_result::does_not_exist:
+ rax = (uint64_t)application::stream_result::does_not_exist;
+ return;
+ case storage::fs_result::device_error:
+ case storage::fs_result::fs_corrupt:
+ rax = (uint64_t)application::stream_result::io_error;
+ return;
+ case storage::fs_result::success:
+ break;
+ }
+
+ app_memory *memory = new app_memory();
+ uint64_t entry_point;
+ load_app_result load_result = load_app(file, *memory, entry_point);
+
+ switch (load_result) {
+ case load_app_result::io_error:
+ rax = (uint64_t)application::stream_result::io_error;
+ delete memory;
+ return;
+ case load_app_result::not_app:
+ rax = (uint64_t)application::stream_result::not_an_executable;
+ delete memory;
+ return;
+ case load_app_result::success:
+ break;
+ }
+
+ application::process *p = new application::process(memory);
+
+ for (uint64_t i = 0; i < psi->env_var_count; ++i)
+ p->add_environment_variable(
+ utility::string(psi->env_vars[i].name, psi->env_vars[i].name_len),
+ utility::string(psi->env_vars[i].value, psi->env_vars[i].value_len));
+
+ for (uint64_t i = 0; i < psi->gstream_count; ++i) {
+ auto s = owner->take_stream(psi->gstreams[i].parent_handle);
+ if (s.is_socket && s.as_socket_stream->is_other_side_open)
+ s.as_socket_stream->other_end->other_process = p;
+ p->add_stream_with_handle(psi->gstreams[i].child_handle, s);
+ }
+
+ rax = (uint64_t)application::stream_result::success;
+ rdi = application::add_process(p);
+ application::thread *t = new application::thread(p, entry_point);
+ p->add_thread(t);
+ application::paused_threads->insert(t);
+
}
void end_this_process_syscall(
- uint64_t &, uint64_t &rdi, uint64_t &, uint64_t &
- ) {
- application::running_thread->the_process->end_process((unsigned)rdi);
- application::resume_next();
+ uint64_t &, uint64_t &rdi, uint64_t &, uint64_t &) {
+
+ int exit_code = (int32_t)(uint32_t)rdi;
+ auto *p = application::running_thread->owner;
+ p->on_end_process(exit_code);
+ application::resume_next_thread();
+
}
void set_stream_length_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
- ) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
unsigned handle = (unsigned)rdi;
- uint64_t new_length = rsi;
set_zero(rax, rdi, rsi, rdx);
- auto *p = application::running_thread->the_process;
+ auto *t = application::running_thread;
- if (!p->open_streams.has_id(handle)) {
+ auto stream = t->owner->get_stream(handle);
+
+ if (stream.is_null())
rax = (uint64_t)application::stream_result::bad_handle;
- return;
+
+ else if (stream.is_socket)
+ rax = (uint64_t)application::stream_result::not_sized;
+
+ else {
+ //TODO
+ panic(0x9af5e6);
}
- rax = (uint64_t)p->open_streams.get(handle)->set_length(new_length);
+ }
+
+ void get_other_end_process_handle_syscall(
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
+
+ unsigned handle = (unsigned)rdi;
+ set_zero(rax, rdi, rsi, rdx);
+
+ auto *t = application::running_thread;
+
+ auto stream = t->owner->get_stream(handle);
+
+ if (stream.is_null())
+ rax = (uint64_t)application::stream_result::bad_handle;
+
+ else if (!stream.is_socket)
+ rax = (uint64_t)application::stream_result::other_end_closed;
+
+ else {
+ auto s = stream.as_socket_stream;
+ if (!s->is_other_side_open)
+ rax = (uint64_t)application::stream_result::other_end_closed;
+ else {
+ rax = (uint64_t)application::stream_result::success;
+ rdi = (uint64_t)s->other_process->id;
+ }
+ }
}
@@ -526,7 +722,8 @@ namespace hilbert::kernel::syscall {
&get_stream_length_syscall,
&start_process_syscall,
&end_this_process_syscall,
- &set_stream_length_syscall
+ &set_stream_length_syscall,
+ &get_other_end_process_handle_syscall
};
static constexpr int max_syscall_number = 19;
@@ -536,8 +733,7 @@ namespace hilbert::kernel::syscall {
using namespace hilbert::kernel::syscall;
extern "C" void do_syscall(
- uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
-) {
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
if (rax <= max_syscall_number && handlers[rax] != 0)
handlers[rax](rax, rdi, rsi, rdx);