summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--applications/goldman/makefile2
-rw-r--r--applications/goldman/source/input.cpp21
-rw-r--r--applications/goldman/source/input.hpp3
-rw-r--r--applications/goldman/source/main.cpp84
-rw-r--r--applications/goldman/source/main.hpp5
-rw-r--r--applications/goldman/source/renderer.cpp102
-rw-r--r--applications/goldman/source/renderer.hpp61
-rw-r--r--applications/goldman/source/socket.cpp162
-rw-r--r--applications/goldman/source/socket.hpp5
-rw-r--r--applications/goldman/source/window.hpp14
-rw-r--r--applications/hello/makefile12
-rw-r--r--applications/hello/source/main.cpp37
-rw-r--r--documentation/compositor.txt15
-rw-r--r--documentation/kernel-interfaces/syscalls.txt5
-rw-r--r--euler/include/euler/syscall.hpp33
-rw-r--r--euler/include/list3
-rw-r--r--euler/include/mutex4
-rw-r--r--euler/include/std/allocator.hpp2
-rw-r--r--euler/include/std/fwd/allocator.hpp6
-rw-r--r--euler/include/std/fwd/string.hpp5
-rw-r--r--euler/include/std/fwd/vector.hpp8
-rw-r--r--euler/include/std/list.hpp157
-rw-r--r--euler/include/std/mutex.hpp40
-rw-r--r--euler/include/std/string.hpp7
-rw-r--r--euler/include/std/unique_lock.hpp53
-rw-r--r--euler/include/std/vector.hpp4
-rw-r--r--euler/source/entry.cpp2
-rw-r--r--euler/source/std/cstdio.cpp1
-rw-r--r--euler/source/std/string.cpp6
-rw-r--r--euler/source/stream.cpp1
-rw-r--r--euler/source/syscall.cpp13
-rw-r--r--kernel/include/hilbert/kernel/application.hpp9
-rw-r--r--kernel/include/hilbert/kernel/serial.hpp6
-rw-r--r--kernel/include/hilbert/kernel/utility.hpp15
-rw-r--r--kernel/source/application.cpp15
-rw-r--r--kernel/source/entry.cpp3
-rw-r--r--kernel/source/interrupts.cpp5
-rw-r--r--kernel/source/syscall.cpp78
-rw-r--r--libraries/daguerre/include/daguerre/impl/fixed-font.hpp4
-rw-r--r--libraries/daguerre/include/daguerre/impl/image.hpp2
-rw-r--r--libraries/goldman/include/goldman/protocol.hpp85
-rw-r--r--makefile17
-rw-r--r--qemu.gdb1
-rw-r--r--readme.txt5
44 files changed, 1018 insertions, 100 deletions
diff --git a/applications/goldman/makefile b/applications/goldman/makefile
index 56f633d..c6de0e7 100644
--- a/applications/goldman/makefile
+++ b/applications/goldman/makefile
@@ -1,5 +1,5 @@
SOURCES = \
- main.cpp
+ main.cpp renderer.cpp input.cpp socket.cpp
build/%.cpp.o: source/%.cpp
@mkdir -p $(@D)
diff --git a/applications/goldman/source/input.cpp b/applications/goldman/source/input.cpp
new file mode 100644
index 0000000..0cd6922
--- /dev/null
+++ b/applications/goldman/source/input.cpp
@@ -0,0 +1,21 @@
+#include "input.hpp"
+#include "main.hpp"
+
+[[noreturn]] void input_thread_main() {
+
+ euler::syscall::set_thread_name("input thread");
+
+ while (true) {
+
+ auto result = euler::syscall::get_input_packet();
+ if (std::holds_alternative<euler::syscall::mouse_packet>(result)) {
+ auto packet = std::get<euler::syscall::mouse_packet>(result);
+ r->lock();
+ r->bump_cursor(packet.x_changed, packet.y_changed);
+ r->unlock();
+ r->dispatch_render();
+ }
+
+ }
+
+}
diff --git a/applications/goldman/source/input.hpp b/applications/goldman/source/input.hpp
new file mode 100644
index 0000000..108cdad
--- /dev/null
+++ b/applications/goldman/source/input.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+[[noreturn]] void input_thread_main();
diff --git a/applications/goldman/source/main.cpp b/applications/goldman/source/main.cpp
index d74eaad..475129f 100644
--- a/applications/goldman/source/main.cpp
+++ b/applications/goldman/source/main.cpp
@@ -1,79 +1,37 @@
#include <daguerre/framebuffer.hpp>
#include <daguerre/ppm.hpp>
+#include "renderer.hpp"
+#include "socket.hpp"
+#include "input.hpp"
+#include "main.hpp"
-daguerre::hilbert_color trans_color;
+//TODO: handle errors
-void convert_pointer(
- daguerre::hilbert_color &dest, const daguerre::hilbert_color &src) {
- if (src != trans_color)
- dest = src;
-}
+renderer *r;
int main(int, char **) {
- trans_color = euler::syscall::encode_color(0xff, 0x00, 0xff);
-
- daguerre::image<daguerre::hilbert_color> framebuffer =
- daguerre::get_hilbert_framebuffer();
-
- int fw = framebuffer.width;
- int fh = framebuffer.height;
-
- daguerre::image<daguerre::hilbert_color> double_buffer(fw, fh);
+ euler::syscall::listener_handle listener;
+ euler::syscall::create_socket_listener("hilbert.compositor", listener);
- std::optional<daguerre::image<daguerre::hilbert_color>>
- background_original = daguerre::try_load_ppm("/assets/background.ppm");
-
- daguerre::image<daguerre::hilbert_color> background;
-
- if (background_original.has_value())
- background = background_original->stretch(fw, fh);
- else {
- background = daguerre::image<daguerre::hilbert_color>(fw, fh);
- background.fill(euler::syscall::encode_color(0, 0, 0));
- }
+ r = new renderer(
+ daguerre::get_hilbert_framebuffer(),
+ *daguerre::try_load_ppm("/assets/background.ppm"),
+ euler::syscall::encode_color(0x00, 0x00, 0x00),
+ *daguerre::try_load_ppm("/assets/pointer.ppm"),
+ euler::syscall::encode_color(0xff, 0x00, 0xff));
- std::optional<daguerre::image<daguerre::hilbert_color>>
- pointer_original = daguerre::try_load_ppm("/assets/pointer.ppm");
+ euler::syscall::start_thread([]() { r->render_thread_main(); });
+ euler::syscall::start_thread(input_thread_main);
- if (!pointer_original.has_value())
- //TODO
- while (1)
- ;
+ r->dispatch_render();
- daguerre::image<daguerre::hilbert_color>
- pointer = std::move(*pointer_original);
-
- int mouse_x = fw / 2;
- int mouse_y = fh / 2;
+ euler::syscall::set_thread_name("socket listener thread");
while (true) {
-
- double_buffer.copy_from(background, 0, 0);
- double_buffer.convert_from(pointer, mouse_x, mouse_y, 0, 0,
- std::min(pointer. width, double_buffer. width - mouse_x),
- std::min(pointer.height, double_buffer.height - mouse_y),
- &convert_pointer);
-
- framebuffer.copy_from(double_buffer, 0, 0);
-
- auto result = euler::syscall::get_input_packet();
- if (std::holds_alternative<euler::syscall::mouse_packet>(result)) {
- const auto &packet = std::get<euler::syscall::mouse_packet>(result);
- mouse_x += packet.x_changed;
- mouse_y += packet.y_changed;
- if (mouse_x < 0)
- mouse_x = 0;
- else if (mouse_x >= fw)
- mouse_x = fw - 1;
- if (mouse_y < 0)
- mouse_y = 0;
- else if (mouse_y >= fh)
- mouse_y = fh - 1;
- }
-
+ euler::syscall::stream_handle socket;
+ euler::syscall::accept_socket_connection(listener, socket);
+ euler::syscall::start_thread(socket_thread_main, socket);
}
- return 0;
-
}
diff --git a/applications/goldman/source/main.hpp b/applications/goldman/source/main.hpp
new file mode 100644
index 0000000..57de676
--- /dev/null
+++ b/applications/goldman/source/main.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "renderer.hpp"
+
+extern renderer *r;
diff --git a/applications/goldman/source/renderer.cpp b/applications/goldman/source/renderer.cpp
new file mode 100644
index 0000000..629c375
--- /dev/null
+++ b/applications/goldman/source/renderer.cpp
@@ -0,0 +1,102 @@
+#include "renderer.hpp"
+
+renderer::renderer(
+ daguerre::image<daguerre::hilbert_color> &&fb,
+ daguerre::image<daguerre::hilbert_color> &&bg,
+ daguerre::hilbert_color bgc,
+ daguerre::image<daguerre::hilbert_color> &&c,
+ daguerre::hilbert_color cbg)
+
+: framebuffer(std::move(fb)),
+ double_buffer(framebuffer.width, framebuffer.height),
+ background(std::move(bg)), cursor(std::move(c)), cursor_background(cbg),
+ cursor_x(framebuffer.width / 2), cursor_y(framebuffer.height / 2) {
+
+ euler::syscall::create_private_socket(dispatcher_handle_1, dispatcher_handle_2);
+
+ if (background.width != framebuffer.width ||
+ background.height != framebuffer.height) {
+
+ daguerre::image<daguerre::hilbert_color>
+ new_background(framebuffer.width, framebuffer.height);
+
+ new_background.fill(bgc);
+
+ int from_x = 0;
+ int from_y = 0;
+ int to_x = framebuffer.width / 2 - background.width / 2;
+ int to_y = framebuffer.height / 2 - background.height / 2;
+ int width = background.width;
+ int height = background.height;
+
+ daguerre::make_safe(to_x, from_x, width, 0, framebuffer.width);
+ daguerre::make_safe(to_y, from_y, height, 0, framebuffer.height);
+
+ new_background.copy_from(background, to_x, to_y, from_x, from_y, width, height);
+ background = std::move(new_background);
+
+ }
+
+}
+
+template <class color_t>
+void overlay_trans(color_t &to, const color_t &from, const color_t &param) {
+ if (from != param)
+ to = from;
+}
+
+void renderer::do_render() {
+
+ double_buffer.copy_from(background, 0, 0);
+
+ for (auto it = windows.begin(); it != windows.end(); ++it)
+
+ double_buffer.copy_from(
+ (*it)->contents, (*it)->x, (*it)->y, 0, 0,
+ std::min((*it)->contents.width, double_buffer.width - (*it)->x),
+ std::min((*it)->contents.height, double_buffer.height - (*it)->y));
+
+ double_buffer.convert_from(
+ cursor_background, cursor, cursor_x, cursor_y, 0, 0,
+ std::min(cursor.width, framebuffer.width - cursor_x),
+ std::min(cursor.height, framebuffer.height - cursor_y),
+ &overlay_trans);
+
+}
+
+[[noreturn]] void renderer::render_thread_main() {
+ euler::syscall::set_thread_name("render thread");
+ while (true) {
+ uint8_t byte;
+ euler::syscall::read_from_stream(dispatcher_handle_2, 1, &byte);
+ mut.lock();
+ euler::syscall::clear_socket_read_queue(dispatcher_handle_2);
+ do_render();
+ mut.unlock();
+ framebuffer.copy_from(double_buffer, 0, 0);
+ }
+}
+
+void renderer::bump_cursor(int x_offset, int y_offset) {
+
+ cursor_x += x_offset;
+ if (cursor_x < 0)
+ cursor_x = 0;
+ else if (cursor_x >= framebuffer.width)
+ cursor_x = framebuffer.width - 1;
+
+ cursor_y += y_offset;
+ if (cursor_y < 0)
+ cursor_y = 0;
+ else if (cursor_y >= framebuffer.height)
+ cursor_y = framebuffer.height - 1;
+
+}
+
+void renderer::add_window(const window *w) {
+ windows.push_back(w);
+}
+
+void renderer::remove_window(const window *w) {
+ windows.remove(w);
+}
diff --git a/applications/goldman/source/renderer.hpp b/applications/goldman/source/renderer.hpp
new file mode 100644
index 0000000..14a5964
--- /dev/null
+++ b/applications/goldman/source/renderer.hpp
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <daguerre/image.hpp>
+#include "window.hpp"
+#include <mutex>
+#include <list>
+
+class renderer {
+
+ daguerre::image<daguerre::hilbert_color> framebuffer;
+ daguerre::image<daguerre::hilbert_color> double_buffer;
+
+ daguerre::image<daguerre::hilbert_color> background;
+ daguerre::image<daguerre::hilbert_color> cursor;
+ daguerre::hilbert_color cursor_background;
+
+ int cursor_x;
+ int cursor_y;
+
+ //bottom to top
+ std::list<const window *> windows;
+
+ std::mutex mut;
+
+ euler::syscall::stream_handle
+ dispatcher_handle_1, dispatcher_handle_2;
+
+ void do_render();
+
+public:
+ renderer(
+ daguerre::image<daguerre::hilbert_color> &&framebuffer,
+ daguerre::image<daguerre::hilbert_color> &&background,
+ daguerre::hilbert_color background_color,
+ daguerre::image<daguerre::hilbert_color> &&cursor,
+ daguerre::hilbert_color cursor_background);
+
+ inline ~renderer() {
+ euler::syscall::close_stream(dispatcher_handle_1);
+ euler::syscall::close_stream(dispatcher_handle_2);
+ }
+
+ renderer(const renderer &) = delete;
+ renderer &operator =(const renderer &) = delete;
+
+ [[noreturn]] void render_thread_main();
+
+ inline void lock() { mut.lock(); }
+ inline void unlock() { mut.unlock(); }
+
+ inline void dispatch_render() {
+ uint8_t byte = 0;
+ euler::syscall::write_to_stream(dispatcher_handle_1, 1, &byte);
+ }
+
+ void bump_cursor(int x_offset, int y_offset);
+
+ void add_window(const window *w);
+ void remove_window(const window *w);
+
+};
diff --git a/applications/goldman/source/socket.cpp b/applications/goldman/source/socket.cpp
new file mode 100644
index 0000000..b175fe9
--- /dev/null
+++ b/applications/goldman/source/socket.cpp
@@ -0,0 +1,162 @@
+#include <daguerre/image.hpp>
+#include "socket.hpp"
+#include "window.hpp"
+#include "main.hpp"
+#include <memory>
+#include <vector>
+
+struct socket_state {
+
+ euler::syscall::stream_handle socket;
+ std::vector<window *> windows;
+ daguerre::hilbert_color window_bg = euler::syscall::encode_color(0, 0, 0);
+
+ bool try_open_window() {
+
+ struct [[gnu::packed]] {
+ uint32_t width;
+ uint32_t height;
+ } body;
+
+ if (euler::syscall::read_from_stream(socket, sizeof(body), &body) !=
+ euler::syscall::stream_result::success)
+ return false;
+
+ window *w = new window(body.width, body.height);
+ w->contents.fill(window_bg);
+
+ uint16_t wid = 0;
+
+ while (wid < windows.size())
+ if (windows[wid] != 0)
+ ++wid;
+ else
+ break;
+
+ if (wid == windows.size())
+ windows.push_back(w);
+ else
+ windows[wid] = w;
+
+ r->lock();
+ r->add_window(w);
+ r->unlock();
+
+ struct [[gnu::packed]] {
+ uint8_t type;
+ uint16_t the_window;
+ } response {
+ .type = 0x00,
+ .the_window = wid
+ };
+
+ return
+ euler::syscall::write_to_stream(socket, sizeof(response), &response) ==
+ euler::syscall::stream_result::success;
+
+ }
+
+ bool try_update_window_region() {
+
+ struct [[gnu::packed]] {
+ uint16_t window;
+ uint32_t start_x;
+ uint32_t start_y;
+ uint32_t width;
+ uint32_t height;
+ } body_head;
+
+ if (euler::syscall::read_from_stream(socket, sizeof(body_head), &body_head) !=
+ euler::syscall::stream_result::success)
+ return false;
+
+ std::vector<daguerre::hilbert_color> data(body_head.width * body_head.height);
+
+ if (euler::syscall::read_from_stream(socket, data.size() * 4, data.data()) !=
+ euler::syscall::stream_result::success)
+ return false;
+
+ daguerre::image<daguerre::hilbert_color>
+ data_as_image(body_head.width, body_head.height, data.data(), body_head.width, false);
+
+ if (body_head.window >= windows.size() || !windows[body_head.window])
+ return false;
+
+ window *w = windows[body_head.window];
+
+ r->lock();
+
+ if ((int)body_head.start_x + data_as_image.width > w->contents.width ||
+ (int)body_head.start_y + data_as_image.height > w->contents.height) {
+ r->unlock();
+ return false;
+ }
+
+ w->contents.copy_from(data_as_image, body_head.start_x, body_head.start_y);
+
+ r->unlock();
+ r->dispatch_render();
+ return true;
+
+ }
+
+ bool try_close_window() {
+
+ uint16_t wid;
+
+ if (euler::syscall::read_from_stream(socket, 2, &wid) !=
+ euler::syscall::stream_result::success)
+ return false;
+
+ if (wid >= windows.size() || !windows[wid])
+ return false;
+
+ r->lock();
+
+ r->remove_window(windows[wid]);
+ windows[wid] = 0;
+
+ r->unlock();
+ r->dispatch_render();
+ return true;
+
+ }
+
+ bool try_process_request() {
+
+ uint8_t type;
+ if (euler::syscall::read_from_stream(socket, 1, &type) !=
+ euler::syscall::stream_result::success)
+ return false;
+
+ switch (type) {
+ case 0x00: return try_open_window();
+ case 0x01: return try_update_window_region();
+ case 0x02: return try_close_window();
+ default: return false;
+ }
+
+ }
+
+};
+
+[[noreturn]] void socket_thread_main(euler::syscall::stream_handle socket) {
+
+ euler::syscall::set_thread_name("socket thread");
+
+ socket_state *state = new socket_state {
+ .socket = socket, .windows = {} };
+ while (state->try_process_request()) ;
+
+ r->lock();
+ for (unsigned i = 0; i < state->windows.size(); ++i) {
+ r->remove_window(state->windows[i]);
+ delete state->windows[i];
+ }
+ r->unlock();
+
+ delete state;
+ euler::syscall::close_stream(socket);
+ euler::syscall::end_this_thread(0);
+
+}
diff --git a/applications/goldman/source/socket.hpp b/applications/goldman/source/socket.hpp
new file mode 100644
index 0000000..a9dbeb2
--- /dev/null
+++ b/applications/goldman/source/socket.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include <euler/syscall.hpp>
+
+[[noreturn]] void socket_thread_main(euler::syscall::stream_handle socket);
diff --git a/applications/goldman/source/window.hpp b/applications/goldman/source/window.hpp
new file mode 100644
index 0000000..008af2f
--- /dev/null
+++ b/applications/goldman/source/window.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <daguerre/image.hpp>
+
+struct window {
+
+ daguerre::image<daguerre::hilbert_color> contents;
+
+ int x;
+ int y;
+
+ window(int width, int height) : contents(width, height), x(0), y(0) {}
+
+};
diff --git a/applications/hello/makefile b/applications/hello/makefile
new file mode 100644
index 0000000..5e12644
--- /dev/null
+++ b/applications/hello/makefile
@@ -0,0 +1,12 @@
+SOURCES = \
+ main.cpp
+
+build/%.cpp.o: source/%.cpp
+ @mkdir -p $(@D)
+ $(HILBERT_CC) -c $^ -o $@
+
+build/hello.elf: $(SOURCES:%=build/%.o)
+ $(HILBERT_CC) $^ -ldaguerre -o $@
+
+clean:
+ rm -rf build
diff --git a/applications/hello/source/main.cpp b/applications/hello/source/main.cpp
new file mode 100644
index 0000000..3f132c6
--- /dev/null
+++ b/applications/hello/source/main.cpp
@@ -0,0 +1,37 @@
+#include <goldman/protocol.hpp>
+#include <daguerre/psf.hpp>
+
+template <class color_t>
+void overlay(color_t &to, const bool &from, const color_t &param) {
+ if (from)
+ to = param;
+}
+
+int main(int, char **) {
+
+ auto bg = euler::syscall::encode_color(0xaa, 0xaa, 0xaa);
+ auto fg = euler::syscall::encode_color(0x00, 0x00, 0x00);
+
+ daguerre::image<daguerre::hilbert_color> image(300, 200);
+ image.fill(bg);
+
+ auto font = daguerre::try_load_psf("/assets/terminus-bold-18x10.psf");
+ image.render_text(*font, fg, 10, 10, "Hello, world!", &overlay);
+
+ euler::syscall::stream_handle s;
+ euler::syscall::connect_to_socket("hilbert.compositor", s);
+
+ goldman::protocol::send_open_window(s, 300, 200);
+
+ uint8_t byte;
+ euler::syscall::read_from_stream(s, 1, &byte);
+
+ auto w = goldman::protocol::get_window_opened_body(s);
+
+ goldman::protocol::send_update_window_region(
+ s, w, 0, 0, 300, 200, image.buffer, image.buffer_pitch);
+
+ euler::syscall::read_from_stream(s, 1, &byte);
+ __builtin_unreachable();
+
+}
diff --git a/documentation/compositor.txt b/documentation/compositor.txt
index 4d8e70f..38bd482 100644
--- a/documentation/compositor.txt
+++ b/documentation/compositor.txt
@@ -1,11 +1,11 @@
compositors listen on the socket id "hilbert.compositor".
when a window is opened by an application, that window can only be referred to
-on that stream. the opaque value given in the "window opened" message refers to
-that window in future messages on that stream. it is guaranteed to be distinct
-for different windows on the same stream, and in no way guaranteed to be
-distinct for different windows on different streams. the window is bound
-just to the stream, not to the application. if the stream where a window
+on that socket. the opaque value given in the "window opened" message refers to
+that window in future messages on that socket. it is guaranteed to be distinct
+for different windows on the same socket, and in no way guaranteed to be
+distinct for different windows on different sockets. the window is bound
+just to the socket, not to the application. if the socket where a window
was created is gifted to a new process, the new process has complete control
over the window, and the compositor does not need to be informed.
@@ -37,8 +37,13 @@ messages from applications to compositor:
dword: height
color rectangle: the data
+ close window:
+ byte: 0x02
+ window: the window
+
messages from compositor to application:
window opened:
byte: 0x00
window: the window
+ these come in the order the open window requests were received
diff --git a/documentation/kernel-interfaces/syscalls.txt b/documentation/kernel-interfaces/syscalls.txt
index 399eb19..933ad34 100644
--- a/documentation/kernel-interfaces/syscalls.txt
+++ b/documentation/kernel-interfaces/syscalls.txt
@@ -198,3 +198,8 @@ get environment variable value:
rdi in: pointer to variable name
rsi in: variable name length
rdx in: pointer to buffer for variable value
+
+set thread name:
+ rax in: 24
+ rdi in: pointer to thread name
+ rsi in: thread name length
diff --git a/euler/include/euler/syscall.hpp b/euler/include/euler/syscall.hpp
index 64456ae..4a3daa4 100644
--- a/euler/include/euler/syscall.hpp
+++ b/euler/include/euler/syscall.hpp
@@ -1,11 +1,11 @@
#pragma once
+#include <std/fwd/string.hpp>
+#include <std/fwd/vector.hpp>
#include <optional>
#include <cstdint>
#include <utility>
#include <variant>
-#include <string>
-#include <vector>
namespace euler::syscall {
@@ -125,6 +125,30 @@ namespace euler::syscall {
void start_thread(void (*entry_point)(uint64_t), uint64_t arg);
//entry_point must not return
+ template <class obj_t>
+ void start_thread(void (*entry_point)(obj_t *), obj_t *arg) {
+ start_thread((void (*)(uint64_t))entry_point, (uint64_t)arg);
+ }
+
+ //entry_point must not return
+ template <class obj_t>
+ void start_thread(void (*entry_point)(const obj_t *), const obj_t *arg) {
+ start_thread((void (*)(uint64_t))entry_point, (uint64_t)arg);
+ }
+
+ //entry_point must not return
+ template <class obj_t>
+ void start_thread(void (*entry_point)(obj_t &), obj_t &arg) {
+ start_thread((void (*)(uint64_t))entry_point, (uint64_t)&arg);
+ }
+
+ //entry_point must not return
+ template <class obj_t>
+ void start_thread(void (*entry_point)(const obj_t &), const obj_t &arg) {
+ start_thread((void (*)(uint64_t))entry_point, (uint64_t)&arg);
+ }
+
+ //entry_point must not return
void start_thread(void (*entry_point)());
//return value is number of bytes cleared
@@ -133,4 +157,9 @@ namespace euler::syscall {
std::optional<std::string> try_get_environment_variable(
const std::string &name);
+ void set_thread_name(const std::string &name);
+
}
+
+#include <string>
+#include <vector>
diff --git a/euler/include/list b/euler/include/list
new file mode 100644
index 0000000..51eb3ba
--- /dev/null
+++ b/euler/include/list
@@ -0,0 +1,3 @@
+#pragma once
+
+#include <std/list.hpp>
diff --git a/euler/include/mutex b/euler/include/mutex
new file mode 100644
index 0000000..7a03381
--- /dev/null
+++ b/euler/include/mutex
@@ -0,0 +1,4 @@
+#pragma once
+
+#include <std/unique_lock.hpp>
+#include <std/mutex.hpp>
diff --git a/euler/include/std/allocator.hpp b/euler/include/std/allocator.hpp
index 32ba005..e76feb9 100644
--- a/euler/include/std/allocator.hpp
+++ b/euler/include/std/allocator.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include <std/fwd/allocator.hpp>
+
#include <euler/heap.hpp>
namespace std {
diff --git a/euler/include/std/fwd/allocator.hpp b/euler/include/std/fwd/allocator.hpp
new file mode 100644
index 0000000..18e14a8
--- /dev/null
+++ b/euler/include/std/fwd/allocator.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+namespace std {
+ template <class T>
+ struct allocator;
+}
diff --git a/euler/include/std/fwd/string.hpp b/euler/include/std/fwd/string.hpp
new file mode 100644
index 0000000..5e46abf
--- /dev/null
+++ b/euler/include/std/fwd/string.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+namespace std {
+ class string;
+}
diff --git a/euler/include/std/fwd/vector.hpp b/euler/include/std/fwd/vector.hpp
new file mode 100644
index 0000000..fd8fe15
--- /dev/null
+++ b/euler/include/std/fwd/vector.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include <std/fwd/allocator.hpp>
+
+namespace std {
+ template <class T, class Allocator = std::allocator<T>>
+ class vector;
+}
diff --git a/euler/include/std/list.hpp b/euler/include/std/list.hpp
new file mode 100644
index 0000000..77eaaec
--- /dev/null
+++ b/euler/include/std/list.hpp
@@ -0,0 +1,157 @@
+#pragma once
+
+#include <memory>
+
+namespace std {
+
+ template <class T, class Allocator = std::allocator<T>>
+ class list {
+
+ public:
+ struct node {
+ T value;
+ node *prev;
+ node *next;
+ };
+
+ template <class V>
+ struct generic_iterator {
+
+ node *the_node;
+
+ bool operator ==(const generic_iterator &other) {
+ return the_node == other.the_node;
+ }
+
+ bool operator !=(const generic_iterator &other) {
+ return the_node != other.the_node;
+ }
+
+ V &operator *() {
+ return the_node->value;
+ }
+
+ V *operator ->() {
+ return &the_node->value;
+ }
+
+ generic_iterator &operator ++() {
+ the_node = the_node->next;
+ return *this;
+ }
+
+ };
+
+ using iterator = generic_iterator<T>;
+ using const_iterator = generic_iterator<const T>;
+
+ private:
+ node *first_node;
+ node *last_node;
+ size_t count;
+
+ public:
+ void push_back(const T &value) {
+ node *n = new node { .value = value,
+ .prev = last_node, .next = 0 };
+ if (last_node) last_node->next = n;
+ else first_node = n;
+ last_node = n;
+ ++count;
+ }
+
+ void push_back(T &&value) {
+ node *n = new node {
+ .value = std::move(value),
+ .prev = last_node, .next = 0 };
+ if (last_node) last_node->next = n;
+ else first_node = n;
+ last_node = n;
+ ++count;
+ }
+
+ iterator erase(iterator pos) {
+ --count;
+ auto *n = pos.the_node;
+ auto *r = n->next;
+ if (n->prev) n->prev->next = n->next;
+ else first_node = n->next;
+ if (n->next) n->next->prev = n->prev;
+ else last_node = n->prev;
+ delete n;
+ return iterator { .the_node = r };
+ }
+
+ iterator begin() const noexcept {
+ return iterator { .the_node = first_node };
+ }
+
+ iterator end() const noexcept {
+ return iterator { .the_node = 0 };
+ }
+
+ size_t remove(const T &value) {
+ size_t removed = 0;
+ auto it = begin();
+ while (it != end())
+ if (*it == value) {
+ it = erase(it);
+ ++removed;
+ }
+ else
+ ++it;
+ count -= removed;
+ return removed;
+ }
+
+ list() : first_node(0), last_node(0), count(0) {}
+
+ list(const list &other) : first_node(0), last_node(0), count(0) {
+ for (node *n = other.first_node; n; n = n->next)
+ push_back(n->value);
+ }
+
+ list(list &&other) : first_node(other.first_node),
+ last_node(other.last_node), count(other.count) {
+ other.first_node = 0;
+ other.last_node = 0;
+ other.count = 0;
+ }
+
+ void clear() {
+
+ if (count == 0) return;
+
+ for (node *n = first_node->next; n; n = n->next)
+ delete n->prev;
+ delete last_node;
+
+ first_node = 0;
+ last_node = 0;
+ count = 0;
+
+ }
+
+ ~list() {
+ clear();
+ }
+
+ list &operator =(const list &other) {
+ clear();
+ for (node *n = other.first_node; n; n = n->next)
+ push_back(n->value);
+ }
+
+ list &operator =(list &&other) {
+ clear();
+ first_node = other.first_node;
+ last_node = other.last_node;
+ count = other.count;
+ other.first_node = 0;
+ other.last_node = 0;
+ other.count = 0;
+ }
+
+ };
+
+}
diff --git a/euler/include/std/mutex.hpp b/euler/include/std/mutex.hpp
new file mode 100644
index 0000000..0a27877
--- /dev/null
+++ b/euler/include/std/mutex.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <euler/syscall.hpp>
+
+namespace std {
+
+ class mutex {
+
+ euler::syscall::stream_handle in_handle;
+ euler::syscall::stream_handle out_handle;
+
+ public:
+ inline mutex() noexcept {
+ euler::syscall::create_private_socket(in_handle, out_handle);
+ uint8_t byte = 0;
+ euler::syscall::write_to_stream(in_handle, 1, &byte);
+ }
+
+ mutex(const mutex &) = delete;
+
+ inline ~mutex() {
+ euler::syscall::close_stream(in_handle);
+ euler::syscall::close_stream(out_handle);
+ }
+
+ mutex &operator =(const mutex &) = delete;
+
+ inline void lock() {
+ uint8_t byte;
+ euler::syscall::read_from_stream(out_handle, 1, &byte);
+ }
+
+ inline void unlock() {
+ uint8_t byte = 0;
+ euler::syscall::write_to_stream(in_handle, 1, &byte);
+ }
+
+ };
+
+}
diff --git a/euler/include/std/string.hpp b/euler/include/std/string.hpp
index 7ccdbc2..505ee69 100644
--- a/euler/include/std/string.hpp
+++ b/euler/include/std/string.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include <std/fwd/string.hpp>
+
#include <cstddef>
#include <vector>
@@ -16,9 +18,7 @@ namespace std {
: characters(other.characters) {}
constexpr string(string &&other) noexcept
- : characters(std::move(other.characters)) {
- other.characters.push_back('\0');
- }
+ : characters(std::move(other.characters)) {}
constexpr string(const char *s) {
size_t count = 0;
@@ -38,7 +38,6 @@ namespace std {
constexpr string &operator =(string &&str) noexcept {
characters = std::move(str.characters);
- str.characters.push_back('\0');
return *this;
}
diff --git a/euler/include/std/unique_lock.hpp b/euler/include/std/unique_lock.hpp
new file mode 100644
index 0000000..14b3645
--- /dev/null
+++ b/euler/include/std/unique_lock.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+namespace std {
+
+ template <class Mutex>
+ class unique_lock {
+
+ Mutex *the_mutex;
+ bool has_locked;
+
+ public:
+ inline unique_lock() noexcept : the_mutex(0) {}
+
+ unique_lock(const unique_lock &other) = delete;
+
+ inline unique_lock(unique_lock &&other) noexcept
+ : the_mutex(other.the_mutex), has_locked(other.has_locked) {
+ other.the_mutex = 0;
+ }
+
+ inline explicit unique_lock(Mutex &m)
+ : the_mutex(&m), has_locked(true) {
+ the_mutex->lock();
+ }
+
+ inline ~unique_lock() {
+ if (the_mutex && has_locked)
+ the_mutex->unlock();
+ }
+
+ unique_lock &operator =(const unique_lock &other) = delete;
+
+ inline unique_lock &operator =(unique_lock &&other) {
+ if (the_mutex && has_locked)
+ the_mutex->unlock();
+ the_mutex = other.the_mutex;
+ has_locked = other.has_locked;
+ other.the_mutex = 0;
+ }
+
+ inline void lock() {
+ the_mutex->lock();
+ has_locked = true;
+ }
+
+ inline void unlock() {
+ the_mutex->unlock();
+ has_locked = false;
+ }
+
+ };
+
+}
diff --git a/euler/include/std/vector.hpp b/euler/include/std/vector.hpp
index a1ac21d..1c35d9d 100644
--- a/euler/include/std/vector.hpp
+++ b/euler/include/std/vector.hpp
@@ -1,10 +1,12 @@
#pragma once
+#include <std/fwd/vector.hpp>
+
#include <memory>
namespace std {
- template <class T, class Allocator = std::allocator<T>>
+ template <class T, class Allocator>
class vector {
public:
diff --git a/euler/source/entry.cpp b/euler/source/entry.cpp
index e79209c..ab721f1 100644
--- a/euler/source/entry.cpp
+++ b/euler/source/entry.cpp
@@ -6,6 +6,8 @@ int main(int argc, char **argv);
extern "C" [[noreturn]] void _start() {
+ //TODO: call static initializers
+
auto argc_raw = euler::syscall::try_get_environment_variable("ARGC");
int argc = argc_raw.has_value() ? std::stoi(argc_raw.value()) : 0;
diff --git a/euler/source/std/cstdio.cpp b/euler/source/std/cstdio.cpp
index 8c12a7c..485efc3 100644
--- a/euler/source/std/cstdio.cpp
+++ b/euler/source/std/cstdio.cpp
@@ -1,4 +1,5 @@
#include <cstdio>
+#include <string>
extern "C" FILE *fopen(const char *filename, const char *mode) {
diff --git a/euler/source/std/string.cpp b/euler/source/std/string.cpp
index 31c47a5..ae397b1 100644
--- a/euler/source/std/string.cpp
+++ b/euler/source/std/string.cpp
@@ -44,6 +44,7 @@ namespace std {
value = value * base + c - 'A' + 10;
else
break;
+ ++i;
}
if (pos != 0)
@@ -75,10 +76,11 @@ namespace std {
}
std::string operator +(std::string &&lhs, std::string &&rhs) {
+ size_t og_lhs_s = lhs.size();
std::string s = std::move(lhs);
- s.resize(lhs.size() + rhs.size());
+ s.resize(og_lhs_s + rhs.size());
for (size_t i = 0; i < rhs.size(); ++i)
- s[lhs.size() + i] = rhs[i];
+ s[og_lhs_s + i] = rhs[i];
rhs.clear();
return s;
}
diff --git a/euler/source/stream.cpp b/euler/source/stream.cpp
index faf2907..da973ba 100644
--- a/euler/source/stream.cpp
+++ b/euler/source/stream.cpp
@@ -1,4 +1,5 @@
#include <euler/stream.hpp>
+#include <algorithm>
#include <cstring>
namespace euler {
diff --git a/euler/source/syscall.cpp b/euler/source/syscall.cpp
index b3ed3a8..0d30c4a 100644
--- a/euler/source/syscall.cpp
+++ b/euler/source/syscall.cpp
@@ -1,4 +1,6 @@
#include <euler/syscall.hpp>
+#include <string>
+#include <vector>
extern "C" void __euler_do_syscall(
uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx);
@@ -394,4 +396,15 @@ namespace euler::syscall {
}
+ void set_thread_name(const std::string &name) {
+
+ uint64_t rax = 24;
+ uint64_t rdi = (uint64_t)name.data();
+ uint64_t rsi = name.size();
+ uint64_t rdx;
+
+ __euler_do_syscall(rax, rdi, rsi, rdx);
+
+ }
+
}
diff --git a/kernel/include/hilbert/kernel/application.hpp b/kernel/include/hilbert/kernel/application.hpp
index a4b59ff..e7c7d2e 100644
--- a/kernel/include/hilbert/kernel/application.hpp
+++ b/kernel/include/hilbert/kernel/application.hpp
@@ -112,6 +112,8 @@ namespace hilbert::kernel::application {
utility::list<string_pair> environment_variables;
public:
+ utility::string name;
+
app_memory *memory;
//set in get_framebuffer syscall
@@ -121,13 +123,16 @@ namespace hilbert::kernel::application {
uint64_t id;
//this class takes ownership of memory
- process(app_memory *memory);
+ process(app_memory *memory, const utility::string &name);
~process();
//arguments are utility::move'd
void add_environment_variable(
utility::string &&name, utility::string &&value);
+ //null if unset
+ utility::string *get_environment_variable(const utility::string &name);
+
void add_thread(thread *t);
void notify_thread_ended(thread *t, int exit_code);
void on_end_process(int exit_code);
@@ -180,6 +185,8 @@ namespace hilbert::kernel::application {
utility::maybe<unsigned> new_socket_stream_id;
public:
+ utility::string name;
+
process *owner;
//the cpu state is saved here when the thread is not running.
diff --git a/kernel/include/hilbert/kernel/serial.hpp b/kernel/include/hilbert/kernel/serial.hpp
index e7a44f2..7751fa0 100644
--- a/kernel/include/hilbert/kernel/serial.hpp
+++ b/kernel/include/hilbert/kernel/serial.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <hilbert/kernel/utility.hpp>
#include <stdint.h>
namespace hilbert::kernel {
@@ -15,6 +16,11 @@ namespace hilbert::kernel {
}
}
+ static inline void serial_putstr(const utility::string &str) {
+ for (unsigned i = 0; i < str.count; ++i)
+ serial_putchar(str.buffer[i]);
+ }
+
template <int digits, int dot_every = 4>
static inline void serial_puthex(uint64_t n) {
for (int d = digits - 1; d >= 0; --d) {
diff --git a/kernel/include/hilbert/kernel/utility.hpp b/kernel/include/hilbert/kernel/utility.hpp
index b7f1a1b..a21d3fe 100644
--- a/kernel/include/hilbert/kernel/utility.hpp
+++ b/kernel/include/hilbert/kernel/utility.hpp
@@ -107,6 +107,10 @@ namespace hilbert::kernel::utility {
n->value = value;
n->next = 0;
n->prev = last;
+ if (last)
+ last->next = n;
+ else
+ first = n;
last = n;
}
@@ -115,12 +119,19 @@ namespace hilbert::kernel::utility {
n->value = value;
n->next = 0;
n->prev = last;
+ if (last)
+ last->next = n;
+ else
+ first = n;
last = n;
}
void clear() {
- for (node *n = first; n; n = n->next)
- delete n;
+ if (first) {
+ for (node *n = first->next; n; n = n->next)
+ delete n->prev;
+ delete last;
+ }
first = 0;
last = 0;
}
diff --git a/kernel/source/application.cpp b/kernel/source/application.cpp
index 8070019..6df49cd 100644
--- a/kernel/source/application.cpp
+++ b/kernel/source/application.cpp
@@ -83,7 +83,8 @@ namespace hilbert::kernel::application {
resume_thread(t->saved_state);
}
- process::process(app_memory *memory) : memory(memory) {}
+ process::process(app_memory *memory, const utility::string &name)
+ : name(name), memory(memory) {}
process::~process() {
delete memory; //:p
@@ -94,6 +95,14 @@ namespace hilbert::kernel::application {
environment_variables.insert_end({.a = name, .b = value});
}
+ utility::string *process::get_environment_variable(
+ const utility::string &name) {
+ for (auto *i = environment_variables.first; i; i = i->next)
+ if (i->value.a == name)
+ return &i->value.b;
+ return 0;
+ }
+
void process::add_thread(thread *t) {
threads.insert_end(t);
}
@@ -197,8 +206,8 @@ namespace hilbert::kernel::application {
thread::thread(process *owner, uint64_t entry)
: stack_top(owner->memory->map_new_stack()), waiting_for_socket_stream(0),
- waiting_to_accept_from(0), waiting_to_connect_to(0),
- waiting_for_input(false), owner(owner) {
+ waiting_to_accept_from(0), waiting_to_connect_to(0), waiting_for_input(false),
+ name(utility::string("main", 4)), owner(owner) {
saved_state.rax = 0;
saved_state.rbx = 0;
diff --git a/kernel/source/entry.cpp b/kernel/source/entry.cpp
index 2389bb1..efa70fd 100644
--- a/kernel/source/entry.cpp
+++ b/kernel/source/entry.cpp
@@ -214,7 +214,8 @@ extern "C" [[noreturn]] void entry() {
if (load_init_result != load_app_result::success)
panic(0xc39db3);
- application::process *init_process = new application::process(init_memory);
+ application::process *init_process =
+ new application::process(init_memory, utility::string("init", 4));
init_process->add_environment_variable(
utility::string("ARGC", 4), utility::string("1", 1));
init_process->add_environment_variable(
diff --git a/kernel/source/interrupts.cpp b/kernel/source/interrupts.cpp
index 41d632c..1a1f4d1 100644
--- a/kernel/source/interrupts.cpp
+++ b/kernel/source/interrupts.cpp
@@ -79,6 +79,11 @@ extern "C" [[noreturn]] void print_exception() {
print_reg("r14", exception_info.r14);
print_reg("r15", exception_info.r15);
+ if (application::running_thread != 0) {
+ serial_putstr("running app = ");
+ serial_putstr(application::running_thread->owner->name);
+ }
+
panic(0xba40bb);
}
diff --git a/kernel/source/syscall.cpp b/kernel/source/syscall.cpp
index f2a6801..c631df1 100644
--- a/kernel/source/syscall.cpp
+++ b/kernel/source/syscall.cpp
@@ -183,7 +183,7 @@ namespace hilbert::kernel::syscall {
.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,
+ .the_socket = s, .read_queue = s->queue_2, .write_queue = s->queue_1,
.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;
@@ -494,8 +494,12 @@ namespace hilbert::kernel::syscall {
rax = (uint64_t)application::stream_result::other_end_closed;
return;
}
- for (uint64_t i = 0; i < count; ++i)
+ auto &wtr_queue = ss->other_end->waiting_to_read;
+ for (uint64_t i = 0; i < count; ++i) {
ss->write_queue.insert(buffer[i]);
+ if (wtr_queue.count > 0)
+ application::paused_threads->insert(wtr_queue.take());
+ }
rax = (uint64_t)application::stream_result::success;
}
@@ -617,7 +621,8 @@ namespace hilbert::kernel::syscall {
break;
}
- application::process *p = new application::process(memory);
+ application::process *p =
+ new application::process(memory, file.dir_entry.name);
for (uint64_t i = 0; i < psi->env_var_count; ++i)
p->add_environment_variable(
@@ -735,6 +740,66 @@ namespace hilbert::kernel::syscall {
}
+ void get_environment_variable_length_syscall(
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
+
+ const char *name = (const char *)rdi;
+ uint64_t name_len = rsi;
+ set_zero(rax, rdi, rsi, rdx);
+
+ auto *app = application::running_thread->owner;
+
+ if (!app->memory->valid_to_read(name, name + name_len, false))
+ return;
+
+ utility::string name_string(name, name_len);
+ utility::string *value = app->get_environment_variable(name_string);
+ rax = value == 0 ? (uint64_t)-1 : value->count;
+
+ }
+
+ void get_environment_variable_value_syscall(
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
+
+ const char *name = (const char *)rdi;
+ uint64_t name_len = rsi;
+ char *buffer = (char *)rdx;
+ set_zero(rax, rdi, rsi, rdx);
+
+ auto *app = application::running_thread->owner;
+
+ if (!app->memory->valid_to_read(name, name + name_len, false))
+ return;
+
+ utility::string name_string(name, name_len);
+ utility::string *value = app->get_environment_variable(name_string);
+ if (value == 0)
+ return;
+
+ if (!app->memory->valid_to_read(buffer, buffer + value->count, true))
+ return;
+
+ for (unsigned i = 0; i < value->count; ++i)
+ buffer[i] = value->buffer[i];
+
+ }
+
+ void set_thread_name_syscall(
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
+
+ const char *name = (const char *)rdi;
+ uint64_t name_len = rsi;
+ set_zero(rax, rdi, rsi, rdx);
+
+ auto *t = application::running_thread;
+
+ if (!t->owner->memory->valid_to_read(name, name + name_len, false))
+ return;
+
+ t->name = utility::string(name, name_len);
+
+ }
+
void (*handlers[])(
uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) = {
@@ -759,11 +824,14 @@ namespace hilbert::kernel::syscall {
&set_stream_length_syscall,
&get_other_end_process_handle_syscall,
&start_thread_syscall,
- &clear_socket_read_queue_syscall
+ &clear_socket_read_queue_syscall,
+ &get_environment_variable_length_syscall,
+ &get_environment_variable_value_syscall,
+ &set_thread_name_syscall
};
- static constexpr int max_syscall_number = 20;
+ static constexpr int max_syscall_number = 24;
}
diff --git a/libraries/daguerre/include/daguerre/impl/fixed-font.hpp b/libraries/daguerre/include/daguerre/impl/fixed-font.hpp
index dbff798..1a5f3d8 100644
--- a/libraries/daguerre/include/daguerre/impl/fixed-font.hpp
+++ b/libraries/daguerre/include/daguerre/impl/fixed-font.hpp
@@ -20,7 +20,7 @@ namespace daguerre {
template <class color_t>
fixed_font<color_t>::fixed_font(fixed_font<color_t> &&other)
: glyph_width(other.glyph_width), glyph_height(other.glyph_height) {
- for (int i = 0; 0 < 128; ++i)
+ for (int i = 0; i < 128; ++i)
glyphs[i] = std::move(other.glyphs[i]);
other.glyph_width = 0;
other.glyph_height = 0;
@@ -31,7 +31,7 @@ namespace daguerre {
fixed_font<color_t> &&other) {
glyph_width = other.glyph_width;
glyph_height = other.glyph_height;
- for (int i = 0; 0 < 128; ++i)
+ for (int i = 0; i < 128; ++i)
glyphs[i] = std::move(other.glyphs[i]);
other.glyph_width = 0;
other.glyph_height = 0;
diff --git a/libraries/daguerre/include/daguerre/impl/image.hpp b/libraries/daguerre/include/daguerre/impl/image.hpp
index 1264879..9160951 100644
--- a/libraries/daguerre/include/daguerre/impl/image.hpp
+++ b/libraries/daguerre/include/daguerre/impl/image.hpp
@@ -185,7 +185,7 @@ namespace daguerre {
const param_t &param, const image<other_color_t> &other, int to_x,
int to_y, param_converter_t<color_t, other_color_t, param_t> *conversion) {
convert_from(
- param, other, to_x, to_y, 0, 0, other.width, other.y, conversion);
+ param, other, to_x, to_y, 0, 0, other.width, other.height, conversion);
}
template <class color_t>
diff --git a/libraries/goldman/include/goldman/protocol.hpp b/libraries/goldman/include/goldman/protocol.hpp
new file mode 100644
index 0000000..b7f4d51
--- /dev/null
+++ b/libraries/goldman/include/goldman/protocol.hpp
@@ -0,0 +1,85 @@
+#pragma once
+
+#include <euler/syscall.hpp>
+#include <memory>
+
+//TODO: handle stream errors, make thread safe
+
+namespace goldman::protocol {
+
+ typedef euler::syscall::encoded_color color;
+ typedef uint16_t window;
+
+ static inline void send_open_window(
+ euler::syscall::stream_handle socket, uint32_t width, uint32_t height) {
+
+ struct [[gnu::packed]] {
+ uint8_t type;
+ uint32_t width;
+ uint32_t height;
+ } packet {
+ .type = 0x00,
+ .width = width,
+ .height = height
+ };
+
+ euler::syscall::write_to_stream(socket, sizeof(packet), &packet);
+
+ }
+
+ void send_update_window_region(
+ euler::syscall::stream_handle socket, window the_window,
+ uint32_t start_x, uint32_t start_y, uint32_t width,
+ uint32_t height, const color *the_data, size_t data_pitch) {
+
+ struct [[gnu::packed]] {
+ uint8_t type;
+ window the_window;
+ uint32_t start_x;
+ uint32_t start_y;
+ uint32_t width;
+ uint32_t height;
+ } packet_head {
+ .type = 0x01,
+ .the_window = the_window,
+ .start_x = start_x,
+ .start_y = start_y,
+ .width = width,
+ .height = height
+ };
+
+ euler::syscall::write_to_stream(socket, sizeof(packet_head), &packet_head);
+ for (uint32_t y = 0; y < height; ++y)
+ euler::syscall::write_to_stream(
+ socket, width * sizeof(color), the_data + data_pitch * y);
+
+ }
+
+ void send_close_window(
+ euler::syscall::stream_handle socket, window the_window) {
+
+ struct [[gnu::packed]] {
+ uint8_t type;
+ window the_window;
+ } packet {
+ .type = 0x02,
+ .the_window = the_window
+ };
+
+ euler::syscall::write_to_stream(socket, sizeof(packet), &packet);
+
+ }
+
+ enum class response_id : uint8_t {
+ window_opened
+ };
+
+ window get_window_opened_body(euler::syscall::stream_handle socket) {
+
+ window w;
+ euler::syscall::read_from_stream(socket, sizeof(w), &w);
+ return w;
+
+ }
+
+}
diff --git a/makefile b/makefile
index 711bb03..c3f4ad3 100644
--- a/makefile
+++ b/makefile
@@ -7,7 +7,8 @@ EXTRA_CC_ARGS = -Wall -Wextra -Og -ggdb -fno-exceptions
HILBERT_NASM = nasm -f elf64
HILBERT_CC = ${TOOLCHAIN_DIR}/usr/bin/x86_64-elf-c++ -std=c++20 \
${EXTRA_CC_ARGS} -static -mno-sse -I include -I $(abspath euler/include) \
- -I $(abspath libraries/daguerre/include) -I ${MINTSUKI_HEADERS_DIR}
+ -I $(abspath libraries/daguerre/include) -I ${MINTSUKI_HEADERS_DIR} \
+ -I $(abspath libraries/goldman/include)
HILBERT_AR = ${TOOLCHAIN_DIR}/usr/bin/x86_64-elf-ar
HILBERT_LD = ${TOOLCHAIN_DIR}/usr/bin/x86_64-elf-ld -z noexecstack
@@ -25,8 +26,8 @@ LIBSTDCPP_DEP = toolchain/.libstdcpp-done
EULER_DEP = toolchain/.euler-done
DAGUERRE_DEP = toolchain/.daguerre-done
-APP_DEPS = ${GCC_DEP} ${LIBGCC_DEP} ${LIBSTDCPP_DEP} ${EULER_DEP}
-LIBRARY_DEPS = ${GCC_DEP} ${LIBSTDCPP_DEP}
+APP_DEPS = ${EULER_DEP}
+LIBRARY_DEPS = ${LIBSTDCPP_DEP}
.PHONY: default run clean clean-dependencies
@@ -41,6 +42,7 @@ clean:
make -C kernel clean
make -C applications/init clean
make -C applications/goldman clean
+ make -C applications/hello clean
make -C libraries/daguerre clean
clean-dependencies: clean
@@ -90,7 +92,7 @@ ${LIBGCC_DEP}: ${GCC_DEP}
+make -C dependencies/gcc/build install-target-libgcc
touch $@
-${LIBSTDCPP_DEP}: ${GCC_DEP}
+${LIBSTDCPP_DEP}: ${LIBGCC_DEP}
+make -C dependencies/gcc/build all-target-libstdc++-v3
+make -C dependencies/gcc/build install-target-libstdc++-v3
patch toolchain/usr/x86_64-elf/include/c++/14.1.0/memory patches/gcc-memory.patch
@@ -117,13 +119,18 @@ applications/init/build/init.elf: ${APP_DEPS}
applications/goldman/build/goldman.elf: ${APP_DEPS} ${DAGUERRE_DEP}
+make -C applications/goldman build/goldman.elf
+applications/hello/build/hello.elf: ${APP_DEPS} ${DAGUERRE_DEP}
+ +make -C applications/hello build/hello.elf
+
build/initfs.tgz: applications/init/build/init.elf \
- applications/goldman/build/goldman.elf
+ applications/goldman/build/goldman.elf \
+ applications/hello/build/hello.elf
@mkdir -p build
rm -rf build/initfs
cp -r skeleton build/initfs
cp applications/init/build/init.elf build/initfs/bin/init
cp applications/goldman/build/goldman.elf build/initfs/bin/goldman
+ cp applications/hello/build/hello.elf build/initfs/bin/hello
cd build/initfs && tar czf ../initfs.tgz .
build/disk.iso: kernel/build/kernel.elf build/initfs.tgz ${LIMINE_DEP}
diff --git a/qemu.gdb b/qemu.gdb
index 21d8389..65c24a6 100644
--- a/qemu.gdb
+++ b/qemu.gdb
@@ -1,6 +1,5 @@
target remote | qemu-system-x86_64 -gdb stdio -cdrom build/disk.iso -boot d
symbol-file kernel/build/kernel.elf
-add-symbol-file applications/goldman/build/goldman.elf
set disassembly-flavor intel
set print asm-demangle on
layout src
diff --git a/readme.txt b/readme.txt
index 1226991..d1f2829 100644
--- a/readme.txt
+++ b/readme.txt
@@ -67,7 +67,7 @@ the following directories and files are released under the text in cc0.txt
project structure:
- applications/goldman:
- in the future, this will be the default compositor.
+ the default compositor, in a very early stage
- applications/init:
the initial program loaded by the kernel. currently it just
@@ -87,6 +87,9 @@ project structure:
- libraries/daguerre:
an image loading / rendering library.
+ - libraries/goldman:
+ a library for interfacing with the goldman compositor
+
- patches:
a couple patches that are applied to dependencies