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

[tyndur-devel] [PATCH 1/6] kernel2: Refcounting für lio_stream



+ kernel2: lio_streams haben jetzt einen Refcount, so dass mehrere
  Userspace-IDs auf denselben Stream verweisen können.

Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 src/kernel2/include/lostio/core.h      |  2 ++
 src/kernel2/include/lostio/userspace.h |  7 +++++--
 src/kernel2/src/lostio/userspace.c     | 32 +++++++++++++++++++++++++++-----
 src/kernel2/src/syscalls/lostio.c      | 22 ++++++++--------------
 src/kernel2/src/tasks/pm.c             |  8 ++------
 5 files changed, 44 insertions(+), 27 deletions(-)

diff --git a/src/kernel2/include/lostio/core.h b/src/kernel2/include/lostio/core.h
index b1183b4..3e71dc3 100644
--- a/src/kernel2/include/lostio/core.h
+++ b/src/kernel2/include/lostio/core.h
@@ -54,6 +54,8 @@ struct lio_stream {
 
     int                     flags;
     bool                    eof;
+
+    int                     usp_refcount;
 };
 
 struct lio_usp_stream {
diff --git a/src/kernel2/include/lostio/userspace.h b/src/kernel2/include/lostio/userspace.h
index a8a5cdc..cde9778 100644
--- a/src/kernel2/include/lostio/userspace.h
+++ b/src/kernel2/include/lostio/userspace.h
@@ -53,8 +53,11 @@ struct lio_usp_stream* lio_usp_add_stream(pm_process_t* proc,
 struct lio_usp_stream* lio_usp_get_stream(pm_process_t* proc,
     lio_usp_stream_t id);
 
-/** Gibt die Userspace-ID des Streams wieder frei */
-void lio_usp_remove_stream(pm_process_t* proc, struct lio_usp_stream* stream);
+/**
+ * Gibt die Userspace-ID des Streams wieder frei und schließt den Stream, wenn
+ * das die letzte Userspace-Referenz war.
+ */
+int lio_usp_unref_stream(pm_process_t* proc, struct lio_usp_stream* stream);
 
 
 
diff --git a/src/kernel2/src/lostio/userspace.c b/src/kernel2/src/lostio/userspace.c
index d6376de..76874fc 100644
--- a/src/kernel2/src/lostio/userspace.c
+++ b/src/kernel2/src/lostio/userspace.c
@@ -35,7 +35,9 @@
 
 #include <stdlib.h>
 
+#include "kernel.h"
 #include "lostio/core.h"
+#include "lostio/client.h"
 #include "lostio_int.h"
 
 static tree_t* resource_tree;
@@ -101,8 +103,10 @@ struct lio_usp_stream* lio_usp_add_stream(pm_process_t* proc,
 
     entry->stream = stream;
     entry->usp_id = new_streamid();
-
     tree_insert(proc->lio_streams, entry);
+
+    stream->usp_refcount++;
+
     return entry;
 }
 
@@ -116,11 +120,29 @@ struct lio_usp_stream* lio_usp_get_stream(pm_process_t* proc,
     return tree_search(proc->lio_streams, id);
 }
 
-/** Gibt die Userspace-ID des Streams wieder frei */
-void lio_usp_remove_stream(pm_process_t* proc, struct lio_usp_stream* stream)
+/**
+ * Gibt die Userspace-ID des Streams wieder frei und schließt den Stream, wenn
+ * das die letzte Userspace-Referenz war.
+ */
+int lio_usp_unref_stream(pm_process_t* proc, struct lio_usp_stream* us)
 {
-    tree_remove(proc->lio_streams, stream);
-    free(stream);
+    struct lio_stream* stream = us->stream;
+    int ret;
+
+    BUG_ON(stream->usp_refcount <= 0);
+    stream->usp_refcount--;
+
+    if (stream->usp_refcount == 0) {
+        ret = lio_close(stream);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    tree_remove(proc->lio_streams, us);
+    free(us);
+
+    return 0;
 }
 
 /** Weist einem Verzeichnisbaum eine Userspace-ID zu */
diff --git a/src/kernel2/src/syscalls/lostio.c b/src/kernel2/src/syscalls/lostio.c
index 1c978d4..314ca98 100644
--- a/src/kernel2/src/syscalls/lostio.c
+++ b/src/kernel2/src/syscalls/lostio.c
@@ -37,6 +37,7 @@
 #include <stdlib.h>
 #include <errno.h>
 
+#include "kernel.h"
 #include "kprintf.h"
 #include "syscall.h"
 #include <syscall_structs.h>
@@ -107,8 +108,6 @@ void syscall_lio_open(lio_usp_resource_t* resid, int flags,
 int syscall_lio_close(lio_usp_stream_t* stream_id)
 {
     struct lio_usp_stream* fd;
-    struct lio_stream* stream;
-    int ret;
 
     // TODO: is_userspace
     fd = lio_usp_get_stream(current_process, *stream_id);
@@ -116,17 +115,7 @@ int syscall_lio_close(lio_usp_stream_t* stream_id)
         return -EBADF;
     }
 
-    // lio_close gibt stream im Erfolgsfall frei, wir koennen es also nicht
-    // erst hinterher aus dem Baum entfernen. Falls close schiefgeht, muessen
-    // wir es wohl oder uebel wieder eintragen.
-    stream = fd->stream;
-    lio_usp_remove_stream(current_process, fd);
-    ret = lio_close(stream);
-    if (ret < 0) {
-        lio_usp_add_stream(current_process, stream);
-    }
-
-    return ret;
+    return lio_usp_unref_stream(current_process, fd);
 }
 
 /// Stream an anderen Prozess weitergeben
@@ -135,6 +124,7 @@ int syscall_lio_pass_fd(lio_usp_stream_t* stream_id, pid_t pid)
     struct lio_usp_stream* fd;
     struct lio_stream* stream;
     pm_process_t* process;
+    int ret;
 
     process = pm_get(pid);
     if (process == NULL) {
@@ -148,10 +138,14 @@ int syscall_lio_pass_fd(lio_usp_stream_t* stream_id, pid_t pid)
     }
 
     stream = fd->stream;
-    lio_usp_remove_stream(current_process, fd);
     fd = lio_usp_add_stream(process, stream);
     *stream_id = fd->usp_id;
 
+    // Wir haben gerade eine zweite Referenz hinzugefügt, also kann kein
+    // lio_close() aufgerufen, das fehlschlagen könnte.
+    ret = lio_usp_unref_stream(current_process, fd);
+    BUG_ON(ret != 0);
+
     return 0;
 }
 
diff --git a/src/kernel2/src/tasks/pm.c b/src/kernel2/src/tasks/pm.c
index 8219022..bb95923 100644
--- a/src/kernel2/src/tasks/pm.c
+++ b/src/kernel2/src/tasks/pm.c
@@ -192,16 +192,12 @@ void pm_prepare_destroy(pm_process_t* process)
     // Alle Dateien schliessen und freigeben
     struct lio_usp_stream* fd = NULL;
     struct lio_usp_stream* next = NULL;
-    struct lio_stream* s;
 
     fd = tree_next(process->lio_streams, NULL);
     while (fd != NULL) {
         next = tree_next(process->lio_streams, fd);
-
-        s = fd->stream;
-        lio_usp_remove_stream(process, fd);
-        lio_close(s);
-
+        // TODO Was machen mit Dateien, die sich nicht schließen lassen?
+        (void) lio_usp_unref_stream(process, fd);
         fd = next;
     }
     tree_destroy(process->lio_streams);
-- 
2.1.2