[freenos] r416 committed - Implemented api_proc_destroy() for deleting processes....

  • From: freenos@xxxxxxxxxxxxxx
  • To: freenos@xxxxxxxxxxxxx
  • Date: Fri, 22 Oct 2010 22:06:51 +0000

Revision: 416
Author: nieklinnenbank
Date: Fri Oct 22 15:05:50 2010
Log: Implemented api_proc_destroy() for deleting processes.
The virt_release() function is used to release all claimed
non-pinned memory in the process. Only another processes
may invoke api_proc_destroy() on it. Additionally, proc_pause()
and proc_resume() now take a process_t pointer instead of pid_t.

http://code.google.com/p/freenos/source/detail?r=416

Modified:
 /branches/scratch/include/kernel/api.h
 /branches/scratch/include/kernel/process.h
 /branches/scratch/include/kernel/virt_memory.h
 /branches/scratch/include/x86/virt_memory.h
 /branches/scratch/server/serial/main.c
 /branches/scratch/system/api.c
 /branches/scratch/system/process.c
 /branches/scratch/system/x86/pc/virt_memory.c

=======================================
--- /branches/scratch/include/kernel/api.h      Tue Oct 19 14:39:53 2010
+++ /branches/scratch/include/kernel/api.h      Fri Oct 22 15:05:50 2010
@@ -20,14 +20,20 @@

 #include "types.h"

-#define API_PROC_ID  (1 << 0)
-#define API_IO_READ  (1 << 1)
-#define API_IO_WRITE (1 << 2)
+#define API_PROC_ID      (1 << 0)
+#define API_PROC_DESTROY (1 << 1)
+#define API_IO_READ      (1 << 2)
+#define API_IO_WRITE     (1 << 3)

 __inline__ static pid_t api_proc_id(void)
 {
     return (pid_t) sys_call0(API_PROC_ID);
 }
+
+__inline__ static result_t api_proc_destroy(pid_t pid)
+{
+    return sys_call1(API_PROC_DESTROY, pid);
+}

 __inline__ static result_t api_io_read(uint port, size_t size)
 {
=======================================
--- /branches/scratch/include/kernel/process.h  Sun Oct 10 16:06:55 2010
+++ /branches/scratch/include/kernel/process.h  Fri Oct 22 15:05:50 2010
@@ -51,9 +51,9 @@
 extern u16 proc_create(addr_t entry);
 extern process_t * proc_find(u16 pid);
 extern u16 proc_lookup(process_t *proc);
-extern void proc_resume(pid_t pid);
-extern void proc_pause(pid_t pid);
-extern void proc_destroy(pid_t pid);
+extern void proc_resume(process_t *proc);
+extern void proc_pause(process_t *proc);
+extern result_t proc_destroy(process_t *proc);
 extern void proc_schedule(void);

 #endif /* __ASSEMBLER__ */
=======================================
--- /branches/scratch/include/kernel/virt_memory.h      Mon Oct 18 16:52:53 2010
+++ /branches/scratch/include/kernel/virt_memory.h      Fri Oct 22 15:05:50 2010
@@ -34,12 +34,14 @@
extern void virt_memory_proc(process_t *proc, addr_t kern_stack, addr_t user_stack);

 extern result_t virt_map(addr_t dir_base, addr_t vaddr,
-                        addr_t paddr, size_t size, u8 flags);
+                        addr_t paddr, size_t size, u16 flags);

 extern void * virt_temp_map(addr_t paddr, size_t size);

 extern void virt_unmap(void *vaddr, size_t size);

+extern void virt_release(addr_t dir_base);
+
 extern page_entry_t * virt_map_remote_dir(process_t *proc);

 extern void virt_unmap_remote_dir(process_t *proc);
=======================================
--- /branches/scratch/include/x86/virt_memory.h Mon Oct 18 16:53:47 2010
+++ /branches/scratch/include/x86/virt_memory.h Fri Oct 22 15:05:50 2010
@@ -66,11 +66,28 @@
  */
 #define virt_reload_all() \
     __asm__ volatile("mov %cr3, %eax\n" \
-                "mov %eax, %cr3\n")
-
-#define PAGE_PR   (1 << 0)
-#define PAGE_WR   (1 << 1)
-#define PAGE_USER (1 << 2)
+                    "mov %eax, %cr3\n")
+
+/**
+ * @brief Page Enter Flags.
+ * @{
+ */
+
+/** Page is present. */
+#define PAGE_PR     (1 << 0)
+
+/** Page is writable. */
+#define PAGE_WR     (1 << 1)
+
+/** Page is accessibl by unprivileged userland processes. */
+#define PAGE_USER   (1 << 2)
+
+/** Pinned pages cannot be released. */
+#define PAGE_PIN (1 << 9)
+
+/**
+ * @}
+ */

 #define DIR_VADDR       (1024 * 1024 * 4)
 #define RDIR_VADDR      (1024 * 1024 * 8)
=======================================
--- /branches/scratch/server/serial/main.c      Tue Oct 19 14:41:22 2010
+++ /branches/scratch/server/serial/main.c      Fri Oct 22 15:05:50 2010
@@ -43,6 +43,9 @@
             getpid());
     serial_write(buf, strlen(buf));

+    /* Let kill init. */
+    api_proc_destroy(0);
+
     /* Loop forever. */
     for (;;);
     return 0;
=======================================
--- /branches/scratch/system/api.c      Tue Oct 19 14:39:53 2010
+++ /branches/scratch/system/api.c      Fri Oct 22 15:05:50 2010
@@ -15,10 +15,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */

-#define API_PROC_ID  (1 << 0)
-#define API_IO_READ  (1 << 1)
-#define API_IO_WRITE (1 << 2)
-
 #include <FreeNOS/api.h>
 #include <FreeNOS/io.h>
 #include <FreeNOS/types.h>
@@ -30,11 +26,21 @@
 result_t api_execute(uint func,  ulong arg1,
                     ulong arg2, ulong arg3)
 {
+    process_t *p;
+
     switch (func)
     {
        case API_PROC_ID:
            return proc_lookup(smp_cpu()->proc);

+       case API_PROC_DESTROY:
+           if ((p = proc_find(arg1)) != NULL)
+           {
+               return proc_destroy(p);
+           }
+           else
+               return -ESRCH;
+
        case API_IO_READ:
            return inb(arg1);

=======================================
--- /branches/scratch/system/process.c  Mon Oct 18 16:59:47 2010
+++ /branches/scratch/system/process.c  Fri Oct 22 15:05:50 2010
@@ -90,7 +90,7 @@
                num = 0;
        }
        else
-           proc_resume(pid);
+           proc_resume(proc);
     }
 }

@@ -140,20 +140,45 @@
     return proc ? proc - proc_table : (pid_t) -1;
 }

-void proc_resume(pid_t pid)
-{
-    if (proc_find(pid))
-       proc_find(pid)->flags |= PROC_READY;
+void proc_resume(process_t *p)
+{
+    spinlock_enter(&proc_lock);
+    p->flags |= PROC_READY;
+    spinlock_leave(&proc_lock);
 }

-void proc_pause(pid_t pid)
-{
-    if (proc_find(pid))
-       proc_find(pid)->flags &= ~PROC_READY;
+void proc_pause(process_t *p)
+{
+    spinlock_enter(&proc_lock);
+    p->flags &= ~PROC_READY;
+    spinlock_leave(&proc_lock);
 }

-void proc_destroy(pid_t pid)
-{
+result_t proc_destroy(process_t *p)
+{
+    /*
+     * Cannot kill itself. This avoid the
+     * scenario where all pages have been pfree()'ed, including page_dir,
+     * and some other CPU claims it and messes it up before we
+     * are able to schedule anything yet. Another process simply needs to
+     * do the dirty work while safely running under its own page_dir.
+     */
+    if (smp_cpu()->proc == p)
+    {
+       return -EINVAL;
+    }
+    /* Release physical memory. */
+    virt_map_remote_dir(p);
+    virt_release(RDIR_VADDR);
+    virt_unmap_remote_dir(p);
+
+    /* Clear process table entry. */
+    spinlock_enter(&proc_lock);
+    memset(p, 0, sizeof(*p));
+    spinlock_leave(&proc_lock);
+
+    /* Done. */
+    return 0;
 }

 void proc_schedule(void)
=======================================
--- /branches/scratch/system/x86/pc/virt_memory.c       Mon Oct 18 17:03:00 2010
+++ /branches/scratch/system/x86/pc/virt_memory.c       Fri Oct 22 15:05:50 2010
@@ -25,14 +25,14 @@
 #include <string.h>

 static void virt_dir_setmap(page_entry_t *dir, addr_t vaddr,
-                           addr_t paddr, u8 flags)
+                           addr_t paddr, u16 flags)
 {
     dir[DIRENTRY(vaddr)]  = paddr;
     dir[DIRENTRY(vaddr)] |= flags;
 }

 static void virt_tab_setmap(page_entry_t *tab, addr_t vaddr,
-                           addr_t paddr, u8 flags)
+                           addr_t paddr, u16 flags)
 {
     tab[TABENTRY(vaddr)]  = paddr;
     tab[TABENTRY(vaddr)] |= flags;
@@ -81,7 +81,7 @@
 }

 result_t virt_map(addr_t dir_base, addr_t vaddr,
-                 addr_t paddr, size_t size, u8 flags)
+                 addr_t paddr, size_t size, u16 flags)
 {
     page_entry_t *dir = TABADDR(dir_base, DIR_VADDR);
     page_entry_t *tab = 0;
@@ -142,6 +142,31 @@
 {
     virt_map(DIR_VADDR, (addr_t) vaddr, 0, size, 0);
 }
+
+void virt_release(addr_t dir_base)
+{
+    page_entry_t *dir = TABADDR(dir_base, DIR_VADDR);
+    page_entry_t *tab;
+    size_t i,j;
+
+    for (i = 0; i < 1024; i++)
+    {
+       if (dir[DIRENTRY(i)] & PAGE_PR &&
+         !(dir[DIRENTRY(i)] & PAGE_PIN))
+       {
+           tab = TABADDR(dir_base, i);
+
+           for (j = 0; i < 1024; j++)
+           {
+               if (tab[j] & PAGE_PR &&
+                 !(tab[j] & PAGE_PIN))
+               {
+                   pfree(tab[j] & PAGE_MASK);
+               }
+           }
+       }
+    }
+}

 page_entry_t * virt_map_remote_dir(process_t *proc)
 {
@@ -173,9 +198,9 @@

     /* Map kernel, APIC, initial stack and page directory. */
     virt_map(RDIR_VADDR, KERN_VADDR, KERN_VADDR,
-            kernel_size, PAGE_PR|PAGE_WR);
+            kernel_size, PAGE_PR|PAGE_WR|PAGE_PIN);
     virt_map(RDIR_VADDR, APIC_BASE, APIC_BASE,
-            PAGE_SIZE, PAGE_PR|PAGE_WR);
+            PAGE_SIZE, PAGE_PR|PAGE_WR|PAGE_PIN);
     virt_map(RDIR_VADDR, KERN_STACK, kern_stack,
             STACK_SIZE, PAGE_PR|PAGE_WR);
     virt_map(RDIR_VADDR, USER_STACK, user_stack,
@@ -184,4 +209,3 @@
     /* Done. */
     virt_unmap_remote_dir(proc);
 }
-

Other related posts:

  • » [freenos] r416 committed - Implemented api_proc_destroy() for deleting processes.... - freenos