[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