aboutsummaryrefslogtreecommitdiff
path: root/libpager/data-return.c
diff options
context:
space:
mode:
authorThomas Bushnell <thomas@gnu.org>2000-07-25 19:40:27 +0000
committerThomas Bushnell <thomas@gnu.org>2000-07-25 19:40:27 +0000
commit2f7e8f040f18b7f9bce6879d4b077094aa7d01c0 (patch)
tree80be9465da90cda7839b49574a3c232880b8fe49 /libpager/data-return.c
parent0e0bcad3e157579dbeafec933ac6ccbc00a515a3 (diff)
downloadhurd-2f7e8f040f18b7f9bce6879d4b077094aa7d01c0.tar.gz
hurd-2f7e8f040f18b7f9bce6879d4b077094aa7d01c0.tar.bz2
hurd-2f7e8f040f18b7f9bce6879d4b077094aa7d01c0.zip
2000-07-25 Thomas Bushnell, BSG <tb@mit.edu>
* priv.h (PM_WRITEWAIT): New pagemap bit. * data-return.c (_pager_do_write_request): Don't proceed with a pageout if one is already in progress. Once we finish, wake up any potential PM_WRITEWAIT waiters. * priv.h (PM_INIT): Provide value again. * data-return.c (_pager_do_write_request): Track PM_INIT again. * priv.h (struct pager): Make pagemap consist of 16-bit elements instead of only 8 bits. * data-request.c (_pager_seqnos_memory_object_data_request): Make PM_ENTRY a short pointer. * data-return.c (_pager_do_write_request): Make PM_ENTRIES a short pointer. * lock-object.c (_pager_lock_object): Make PM_ENTRIES a short pointer. * mark-error.c (_pager_mark_next_request_error): Make P a short pointer. (_pager_mark_object_error): Likewise. * offer-page.c (pager_offer_page): Make PM_ENTRY a short pointer. * object-terminate.c (_pager_free_structure): Interpret pagemapsize correctly. * pagemap.c (_pager_pagemap_resize): Likewise.
Diffstat (limited to 'libpager/data-return.c')
-rw-r--r--libpager/data-return.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/libpager/data-return.c b/libpager/data-return.c
index 9f107793..a83026fc 100644
--- a/libpager/data-return.c
+++ b/libpager/data-return.c
@@ -1,5 +1,5 @@
/* Implementation of memory_object_data_return for pager library
- Copyright (C) 1994, 1995, 1996, 1999 Free Software Foundation
+ Copyright (C) 1994, 1995, 1996, 1999, 2000 Free Software Foundation
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -37,7 +37,7 @@ _pager_do_write_request (mach_port_t object,
int initializing)
{
struct pager *p;
- char *pm_entries;
+ short *pm_entries;
int npages, i;
error_t *pagerrs;
struct lock_request *lr;
@@ -90,8 +90,21 @@ _pager_do_write_request (mach_port_t object,
pm_entries = &p->pagemap[offset / __vm_page_size];
+ /* 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
+ this object are going to wait for seqno while we wait for the
+ previous write), but the case is relatively infrequent. */
+ retry:
+ for (i = 0; i < npages; i++)
+ if (pm_entries[i] & PM_PAGINGOUT)
+ {
+ pm_entries[i] |= PM_WRITEWAIT;
+ condition_wait (&p->wakeup, &p->interlock);
+ goto retry;
+ }
+
/* Mark these pages as being paged out. */
-#if 0
if (initializing)
{
assert (npages <= 32);
@@ -106,13 +119,10 @@ _pager_do_write_request (mach_port_t object,
else
for (i = 0; i < npages; i++)
pm_entries[i] |= PM_PAGINGOUT | PM_INIT;
-#else
- for (i = 0; i < npages; i++)
- pm_entries[i] |= PM_PAGINGOUT;
+
if (!kcopy)
for (i = 0; i < npages; i++)
pm_entries[i] &= ~PM_INCORE;
-#endif
/* If this write occurs while a lock is pending, record
it. We have to keep this list because a lock request
@@ -149,11 +159,15 @@ _pager_do_write_request (mach_port_t object,
_pager_pagemap_resize (p, offset + length);
pm_entries = &p->pagemap[offset / __vm_page_size];
+ wakeup = 0;
for (i = 0; i < npages; i++)
{
if (omitdata & (1 << i))
continue;
+ if (pm_entries[i] & PM_WRITEWAIT)
+ wakeup = 1;
+
if (pagerrs[i] && ! (pm_entries[i] & PM_PAGEINWAIT))
/* The only thing we can do here is mark the page, and give
errors from now on when it is to be read. This is
@@ -174,13 +188,13 @@ _pager_do_write_request (mach_port_t object,
munmap ((caddr_t) (data + (vm_page_size * i)),
vm_page_size);
- pm_entries[i] &= ~(PM_PAGINGOUT | PM_PAGEINWAIT);
+ pm_entries[i] &= ~(PM_PAGINGOUT | PM_PAGEINWAIT | PM_WRITEWAIT);
}
- wakeup = 0;
for (ll = lock_list; ll; ll = ll->next)
if (!--ll->lr->pending_writes && !ll->lr->locks_pending)
wakeup = 1;
+
if (wakeup)
condition_broadcast (&p->wakeup);