[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