[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Lost] [Patch 3/3] kernel2: Syscall pm_init_page
+ kernel2: Syscall pm_init_page
Index: trunk/src/kernel2/include/syscall.h
===================================================================
--- trunk.orig/src/kernel2/include/syscall.h
+++ trunk/src/kernel2/include/syscall.h
@@ -100,6 +100,10 @@ int syscall_pm_v(pid_t pid);
pid_t syscall_pm_create_process(vaddr_t start, uid_t uid,
const char* cmdline, pid_t parent_pid);
+/// Speicher an einen anderen Prozess uebergeben
+void syscall_init_child_page(pid_t pid, vaddr_t src, vaddr_t dest,
+ size_t size);
+
// RPC
/// RPC-Handler registrieren
Index: trunk/src/kernel2/src/syscall.c
===================================================================
--- trunk.orig/src/kernel2/src/syscall.c
+++ trunk/src/kernel2/src/syscall.c
@@ -61,6 +61,7 @@ void syscall_init()
syscall_register(SYSCALL_PM_V, (void*) &syscall_pm_v, 1);
syscall_register(SYSCALL_PM_CREATE_PROCESS, &syscall_pm_create_process, 4);
+ syscall_register(SYSCALL_PM_INIT_PAGE, &syscall_init_child_page, 4);
syscall_register(SYSCALL_SET_RPC_HANDLER, (void*) &syscall_set_rpc_handler,
1);
Index: trunk/src/kernel2/src/syscalls/pm.c
===================================================================
--- trunk.orig/src/kernel2/src/syscalls/pm.c
+++ trunk/src/kernel2/src/syscalls/pm.c
@@ -108,3 +108,62 @@ const char* syscall_pm_get_cmdline()
return (const char*) address;
}
+/**
+ * Einen Speicherbereich vom aktuellen an einen anderen Prozess uebertragen.
+ * Die Pages werden aus dem Adressraum des aktuellen Prozess entfernt. Dieser
+ * Syscall darf nur benutzt werden, solange der Prozess noch nicht gestartet
+ * wurde. Falls der Bereich schon gemappt ist im Zielprozess wird er
+ * ueberschrieben. Dabei muss beachtet werden, dass immer ganze Pages kopiert
+ * oder verschoben werden!
+ *
+ * @param pid PID des Prozess an den die Page uebertragen werden soll
+ * @param src Adresse im Adressraum des aktuellen Prozesses
+ * @param dest Adresse im Adressraum des Zielprozesses
+ * @param size Groesse des Speicherbereichs.
+ */
+void syscall_init_child_page(pid_t pid, vaddr_t dest, vaddr_t src, size_t size)
+{
+ //kprintf("init child_page %d 0x%08x 0x%08x Bytes\n", pid, dest, size);
+ pm_process_t* process = pm_get(pid);
+ if (process == NULL) {
+ return;
+ }
+
+ // TODO Im Kommentar genannte Bedingungen und Berechtigungen pruefen
+
+ // Adressen abrunden auf ein Vielfaches von PAGE_SIZE
+ src = (vaddr_t) PAGE_ALIGN_ROUND_DOWN((uintptr_t) src);
+ dest = (vaddr_t) PAGE_ALIGN_ROUND_DOWN((uintptr_t) dest);
+
+ // Anzahl der Seiten berechnen
+ size_t num_pages = NUM_PAGES(size);
+
+ // Adressen kopieren damit sie veraendert werden koennen
+ // Sie duerfen nicht ueberschrieben werden, weil sie am Schluss noch
+ // gebraucht werden, um den Speicher aus dem Quellprozess zu entfernen
+ vaddr_t src_cur = src;
+ vaddr_t dest_cur = dest;
+ while (num_pages-- != 0) {
+ // Wenn die Page schon gemappt ist, wird der notwendige Bereich kopiert
+ // sonst wird die Page nur umgemappt
+ paddr_t dest_phys = mmc_resolve(&process->context, dest_cur);
+ paddr_t src_phys = mmc_resolve(&mmc_current_context(), src_cur);
+
+ if (dest_phys != NULL) {
+ // Die Page temporaer mappen
+ vaddr_t dest_vaddr = vmm_kernel_automap(dest_phys, PAGE_SIZE);
+ memcpy(dest_vaddr, src_cur, PAGE_SIZE);
+ vmm_kernel_unmap(dest_vaddr, PAGE_SIZE);
+ } else {
+ // Page in den anderen Prozess mappen
+ mmc_map(&process->context, dest_cur, src_phys, MM_FLAGS_USER_DATA,
+ 1);
+ }
+ // Adressen erhoehen
+ src_cur = (vaddr_t) ((uintptr_t) src_cur + PAGE_SIZE);
+ dest_cur = (vaddr_t) ((uintptr_t) dest_cur + PAGE_SIZE);
+ }
+
+ // Speicherbereich aus dem Adressraum des Quellprozesses entfernen
+ mmc_unmap(&mmc_current_context(), src, NUM_PAGES(size));
+}