diff options
-rw-r--r-- | libpager/ChangeLog | 26 | ||||
-rw-r--r-- | libpager/data-request.c | 4 | ||||
-rw-r--r-- | libpager/data-return.c | 32 | ||||
-rw-r--r-- | libpager/lock-object.c | 4 | ||||
-rw-r--r-- | libpager/mark-error.c | 4 | ||||
-rw-r--r-- | libpager/object-terminate.c | 4 | ||||
-rw-r--r-- | libpager/offer-page.c | 4 | ||||
-rw-r--r-- | libpager/pagemap.c | 9 | ||||
-rw-r--r-- | libpager/priv.h | 17 |
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 */ |