Messages in this thread Patch in this message |  | | | Date | Fri, 18 Dec 2009 09:43:36 +0900 | | From | KAMEZAWA Hiroyuki <> | | Subject | [RFC 2/4] add mm event counter |
| |
From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Add version counter to mm_struct. It's updated when write_lock is held and released. And this patch also adds task->mm_version. By this, mm_semaphore can provides some operation like seqlock.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> --- include/linux/mm_types.h | 1 + include/linux/sched.h | 2 +- mm/mm_accessor.c | 29 ++++++++++++++++++++++++++--- 3 files changed, 28 insertions(+), 4 deletions(-) Index: mmotm-mm-accessor/include/linux/mm_types.h =================================================================== --- mmotm-mm-accessor.orig/include/linux/mm_types.h +++ mmotm-mm-accessor/include/linux/mm_types.h @@ -216,6 +216,7 @@ struct mm_struct { atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */ int map_count; /* number of VMAs */ struct rw_semaphore mmap_sem; + int version; spinlock_t page_table_lock; /* Protects page tables and some counters */ struct list_head mmlist; /* List of maybe swapped mm's. These are globally strung Index: mmotm-mm-accessor/include/linux/sched.h =================================================================== --- mmotm-mm-accessor.orig/include/linux/sched.h +++ mmotm-mm-accessor/include/linux/sched.h @@ -1276,7 +1276,7 @@ struct task_struct { struct plist_node pushable_tasks; struct mm_struct *mm, *active_mm; - + int mm_version; /* task state */ int exit_state; int exit_code, exit_signal; Index: mmotm-mm-accessor/mm/mm_accessor.c =================================================================== --- mmotm-mm-accessor.orig/mm/mm_accessor.c +++ mmotm-mm-accessor/mm/mm_accessor.c @@ -1,15 +1,20 @@ -#include <linux/mm_types.h> +#include <linux/sched.h> #include <linux/module.h> void mm_read_lock(struct mm_struct *mm) { down_read(&mm->mmap_sem); + if (current->mm == mm && current->mm_version != mm->version) + current->mm_version = mm->version; } EXPORT_SYMBOL(mm_read_lock); int mm_read_trylock(struct mm_struct *mm) { - return down_read_trylock(&mm->mmap_sem); + int ret = down_read_trylock(&mm->mmap_sem); + if (ret && current->mm == mm && current->mm_version != mm->version) + current->mm_version = mm->version; + return ret; } EXPORT_SYMBOL(mm_read_trylock); @@ -22,18 +27,24 @@ EXPORT_SYMBOL(mm_read_unlock); void mm_write_lock(struct mm_struct *mm) { down_write(&mm->mmap_sem); + mm->version++; } EXPORT_SYMBOL(mm_write_lock); void mm_write_unlock(struct mm_struct *mm) { + mm->version++; up_write(&mm->mmap_sem); } EXPORT_SYMBOL(mm_write_unlock); int mm_write_trylock(struct mm_struct *mm) { - return down_write_trylock(&mm->mmap_sem); + int ret = down_write_trylock(&mm->mmap_sem); + + if (ret) + mm->version++; + return ret; } EXPORT_SYMBOL(mm_write_trylock); @@ -45,6 +56,7 @@ EXPORT_SYMBOL(mm_is_locked); void mm_write_to_read_lock(struct mm_struct *mm) { + mm->version++; downgrade_write(&mm->mmap_sem); } EXPORT_SYMBOL(mm_write_to_read_lock); @@ -78,3 +90,14 @@ void mm_read_might_lock(struct mm_struct might_lock_read(&mm->mmap_sem); } EXPORT_SYMBOL(mm_read_might_lock); + +/* + * Called when mm is accessed without read-lock or for chekcing + * per-thread cached value is stale or not. + */ +int mm_version_check(struct mm_struct *mm) +{ + if ((current->mm == mm) && (current->mm_version != mm->version)) + return 0; + return 1; +}
|  |