diff options
Diffstat (limited to 'libpager')
-rw-r--r-- | libpager/ChangeLog | 374 | ||||
-rw-r--r-- | libpager/Makefile | 3 | ||||
-rw-r--r-- | libpager/data-init.c | 34 | ||||
-rw-r--r-- | libpager/data-request.c | 38 | ||||
-rw-r--r-- | libpager/data-return.c | 57 | ||||
-rw-r--r-- | libpager/data-unlock.c | 13 | ||||
-rw-r--r-- | libpager/demuxer.c | 16 | ||||
-rw-r--r-- | libpager/lock-object.c | 21 | ||||
-rw-r--r-- | libpager/mark-error.c | 24 | ||||
-rw-r--r-- | libpager/notify-stubs.c | 43 | ||||
-rw-r--r-- | libpager/object-create.c | 73 | ||||
-rw-r--r-- | libpager/object-terminate.c | 22 | ||||
-rw-r--r-- | libpager/offer-page.c | 30 | ||||
-rw-r--r-- | libpager/pagemap.c | 38 | ||||
-rw-r--r-- | libpager/pager-memcpy.c | 195 | ||||
-rw-r--r-- | libpager/pager.h | 10 | ||||
-rw-r--r-- | libpager/priv.h | 35 | ||||
-rw-r--r-- | libpager/seqnos.c | 26 | ||||
-rw-r--r-- | libpager/stubs.c | 18 |
19 files changed, 396 insertions, 674 deletions
diff --git a/libpager/ChangeLog b/libpager/ChangeLog deleted file mode 100644 index ed8e3cca..00000000 --- a/libpager/ChangeLog +++ /dev/null @@ -1,374 +0,0 @@ -Thu May 9 11:10:11 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * pager-create.c: Get rid of link warning. - - * pager-create.c (pager_create): ports_allocate_port -> - ports_create_port; if we get an error return a null structure. - -Thu May 2 11:17:17 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * offer-page.c (pager_offer_page): Make sure we hold lock across - operation. Also set incore bit when operation is complete. - -Tue Apr 30 12:40:33 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * lock-object.c (_pager_lock_object): Eliminate spurious extra - lock acquisition around pagemap frobbing. - -Sun Apr 28 15:46:12 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> - - * pager-create.c (pager_create): Add link warning. - -Thu Apr 18 13:03:55 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * data-return.c (_pager_do_write_request): If kernel didn't keep a - copy, turn off INCORE bit. Don't track INIT bit for now. - * lock-object.c (_pager_lock_object): If SYNC and SHOULD_FLUSH, - then turn off PM_INCORE bits when flush is complete. - * data-request.c (_pager_seqnos_memory_object_data_request): Set - PM_INCORE. - * priv.h (PM_INIT): Comment out. - (PM_INCORE): New bit. - * offer-page.c: New file. - * Makefile (SRCS): Add offer-page.c. - * pager.h (pager_offer_page): New function. - -Thu Apr 11 17:50:57 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * pager-memcpy.c (pager_memcpy [copy]): Return error_t so that - this function has the proper type as an arg for - hurd_catch_signal. - (pager_memcpy): Cast FAULT to proper type in call to - hurd_catch_signal. - -Tue Mar 26 15:38:06 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * lock-completed.c: Include <stdio.h>. - - * data-return.c (_pager_do_write_request): Delete unused label - `out'. - - * pager-sync.c (pager_sync, pager_sync_some): Ask for RETURN_ALL - and not just RETURN_DIRTY, because we treat precious pages as - dirty in this library. - * pager-return.c (pager_return, pager_return_some): Likewise. - -Mon Mar 18 13:10:32 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * pager.h (pager_return, pager_return_some): New declarations. - * Makefile (SRCS): Add pager-return.c. - * pager-return.c: New file. - - * pager-flush.c (pager_flush): Lock request should be - VM_PROT_NO_CHANGE, not VM_PROT_NONE. - (pager_flush_some): Likewise. - -Wed Mar 6 17:53:20 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * lock-object.c (_pager_lock_object): Correctly remove LR from - P's linked list of lock requests. - * pager-attr.c (pager_change_attributes): Likewise for attributes. - - * lock-object.c (_pager_lock_object): Don't barf anymore. - * lock-completed.c (_pager_seqnos_memory_object_lock_completed): Ditto. - * Makefile (SRCS): Remove barf.c. - -Wed Feb 21 14:15:26 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * lock-completed.c (_pager_seqnos_memory_object_lock_completed): - Get rid of bletcherous semi. - Make barf more voluminous. - - * lock-completed.c (_pager_seqnos_memory_object_lock_completed): - Be picky about always releasing SEQNO. - * object-init.c (_pager_seqnos_memory_object_init): Likewise. - -Tue Feb 20 17:44:59 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * lock-object.c (_pager_lock_object): Use barf instead of printf. - * lock-completed.c (_pager_seqnos_memory_object_lock_completed): Ditto. - * Makefile (SRCS): Add barf.c. - - * data-return.c (_pager_do_write_request): Always wait for and - release SEQNO if OBJECT is a valid pager. - * data-request.c (_pager_seqnos_memory_object_data_request): Likewise. - * object-terminate.c (_pager_seqnos_memory_object_terminate): Likewise. - -Tue Feb 20 16:05:42 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * lock-object.c (_pager_lock_object): Print debugging message when - SYNC. - * lock-completed.c (_pager_seqnos_memory_object_lock_completed): - Print a notice when an incoming lock completion corresponds to no - outstanding lock request. - -Tue Feb 20 15:10:29 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * lock-object.c (_pager_lock_object): Remove `sync = 0'. - -Fri Jan 5 17:09:43 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * pager-memcpy.c: New file. - * Makefile (SRCS): Add pager-memcpy.c. - -Thu Jan 4 15:37:21 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * pager.h: Declare pager_memcpy. - -Mon Oct 9 14:57:48 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * priv.h: Declare _pager_page_errors extern, not common. - - * Makefile: Specify shared library dependencies. - -Wed Sep 13 14:49:53 1995 Michael I. Bushnell, p/BSG <mib@duality.gnu.ai.mit.edu> - - * lock-completed.c (_pager_seqnos_memory_object_lock_completed): - Don't push the locks_pending field negative in the case where the - pager was terminated before we get called. - -Tue Sep 5 15:50:12 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * chg-compl.c (_pager_seqnos_memory_object_change_completed): - Don't push the attrs_pending field negative in the case where the - pager was terminated before we get called. - -Wed Aug 23 15:00:46 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * Makefile (SRCS): Make this the main list of files, from which - the others are derived. - (COBJS, REMHDRS): Removed. - (OBJS): Derived mostly from $(SRCS). - -Fri Jul 21 16:43:19 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * object-create.c (_pager_seqnos_memory_object_create): Drop - initial reference created by ports_intern_external_reference when - we're done with P. - -Thu Jul 6 15:36:36 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> - - * Makefile: Removed dependencies that are now automatically - generated. - -Mon Jun 26 20:15:03 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> - - * get-upi.c: New file. - * pager.h (pager_get_upi): New function. - * Makefile (COBJS): Add get-upi.o. - -Thu Jun 22 11:43:15 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> - - * object-init.c (_pager_seqnos_memory_object_init): Rather than an - empty `if' body and an unconditional return, how about a real - test? - - * notify-stubs.c: New file. - * Makefile (COBJS): Add notify-stubs.o. - -Tue Jun 20 12:44:22 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> - - * chg-compl.c (_pager_seqnos_memory_object_change_completed): Use - new ports routines. - * pager-shutdown.c (pager_shutdown): Likewise. - * object-terminate.c (_pager_free_structure): Likewise. - * object-init.c (_pager_seqnos_memory_object_init): Likewise. - * lock-completed.c (_pager_seqnos_memory_object_lock_completed): - Likewise. - * data-unlock.c (_pager_seqnos_memory_object_data_unlock): Likewise. - * data-return.c (_pager_do_write_request): Likewise. - * data-request.c (_pager_seqnos_memory_object_data_request): - Likewise. - * pager-create.c (pager_create): New parm BUCKET. Allocate port - using new ports interface. Arrange to have _pager_class - initialized at startup. - * clean.c, dropweak.c: New files. - * no-senders.c: Rename pager_no_senders to - _pager_do_seqnos_mach_notify_no_senders. Lookup up port right - ourselves. Remove function pager_clean (now in clean.c). - * priv.h (_pager_class): New var. - (_pager_clean, _pager_real_dropweak): New decls. - * Makefile (COBJS): Delete reference.o. Add clean.o and dropweak.o - (OBJS): Add notifyServer.o. - (demuxer.o): Depend on notify_S.h. - * demuxer.c: Include "notify_S.h". - (pager_demuxer): Declare and use _pager_seqnos_notify_server. - * pager.h: Include <hurd/ports.h>. - (pager_no_senders, pager_reference, pager_unreference, - pager_port_type, pager_clean): Remove declarations. - (pager_create): New parm BUCKET. - (pager_clean): Doc fix. - (pager_dropweak): New decl. - * reference.c: Deleted file. - -Thu May 11 11:19:44 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * priv.h (PM_NEXTERROR, SET_PM_NEXTERROR): Mask 2-bit error code - with 0x3, not 0x2! - - * mark-error.c (_pager_mark_next_request_error, - _pager_mark_object_error): Put the error code in the correct place - in the pagemap rather than always at the beginning. - (pager_get_error): Get the error code from the pagemap rather than - just using the pagemap offset! - -Wed Nov 23 00:28:19 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * demuxer.c (pager_demuxer): Call - _pager_seqnos_memory_object_server, not - seqnos_memory_object_server. - -Tue Nov 8 14:15:01 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * lock-object.c (_pager_lock_object): Hammer SYNC to zero for now; - there's some deadlock bug in noticing when the sync finishes. - -Tue Aug 30 17:55:34 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * data-return.c: Include <assert.h>. - (_pager_seqnos_memory_object_data_return): Use return correctly. - -Mon Aug 29 17:30:52 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * priv.h (PM_INIT): New pagemap bit. - * data-return.c (_pager_do_write-request): Set PM_INIT for - affected pages. New var `omitdata' hold a bitmap of the - pages that we are not actually writing. Set accordingly - while looking through pagemap before starting I/O. Don't - actually call I/O on these pages or frob the page map with them - later. - - * data-return.c (_pager_seqnos_memory_object_data_return): Split - into two functions; _pager_do_write_request does the real work - now. - - * object-create.c: New file. - * data-init.c: New file. - -Fri Jul 22 11:54:05 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * Makefile: Rewritten to use new scheme. - * data-request.c: Include "memory_object_S.h" instead of - "memory_object.h". - * data-return.c: Likewise. - * data-unlock.c: Likewise. - * lock-completed: Likewise. - * stubs.c: Likewise. - * object-init.c: Likewise. - * demuxer.c: Likewise. - * object-terminate.c: Likewise. - -Tue Jul 5 14:14:17 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * Makefile (TAGSHDRS): New variable. - -Wed Jun 1 11:41:24 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * pager-attr.c (pager_change_attributes): Return immediately - if we are already in the requested state. - - * lock-completed.c (_pager_seqnos_memory_object_lock_completed): - Call ports_done_with_port before returning to free reference - created by ports_check_port_type. - * chg-compl.c (_pager_seqnos_memory_object_change_completed): - Likewise. - - * seqnos.c (_pager_release_seqno): New second arg SEQNO. - Set p->seqno here. All callers changed. - (_pager_wait_for_seqno): Don't set p->seqno here; then it - might get released before we actually call _pager_release_seqno. - * priv.h (_pager_release_seqno): Declare new second arg. - - * priv.h (KERNEL_INIT_RACE): New compilation option. All the - changes in this block are conditionalized by this macro. - * priv.h (struct pager): New members init_head and init_tail. - (struct pending_init): New type. - * object-init.c (_pager_seqnos_memory_object_init): If the object - is not ready for init, then queue the init for later processing. - * object-terminate.c (_pager_seqnos_memory_object_terminate): If - there is a pending init, return it here. - * no-senders.c (pager_clean): Destroy all pending inits here. - - * object-terminate.c (_pager_free_structure): Don't unlock - interlock or free the seqno here. - (_pager_seqnos_memory_object_terminate): Unlock interlock and - free seqno after calling _pager_free_structure. - * no-senders.c (pager_clean): Unlock interlock after calling - _pager_free_structure. Don't free seqno here at all. - -Tue May 24 15:25:54 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * data-return.c (_pager_seqnos_memory_object_data_return): New - vars NPAGES, I, and PAGERRS. Rename var PM_ENTRY to be - PM_ENTRIES. Deal with multiple-page data_return calls by dealing - with multiple pagemap slots and calling pager_write_page multiple - times. - - * data-return.c (_pager_seqnos_memory_object_data_return): Fix - printf messages; include length in bogus length messages. - - *data-unlock (_pager_seqnos_memory_object_data_unlock): Likewise. - -Mon May 23 13:06:31 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * data-request.c (_pager_seqnos_memory_object_data_request): - Report length in bogus arg messages; terminate messages with - newlines. - - * chg-compl.c: Include <stdio.h>. - - * priv.h (struct pager [may_cache, copy_strategy]): New members. - * pager.h (pager_create_pager): Added new args MAY_CACHE and - COPY_STRATEGY. - (pager_report_attributes): Deleted declaration. - * object-init.c (_pager_seqnos_memory_object_init): Set attributes - from values in P rather than by calling pager_report_attributes. - * pager-attr.c (pager_change_attributes): Don't panic if the - pager isn't yet initialized by the kernel; record the provided - values in may_cache and copy_strategy. - - * pager-attr.c: Spelling fix. - Include <assert.h>. - * Makefile (COBJS): Added pager-attr.o. - -Fri May 20 15:41:12 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * lock-completed.c (_pager_seqnos_memory_object_lock_completed): - Delete unneeded variable wakeup. Break out of loop as soon - as we find the right record. Call condition_broadcast only - if we need bother. - - * pager.h (pager_change_attributes, pager_report_attributes): - New declarations. - * priv.h (struct attribute_request): New structure. - (struct pager [attribute_requests]): New member. - * pager-create.c (pager_create): Initialize new member. - * object-init.c (_pager_seqnos_memory_object_init): Call - pager_report_attributes for correct args to memory_object_ready. - * pager-attr.c: New file. - * object-terminate.c (_pager_free_structure): Wakeup pending - pager_change_attribute requests. - * stubs.c (_pager_seqnos_memory_object_change_completed): Deleted - function. - * chg-compl.c: New file. - * Makefile (COBJS): Added chg-compl.o. - -Thu May 5 07:49:21 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) - - * stubs.c (_pager_seqnos_memory_object_supply_completed): Change - RESULT arg to type kern_return_t; error_t is not compatible. - - * demuxer.c (pager_demuxer): Declare seqnos_memory_object_server. - - * stubs.c, lock-completed.c: Changed return type of all RPC server - functions to kern_return_t. error_t is not compatible with the - declarations in the mig-generated header files. - - * Makefile: Change uses of $(headers) to $(includedir). - -Tue Apr 26 15:08:57 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * object-init.c (_pager_seqnos_memory_object_init): Only check - for inits of active objects AFTER waiting for seqno; otherwise we - could race against a prior terminate. - diff --git a/libpager/Makefile b/libpager/Makefile index f8c0999a..fc23364a 100644 --- a/libpager/Makefile +++ b/libpager/Makefile @@ -29,6 +29,7 @@ SRCS = data-request.c data-return.c data-unlock.c pager-port.c \ LCLHDRS = pager.h priv.h installhdrs = pager.h +HURDLIBS= threads ports OBJS = $(SRCS:.c=.o) memory_objectServer.o notifyServer.o MIGSFLAGS = -DSEQNOS @@ -36,5 +37,3 @@ MIGCOMSFLAGS = -prefix _pager_ include ../Makeconf -libpager.so: $(foreach lib,threads ports,\ - ../lib$(lib)/lib$(lib).so) diff --git a/libpager/data-init.c b/libpager/data-init.c deleted file mode 100644 index f411a938..00000000 --- a/libpager/data-init.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Initial contents of memory object (default pager only) - Copyright (C) 1994 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include "priv.h" -#include "memory_object_default_S.h" - -kern_return_t -_pager_seqnos_memory_object_data_initialize (mach_port_t object, - mach_port_seqno_t seqno, - mach_port_t control, - vm_offset_t offset, - pointer_t data, - vm_size_t datalen) -{ - _pager_do_write_request (object, seqno, control, offset, data, - datalen, 1, 0, 1); -} diff --git a/libpager/data-request.c b/libpager/data-request.c index 341fb924..36725b11 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 Free Software Foundation + Copyright (C) 1994,95,96,97,2000,02,10 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 @@ -22,7 +22,7 @@ /* Implement pagein callback as described in <mach/memory_object.defs>. */ kern_return_t -_pager_seqnos_memory_object_data_request (mach_port_t object, +_pager_seqnos_memory_object_data_request (mach_port_t object, mach_port_seqno_t seqno, mach_port_t control, vm_offset_t offset, @@ -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; @@ -43,7 +43,7 @@ _pager_seqnos_memory_object_data_request (mach_port_t object, /* Acquire the right to meddle with the pagemap */ mutex_lock (&p->interlock); _pager_wait_for_seqno (p, seqno); - + /* sanity checks -- we don't do multi-page requests yet. */ if (control != p->memobjcntl) { @@ -52,7 +52,7 @@ _pager_seqnos_memory_object_data_request (mach_port_t object, } if (length != __vm_page_size) { - printf ("incg data request: bad length size %d\n", length); + printf ("incg data request: bad length size %zd\n", length); goto release_out; } if (offset % __vm_page_size) @@ -61,18 +61,18 @@ _pager_seqnos_memory_object_data_request (mach_port_t object, goto release_out; } - _pager_block_termination (p); /* prevent termination until + _pager_block_termination (p); /* prevent termination until mark_object_error is done */ if (p->pager_state != NORMAL) { printf ("pager in wrong state for read\n"); - _pager_release_seqno (p, seqno); - mutex_unlock (&p->interlock); - goto allow_term_out; + goto allow_release_out; } - _pager_pagemap_resize (p, offset + length); + err = _pager_pagemap_resize (p, offset + length); + if (err) + goto allow_release_out; /* Can't do much about the actual error. */ /* If someone is paging this out right now, the disk contents are unreliable, so we have to wait. It is too expensive (right now) to @@ -97,9 +97,9 @@ _pager_seqnos_memory_object_data_request (mach_port_t object, if (PM_NEXTERROR (*pm_entry) != PAGE_NOERR && (access & VM_PROT_WRITE)) { - memory_object_data_error (control, offset, length, + memory_object_data_error (control, offset, length, _pager_page_errors[PM_NEXTERROR (*pm_entry)]); - _pager_mark_object_error (p, offset, length, + _pager_mark_object_error (p, offset, length, _pager_page_errors[PM_NEXTERROR (*pm_entry)]); *pm_entry = SET_PM_NEXTERROR (*pm_entry, PAGE_NOERR); doread = 0; @@ -117,7 +117,7 @@ _pager_seqnos_memory_object_data_request (mach_port_t object, err = pager_read_page (p->upi, offset, &page, &write_lock); if (err) goto error_read; - + memory_object_data_supply (p->memobjcntl, offset, page, length, 1, write_lock ? VM_PROT_WRITE : VM_PROT_NONE, 0, MACH_PORT_NULL); @@ -128,20 +128,18 @@ _pager_seqnos_memory_object_data_request (mach_port_t object, ports_port_deref (p); return 0; - allow_term_out: - mutex_lock (&p->interlock); - _pager_allow_termination (p); - mutex_unlock (&p->interlock); - ports_port_deref (p); - return 0; - error_read: memory_object_data_error (p->memobjcntl, offset, length, EIO); _pager_mark_object_error (p, offset, length, EIO); + allow_term_out: + mutex_lock (&p->interlock); _pager_allow_termination (p); + mutex_unlock (&p->interlock); ports_port_deref (p); return 0; + allow_release_out: + _pager_allow_termination (p); release_out: _pager_release_seqno (p, seqno); mutex_unlock (&p->interlock); diff --git a/libpager/data-return.c b/libpager/data-return.c index 562af955..a010c6dc 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 Free Software Foundation + Copyright (C) 1994,95,96,99,2000,02 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 @@ -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; @@ -45,7 +45,7 @@ _pager_do_write_request (mach_port_t object, struct lock_list *next;} *lock_list, *ll; int wakeup; int omitdata = 0; - + p = ports_lookup_port (0, object, _pager_class); if (!p) return EOPNOTSUPP; @@ -53,7 +53,7 @@ _pager_do_write_request (mach_port_t object, /* Acquire the right to meddle with the pagemap */ mutex_lock (&p->interlock); _pager_wait_for_seqno (p, seqno); - + /* sanity checks -- we don't do multi-page requests yet. */ if (control != p->memobjcntl) { @@ -62,7 +62,7 @@ _pager_do_write_request (mach_port_t object, } if (length % __vm_page_size) { - printf ("incg data return: bad length size %d\n", length); + printf ("incg data return: bad length size %zd\n", length); goto release_out; } if (offset % __vm_page_size) @@ -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 @@ -140,8 +150,8 @@ _pager_do_write_request (mach_port_t object, for (i = 0; i < npages; i++) if (!(omitdata & (1 << i))) - pagerrs[i] = pager_write_page (p->upi, - offset + (vm_page_size * 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 */ @@ -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 @@ -165,23 +179,22 @@ _pager_do_write_request (mach_port_t object, 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), + 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); + 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); @@ -201,7 +214,7 @@ _pager_do_write_request (mach_port_t object, /* Implement pageout call back as described by <mach/memory_object.defs>. */ kern_return_t -_pager_seqnos_memory_object_data_return (mach_port_t object, +_pager_seqnos_memory_object_data_return (mach_port_t object, mach_port_seqno_t seqno, mach_port_t control, vm_offset_t offset, diff --git a/libpager/data-unlock.c b/libpager/data-unlock.c index a4ef0600..9692f589 100644 --- a/libpager/data-unlock.c +++ b/libpager/data-unlock.c @@ -1,5 +1,5 @@ /* Implementation of memory_object_data_unlock for pager library - Copyright (C) 1994, 1995 Free Software Foundation + Copyright (C) 1994,95,2002 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 @@ -19,10 +19,10 @@ #include "memory_object_S.h" #include <stdio.h> -/* Implement kernel requests for access as described in +/* Implement kernel requests for access as described in <mach/memory_object.defs>. */ kern_return_t -_pager_seqnos_memory_object_data_unlock (mach_port_t object, +_pager_seqnos_memory_object_data_unlock (mach_port_t object, mach_port_seqno_t seqno, mach_port_t control, vm_offset_t offset, @@ -31,7 +31,7 @@ _pager_seqnos_memory_object_data_unlock (mach_port_t object, { struct pager *p; volatile int err; - + p = ports_lookup_port (0, object, _pager_class); if (!p) return EOPNOTSUPP; @@ -65,12 +65,12 @@ _pager_seqnos_memory_object_data_unlock (mach_port_t object, } if (length != __vm_page_size) { - printf ("incg data unlock: bad length size %d\n", length); + printf ("incg data unlock: bad length size %zd\n", length); goto out; } err = pager_unlock_page (p->upi, offset); - + if (!err) /* We can go ahead and release the lock. */ _pager_lock_object (p, offset, length, MEMORY_OBJECT_RETURN_NONE, 0, @@ -87,4 +87,3 @@ _pager_seqnos_memory_object_data_unlock (mach_port_t object, ports_port_deref (p); return 0; } - diff --git a/libpager/demuxer.c b/libpager/demuxer.c index f233d1c0..79c0ddc5 100644 --- a/libpager/demuxer.c +++ b/libpager/demuxer.c @@ -1,5 +1,5 @@ /* Demuxer for pager library - Copyright (C) 1994, 1995 Free Software Foundation + Copyright (C) 1994, 1995, 2002, 2011 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 @@ -20,7 +20,7 @@ #include "notify_S.h" /* Demultiplex a single message directed at a pager port; INP is the - message received; fille OUTP with the reply. */ + message received; fill OUTP with the reply. */ int pager_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) @@ -29,8 +29,12 @@ pager_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp); extern int _pager_seqnos_notify_server (mach_msg_header_t *inp, mach_msg_header_t *outp); - - return (_pager_seqnos_memory_object_server (inp, outp) - || _pager_seqnos_notify_server (inp, outp)); -} + int result = _pager_seqnos_memory_object_server (inp, outp) + || _pager_seqnos_notify_server (inp, outp); + if (!result) + /* Synchronize our bookkeeping of the port's seqno with the one consumed by + this bogus message. */ + _pager_update_seqno (inp->msgh_local_port, inp->msgh_seqno); + return result; +} diff --git a/libpager/lock-object.c b/libpager/lock-object.c index d2f6da6d..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 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 @@ -30,9 +30,8 @@ _pager_lock_object (struct pager *p, vm_prot_t lock_value, int sync) { - struct lock_request *lr = 0; - char *pm_entries; int i; + struct lock_request *lr = 0; mutex_lock (&p->interlock); if (p->pager_state != NORMAL) @@ -85,10 +84,20 @@ _pager_lock_object (struct pager *p, if (should_flush) { + vm_offset_t pm_offs = offset / __vm_page_size; + _pager_pagemap_resize (p, offset + size); - pm_entries = &p->pagemap[offset / __vm_page_size]; - for (i = 0; i < size / vm_page_size; i++) - pm_entries[i] &= ~PM_INCORE; + if (p->pagemapsize > pm_offs) + { + short *pm_entries = &p->pagemap[pm_offs]; + vm_offset_t bound = size / vm_page_size; + + if (bound > p->pagemapsize) + bound = p->pagemapsize; + + for (i = 0; i < bound; i++) + pm_entries[i] &= ~PM_INCORE; + } } } diff --git a/libpager/mark-error.c b/libpager/mark-error.c index 411d3a7d..5c4e029d 100644 --- a/libpager/mark-error.c +++ b/libpager/mark-error.c @@ -1,5 +1,5 @@ /* Recording errors for pager library - Copyright (C) 1994 Free Software Foundation + Copyright (C) 1994, 1997 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 @@ -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; @@ -99,16 +99,24 @@ _pager_mark_object_error(struct pager *pager, /* Tell us what the error (set with mark_object_error) for pager P is on page ADDR. */ error_t -pager_get_error (struct pager *p, - vm_address_t addr) +pager_get_error (struct pager *p, vm_address_t addr) { error_t err; mutex_lock (&p->interlock); - _pager_pagemap_resize (p, addr); - - err = _pager_page_errors[PM_ERROR(p->pagemap[addr/__vm_page_size])]; + + addr /= vm_page_size; + + /* If there really is no error for ADDR, we should be able to exted the + pagemap table; otherwise, if some previous operation failed because it + couldn't extend the table, this attempt will *probably* (heh) fail for + the same reason. */ + err = _pager_pagemap_resize (p, addr); + + if (! err) + err = _pager_page_errors[PM_ERROR(p->pagemap[addr])]; mutex_unlock (&p->interlock); + return err; } diff --git a/libpager/notify-stubs.c b/libpager/notify-stubs.c index 728163e4..2d791aac 100644 --- a/libpager/notify-stubs.c +++ b/libpager/notify-stubs.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1995 Free Software Foundation, Inc. + Copyright (C) 1995, 2011 Free Software Foundation, Inc. Written by Michael I. Bushnell. This file is part of the GNU Hurd. @@ -18,58 +18,59 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ +#include "priv.h" #include "notify_S.h" #include <errno.h> error_t -_pager_do_seqnos_mach_notify_port_deleted (mach_port_t notify - __attribute__ ((unused)), - mach_port_seqno_t seqno - __attribute__ ((unused)), +_pager_do_seqnos_mach_notify_port_deleted (mach_port_t notify, + mach_port_seqno_t seqno, mach_port_t name __attribute__ ((unused))) { + _pager_update_seqno (notify, seqno); + return 0; } error_t -_pager_do_seqnos_mach_notify_msg_accepted (mach_port_t notify - __attribute__ ((unused)), - mach_port_seqno_t seqno - __attribute__ ((unused)), +_pager_do_seqnos_mach_notify_msg_accepted (mach_port_t notify, + mach_port_seqno_t seqno, mach_port_t name __attribute__ ((unused))) { + _pager_update_seqno (notify, seqno); + return 0; } error_t -_pager_do_seqnos_mach_notify_port_destroyed (mach_port_t notify - __attribute__ ((unused)), - mach_port_seqno_t seqno - __attribute__ ((unused)), +_pager_do_seqnos_mach_notify_port_destroyed (mach_port_t notify, + mach_port_seqno_t seqno, mach_port_t name __attribute__ ((unused))) { + _pager_update_seqno (notify, seqno); + return 0; } error_t -_pager_do_seqnos_mach_notify_send_once (mach_port_t notify - __attribute__ ((unused)), - mach_port_seqno_t seqno - __attribute__ ((unused))) +_pager_do_seqnos_mach_notify_send_once (mach_port_t notify, + mach_port_seqno_t seqno) { + _pager_update_seqno (notify, seqno); + return 0; } error_t -_pager_do_seqnos_mach_notify_dead_name (mach_port_t notify - __attribute__ ((unused)), - mach_port_seqno_t seqno - __attribute__ ((unused)), +_pager_do_seqnos_mach_notify_dead_name (mach_port_t notify, + mach_port_seqno_t seqno, mach_port_t name __attribute__ ((unused))) { + _pager_update_seqno (notify, seqno); + return 0; } diff --git a/libpager/object-create.c b/libpager/object-create.c deleted file mode 100644 index c8dfe6de..00000000 --- a/libpager/object-create.c +++ /dev/null @@ -1,73 +0,0 @@ -/* Create a new memory object (Default pager only) - Copyright (C) 1994, 1995 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - - -#include "priv.h" -#include "memory_object_create_S.h" - -/* Implement the object creation call as described in - <mach/memory_object_default.defs>. */ -kern_return_t -_pager_seqnos_memory_object_create (mach_port_t master, - mach_port_seqno_t seqno, - mach_port_t newobject, - vm_size_t objectsize, - mach_port_t newctl, - mach_port_t newname, - vm_size_t objectpagesize) -{ - struct port_info *masterpi; - struct pager *p; - - if (!pager_support_defpager) - return EOPNOTSUPP; - - if (objectpagesize != vm_page_size) - return EINVAL; - - masterpi = ports_check_port_type (object, pager_master_port_type); - if (!masterpi) - return EOPNOTSUPP; - - p = ports_intern_external_port (newobject, sizeof (struct pager), - pager_port_type); - - p->pager_state = NORMAL; - mutex_init (&p->interlock); - condition_init (&p->wakeup); - p->lock_requests = 0; - p->attribute_requests = 0; - p->may_cache = 0; - p->copy_strategy = MEMORY_OBJECT_COPY_DELAY; - p->memobjcntl = newctl; - p->memobjname = newname; - p->seqno = -1; - p->noterm = 0; - p->waitingforseqno = 0; - p->pagemap = 0; - p->pagemapsize = 0; - - p->upi = pager_create_upi (p); - - ports_port_deref (p); - return 0; -} - - diff --git a/libpager/object-terminate.c b/libpager/object-terminate.c index 8598ab50..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 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 @@ -53,6 +53,12 @@ _pager_seqnos_memory_object_terminate (mach_port_t object, condition_wait (&p->wakeup, &p->interlock); } + /* Destry the ports we received; mark that in P so that it doesn't bother + doing it again. */ + mach_port_destroy (mach_task_self (), control); + mach_port_destroy (mach_task_self (), name); + p->memobjcntl = p->memobjname = MACH_PORT_NULL; + _pager_free_structure (p); #ifdef KERNEL_INIT_RACE @@ -104,13 +110,21 @@ _pager_free_structure (struct pager *p) if (wakeup) condition_broadcast (&p->wakeup); - mach_port_deallocate (mach_task_self (), p->memobjcntl); - mach_port_deallocate (mach_task_self (), p->memobjname); + if (p->memobjcntl != MACH_PORT_NULL) + { + mach_port_deallocate (mach_task_self (), p->memobjcntl); + p->memobjcntl = MACH_PORT_NULL; + } + if (p->memobjname != MACH_PORT_NULL) + { + mach_port_deallocate (mach_task_self (), p->memobjname); + p->memobjname = MACH_PORT_NULL; + } /* Free the pagemap */ if (p->pagemapsize) { - vm_deallocate (mach_task_self (), (u_int)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 fe08d3b4..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 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. @@ -28,23 +28,25 @@ pager_offer_page (struct pager *p, vm_offset_t offset, vm_address_t buf) { - char *pm_entry; - - try_again: mutex_lock (&p->interlock); - _pager_pagemap_resize (p, offset + vm_page_size); - pm_entry = &p->pagemap[offset / vm_page_size]; - if (*pm_entry & PM_INCORE) + + if (_pager_pagemap_resize (p, offset + vm_page_size)) { - mutex_unlock (&p->interlock); - pager_flush_some (p, offset, vm_page_size, 1); - goto try_again; + short *pm_entry = &p->pagemap[offset / vm_page_size]; + + while (*pm_entry & PM_INCORE) + { + mutex_unlock (&p->interlock); + pager_flush_some (p, offset, vm_page_size, 1); + mutex_lock (&p->interlock); + } + *pm_entry |= PM_INCORE; + + memory_object_data_supply (p->memobjcntl, offset, buf, vm_page_size, 0, + writelock ? VM_PROT_WRITE : VM_PROT_NONE, + precious, MACH_PORT_NULL); } - *pm_entry |= PM_INCORE; - memory_object_data_supply (p->memobjcntl, offset, buf, vm_page_size, 0, - writelock ? VM_PROT_WRITE : VM_PROT_NONE, - precious, MACH_PORT_NULL); mutex_unlock (&p->interlock); } diff --git a/libpager/pagemap.c b/libpager/pagemap.c index 2adbcc0e..b8b3362c 100644 --- a/libpager/pagemap.c +++ b/libpager/pagemap.c @@ -1,5 +1,5 @@ /* Pagemap manipulation for pager library - Copyright (C) 1994 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 @@ -19,21 +19,29 @@ #include <string.h> /* Grow the pagemap of pager P as necessary to deal with address OFF */ -void -_pager_pagemap_resize (struct pager *p, - vm_address_t off) +error_t +_pager_pagemap_resize (struct pager *p, vm_address_t off) { - void *newaddr; - int newsize; + error_t err = 0; off /= __vm_page_size; - if (p->pagemapsize >= off) - return; - - newsize = round_page (off); - vm_allocate (mach_task_self (), (u_int *)&newaddr, newsize, 1); - bcopy (p->pagemap, newaddr, p->pagemapsize); - vm_deallocate (mach_task_self (), (u_int)p->pagemap, p->pagemapsize); - p->pagemap = newaddr; - p->pagemapsize = newsize; + + if (p->pagemapsize < off) + { + void *newaddr; + int newsize = round_page (off); + + 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 * sizeof (*p->pagemap)); + munmap (p->pagemap, p->pagemapsize * sizeof (*p->pagemap)); + p->pagemap = newaddr; + p->pagemapsize = newsize; + } + } + + return err; } diff --git a/libpager/pager-memcpy.c b/libpager/pager-memcpy.c index 0333c805..f2be5585 100644 --- a/libpager/pager-memcpy.c +++ b/libpager/pager-memcpy.c @@ -1,5 +1,5 @@ /* Fault-safe copy into or out of pager-backed memory. - Copyright (C) 1996 Free Software Foundation, Inc. + Copyright (C) 1996,97,99, 2000,01,02 Free Software Foundation, Inc. Written by Roland McGrath. This program is free software; you can redistribute it and/or @@ -16,9 +16,17 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "priv.h" #include "pager.h" +#include <sys/mman.h> #include <hurd/sigpreempt.h> #include <assert.h> +#include <string.h> + +/* Start using vm_copy over memcpy when we have that many page. This is + roughly the L1 cache size. (This value *cannot* be less than + vm_page_size.) */ +#define VMCOPY_BETTER_THAN_MEMCPY (8*vm_page_size) /* Try to copy *SIZE bytes between the region OTHER points to and the region at OFFSET in the pager indicated by PAGER and MEMOBJ. @@ -27,55 +35,136 @@ *SIZE is always filled in the actual number of bytes successfully copied. Returns an error code if the pager-backed memory faults; if there is no fault, returns 0 and *SIZE will be unchanged. */ - error_t pager_memcpy (struct pager *pager, memory_object_t memobj, vm_offset_t offset, void *other, size_t *size, vm_prot_t prot) { - vm_address_t window = 0; - vm_size_t windowsize = 8 * vm_page_size; - size_t to_copy = *size; error_t err; + size_t n = *size; - error_t copy (struct hurd_signal_preempter *preempter) +#define VMCOPY_WINDOW_DEFAULT_SIZE (32 * vm_page_size) +#define MEMCPY_WINDOW_DEFAULT_SIZE (32 * vm_page_size) + vm_address_t window; + vm_size_t window_size; + + error_t do_vm_copy (void) { - while (to_copy > 0) - { - size_t pageoff = offset & (vm_page_size - 1); + assert ((offset & (vm_page_size - 1)) == 0); + assert (((vm_address_t) other & (vm_page_size - 1)) == 0); + assert (n >= vm_page_size); - if (window) - /* Deallocate the old window. */ - vm_deallocate (mach_task_self (), window, windowsize); + do + { + window_size = + VMCOPY_WINDOW_DEFAULT_SIZE > n + ? (n - (n & (vm_page_size - 1))) + : VMCOPY_WINDOW_DEFAULT_SIZE; + + assert (window_size >= VMCOPY_BETTER_THAN_MEMCPY); + assert ((window_size & (vm_page_size - 1)) == 0); + + err = vm_map (mach_task_self (), &window, window_size, 0, 1, + memobj, offset, 0, prot, prot, VM_INHERIT_NONE); + if (err) + return err; - /* Map in and copy a standard-sized window, unless that is - more than the total left to be copied. */ + if (prot == VM_PROT_READ) + err = vm_copy (mach_task_self (), window, window_size, + (vm_address_t) other); + else + err = vm_copy (mach_task_self (), (vm_address_t) other, + window_size, window); - if (windowsize > pageoff + to_copy) - windowsize = pageoff + to_copy; + vm_deallocate (mach_task_self (), window, window_size); - window = 0; - err = vm_map (mach_task_self (), &window, windowsize, 0, 1, - memobj, offset - pageoff, 0, - prot, prot, VM_INHERIT_NONE); if (err) - return 0; + return err; - /* Realign the fault preempter for the new mapping window. */ - preempter->first = window; - preempter->last = window + windowsize; + other += window_size; + offset += window_size; + n -= window_size; + } + while (n >= VMCOPY_BETTER_THAN_MEMCPY); - if (prot == VM_PROT_READ) - memcpy (other, (const void *) window + pageoff, - windowsize - pageoff); - else - memcpy ((void *) window + pageoff, other, windowsize - pageoff); + return 0; + } - offset += windowsize - pageoff; - other += windowsize - pageoff; - to_copy -= windowsize - pageoff; + error_t do_copy (struct hurd_signal_preemptor *preemptor) + { + error_t do_memcpy (size_t to_copy) + { + window_size = MEMCPY_WINDOW_DEFAULT_SIZE; + + do + { + size_t pageoff = offset & (vm_page_size - 1); + size_t copy_count = window_size - pageoff; + + /* Map in and copy a standard-sized window, unless that is + more than the total left to be copied. */ + + if (window_size >= round_page (pageoff + to_copy)) + { + copy_count = to_copy; + window_size = round_page (pageoff + to_copy); + } + + err = vm_map (mach_task_self (), &window, window_size, 0, 1, + memobj, offset - pageoff, 0, + prot, prot, VM_INHERIT_NONE); + if (err) + return err; + + /* Realign the fault preemptor for the new mapping window. */ + preemptor->first = window; + preemptor->last = window + window_size; + + if (prot == VM_PROT_READ) + memcpy (other, (const void *) window + pageoff, copy_count); + else + memcpy ((void *) window + pageoff, other, copy_count); + + vm_deallocate (mach_task_self (), window, window_size); + + offset += copy_count; + other += copy_count; + to_copy -= copy_count; + n -= copy_count; + + assert (n >= 0); + assert (to_copy >= 0); + } + while (to_copy > 0); + + return 0; } - return 0; + + /* Can we use vm_copy? */ + if ((((vm_address_t) other & (vm_page_size - 1)) + == (offset & (vm_page_size - 1))) + && (n >= (VMCOPY_BETTER_THAN_MEMCPY + vm_page_size + - ((vm_address_t) other & (vm_page_size - 1))))) + /* 1) other and offset are aligned with repect to each other; + and 2) we have at least VMCOPY_BETTER_THAN_MEMCPY fully + aligned pages. */ + { + err = do_memcpy (vm_page_size + - ((vm_address_t) other & (vm_page_size - 1))); + if (err) + return err; + + assert (n >= VMCOPY_BETTER_THAN_MEMCPY); + + err = do_vm_copy (); + if (err || n == 0) + /* We failed or we finished. */ + return err; + + assert (n < VMCOPY_BETTER_THAN_MEMCPY); + } + + return do_memcpy (n); } jmp_buf buf; @@ -83,19 +172,47 @@ pager_memcpy (struct pager *pager, memory_object_t memobj, { assert (scp->sc_error == EKERN_MEMORY_ERROR); err = pager_get_error (pager, sigcode - window + offset); - to_copy -= sigcode - window; + n -= sigcode - window; + vm_deallocate (mach_task_self (), window, window_size); longjmp (buf, 1); } + if (n == 0) + /* Nothing to do. */ + return 0; + + if (((vm_address_t) other & (vm_page_size - 1)) == 0 + && (offset & (vm_page_size - 1)) == 0 + && n >= VMCOPY_BETTER_THAN_MEMCPY) + /* 1) the start address is page aligned; 2) the offset is page + aligned; and 3) we have more than VMCOPY_BETTER_THAN_MEMCPY + pages. */ + { + err = do_vm_copy (); + if (err || n == 0) + /* We failed or we finished. */ + { + *size -= n; + return err; + } + + assert (n < VMCOPY_BETTER_THAN_MEMCPY); + } + + /* Need to do it the hard way. */ + + window = 0; + window_size = 0; + if (setjmp (buf) == 0) hurd_catch_signal (sigmask (SIGSEGV) | sigmask (SIGBUS), - window, window + windowsize, - ©, (sighandler_t) &fault); + window, window + window_size, + &do_copy, (sighandler_t) &fault); - if (window) - vm_deallocate (mach_task_self (), window, windowsize); + if (! err) + assert (n == 0); - *size -= to_copy; + *size -= n; return err; } diff --git a/libpager/pager.h b/libpager/pager.h index c6bd4971..99fb3845 100644 --- a/libpager/pager.h +++ b/libpager/pager.h @@ -1,5 +1,5 @@ /* Definitions for multi-threaded pager library - Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1994, 1995, 1996, 1997, 1999 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 @@ -38,7 +38,7 @@ int pager_demuxer (mach_msg_header_t *inp, created. MAY_CACHE and COPY_STRATEGY are the original values of those attributes as for memory_object_ready. Users may create references to pagers by use of the relevant ports library - functions. */ + functions. On errors, return null and set errno. */ struct pager * pager_create (struct user_pager_info *u_pager, struct port_bucket *bucket, @@ -151,7 +151,7 @@ pager_memcpy (struct pager *pager, memory_object_t memobj, /* The user must define this function. For pager PAGER, read one page from offset PAGE. Set *BUF to be the address of the page, and set *WRITE_LOCK if the page must be provided read-only. - The only permissable error returns are EIO, EDQUOT, and ENOSPC. */ + The only permissible error returns are EIO, EDQUOT, and ENOSPC. */ error_t pager_read_page (struct user_pager_info *pager, vm_offset_t page, @@ -159,8 +159,8 @@ pager_read_page (struct user_pager_info *pager, int *write_lock); /* The user must define this function. For pager PAGER, synchronously - write one page from BUF to offset PAGE. In addition, vm_deallocate - (or equivalent) BUF. The only permissable error returns are EIO, + write one page from BUF to offset PAGE. In addition, mfree + (or equivalent) BUF. The only permissible error returns are EIO, EDQUOT, and ENOSPC. */ error_t pager_write_page (struct user_pager_info *pager, diff --git a/libpager/priv.h b/libpager/priv.h index 98fca8d4..586bccbf 100644 --- a/libpager/priv.h +++ b/libpager/priv.h @@ -1,5 +1,5 @@ /* Private data for pager library. - Copyright (C) 1994, 1995, 1996 Free Software Foundation + Copyright (C) 1994-1997, 1999, 2000, 2011 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 @@ -17,6 +17,7 @@ #include <mach.h> #include <hurd.h> +#include <sys/mman.h> #include "pager.h" #include <hurd/ports.h> @@ -35,21 +36,21 @@ struct pager NORMAL, /* while running */ SHUTDOWN, /* ignore all further requests */ } pager_state; - + struct mutex interlock; struct condition wakeup; struct lock_request *lock_requests; /* pending lock requests */ struct attribute_request *attribute_requests; /* pending attr requests */ - + boolean_t may_cache; memory_object_copy_strategy_t copy_strategy; /* Interface ports */ memory_object_control_t memobjcntl; memory_object_name_t memobjname; - - int seqno; + + mach_port_seqno_t seqno; int noterm; /* number of threads blocking termination */ @@ -57,15 +58,15 @@ struct pager int termwaiting:1; int waitingforseqno:1; - + #ifdef KERNEL_INIT_RACE /* Out of sequence object_init calls waiting for terminations. */ struct pending_init *init_head, *init_tail; #endif - char *pagemap; - int pagemapsize; + short *pagemap; + int pagemapsize; /* number of elements in PAGEMAP */ }; struct lock_request @@ -107,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 */ @@ -129,11 +131,12 @@ extern int _pager_page_errors[]; struct port_class *_pager_class; -void _pager_wait_for_seqno (struct pager *, int); -void _pager_release_seqno (struct pager *, int); +void _pager_wait_for_seqno (struct pager *, mach_port_seqno_t); +void _pager_release_seqno (struct pager *, mach_port_seqno_t); +void _pager_update_seqno (mach_port_t, mach_port_seqno_t); void _pager_block_termination (struct pager *); void _pager_allow_termination (struct pager *); -void _pager_pagemap_resize (struct pager *, vm_address_t); +error_t _pager_pagemap_resize (struct pager *, vm_address_t); void _pager_mark_next_request_error (struct pager *, vm_address_t, vm_size_t, error_t); void _pager_mark_object_error (struct pager *, vm_address_t, diff --git a/libpager/seqnos.c b/libpager/seqnos.c index 94cce93b..7d8bcba7 100644 --- a/libpager/seqnos.c +++ b/libpager/seqnos.c @@ -1,5 +1,5 @@ /* Sequence number synchronization routines for pager library - Copyright (C) 1994 Free Software Foundation + Copyright (C) 1994, 2011 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 @@ -23,7 +23,7 @@ return. */ void _pager_wait_for_seqno (struct pager *p, - int seqno) + mach_port_seqno_t seqno) { while (seqno != p->seqno + 1) { @@ -37,7 +37,7 @@ _pager_wait_for_seqno (struct pager *p, _pager_wait_for_seqno) to be handled. */ void _pager_release_seqno (struct pager *p, - int seqno) + mach_port_seqno_t seqno) { assert (seqno == p->seqno + 1); p->seqno = seqno; @@ -47,3 +47,23 @@ _pager_release_seqno (struct pager *p, condition_broadcast (&p->wakeup); } } + + +/* Just update the seqno. */ +void +_pager_update_seqno (mach_port_t object, + mach_port_seqno_t seqno) +{ + struct pager *p; + + p = ports_lookup_port (0, object, _pager_class); + if (p) + { + mutex_lock (&p->interlock); + _pager_wait_for_seqno (p, seqno); + _pager_release_seqno (p, seqno); + mutex_unlock (&p->interlock); + + ports_port_deref (p); + } +} diff --git a/libpager/stubs.c b/libpager/stubs.c index b455699e..84782120 100644 --- a/libpager/stubs.c +++ b/libpager/stubs.c @@ -1,5 +1,5 @@ /* Unused memory object interface stubs - Copyright (C) 1994 Free Software Foundation + Copyright (C) 1994, 2011 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 @@ -21,19 +21,22 @@ #include <stdio.h> kern_return_t -_pager_seqnos_memory_object_copy (mach_port_t old, +_pager_seqnos_memory_object_copy (mach_port_t obj, mach_port_seqno_t seq, - memory_object_control_t old_ctl, + memory_object_control_t obj_ctl, vm_offset_t off, vm_size_t len, mach_port_t new) { printf ("m_o_copy called\n"); + + _pager_update_seqno (obj, seq); + return EOPNOTSUPP; } kern_return_t -_pager_seqnos_memory_object_data_write (mach_port_t old, +_pager_seqnos_memory_object_data_write (mach_port_t obj, mach_port_seqno_t seq, mach_port_t ctl, vm_offset_t off, @@ -41,6 +44,9 @@ _pager_seqnos_memory_object_data_write (mach_port_t old, vm_size_t data_cnt) { printf ("m_o_data_write called\n"); + + _pager_update_seqno (obj, seq); + return EOPNOTSUPP; } @@ -54,6 +60,8 @@ _pager_seqnos_memory_object_supply_completed (mach_port_t obj, vm_offset_t err_off) { printf ("m_o_supply_completed called\n"); + + _pager_update_seqno (obj, seq); + return EOPNOTSUPP; } - |