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); } -