diff options
author | Maksym Planeta <mcsim.planeta@gmail.com> | 2012-09-30 15:05:23 +0300 |
---|---|---|
committer | Maksym Planeta <mcsim.planeta@gmail.com> | 2012-09-30 15:08:03 +0300 |
commit | aa3331b4e79f005a8e0d1fb7b46a186eee75568f (patch) | |
tree | ca887a26e521d4abd6a40dfd09a88964dad9ff53 | |
parent | 2ca8719606eeca99c425b3282017a6412b49213a (diff) |
Add notification interface to libpager.
* libpager/data-return.c (_pager_seqnos_memory_object_data_return):
Notify pager on data eviction.
* libpager/priv.h (struct pager): New field.
* libpager/pager.h (struct pager_ops): New field.
-rw-r--r-- | libpager/data-return.c | 36 | ||||
-rw-r--r-- | libpager/pager.h | 9 | ||||
-rw-r--r-- | libpager/priv.h | 1 |
3 files changed, 43 insertions, 3 deletions
diff --git a/libpager/data-return.c b/libpager/data-return.c index 08255e3d..b8fb920c 100644 --- a/libpager/data-return.c +++ b/libpager/data-return.c @@ -37,6 +37,7 @@ _pager_seqnos_memory_object_data_return (mach_port_t object, off_t start; int npages; int i; + char notified; struct lock_request *lr; struct lock_list {struct lock_request *lr; struct lock_list *next;} *lock_list, *ll; @@ -66,9 +67,6 @@ _pager_seqnos_memory_object_data_return (mach_port_t object, goto release_out; } - if (! dirty) - goto release_out; - if (p->pager_state != NORMAL) { printf ("pager in wrong state for write\n"); @@ -85,6 +83,20 @@ _pager_seqnos_memory_object_data_return (mach_port_t object, pm_entries = &p->pagemap[start]; + /* Prepare notified flag. */ + notified = !kcopy && p->ops->notify_evict; + if (! dirty && ! kcopy) + { + _pager_release_seqno (p, seqno); + goto notify; + } + + if (! dirty) + { + _pager_allow_termination (p); + goto release_out; + } + /* Make sure there are no other in-progress writes for any of these pages before we begin. This imposes a little more serialization than we really have to require (because *all* future writes on @@ -151,6 +163,24 @@ _pager_seqnos_memory_object_data_return (mach_port_t object, if (wakeup) condition_broadcast (&p->wakeup); + notify: + + if (notified) + { + for (i = 0; i < npages; i++) + { + short *pm_entry = &pm_entries[i]; + + /* Clear any error that is left. Notification on eviction + is used only to change association of page, so any + error may no longer be valid. */ + *pm_entry = SET_PM_ERROR (SET_PM_NEXTERROR (*pm_entry, 0), 0); + } + + /* Do notify user. */ + p->ops->notify_evict ((struct user_pager_info *) &p->upi, + start, npages); + } _pager_allow_termination (p); mutex_unlock (&p->interlock); ports_port_deref (p); diff --git a/libpager/pager.h b/libpager/pager.h index 1f73078a..d8b38978 100644 --- a/libpager/pager.h +++ b/libpager/pager.h @@ -76,6 +76,15 @@ struct pager_ops If the user doesn't either, then it's OK for this function to do nothing or be set to NULL. */ void (*dropweak)(struct user_pager_info *upi); + + /* The user may define this function. If non-NULL, it is called when + you want be able to change association of pages to backing store. + You can change association of page only when notify_evict has been + called and you haven't touched page content after that. Note there + is a possibility that a page is evicted, but user is not notified + about that. The user should be able to handle this case. */ + void (*notify_evict) (struct user_pager_info *upi, off_t page, + off_t npages); }; /* This de-muxer function is for use within libports_demuxer. */ diff --git a/libpager/priv.h b/libpager/priv.h index e7665d3e..238023e2 100644 --- a/libpager/priv.h +++ b/libpager/priv.h @@ -53,6 +53,7 @@ struct pager boolean_t may_cache; memory_object_copy_strategy_t copy_strategy; + boolean_t notify_on_evict; /* Interface ports */ memory_object_control_t memobjcntl; |