[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH 6/6] vterm: Nach LostIOv2 konvertiert



* vterm: Der Stand nach diesem Commit ist, dass hoffentlich alles noch
  genausoo funktioniert wie davor. Spannend wird die Konvertierung dann,
  wenn der Kernel lernt, was blockierende Reads sind. Dann dürften wir
  nämlich die 100% CPU fürs Pollen des Terminals endlich los werden.

Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 src/modules/vterm/include/keymap.h |  11 +-
 src/modules/vterm/keymap.c         |  39 ++---
 src/modules/vterm/lostio.c         | 318 +++++++++++++++++++++++++++----------
 src/modules/vterm/term.c           |  30 +---
 src/modules/vterm/vterm.c          |   8 +-
 src/modules/vterm/vterm.h          |  27 ++++
 6 files changed, 285 insertions(+), 148 deletions(-)

diff --git a/src/modules/vterm/include/keymap.h b/src/modules/vterm/include/keymap.h
index 604080d..9c6ff9f 100644
--- a/src/modules/vterm/include/keymap.h
+++ b/src/modules/vterm/include/keymap.h
@@ -61,21 +61,14 @@ extern keymap_entry_t keymap[128];
 keymap_entry_t* keymap_get(uint8_t keycode);
 
 /**
- * Legt die vterm:/keymap im Verzeichnisbaum an
- */
-void keymap_init(void);
-
-/**
  * LostIO-Handller um die Tastaturbelegung zu lesen
  */
-size_t keymap_read(lostio_filehandle_t* file, void* buf,
-    size_t blocksize, size_t blockcount);
+int keymap_read(uint64_t offset, size_t bytes, void* buf);
 
 /**
  * LostIO-Handler um die Tastaturbelegung zu aendern
  */
-size_t keymap_write(lostio_filehandle_t* file, size_t blocksize,
-    size_t blockcount, void* data);
+int keymap_write(uint64_t offset, size_t bytes, void* buf);
 
 #endif // ifndef _KEYMAP_H_
 
diff --git a/src/modules/vterm/keymap.c b/src/modules/vterm/keymap.c
index 72715e6..28b4905 100644
--- a/src/modules/vterm/keymap.c
+++ b/src/modules/vterm/keymap.c
@@ -35,6 +35,7 @@
 
 #include <io.h>
 #include <string.h>
+#include <errno.h>
 
 #include "vterm.h"
 #include "keymap.h"
@@ -50,47 +51,29 @@ keymap_entry_t* keymap_get(uint8_t keycode)
 }
 
 /**
- * Legt die vterm:/keymap im Verzeichnisbaum an
- */
-void keymap_init(void)
-{
-    vfstree_create_node("/keymap", LOSTIO_TYPES_KEYMAP, 0, NULL, 0);
-}
-
-/**
  * LostIO-Handller um die Tastaturbelegung zu lesen
  */
-size_t keymap_read(lostio_filehandle_t* file, void* buf,
-    size_t blocksize, size_t blockcount)
+int keymap_read(uint64_t offset, size_t bytes, void* buf)
 {
-    size_t size = blocksize * blockcount;
-
-    if (file->pos + size >= sizeof(keymap)) {
-        size = sizeof(keymap) - file->pos;
-        file->flags |= LOSTIO_FLAG_EOF;
+    if (offset > sizeof(keymap) || bytes > sizeof(keymap) - offset) {
+        return -EINVAL;
     }
 
-    memcpy(buf, ((uint8_t*) keymap) + file->pos, size);
-    file->pos += size;
+    memcpy(buf, ((uint8_t*) keymap) + offset, bytes);
 
-    return size;
+    return 0;
 }
 
 /**
  * LostIO-Handler um die Tastaturbelegung zu aendern
  */
-size_t keymap_write(lostio_filehandle_t* file, size_t blocksize,
-    size_t blockcount, void* buf)
+int keymap_write(uint64_t offset, size_t bytes, void* buf)
 {
-    size_t size = blocksize * blockcount;
-
-    if (file->pos + size >= sizeof(keymap)) {
-        size = sizeof(keymap) - file->pos;
-        file->flags |= LOSTIO_FLAG_EOF;
+    if (offset > sizeof(keymap) || bytes > sizeof(keymap) - offset) {
+        return -ENOSPC;
     }
 
-    memcpy(((uint8_t*) keymap) + file->pos, buf, size);
-    file->pos += size;
+    memcpy(((uint8_t*) keymap) + offset, buf, bytes);
 
-    return size;
+    return 0;
 }
diff --git a/src/modules/vterm/lostio.c b/src/modules/vterm/lostio.c
index 7bd1c30..4905f8a 100644
--- a/src/modules/vterm/lostio.c
+++ b/src/modules/vterm/lostio.c
@@ -37,129 +37,283 @@
 #include <stdlib.h>
 #include <syscall.h>
 #include <string.h>
+#include <errno.h>
 
 #include "vterm.h"
 #include "lostio.h"
 #include "keymap.h"
 
-/// Handler fuer Lesen aus in
-size_t terminal_read(lostio_filehandle_t* handle, void* buf,
-    size_t blocksize, size_t blockcount);
+static struct lio_resource* root;
 
-/// Handler fuer schreiben in out
-size_t terminal_write(lostio_filehandle_t* handle, size_t blocksize,
-    size_t blockcount, void* data);
+static void lio_add_vterm_dir(vterminal_t* vterm)
+{
+    struct lio_tree* tree = root->tree;
 
-/// Handler fuer close auf in
-static int lio_in_close(lostio_filehandle_t* fh);
+    struct lio_resource* dir;
+    struct lio_resource* in_node;
+    struct lio_resource* out_node;
 
+    struct lio_vterm* lv;
 
-/**
- * LostIO-Interface vorbereiten, ueber das die Prozesse mit vterm kommunizieren
- * werden.
- */
-void init_lostio_interface()
+    // Verzeichnis
+    dir = lio_resource_create(tree);
+    dir->browsable = 1;
+    dir->blocksize = 1;
+    lio_resource_modified(dir);
+    lio_node_create(root, dir, vterm->name);
+
+    // In-Node
+    lv = malloc(sizeof(*lv));
+    *lv = (struct lio_vterm) {
+        .type   = LOSTIO_TYPES_IN,
+        .vterm  = vterm,
+    };
+
+    in_node = lio_resource_create(tree);
+    in_node->readable = 1;
+    in_node->blocksize = 1;
+    in_node->moredata = 1;
+    in_node->opaque = lv;
+    lio_resource_modified(in_node);
+    lio_node_create(dir, in_node, "in");
+
+    vterm->lio_in_res = in_node;
+
+    // Out-Node
+    lv = malloc(sizeof(*lv));
+    *lv = (struct lio_vterm) {
+        .type   = LOSTIO_TYPES_OUT,
+        .vterm  = vterm,
+    };
+
+    out_node = lio_resource_create(tree);
+    out_node->writable = 1;
+    out_node->blocksize = 1;
+    out_node->opaque = lv;
+    lio_resource_modified(out_node);
+    lio_node_create(dir, out_node, "out");
+}
+
+struct lio_resource* vterm_load_root(struct lio_tree* tree)
 {
-    lostio_init();
-    lostio_type_directory_use();
-
-    // Typehandle fuer Ausgabekanaele
-    typehandle_t* typehandle = malloc(sizeof(typehandle_t));
-    typehandle->id          = LOSTIO_TYPES_OUT;
-    typehandle->not_found   = NULL;
-    typehandle->pre_open    = NULL;
-    typehandle->post_open   = NULL;
-    typehandle->read        = NULL;
-    typehandle->write       = &terminal_write;
-    typehandle->seek        = NULL;
-    typehandle->close       = NULL;
-    lostio_register_typehandle(typehandle);
-
-    // Typehandle fuer Eingabekanaele
-    typehandle = malloc(sizeof(typehandle_t));
-    typehandle->id          = LOSTIO_TYPES_IN;
-    typehandle->not_found   = NULL;
-    typehandle->pre_open    = NULL;
-    typehandle->post_open   = NULL;
-    typehandle->read        = &terminal_read;
-    typehandle->write       = NULL;
-    typehandle->seek        = NULL;
-    typehandle->close       = lio_in_close;
-    typehandle->link        = NULL;
-    typehandle->unlink      = NULL;
-    lostio_register_typehandle(typehandle);
-
-    // Typehandle fuer Keymaps
-    typehandle = calloc(1, sizeof(typehandle_t));
-    typehandle->id          = LOSTIO_TYPES_KEYMAP;
-    typehandle->read        = &keymap_read;
-    typehandle->write       = &keymap_write;
-    lostio_register_typehandle(typehandle);
+    vterminal_t *vterm;
+    struct lio_resource* keymap_node;
+    struct lio_vterm* lv;
+    int i;
+
+    if (tree->source != -1) {
+        return NULL;
+    }
+
+    // Wurzelknoten
+    root = lio_resource_create(tree);
+    root->browsable = 1;
+    root->blocksize = 1;
+    lio_resource_modified(root);
+    lio_node_create(NULL, root, "");
+
+    // keymap
+    lv = malloc(sizeof(*lv));
+    *lv = (struct lio_vterm) {
+        .type   = LOSTIO_TYPES_KEYMAP,
+        .vterm  = NULL,
+    };
+
+    keymap_node = lio_resource_create(tree);
+    keymap_node->readable = 1;
+    keymap_node->writable = 1;
+    keymap_node->blocksize = 1;
+    keymap_node->opaque = lv;
+    lio_resource_modified(keymap_node);
+    lio_node_create(root, keymap_node, "keymap");
+
+    // Terminals
+    for (i = 0; (vterm = list_get_element_at(vterm_list, i)); i++) {
+        lio_add_vterm_dir(vterm);
+    }
+
+    return root;
+}
+
+void lio_add_vterm(vterminal_t* vterm)
+{
+    if (root) {
+        lio_add_vterm_dir(vterm);
+    }
 }
 
 /**
  * LostIO-Handler um in den Ausgabekanal zu schreiben
  */
-size_t terminal_write(lostio_filehandle_t* file, size_t blocksize,
-    size_t blockcount, void* data)
+int term_write(struct lio_resource* res, uint64_t offset, size_t bytes,
+               void* buf)
 {
+    struct lio_vterm *lv = res->opaque;
+
+    //printf("term_write: %s: %d -> %p\n", lv->vterm->name, bytes, buf);
+
     p();
-    vterm_process_output((vterminal_t*) file->node->data, data, blocksize *
-        blockcount);
+    vterm_process_output(lv->vterm, buf, bytes);
     v();
-    return blocksize * blockcount;
+
+    return 0;
 }
 
 /**
  * LostIO-Handller um aus dem Eingabekanal zu lesen
  */
-size_t terminal_read(lostio_filehandle_t* file, void* buf,
-    size_t blocksize, size_t blockcount)
+int term_read(struct lio_resource* res, uint64_t offset, size_t bytes,
+               void* buf)
 {
+    struct lio_vterm *lv = res->opaque;
+
     p();
-    size_t size = blocksize * blockcount;
-    vterminal_t* vterm = (vterminal_t*) file->node->data;
+    vterminal_t* vterm = lv->vterm;
+
+    /*printf("vterm_read: offset %llx + %d bytes [buf %d; res %d; seteof %d; "
+           "moredata %d]\n", offset, bytes,
+           vterm->in_buffer_size, res->size, vterm->set_eof, res->moredata);*/
 
+    // FIXME Erstmal die vorherigen Daten rausgeben
     if (vterm->set_eof) {
         vterm->set_eof = false;
-        file->flags |= LOSTIO_FLAG_EOF;
+        res->moredata = false;
+        lio_resource_modified(res);
         v();
-        return 0;
+        return -EAGAIN;
+    } else if (res->moredata == false) {
+        res->moredata = true;
+        lio_resource_modified(res);
     }
 
-    if (vterm->in_buffer_size == 0) {
+    // Erst einmal alles wegwerfen, was nicht mehr gebraucht wird, weil schon
+    // von einem höheren Offset gelesen wurde
+    if (offset > vterm->in_buffer_offset) {
+        size_t drop;
+
+        drop = offset - vterm->in_buffer_offset;
+        if (drop > vterm->in_buffer_size) {
+            drop = vterm->in_buffer_size;
+        }
+        vterm->in_buffer_size -= drop;
+
+        if (vterm->in_buffer_size != 0) {
+            memmove(vterm->in_buffer, vterm->in_buffer + drop,
+                    vterm->in_buffer_size);
+        } else {
+            free(vterm->in_buffer);
+            vterm->in_buffer = NULL;
+        }
+
+        vterm->in_buffer_offset = offset;
+    }
+
+    if (vterm->in_buffer_size < bytes) {
         v();
-        return 0;
+        return -EAGAIN;
+    }
+
+/*printf("vterm_read: memcpy %p <- %p + %x [buf %x]\n",
+    buf, vterm->in_buffer, bytes, vterm->in_buffer_size);*/
+    memcpy(buf, vterm->in_buffer, bytes);
+
+    v();
+    return 0;
+}
+
+void lio_update_in_file_size(vterminal_t* vterm, size_t length)
+{
+    struct lio_resource* res = vterm->lio_in_res;
+
+    if (res) {
+        res->size += length;
+        lio_resource_modified(res);
     }
-    
-    if (vterm->in_buffer_size < size) {
-        size = vterm->in_buffer_size;
+}
+
+void lio_set_eof(vterminal_t* vterm)
+{
+    struct lio_resource* res = vterm->lio_in_res;
+
+    if (res) {
+        res->moredata = false;
+        lio_resource_modified(res);
     }
+}
 
-    memcpy(buf, vterm->in_buffer, size);
-    
-    vterm->in_buffer_size -= size;
-    // Die uebrigen Daten am ende des Buffers an den Anfang schieben
-    if (vterm->in_buffer_size != 0) {
-        memmove(vterm->in_buffer, vterm->in_buffer + size,
-            vterm->in_buffer_size);
-    } else {
-        free(vterm->in_buffer);
-        vterm->in_buffer = NULL;
+int vterm_read(struct lio_resource* res, uint64_t offset, size_t bytes,
+                void* buf)
+{
+    struct lio_vterm *lv = res->opaque;
+
+    switch (lv->type) {
+        case LOSTIO_TYPES_IN:       return term_read(res, offset, bytes, buf);
+        case LOSTIO_TYPES_OUT:      return -EBADF;
+        case LOSTIO_TYPES_KEYMAP:   return keymap_read(offset, bytes, buf);
     }
 
-    v();
-    return size;
+    return -EBADF;
 }
 
+int vterm_write(struct lio_resource* res, uint64_t offset, size_t bytes,
+                void* buf)
+{
+    struct lio_vterm *lv = res->opaque;
+
+    switch (lv->type) {
+        case LOSTIO_TYPES_IN:       return -EBADF;
+        case LOSTIO_TYPES_OUT:      return term_write(res, offset, bytes, buf);
+        case LOSTIO_TYPES_KEYMAP:   return keymap_write(offset, bytes, buf);
+    }
+
+    return -EBADF;
+}
+
+int vterm_resize(struct lio_resource* res, uint64_t size)
+{
+    struct lio_vterm *lv = res->opaque;
+
+    switch (lv->type) {
+        case LOSTIO_TYPES_IN:       return 0;
+        case LOSTIO_TYPES_OUT:      return 0;
+        case LOSTIO_TYPES_KEYMAP:   return 0; /* TODO -EINVAL; */
+    }
+
+    return -EBADF;
+}
+
+void vterm_close(struct lio_resource* res)
+{
+    struct lio_vterm *lv = res->opaque;
+
+    if (lv->type == LOSTIO_TYPES_IN) {
+        lv->vterm->in_buffer_offset = 0;
+        res->size = lv->vterm->in_buffer_size = 0;
+        lio_resource_modified(res);
+    }
+}
+
+static struct lio_service service = {
+    .name               = "vterm",
+    .lio_ops = {
+        .load_root      = vterm_load_root,
+        .close          = vterm_close,
+        .read           = vterm_read,
+        .write          = vterm_write,
+        .resize         = vterm_resize,
+    },
+};
+
 /**
- * LostIO-Handler der einen allenfalls allozierten Buffer im Filehandle freigibt
+ * LostIO-Interface vorbereiten, ueber das die Prozesse mit vterm kommunizieren
+ * werden.
  */
-static int lio_in_close(lostio_filehandle_t* fh)
+void init_lostio_interface()
 {
-    if (fh->data) {
-        free(fh->data);
-    }
+    // TODO Entfernen, wenn niemand mehr versucht, LIOv1 zu benutzen
+    // Im Moment brauchen wir das noch, damit RPCs beantwortet werden und der
+    // Aufrufer nicht hängt
+    lostio_init();
 
-    return 0;
+    lio_add_service(&service);
 }
diff --git a/src/modules/vterm/term.c b/src/modules/vterm/term.c
index ccf4e6a..5a61ac7 100644
--- a/src/modules/vterm/term.c
+++ b/src/modules/vterm/term.c
@@ -51,7 +51,7 @@ char* strnstr(const char* s, const char* find, size_t slen);
 vterminal_t* current_vterm = NULL;
 
 /// Liste in der alle virtuellen Terminals gespeichert werden
-static list_t* vterm_list;
+list_t* vterm_list;
 
 /// Virtuelles Terminal erstellen
 vterminal_t* vterm_create(char shortcut);
@@ -94,28 +94,9 @@ vterminal_t* vterm_create(char shortcut)
     
     static int next_vterm_id = 0;
     asprintf(&vterm->name, "vterm%d", next_vterm_id++);
-    
-    // Knoten fuer LostIO-Schnittstelle erstellen
-    size_t name_len = strlen(vterm->name);
-    char path[name_len + 7];
-    path[0] = '/';
-    memcpy(path + 1, vterm->name, name_len + 1);
-    
-    // Verzeichnis
-    vfstree_create_node(path, LOSTIO_TYPES_DIRECTORY, 0, NULL,
-        LOSTIO_FLAG_BROWSABLE);
-    // In-Node
-    memcpy(path + name_len + 1, "/in", 4);
-    vfstree_create_node(path, LOSTIO_TYPES_IN, 0, vterm,
-        LOSTIO_FLAG_NOAUTOEOF);
-    vterm->in_node = vfstree_get_node_by_path(path);
-    // Sonst setzt LIO das EOF
-    vterm->in_node->size = 1;
-
-    // Out-Node
-    memcpy(path + name_len + 1, "/out", 5);
-    vfstree_create_node(path, LOSTIO_TYPES_OUT, 0, vterm, 0);
-    vterm->out_node = vfstree_get_node_by_path(path);
+
+    // LostIO-Knoten erstellen
+    lio_add_vterm(vterm);
     
     // Shortcut zuweisen
     vterm->shortcut = shortcut;
@@ -172,6 +153,8 @@ void vterm_process_input(char* data, size_t length)
     for (i = 0; i < length; i++) {
         input_buffer_append(current_vterm, data[i]);
     }
+
+    lio_update_in_file_size(current_vterm, length);
 }
 
 /**
@@ -243,6 +226,7 @@ bool vterm_process_raw_input(uint8_t keycode, struct modifiers* modifiers)
     } else if (modifiers->control && (keycode == 32)) {
         // Strg + D = EOF
         current_vterm->set_eof = true;
+        lio_set_eof(current_vterm);
         return true;
     } else if (keycode == KEYCODE_SCROLL_LOCK) {
         current_vterm->output.scroll_lock = !current_vterm->output.scroll_lock;
diff --git a/src/modules/vterm/vterm.c b/src/modules/vterm/vterm.c
index 0ff461f..5c9af8a 100644
--- a/src/modules/vterm/vterm.c
+++ b/src/modules/vterm/vterm.c
@@ -85,13 +85,9 @@ int main(int argc, char* argv[])
         return -1;
     }
 
-    // Tastaturbelegung konfigurierbar machen
-    keymap_init();
-
     // Auf Anfragen warten
     while(true) {
-        wait_for_rpc();
-        lostio_dispatch();
+        lio_dispatch();
+        lio_srv_wait();
 	}
 }
-
diff --git a/src/modules/vterm/vterm.h b/src/modules/vterm/vterm.h
index a7b6ef7..491a028 100644
--- a/src/modules/vterm/vterm.h
+++ b/src/modules/vterm/vterm.h
@@ -145,6 +145,9 @@ typedef struct {
     /// Groesse des Eingabepuffers
     size_t in_buffer_size;
 
+    /// LIO-Offset, an dem der Eingabepuffer anfängt
+    uint64_t in_buffer_offset;
+
     /// Pointer auf den Eingabenpuffer.
     char* in_buffer;
 
@@ -168,6 +171,9 @@ typedef struct {
 
     /// Beim naechsten Lesen EOF setzen
     bool set_eof;
+
+    /// LostIO-Ressource für Tastatureingaben
+    struct lio_resource* lio_in_res;
 } vterminal_t;
 
 /// Status der Modifiertasten
@@ -178,7 +184,28 @@ struct modifiers {
     bool alt;
 };
 
+/// opaque-Struktur für LIO-Knoten
+struct lio_vterm {
+    /// LOSTIO_TYPES_*
+    int type;
+
+    /// Terminal, zu dem der Knoten gehört
+    vterminal_t* vterm;
+};
+
+/// Neues vterm bei LostIO registrieren
+void lio_add_vterm(vterminal_t* vterm);
+
+/// Informiert LostIO, dass es @length neue Zeichen zu lesen gibt
+void lio_update_in_file_size(vterminal_t* vterm, size_t length);
+
+/// Informiert LostIO, dass ein EOF gesendet werden soll
+void lio_set_eof(vterminal_t* vterm);
+
+
+
 extern vterminal_t* current_vterm;
+extern list_t* vterm_list;
 
 /// Virtuelle terminals einrichten
 void init_vterminals(unsigned int count);
-- 
2.1.2