diff options
author | Benji Dial <benji@benjidial.net> | 2024-05-20 17:40:47 -0400 |
---|---|---|
committer | Benji Dial <benji@benjidial.net> | 2024-05-20 17:40:47 -0400 |
commit | 9af5588c30c4126a2800aae1afcb0de2c373dc6c (patch) | |
tree | d2a48a97b1664f958b5f88a8b0c03ef8366b0f49 /kernel/source/syscall.cpp | |
parent | 5a54df93c4e9368c36e69d1e9c88cd2904e92308 (diff) | |
download | hilbert-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.cpp | 682 |
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); |