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

[tyndur-devel] [PATCH 4/4] kernel2: Blockierendes Lesen



+ kernel2: lio_(p)read() blockiert jetzt, wenn es gar nichts lesen kann,
  aber moredata noch gesetzt ist (d.h. es sonst -EAGAIN zurückgeben
  würde).

  Solange man sich nicht einloggt, verbraten die getterms jetzt nicht
  mehr 100% CPU um die Tastatur zu pollen, sondern der Idle-Thread kommt
  zum Zug.

Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 src/kernel2/include/tasks.h                 |  1 +
 src/kernel2/src/lostio/client.c             | 39 ++++++++++++++++++++++++++---
 src/kernel2/src/lostio/include/lostio_int.h | 11 ++++++++
 src/kernel2/src/lostio/tree.c               |  6 +++++
 src/kernel2/src/syscalls/lio_server.c       |  5 +++-
 5 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/src/kernel2/include/tasks.h b/src/kernel2/include/tasks.h
index e17d22b..8fac5ad 100644
--- a/src/kernel2/include/tasks.h
+++ b/src/kernel2/include/tasks.h
@@ -52,6 +52,7 @@
 #define PM_STATUS_WAIT_FOR_RPC 3
 #define PM_STATUS_WAIT_FOR_LIO 4
 #define PM_STATUS_WAIT_FOR_IO_REQUEST 5
+#define PM_STATUS_WAIT_FOR_DATA 6
 
 typedef struct pm_process {
     /// Die eindeutige Prozessnummer
diff --git a/src/kernel2/src/lostio/client.c b/src/kernel2/src/lostio/client.c
index db98df1..df425f2 100644
--- a/src/kernel2/src/lostio/client.c
+++ b/src/kernel2/src/lostio/client.c
@@ -302,11 +302,12 @@ ssize_t lio_read(struct lio_stream* s, size_t bytes, void* buf)
 
 /**
  * Liest aus einem Stream aus, ohne die Position des streams zu benutzen oder
- * zu veraendern.
+ * zu veraendern. Diese Funktion blockiert nie, sondern gibt -EAGAIN zurück,
+ * wenn es nichts zu lesen gibt.
  *
  * @return Anzahl der gelesenen Bytes oder negativ im Fehlerfall
  */
-ssize_t lio_pread(struct lio_stream* s, uint64_t offset, size_t bytes,
+ssize_t lio_pread_nonblock(struct lio_stream* s, uint64_t offset, size_t bytes,
     void* buf)
 {
     ssize_t ret = 0;
@@ -361,6 +362,36 @@ ssize_t lio_pread(struct lio_stream* s, uint64_t offset, size_t bytes,
     return ret;
 }
 
+static void lio_pread_unblock_cb(void* opaque)
+{
+    pm_thread_t* t = opaque;
+
+    BUG_ON(t->status != PM_STATUS_WAIT_FOR_DATA);
+    t->status = PM_STATUS_READY;
+}
+
+/**
+ * Liest aus einem Stream aus, ohne die Position des streams zu benutzen oder
+ * zu veraendern. Diese Funktion blockiert, bis etwas gelesen werden kann.
+ *
+ * @return Anzahl der gelesenen Bytes oder negativ im Fehlerfall
+ */
+ssize_t lio_pread(struct lio_stream* s, uint64_t offset, size_t bytes,
+    void* buf)
+{
+    ssize_t ret;
+
+    ret = lio_pread_nonblock(s, offset, bytes, buf);
+    while (ret == -EAGAIN) {
+        notifier_add(&s->res_read->on_resize,
+                     lio_pread_unblock_cb, current_thread, true);
+        pm_scheduler_kern_yield(0, PM_STATUS_WAIT_FOR_DATA);
+        ret = lio_pread_nonblock(s, offset, bytes, buf);
+    }
+
+    return ret;
+}
+
 /**
  * Schreibt in einen Stream
  *
@@ -447,7 +478,7 @@ ssize_t lio_pwrite(struct lio_stream* s, uint64_t offset, size_t bytes,
     // Offset zeigt jetzt auf das erste Byte nach dem letzten geschriebenen
     if (ret > 0){
         if (res->size < offset) {
-            res->size = offset;
+            lio_resource_update_size(res, offset);
         }
     }
 
@@ -583,7 +614,7 @@ int lio_truncate(struct lio_stream* s, uint64_t size)
 
     /* Anschliessend die Ressourcengroesse anpassen (drv->truncate kann das
      * u.U. auch schon gemacht haben) */
-    res->size = size;
+    lio_resource_update_size(res, size);
 
     return 0;
 }
diff --git a/src/kernel2/src/lostio/include/lostio_int.h b/src/kernel2/src/lostio/include/lostio_int.h
index 4feb05c..f6a5ed1 100644
--- a/src/kernel2/src/lostio/include/lostio_int.h
+++ b/src/kernel2/src/lostio/include/lostio_int.h
@@ -40,6 +40,7 @@
 #include <syscall_structs.h>
 
 #include "lostio/core.h"
+#include "notifier.h"
 #include "tasks.h"
 
 #define ROUND_TO_NEXT_BLOCK(bytes, blocksize) \
@@ -180,6 +181,13 @@ struct lio_resource {
     bool                        resolvable;
     bool                        retargetable;
 
+    /**
+     * Wird aufgerufen, wenn sich die Größe einer Ressource ändert (dies
+     * schließt Fälle ein, in denen moredata von true zu false wechselt, wenn
+     * dann statt -EGAIN das Dateiende gemeldet wird.
+     */
+    struct notifier*            on_resize;
+
     /** Id der Ressource fuer Userspace-Programme */
     lio_usp_resource_t          usp_id;
 
@@ -281,6 +289,9 @@ void lio_resource_remove_child(struct lio_resource* parent,
 struct lio_node* lio_create_node(struct lio_resource* parent,
     struct lio_resource* res, const char* name);
 
+/** Größe aktualisieren und on_size-Notifier ausführen */
+void lio_resource_update_size(struct lio_resource* res, uint64_t size);
+
 
 /** Weist einer Ressource eine Userspace-ID zu */
 void lio_usp_add_resource(struct lio_resource* res);
diff --git a/src/kernel2/src/lostio/tree.c b/src/kernel2/src/lostio/tree.c
index 60140d5..f53c9cd 100644
--- a/src/kernel2/src/lostio/tree.c
+++ b/src/kernel2/src/lostio/tree.c
@@ -367,3 +367,9 @@ struct lio_node* lio_create_node(struct lio_resource* parent,
     return n;
 }
 
+/** Größe aktualisieren und on_size-Notifier ausführen */
+void lio_resource_update_size(struct lio_resource* res, uint64_t size)
+{
+    res->size = size;
+    notify(res->on_resize);
+}
diff --git a/src/kernel2/src/syscalls/lio_server.c b/src/kernel2/src/syscalls/lio_server.c
index 0ead479..5127d7a 100644
--- a/src/kernel2/src/syscalls/lio_server.c
+++ b/src/kernel2/src/syscalls/lio_server.c
@@ -262,7 +262,6 @@ int syscall_lio_srv_res_upload(struct lio_server_resource* resource)
     }
 
     res->tree = lio_usp_get_tree(resource->tree);
-    res->size = resource->size;
     res->blocksize = resource->blocksize;
     res->readable = ((resource->flags & LIO_SRV_READABLE) ? 1 : 0);
     res->writable = ((resource->flags & LIO_SRV_WRITABLE) ? 1 : 0);
@@ -278,6 +277,10 @@ int syscall_lio_srv_res_upload(struct lio_server_resource* resource)
     }
     res->opaque = resource->opaque;
 
+    /* Auch aufrufen falls sich die Größe nicht geändert hat: moredata könnte
+     * von true auf false gewechselt sein. */
+    lio_resource_update_size(res, resource->size);
+
     return 0;
 }
 
-- 
2.1.2