summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael I. Bushnell <mib@gnu.org>1994-05-24 19:48:50 +0000
committerMichael I. Bushnell <mib@gnu.org>1994-05-24 19:48:50 +0000
commit7d60472c9e610f085729c69441407cf04c632d8a (patch)
treed8425a7d5a6137b70921895d7f58498ea05db5ee
parent3a14ab9fac5a6ce81ba1d59efc96b16953224a68 (diff)
Formerly data-return.c.~7~
-rw-r--r--libpager/data-return.c76
1 files changed, 48 insertions, 28 deletions
diff --git a/libpager/data-return.c b/libpager/data-return.c
index 4aa32dc9..014a8af9 100644
--- a/libpager/data-return.c
+++ b/libpager/data-return.c
@@ -32,8 +32,10 @@ _pager_seqnos_memory_object_data_return (mach_port_t object,
int kcopy)
{
struct pager *p;
- char *pm_entry;
+ char *pm_entries;
error_t err;
+ int npages, i;
+ error_t *pagerrs;
struct lock_request *lr;
struct lock_list {struct lock_request *lr;
struct lock_list *next;} *lock_list, *ll;
@@ -45,19 +47,19 @@ _pager_seqnos_memory_object_data_return (mach_port_t object,
/* sanity checks -- we don't do multi-page requests yet. */
if (control != p->memobjcntl)
{
- printf ("incg data request: wrong control port");
+ printf ("incg data return: wrong control port\n");
err = 0;
goto out;
}
- if (length != __vm_page_size)
+ if (length % __vm_page_size)
{
- printf ("incg data request: bad length size");
+ printf ("incg data return: bad length size %d\n", length);
err = 0;
goto out;
}
if (offset % __vm_page_size)
{
- printf ("incg data request: misaligned request");
+ printf ("incg data return: misaligned request\n");
err = 0;
goto out;
}
@@ -68,6 +70,9 @@ _pager_seqnos_memory_object_data_return (mach_port_t object,
goto out;
}
+ npages = length / __vm_page_size;
+ pagerrs = alloca (npages * sizeof (error_t));
+
/* Acquire the right to meddle with the pagemap */
mutex_lock (&p->interlock);
_pager_wait_for_seqno (p, seqno);
@@ -85,11 +90,11 @@ _pager_seqnos_memory_object_data_return (mach_port_t object,
_pager_pagemap_resize (p, offset + length);
- pm_entry = &p->pagemap[offset / __vm_page_size];
-
- /* Mark this page as being paged out. */
- *pm_entry |= PM_PAGINGOUT;
+ pm_entries = &p->pagemap[offset / __vm_page_size];
+ /* Mark these pages as being paged out. */
+ for (i = 0; i < npages; i++)
+ pm_entries[i] |= PM_PAGINGOUT;
/* If this write occurs while a lock is pending, record
it. We have to keep this list because a lock request
@@ -112,29 +117,44 @@ _pager_seqnos_memory_object_data_return (mach_port_t object,
_pager_release_seqno (p);
mutex_unlock (&p->interlock);
- err = pager_write_page (p->upi, offset, data);
+ /* This is inefficient; we should send all the pages to the device at once
+ but until the pager library interface is changed, this will have to do. */
+
+ for (i = 0; i < npages; i++)
+ pagerrs[i] = pager_write_page (p->upi,
+ offset + (vm_page_size * i),
+ data + (vm_page_size * i));
/* Acquire the right to meddle with the pagemap */
mutex_lock (&p->interlock);
_pager_pagemap_resize (p, offset + length);
- pm_entry = &p->pagemap[offset / __vm_page_size];
-
- if (err && ! (*pm_entry & 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 imperfect, because
- if all users go away, the pagemap will be freed, and this information
- lost. Oh well. It's still better than Un*x. Of course, if we
- are about to hand this data to the kernel, the error isn't a problem,
- hence the check for pageinwait. */
- *pm_entry |= PM_INVALID;
-
- if (*pm_entry & PM_PAGEINWAIT)
- memory_object_data_supply (p->memobjcntl, offset, data, length, 1,
- VM_PROT_NONE, 0, MACH_PORT_NULL);
- else
- vm_deallocate (mach_task_self (), data, length);
-
- *pm_entry &= ~(PM_PAGINGOUT | PM_PAGEINWAIT);
+ pm_entries = &p->pagemap[offset / __vm_page_size];
+
+ for (i = 0; i < npages; i++)
+ {
+ 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
+ imperfect, because if all users go away, the pagemap will
+ be freed, and this information lost. Oh well. It's still
+ better than Un*x. Of course, if we are about to hand this
+ data to the kernel, the error isn't a problem, hence the
+ check for pageinwait. */
+ pm_entries[i] |= PM_INVALID;
+
+ if (pm_entries[i] & PM_PAGEINWAIT)
+ memory_object_data_supply (p->memobjcntl,
+ offset + (vm_page_size * i),
+ data + (vm_page_size * i),
+ vm_page_size, 1,
+ VM_PROT_NONE, 0, MACH_PORT_NULL);
+ else
+ vm_deallocate (mach_task_self (),
+ data + (vm_page_size * i),
+ vm_page_size);
+
+ pm_entries[i] &= ~(PM_PAGINGOUT | PM_PAGEINWAIT);
+ }
wakeup = 0;
for (ll = lock_list; ll; ll = ll->next)