The kernel invokes memory_object_data_return () with dirty = 0 in two cases: if notification on eviction was requested, or when returning precious pages. Properly distinguish between the two cases, and only throw the clean page away in the former case. --- libpager/data-return.c | 54 ++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 36 deletions(-)
diff --git a/libpager/data-return.c b/libpager/data-return.c index 2cc9f1f8..304e88bc 100644 --- a/libpager/data-return.c +++ b/libpager/data-return.c @@ -93,23 +93,6 @@ _pager_do_write_request (struct pager *p, pm_entries = &p->pagemap[offset / __vm_page_size]; - if (! dirty) - { - munmap ((void *) data, length); - if (!kcopy) { - /* Prepare notified array. */ - for (i = 0; i < npages; i++) - notified[i] = (p->notify_on_evict - && ! (pm_entries[i] & PM_PAGEINWAIT)); - - goto notify; - } - else { - _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 @@ -118,26 +101,24 @@ _pager_do_write_request (struct pager *p, /* XXX: Is this still needed? */ retry: for (i = 0; i < npages; i++) - if (pm_entries[i] & PM_PAGINGOUT) - { - pm_entries[i] |= PM_WRITEWAIT; - pthread_cond_wait (&p->wakeup, &p->interlock); - goto retry; + { + if ((initializing && (pm_entries[i] & PM_INIT)) || + (!dirty && !(pm_entries[i] & PM_PRECIOUS))) + { + omit_data[i] = 1; + continue; + } + if (pm_entries[i] & PM_PAGINGOUT) + { + pm_entries[i] |= PM_WRITEWAIT; + pthread_cond_wait (&p->wakeup, &p->interlock); + goto retry; } + } /* Mark these pages as being paged out. */ - if (initializing) - { - for (i = 0; i < npages; i++) - { - if (pm_entries[i] & PM_INIT) - omit_data[i] = 1; - else - pm_entries[i] |= PM_PAGINGOUT | PM_INIT; - } - } - else - for (i = 0; i < npages; i++) + for (i = 0; i < npages; i++) + if (!omit_data[i]) pm_entries[i] |= PM_PAGINGOUT | PM_INIT; /* If this write occurs while a lock is pending, record @@ -179,7 +160,9 @@ _pager_do_write_request (struct pager *p, { if (omit_data[i]) { - notified[i] = 0; + notified[i] = (p->notify_on_evict + && !kcopy + && ! (pm_entries[i] & PM_PAGEINWAIT)); continue; } @@ -225,7 +208,6 @@ _pager_do_write_request (struct pager *p, if (wakeup) pthread_cond_broadcast (&p->wakeup); - notify: _pager_allow_termination (p); pthread_mutex_unlock (&p->interlock); -- 2.31.1