summaryrefslogtreecommitdiff
path: root/libhurd-mm/pager.c
diff options
context:
space:
mode:
authorneal <neal>2008-06-16 21:27:40 +0000
committerneal <neal>2008-06-16 21:27:40 +0000
commit0cc9b9efcad805a9118c368b72b13417315526c9 (patch)
tree03548e0caa9ec35d3f5326195e9b3ecc30d40679 /libhurd-mm/pager.c
parent64639177cfc19f25b4c65ec7a8f8af110264c907 (diff)
libhurd-mm/
2008-06-16 Neal H. Walfield <neal@gnu.org> * map.h: New file. * map.c: New file. * Makefile.am (libhurd_mm_a_SOURCES): Add map.h and map.c. * headers.m4: Link map.h to sysroot/include/hurd/map.h. * pager.h: Rewrite. * pager.c: Likewise. * anonymous.h (ANONYMOUS_STAGING_AREA): New define. (anonymous_pager_fill_t): Don't pass the base of the region. Pass the location of the storage corresponding to the pages on which the faults were raised and the offset into the region. Update users. (struct anonymous_pager): Add fields map_area, map_area_count and lock. Remove field alloced_region. (anonymous_pager_alloc): Replace size parameter with length parameter. Take access parameter indicating the desired access. Update users. * anonymous.c (offset_compare): Compare the values, not the pointers. (fault): Update signature to be consistent with new API. Lock ANON->LOCK. Always look up the storage descriptor corresponding to the faulted page. Copy the storage to the faulted address as required. Update how we call ANON->FILL to be consistent with the new API. (destroy): Free ANON->STAGING_AREA. (anonymous_pager_alloc): Update signature to be consistent with new API. Allocate the staging area if ANONYMOUS_STAGING_AREA is set. Allocate it separately from the main map. Create a map corresponding to the region. (anonymous_pager_destroy): Just lock ANON->LOCK. Don't call destroy, call pager_deinit. * mmap.c: Include <hurd/map.h>. (mmap): Add support for protection other than read/write. (munmap): Rewrite to use new API. Use map_split to support splitting of memory maps. * exceptions.c: Don't include "pager.h", include "map.h". (exception_handler_normal): Don't call pager_fault but map_fault. (exception_handler_activated): Likewise. ruth/ 2008-06-16 Neal H. Walfield <neal@gnu.org> * ruth.c (main): Improve mmap test. Update use of anonymous_pager_alloc to be consistent with new API. Update fill functions to be consistent with new API. Remove redundant test. benchmarks/ 2008-06-16 Neal H. Walfield <neal@gnu.org> * activity-distribution.c (main): Update use of anonymous_pager_alloc to be consistent with new API. Update fill functions to be consistent with new API.
Diffstat (limited to 'libhurd-mm/pager.c')
-rw-r--r--libhurd-mm/pager.c122
1 files changed, 33 insertions, 89 deletions
diff --git a/libhurd-mm/pager.c b/libhurd-mm/pager.c
index bd639ea..a00927d 100644
--- a/libhurd-mm/pager.c
+++ b/libhurd-mm/pager.c
@@ -1,5 +1,5 @@
-/* pager.c - Generic pager implementation.
- Copyright (C) 2007 Free Software Foundation, Inc.
+/* map.c - Generic map implementation.
+ Copyright (C) 2007, 2008 Free Software Foundation, Inc.
Written by Neal H. Walfield <neal@gnu.org>.
This file is part of the GNU Hurd.
@@ -22,113 +22,57 @@
#include <config.h>
#endif
+#include <string.h>
+
#include "pager.h"
-/* Protects PAGERS and all pager's NODE. This lock may not be taken
- if a pager's LOCK is held by the caller. */
-ss_mutex_t pagers_lock;
-hurd_btree_pager_t pagers;
+extern ss_mutex_t maps_lock;
bool
-pager_install (struct pager *pager)
+pager_init (struct pager *pager)
{
- assert (! ss_mutex_trylock (&pagers_lock));
-
assert (pager->fault);
- assert (pager->region.count);
+ assert (pager->length);
+ assert ((pager->length & (PAGESIZE - 1)) == 0);
- debug (3, "Installing pager at " ADDR_FMT "+%d",
- ADDR_PRINTF (pager->region.start), pager->region.count);
+ debug (3, "Creating pager with size %x (%d pages)",
+ pager->length, pager->length / PAGESIZE);
- struct pager *conflict = hurd_btree_pager_insert (&pagers, pager);
- if (conflict)
- {
- debug (1, "Can't install pager at " ADDR_FMT "+%d; conflicts "
- "with pager at " ADDR_FMT "+%d",
- ADDR_PRINTF (pager->region.start), pager->region.count,
- ADDR_PRINTF (conflict->region.start), conflict->region.count);
- return false;
- }
+ pager->maps = 0;
return true;
}
-bool
-pager_relocate (struct pager *pager, struct pager_region region)
-{
- assert (! ss_mutex_trylock (&pagers_lock));
-
- /* XXX: Grows could be a bit smarter. We could check the next and
- previous pointers, for instance. */
-
- /* Detach the pager. */
- hurd_btree_pager_detach (&pagers, pager);
-
- /* Save the old region in case there is a conflict. */
- struct pager_region old = pager->region;
-
- pager->region = region;
- struct pager *conflict = hurd_btree_pager_insert (&pagers, pager);
- if (conflict)
- /* There is a conflict. Insert the pager back where it was. */
- {
- pager->region = old;
- conflict = hurd_btree_pager_insert (&pagers, pager);
- assert (! conflict);
-
- return false;
- }
- return true;
-}
-
void
-pager_deinstall (struct pager *pager)
+pager_deinit (struct pager *pager)
{
- assert (! ss_mutex_trylock (&pagers_lock));
-
- hurd_btree_pager_detach (&pagers, pager);
-}
+ maps_lock_lock ();
-static void __attribute__ ((noinline))
-ensure_stack (int i)
-{
- /* XXX: If we fault on the stack while we have PAGERS_LOCK, we
- deadlock. Ensure that we have some stack space and hope it is
- enough. (This can't be too much as we may be running on the
- exception handler's stack.) */
- volatile char space[EXCEPTION_STACK_SIZE - PAGESIZE];
- int j;
- for (j = sizeof (space) - 1; j >= 0; j -= PAGESIZE)
- space[j] = i;
-}
+ /* Destroy all but one references with MAPS_LOCK held. */
+ ss_mutex_lock (&pager->lock);
+ while (pager->maps)
+ {
+ struct map *map = pager->maps;
+ map_disconnect (map);
-bool
-pager_fault (addr_t addr, uintptr_t ip, struct exception_info info)
-{
- /* Find the pager. */
- struct pager_region region;
- region.start = addr;
- region.count = 1;
+ if (! map->map_list_next)
+ {
+ maps_lock_unlock ();
- ensure_stack (1);
+ map_destroy (map);
- ss_mutex_lock (&pagers_lock);
+ return;
+ }
- struct pager *pager = hurd_btree_pager_find (&pagers, &region);
- if (! pager)
- {
- debug (3, "No pager covers " ADDR_FMT, ADDR_PRINTF (addr));
- ss_mutex_unlock (&pagers_lock);
- return false;
+ /* This drops PAGER->LOCK. */
+ map_destroy (map);
+ ss_mutex_lock (&pager->lock);
}
- ss_mutex_lock (&pager->lock);
- ss_mutex_unlock (&pagers_lock);
-
- /* Propagate the fault. */
- bool r = pager->fault (pager, addr, ip, info);
- if (! r)
- debug (3, "Pager did not fault " ADDR_FMT, ADDR_PRINTF (addr));
+ ss_mutex_unlock (&pager->lock);
+ maps_lock_unlock ();
- return r;
+ /* PAGER may no longer be valid: destroying the last mapping will
+ have called pager's no refs callback, which may have destroyed
+ PAGER. */
}