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

[tyndur-devel] [PATCH 2/7] kernel2: Unterstützung von lio_dup()



+ kernel2: Neuer Syscall lio_dup(), um zusätzliche Stream-IDs für
  geöffnete Streams zu bekommen (entweder um eine bestimmte ID zu
  überschreiben oder um eine Kopie weiterzureichen)

Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 src/include/syscallno.h                |  1 +
 src/kernel2/include/lostio/userspace.h |  4 ++++
 src/kernel2/include/syscall.h          |  3 +++
 src/kernel2/src/lostio/userspace.c     | 13 +++++++++---
 src/kernel2/src/syscall.c              |  1 +
 src/kernel2/src/syscalls/lostio.c      | 37 ++++++++++++++++++++++++++++++++++
 src/modules/include/syscall.h          | 14 +++++++++++++
 src/modules/lib/syscalls/lostio.c      | 33 ++++++++++++++++++++++++++++++
 8 files changed, 103 insertions(+), 3 deletions(-)

diff --git a/src/include/syscallno.h b/src/include/syscallno.h
index 5fa5cf1..3938718 100644
--- a/src/include/syscallno.h
+++ b/src/include/syscallno.h
@@ -109,6 +109,7 @@
 #define SYSCALL_LIO_SYNC_ALL    99
 #define SYSCALL_LIO_PASS_FD     100
 #define SYSCALL_LIO_PROBE_SERVICE 101
+#define SYSCALL_LIO_DUP         102
 
 #define SYSCALL_LIO_SRV_SERVICE_REGISTER            110
 #define SYSCALL_LIO_SRV_TREE_SET_RING               111
diff --git a/src/kernel2/include/lostio/userspace.h b/src/kernel2/include/lostio/userspace.h
index cde9778..8e53501 100644
--- a/src/kernel2/include/lostio/userspace.h
+++ b/src/kernel2/include/lostio/userspace.h
@@ -46,6 +46,10 @@
 struct lio_usp_stream* lio_usp_add_stream(pm_process_t* proc,
     struct lio_stream* stream);
 
+/** Weist einem Stream eine gegebene Userspace-ID zu */
+struct lio_usp_stream* lio_usp_do_add_stream(pm_process_t* proc,
+    struct lio_stream* stream, lio_usp_stream_t id);
+
 /**
  * Gibt den zur Userspace-ID gehörenden Stream zurück, oder NULL wenn es
  * keinen passenden Stream gibt.
diff --git a/src/kernel2/include/syscall.h b/src/kernel2/include/syscall.h
index d7fce53..c979373 100644
--- a/src/kernel2/include/syscall.h
+++ b/src/kernel2/include/syscall.h
@@ -211,6 +211,9 @@ void syscall_lio_open(lio_usp_resource_t* resid, int flags,
 /// Stream schließen
 int syscall_lio_close(lio_usp_stream_t* stream_id);
 
+/// Zusätzliche ID für Stream erstellen
+int syscall_lio_dup(lio_usp_stream_t* source, lio_usp_stream_t* dest);
+
 /// Stream an anderen Prozess weitergeben
 int syscall_lio_pass_fd(lio_usp_stream_t* stream_id, pid_t pid);
 
diff --git a/src/kernel2/src/lostio/userspace.c b/src/kernel2/src/lostio/userspace.c
index 76874fc..6fd5638 100644
--- a/src/kernel2/src/lostio/userspace.c
+++ b/src/kernel2/src/lostio/userspace.c
@@ -96,13 +96,13 @@ void lio_usp_remove_resource(struct lio_resource* res)
 }
 
 /** Weist einem Stream eine Userspace-ID zu */
-struct lio_usp_stream* lio_usp_add_stream(pm_process_t* proc,
-    struct lio_stream* stream)
+struct lio_usp_stream* lio_usp_do_add_stream(pm_process_t* proc,
+    struct lio_stream* stream, lio_usp_stream_t id)
 {
     struct lio_usp_stream* entry = malloc(sizeof(*entry));
 
     entry->stream = stream;
-    entry->usp_id = new_streamid();
+    entry->usp_id = id;
     tree_insert(proc->lio_streams, entry);
 
     stream->usp_refcount++;
@@ -110,6 +110,13 @@ struct lio_usp_stream* lio_usp_add_stream(pm_process_t* proc,
     return entry;
 }
 
+/** Weist einem Stream eine Userspace-ID zu */
+struct lio_usp_stream* lio_usp_add_stream(pm_process_t* proc,
+    struct lio_stream* stream)
+{
+    return lio_usp_do_add_stream(proc, stream, new_streamid());
+}
+
 /**
  * Gibt den zur Userspace-ID gehörenden Stream zurück, oder NULL wenn es
  * keinen passenden Stream gibt.
diff --git a/src/kernel2/src/syscall.c b/src/kernel2/src/syscall.c
index d1628ba..557ab12 100644
--- a/src/kernel2/src/syscall.c
+++ b/src/kernel2/src/syscall.c
@@ -131,6 +131,7 @@ void syscall_init()
     syscall_register(SYSCALL_LIO_SYNC_ALL, &syscall_lio_sync_all, 0);
     syscall_register(SYSCALL_LIO_PASS_FD, &syscall_lio_pass_fd, 2);
     syscall_register(SYSCALL_LIO_PROBE_SERVICE, &syscall_lio_probe_service, 2);
+    syscall_register(SYSCALL_LIO_DUP, &syscall_lio_dup, 2);
 
     syscall_register(SYSCALL_LIO_SRV_SERVICE_REGISTER,
         &syscall_lio_srv_service_register, 4);
diff --git a/src/kernel2/src/syscalls/lostio.c b/src/kernel2/src/syscalls/lostio.c
index eecffac..73aa98e 100644
--- a/src/kernel2/src/syscalls/lostio.c
+++ b/src/kernel2/src/syscalls/lostio.c
@@ -118,6 +118,43 @@ int syscall_lio_close(lio_usp_stream_t* stream_id)
     return lio_usp_unref_stream(current_process, fd);
 }
 
+/// Zusätzliche ID für Stream erstellen
+int syscall_lio_dup(lio_usp_stream_t* source, lio_usp_stream_t* dest)
+{
+    struct lio_usp_stream* old_fd;
+    struct lio_usp_stream* new_fd;
+    int ret;
+
+    // TODO: is_userspace (source und dest)
+    if (*dest < -1) {
+        return -EBADF;
+    }
+
+    old_fd = lio_usp_get_stream(current_process, *source);
+    if (old_fd == NULL) {
+        return -EBADF;
+    }
+
+    new_fd = lio_usp_get_stream(current_process, *dest);
+    if (old_fd == new_fd) {
+        return 0;
+    } else if (new_fd != NULL) {
+        ret = lio_usp_unref_stream(current_process, new_fd);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    if (*dest != -1) {
+        new_fd = lio_usp_do_add_stream(current_process, old_fd->stream, *dest);
+    } else {
+        new_fd = lio_usp_add_stream(current_process, old_fd->stream);
+    }
+
+    *dest = new_fd->usp_id;
+    return 0;
+}
+
 /// Stream an anderen Prozess weitergeben
 int syscall_lio_pass_fd(lio_usp_stream_t* stream_id, pid_t pid)
 {
diff --git a/src/modules/include/syscall.h b/src/modules/include/syscall.h
index 7ab42a4..2fac1f4 100644
--- a/src/modules/include/syscall.h
+++ b/src/modules/include/syscall.h
@@ -149,6 +149,20 @@ lio_resource_t lio_resource(const char* path, bool follow_symlink);
 lio_stream_t lio_open(lio_resource_t resource, int flags);
 
 /**
+ * Erstellt eine zusätzliche Stream-ID für einen Stream.
+ *
+ * @param source Der zu duplizierende Stream
+ * @param dest Neue ID, die  der Stream erhalten soll, oder -1 für eine
+ * beliebige freie ID. Wenn diese ID bereits einen Stream bezeichnet, wird
+ * dieser geschlossen.
+ *
+ * @return Neue Stream-ID bei Erfolg, negativ im Fehlerfall. Insbesondere:
+ *
+ *      -EBADF      Ein der Stream-IDs ist ungültig
+ */
+lio_stream_t lio_dup(lio_stream_t source, lio_stream_t dest);
+
+/**
  * Gibt Informationen zu einer Ressource zurück.
  *
  * @param resource ID der Ressource
diff --git a/src/modules/lib/syscalls/lostio.c b/src/modules/lib/syscalls/lostio.c
index 81658b7..b898e7a 100644
--- a/src/modules/lib/syscalls/lostio.c
+++ b/src/modules/lib/syscalls/lostio.c
@@ -116,6 +116,39 @@ int lio_stat(lio_resource_t resource, struct lio_stat* sbuf)
 }
 
 /**
+ * Erstellt eine zusätzliche Stream-ID für einen Stream.
+ *
+ * @param source Der zu duplizierende Stream
+ * @param dest Neue ID, die  der Stream erhalten soll, oder -1 für eine
+ * beliebige freie ID. Wenn diese ID bereits einen Stream bezeichnet, wird
+ * dieser geschlossen.
+ *
+ * @return Neue Stream-ID bei Erfolg, negativ im Fehlerfall. Insbesondere:
+ *
+ *      -EBADF      Ein der Stream-IDs ist ungültig
+ */
+lio_stream_t lio_dup(lio_stream_t source, lio_stream_t dest)
+{
+    volatile lio_stream_t d = dest;
+    int result;
+
+    asm(
+        "pushl %3;"
+        "pushl %2;"
+        "mov %1, %%eax;"
+        "int $0x30;"
+        "add $0x8, %%esp;"
+    : "=a" (result) : "i" (SYSCALL_LIO_DUP), "r" (&source), "r" (&d)
+    : "memory");
+
+    if (result < 0) {
+        return result;
+    } else {
+        return d;
+    }
+}
+
+/**
  * Schließt einen Stream.
  *
  * @param s Der zu schließende Stream
-- 
2.1.4