From dd596a2a7870f1a68cd5238f10afb28cc132693f Mon Sep 17 00:00:00 2001 From: "Masamichi Takagi m-takagi@ab.jp.nec.com" Date: Tue, 9 Oct 2012 11:40:49 +0900 Subject: [PATCH] lock when changing process memory region (in syscall.c) and page-table (in process.c) --- kernel/include/process.h | 8 ++++++++ kernel/process.c | 5 +++++ kernel/syscall.c | 6 ++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/kernel/include/process.h b/kernel/include/process.h index 1ee4cf29..f1bbf217 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -69,6 +69,14 @@ struct process_vm { // Address space private futexes struct futex_queue futex_queues[1 << FUTEX_HASHBITS]; + + aal_spinlock_t page_table_lock; + aal_spinlock_t memory_range_lock; + // to protect the followings: + // 1. addition of process "memory range" (extend_process_region, add_process_memory_range) + // 2. addition of process page table (allocate_pages, update_process_page_table) + // note that physical memory allocator (aal_mc_alloc_pages, aal_pagealloc_alloc) + // is protected by its own lock (see aal/manycore/generic/page_alloc.c) }; diff --git a/kernel/process.c b/kernel/process.c index 6a241d9c..b7e9efcd 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -89,6 +89,7 @@ void update_process_page_table(struct process *process, struct vm_range *range, { unsigned long p, pa = range->phys; + unsigned long flags = aal_mc_spinlock_lock(&process->vm->page_table_lock); p = range->start; while (p < range->end) { aal_mc_pt_set_page(process->vm->page_table, (void *)p, @@ -98,6 +99,7 @@ void update_process_page_table(struct process *process, struct vm_range *range, p += PAGE_SIZE; } + aal_mc_spinlock_unlock(&process->vm->page_table_lock, flags); } int add_process_large_range(struct process *process, @@ -282,15 +284,18 @@ unsigned long extend_process_region(struct process *proc, int remove_process_region(struct process *proc, unsigned long start, unsigned long end) { + unsigned long flags; if ((start & (PAGE_SIZE - 1)) || (end & (PAGE_SIZE - 1))) { return -EINVAL; } + flags = aal_mc_spinlock_lock(&proc->vm->page_table_lock); /* We defer freeing to the time of exit */ while (start < end) { aal_mc_pt_clear_page(proc->vm->page_table, (void *)start); start += PAGE_SIZE; } + aal_mc_spinlock_unlock(&proc->vm->page_table_lock, flags); return 0; } diff --git a/kernel/syscall.c b/kernel/syscall.c index 12287bc0..5cd1670c 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -384,6 +384,7 @@ SYSCALL_DECLARE(mmap) } else if ((aal_mc_syscall_arg3(ctx) & 0x20) == 0x20) { // #define MAP_ANONYMOUS 0x20 kprintf("syscall.c,!MAP_FIXED,MAP_ANONYMOUS\n"); + unsigned long flags = aal_mc_spinlock_lock(&cpu_local_var(current)->vm->memory_range_lock); unsigned long s = (region->map_end + PAGE_SIZE - 1) & PAGE_MASK; unsigned long len = (aal_mc_syscall_arg1(ctx) + PAGE_SIZE - 1) & PAGE_MASK; // lockr = aal_mc_spinlock_lock(&cpu_status_lock); @@ -392,13 +393,14 @@ SYSCALL_DECLARE(mmap) region->map_start, region->map_end, s + len); - // aal_mc_spinlock_unlock(&cpu_status_lock, lockr); + aal_mc_spinlock_unlock(&cpu_local_var(current)->vm->memory_range_lock, flags); kprintf("syscall.c,returning to caller...\n"); if (region->map_end == s + len) { return s; } else { return -EINVAL; } } else if ((aal_mc_syscall_arg3(ctx) & 0x02) == 0x02) { // #define MAP_PRIVATE 0x02 + unsigned long flags = aal_mc_spinlock_lock(&cpu_local_var(current)->vm->memory_range_lock); unsigned long s = (region->map_end + PAGE_SIZE - 1) & PAGE_MASK; unsigned long len = (aal_mc_syscall_arg1(ctx) + PAGE_SIZE - 1) & PAGE_MASK; // lockr = aal_mc_spinlock_lock(&cpu_status_lock); @@ -407,7 +409,7 @@ SYSCALL_DECLARE(mmap) region->map_start, region->map_end, s + len); - // aal_mc_spinlock_unlock(&cpu_status_lock, lockr); + aal_mc_spinlock_unlock(&cpu_local_var(current)->vm->memory_range_lock, flags); if (region->map_end != s + len) { return -EINVAL; } struct syscall_request request AAL_DMA_ALIGN;