summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpager/ChangeLog26
-rw-r--r--libpager/data-request.c4
-rw-r--r--libpager/data-return.c32
-rw-r--r--libpager/lock-object.c4
-rw-r--r--libpager/mark-error.c4
-rw-r--r--libpager/object-terminate.c4
-rw-r--r--libpager/offer-page.c4
-rw-r--r--libpager/pagemap.c9
-rw-r--r--libpager/priv.h17
9 files changed, 73 insertions, 31 deletions
diff --git a/libpager/ChangeLog b/libpager/ChangeLog
index 1b0e6a74..1ee91890 100644
--- a/libpager/ChangeLog
+++ b/libpager/ChangeLog
@@ -1,3 +1,29 @@
+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.
+
2000-01-24 Roland McGrath <roland@baalperazim.frob.com>
* pager-memcpy.c (pager_memcpy): Short-circuit return for zero size.
diff --git a/libpager/data-request.c b/libpager/data-request.c
index 0c6d1625..95ec6d27 100644
--- a/libpager/data-request.c
+++ b/libpager/data-request.c
@@ -1,5 +1,5 @@
/* Implementation of memory_object_data_request for pager library
- Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation
+ Copyright (C) 1994, 1995, 1996, 1997, 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
@@ -30,7 +30,7 @@ _pager_seqnos_memory_object_data_request (mach_port_t object,
vm_prot_t access)
{
struct pager *p;
- char *pm_entry;
+ short *pm_entry;
int doread, doerror;
error_t err;
vm_address_t page;
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);
diff --git a/libpager/lock-object.c b/libpager/lock-object.c
index 5182eff8..d108666e 100644
--- a/libpager/lock-object.c
+++ b/libpager/lock-object.c
@@ -1,5 +1,5 @@
/* Synchronous wrapper for memory_object_lock_request
- Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation
+ Copyright (C) 1993, 1994, 1996, 1997, 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
@@ -89,7 +89,7 @@ _pager_lock_object (struct pager *p,
_pager_pagemap_resize (p, offset + size);
if (p->pagemapsize > pm_offs)
{
- char *pm_entries = &p->pagemap[pm_offs];
+ short *pm_entries = &p->pagemap[pm_offs];
vm_offset_t bound = size / vm_page_size;
if (bound > p->pagemapsize)
diff --git a/libpager/mark-error.c b/libpager/mark-error.c
index 8b031479..5c4e029d 100644
--- a/libpager/mark-error.c
+++ b/libpager/mark-error.c
@@ -32,7 +32,7 @@ _pager_mark_next_request_error(struct pager *pager,
error_t error)
{
int page_error;
- char *p;
+ short *p;
offset /= __vm_page_size;
length /= __vm_page_size;
@@ -70,7 +70,7 @@ _pager_mark_object_error(struct pager *pager,
error_t error)
{
int page_error = 0;
- char *p;
+ short *p;
offset /= __vm_page_size;
length /= __vm_page_size;
diff --git a/libpager/object-terminate.c b/libpager/object-terminate.c
index 4315cbbb..dc53541c 100644
--- a/libpager/object-terminate.c
+++ b/libpager/object-terminate.c
@@ -1,5 +1,5 @@
/* Implementation of memory_object_terminate 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
@@ -124,7 +124,7 @@ _pager_free_structure (struct pager *p)
/* Free the pagemap */
if (p->pagemapsize)
{
- munmap (p->pagemap, p->pagemapsize);
+ munmap (p->pagemap, p->pagemapsize * sizeof (* p->pagemap));
p->pagemapsize = 0;
p->pagemap = 0;
}
diff --git a/libpager/offer-page.c b/libpager/offer-page.c
index 0d62da6a..aed22197 100644
--- a/libpager/offer-page.c
+++ b/libpager/offer-page.c
@@ -1,5 +1,5 @@
/* Wrapper for unsolicited memory_object_data_supply
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -32,7 +32,7 @@ pager_offer_page (struct pager *p,
if (_pager_pagemap_resize (p, offset + vm_page_size))
{
- char *pm_entry = &p->pagemap[offset / vm_page_size];
+ short *pm_entry = &p->pagemap[offset / vm_page_size];
while (*pm_entry & PM_INCORE)
{
diff --git a/libpager/pagemap.c b/libpager/pagemap.c
index c6d924c7..b8b3362c 100644
--- a/libpager/pagemap.c
+++ b/libpager/pagemap.c
@@ -1,5 +1,5 @@
/* Pagemap manipulation for pager library
- Copyright (C) 1994, 1997, 1999 Free Software Foundation
+ Copyright (C) 1994, 1997, 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
@@ -31,12 +31,13 @@ _pager_pagemap_resize (struct pager *p, vm_address_t off)
void *newaddr;
int newsize = round_page (off);
- newaddr = mmap (0, newsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ newaddr = mmap (0, newsize * sizeof (*p->pagemap),
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
err = (newaddr == (void *) -1) ? errno : 0;
if (! err)
{
- bcopy (p->pagemap, newaddr, p->pagemapsize);
- munmap (p->pagemap, p->pagemapsize);
+ bcopy (p->pagemap, newaddr, p->pagemapsize * sizeof (*p->pagemap));
+ munmap (p->pagemap, p->pagemapsize * sizeof (*p->pagemap));
p->pagemap = newaddr;
p->pagemapsize = newsize;
}
diff --git a/libpager/priv.h b/libpager/priv.h
index 0232e3e8..80afff1b 100644
--- a/libpager/priv.h
+++ b/libpager/priv.h
@@ -1,5 +1,5 @@
/* Private data for pager library.
- Copyright (C) 1994,95,96,97,99 Free Software Foundation, Inc.
+ Copyright (C) 1994,95,96,97,99, 2000 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -65,8 +65,8 @@ struct pager
struct pending_init *init_head, *init_tail;
#endif
- char *pagemap;
- int pagemapsize;
+ short *pagemap;
+ int pagemapsize; /* number of elements in PAGEMAP */
};
struct lock_request
@@ -108,11 +108,12 @@ extern int _pager_page_errors[];
/* Pagemap format */
/* These are binary state bits */
-/* #define PM_INIT 0x80 data has been written */
-#define PM_INCORE 0x80 /* kernel might have a copy */
-#define PM_PAGINGOUT 0x40 /* being written to disk */
-#define PM_PAGEINWAIT 0x20 /* provide data back when write done */
-#define PM_INVALID 0x10 /* data on disk is irrevocably wrong */
+#define PM_WRITEWAIT 0x0200 /* queue wakeup once write is done */
+#define PM_INIT 0x0100 /* data has been written */
+#define PM_INCORE 0x0080 /* kernel might have a copy */
+#define PM_PAGINGOUT 0x0040 /* being written to disk */
+#define PM_PAGEINWAIT 0x0020 /* provide data back when write done */
+#define PM_INVALID 0x0010 /* data on disk is irrevocably wrong */
/* These take values of enum page_errors */