summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaksym Planeta <mcsim.planeta@gmail.com>2012-09-30 15:05:23 +0300
committerMaksym Planeta <mcsim.planeta@gmail.com>2012-09-30 15:08:03 +0300
commitaa3331b4e79f005a8e0d1fb7b46a186eee75568f (patch)
treeca887a26e521d4abd6a40dfd09a88964dad9ff53
parent2ca8719606eeca99c425b3282017a6412b49213a (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.c36
-rw-r--r--libpager/pager.h9
-rw-r--r--libpager/priv.h1
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;