aboutsummaryrefslogtreecommitdiff
path: root/libpager
diff options
context:
space:
mode:
Diffstat (limited to 'libpager')
-rw-r--r--libpager/ChangeLog428
-rw-r--r--libpager/Makefile39
-rw-r--r--libpager/chg-compl.c57
-rw-r--r--libpager/clean.c50
-rw-r--r--libpager/data-init.c34
-rw-r--r--libpager/data-request.c152
-rw-r--r--libpager/data-return.c214
-rw-r--r--libpager/data-unlock.c90
-rw-r--r--libpager/demuxer.c36
-rw-r--r--libpager/dropweak.c29
-rw-r--r--libpager/get-upi.c27
-rw-r--r--libpager/inhibit-term.c35
-rw-r--r--libpager/lock-completed.c68
-rw-r--r--libpager/lock-object.c105
-rw-r--r--libpager/mark-error.c122
-rw-r--r--libpager/no-senders.c43
-rw-r--r--libpager/notify-stubs.c75
-rw-r--r--libpager/object-create.c73
-rw-r--r--libpager/object-init.c79
-rw-r--r--libpager/object-terminate.c133
-rw-r--r--libpager/offer-page.c52
-rw-r--r--libpager/pagemap.c46
-rw-r--r--libpager/pager-attr.c98
-rw-r--r--libpager/pager-create.c64
-rw-r--r--libpager/pager-flush.c45
-rw-r--r--libpager/pager-memcpy.c107
-rw-r--r--libpager/pager-port.c26
-rw-r--r--libpager/pager-return.c44
-rw-r--r--libpager/pager-shutdown.c33
-rw-r--r--libpager/pager-sync.c45
-rw-r--r--libpager/pager.h195
-rw-r--r--libpager/priv.h146
-rw-r--r--libpager/seqnos.c49
-rw-r--r--libpager/stubs.c59
34 files changed, 2898 insertions, 0 deletions
diff --git a/libpager/ChangeLog b/libpager/ChangeLog
new file mode 100644
index 00000000..1b0e6a74
--- /dev/null
+++ b/libpager/ChangeLog
@@ -0,0 +1,428 @@
+2000-01-24 Roland McGrath <roland@baalperazim.frob.com>
+
+ * pager-memcpy.c (pager_memcpy): Short-circuit return for zero size.
+
+1999-07-10 Roland McGrath <roland@baalperazim.frob.com>
+
+ * priv.h: Add #include <sys/mman.h> for munmap decl.
+ * pager-memcpy.c: Likewise.
+
+1999-07-09 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * pagemap.c (_pager_pagemap_resize): Use mmap instead of vm_allocate.
+
+1999-07-03 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * data-return.c (_pager_do_write_request): Use munmap instead of
+ vm_deallocate.
+ * object-terminate.c (_pager_free_structure): Likewise.
+ * pagemap.c (_pager_pagemap_resize): Likewise.
+ * pager-memcpy.c (pager_memcpy): Likewise.
+
+ * pager.h (pager_write_page): Doc adjustment.
+
+Wed Aug 20 14:47:38 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * pager.h: Doc fix.
+
+Thu Feb 6 12:01:36 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * pagemap.c (_pager_pagemap_resize): Return errors.
+ * offer-page.c (pager_offer_page): Rewrite for clarity.
+ Deal with _pager_pagemap_resize failing.
+ * data-request.c (_pager_seqnos_memory_object_data_request): Deal
+ with _pager_pagemap_resize failing.
+ * lock-object.c (_pager_lock_object): Likewise.
+ * mark-error.c (pager_get_error): Likewise.
+ * priv.h (_pager_pagemap_resize): Returns an error_t.
+
+Mon Jan 20 16:25:39 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * pager-memcpy.c (pager_memcpy): `preempter' -> `preemptor'.
+
+Thu Sep 12 16:21:14 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * Makefile (HURDLIBS): New variable.
+ (libpager.so): Delete special depedency.
+
+Tue Aug 13 10:47:47 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * object-terminate.c (_pager_free_structure): Don't bother calling
+ mach_port_deallocate if the cells are already null; set the cells
+ to null after the deallocation is done.
+ (_pager_seqnos_memory_object_terminate): Destroy the rights passed
+ in for control and name.
+
+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
new file mode 100644
index 00000000..fc23364a
--- /dev/null
+++ b/libpager/Makefile
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 1994, 1995, 1996 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
+# published by the Free Software Foundation; either version 2, or (at
+# your option) any later version.
+#
+# This program 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.
+
+dir := libpager
+makemode := library
+
+libname = libpager
+SRCS = data-request.c data-return.c data-unlock.c pager-port.c \
+ inhibit-term.c lock-completed.c lock-object.c mark-error.c \
+ no-senders.c object-init.c object-terminate.c pagemap.c \
+ pager-create.c pager-flush.c pager-shutdown.c pager-sync.c \
+ stubs.c seqnos.c demuxer.c chg-compl.c pager-attr.c clean.c \
+ dropweak.c notify-stubs.c get-upi.c pager-memcpy.c pager-return.c \
+ offer-page.c
+LCLHDRS = pager.h priv.h
+installhdrs = pager.h
+
+HURDLIBS= threads ports
+OBJS = $(SRCS:.c=.o) memory_objectServer.o notifyServer.o
+
+MIGSFLAGS = -DSEQNOS
+MIGCOMSFLAGS = -prefix _pager_
+
+include ../Makeconf
+
diff --git a/libpager/chg-compl.c b/libpager/chg-compl.c
new file mode 100644
index 00000000..7d3994b0
--- /dev/null
+++ b/libpager/chg-compl.c
@@ -0,0 +1,57 @@
+/* Completion of memory_object_change_attributes
+ Copyright (C) 1994, 1995 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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 <stdio.h>
+
+/* The kernel calls this (as described in <mach/memory_object.defs>)
+ when a memory_object_change_attributes call has completed. Read this
+ in combination with pager-attr.c. */
+kern_return_t
+_pager_seqnos_memory_object_change_completed (mach_port_t obj,
+ mach_port_seqno_t seq,
+ boolean_t maycache,
+ memory_object_copy_strategy_t strat)
+{
+ struct pager *p;
+ struct attribute_request *ar;
+
+ p = ports_lookup_port (0, obj, _pager_class);
+ if (!p)
+ {
+ printf ("Bad change completed\n");
+ return EOPNOTSUPP;
+ }
+
+ mutex_lock (&p->interlock);
+ _pager_wait_for_seqno (p, seq);
+
+ for (ar = p->attribute_requests; ar; ar = ar->next)
+ if (ar->may_cache == maycache && ar->copy_strategy == strat)
+ {
+ if (ar->attrs_pending && !--ar->attrs_pending)
+ condition_broadcast (&p->wakeup);
+ break;
+ }
+
+ _pager_release_seqno (p, seq);
+ mutex_unlock (&p->interlock);
+ ports_port_deref (p);
+ return 0;
+}
+
+
diff --git a/libpager/clean.c b/libpager/clean.c
new file mode 100644
index 00000000..e891617f
--- /dev/null
+++ b/libpager/clean.c
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 1995, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "priv.h"
+
+/* Called by port management routines when the last send-right
+ to a pager has gone away. This is a dual of pager_create. */
+void
+_pager_clean (void *arg)
+{
+ struct pager *p = arg;
+#ifdef KERNEL_INIT_RACE
+ struct pending_init *i, *tmp;
+#endif
+
+ if (p->pager_state != NOTINIT)
+ {
+ mutex_lock (&p->interlock);
+ _pager_free_structure (p);
+#ifdef KERNEL_INIT_RACE
+ for (i = p->init_head; i; i = tmp)
+ {
+ mach_port_deallocate (mach_task_self (), i->control);
+ mach_port_deallocate (mach_task_self (), i->name);
+ tmp = i->next;
+ free (i);
+ }
+#endif
+ mutex_unlock (&p->interlock);
+ }
+
+ pager_clear_user_data (p->upi);
+}
diff --git a/libpager/data-init.c b/libpager/data-init.c
new file mode 100644
index 00000000..f411a938
--- /dev/null
+++ b/libpager/data-init.c
@@ -0,0 +1,34 @@
+/* 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
new file mode 100644
index 00000000..0c6d1625
--- /dev/null
+++ b/libpager/data-request.c
@@ -0,0 +1,152 @@
+/* Implementation of memory_object_data_request for pager library
+ Copyright (C) 1994, 1995, 1996, 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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_S.h"
+#include <stdio.h>
+#include <string.h>
+
+/* Implement pagein callback as described in <mach/memory_object.defs>. */
+kern_return_t
+_pager_seqnos_memory_object_data_request (mach_port_t object,
+ mach_port_seqno_t seqno,
+ mach_port_t control,
+ vm_offset_t offset,
+ vm_size_t length,
+ vm_prot_t access)
+{
+ struct pager *p;
+ char *pm_entry;
+ int doread, doerror;
+ error_t err;
+ vm_address_t page;
+ int write_lock;
+
+ p = ports_lookup_port (0, object, _pager_class);
+ if (!p)
+ return EOPNOTSUPP;
+
+ /* 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)
+ {
+ printf ("incg data request: wrong control port\n");
+ goto release_out;
+ }
+ if (length != __vm_page_size)
+ {
+ printf ("incg data request: bad length size %d\n", length);
+ goto release_out;
+ }
+ if (offset % __vm_page_size)
+ {
+ printf ("incg data request: misaligned request\n");
+ goto release_out;
+ }
+
+ _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;
+ }
+
+ err = _pager_pagemap_resize (p, offset + length);
+ if (err)
+ goto 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
+ find the data and return it, and then interrupt the write, so we just
+ mark the page and have the writing thread do m_o_data_supply when it
+ gets around to it. */
+ pm_entry = &p->pagemap[offset / __vm_page_size];
+ if (*pm_entry & PM_PAGINGOUT)
+ {
+ doread = 0;
+ *pm_entry |= PM_PAGEINWAIT;
+ }
+ else
+ doread = 1;
+
+ if (*pm_entry & PM_INVALID)
+ doerror = 1;
+ else
+ doerror = 0;
+
+ *pm_entry |= PM_INCORE;
+
+ if (PM_NEXTERROR (*pm_entry) != PAGE_NOERR && (access & VM_PROT_WRITE))
+ {
+ memory_object_data_error (control, offset, length,
+ _pager_page_errors[PM_NEXTERROR (*pm_entry)]);
+ _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;
+ }
+
+ /* Let someone else in. */
+ _pager_release_seqno (p, seqno);
+ mutex_unlock (&p->interlock);
+
+ if (!doread)
+ goto allow_term_out;
+ if (doerror)
+ goto error_read;
+
+ 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);
+ mutex_lock (&p->interlock);
+ _pager_mark_object_error (p, offset, length, 0);
+ _pager_allow_termination (p);
+ mutex_unlock (&p->interlock);
+ 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);
+ _pager_allow_termination (p);
+ ports_port_deref (p);
+ return 0;
+
+ release_out:
+ _pager_release_seqno (p, seqno);
+ mutex_unlock (&p->interlock);
+ ports_port_deref (p);
+ return 0;
+}
diff --git a/libpager/data-return.c b/libpager/data-return.c
new file mode 100644
index 00000000..9f107793
--- /dev/null
+++ b/libpager/data-return.c
@@ -0,0 +1,214 @@
+/* Implementation of memory_object_data_return for pager library
+ Copyright (C) 1994, 1995, 1996, 1999 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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_S.h"
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+/* Worker function used by _pager_seqnos_memory_object_data_return
+ and _pager_seqnos_memory_object_data_initialize. All args are
+ as for _pager_seqnos_memory_object_data_return; the additional
+ INITIALIZING arg identifies which function is calling us. */
+kern_return_t
+_pager_do_write_request (mach_port_t object,
+ mach_port_seqno_t seqno,
+ mach_port_t control,
+ vm_offset_t offset,
+ pointer_t data,
+ vm_size_t length,
+ int dirty,
+ int kcopy,
+ int initializing)
+{
+ struct pager *p;
+ char *pm_entries;
+ int npages, i;
+ error_t *pagerrs;
+ struct lock_request *lr;
+ struct lock_list {struct lock_request *lr;
+ struct lock_list *next;} *lock_list, *ll;
+ int wakeup;
+ int omitdata = 0;
+
+ p = ports_lookup_port (0, object, _pager_class);
+ if (!p)
+ return EOPNOTSUPP;
+
+ /* 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)
+ {
+ printf ("incg data return: wrong control port\n");
+ goto release_out;
+ }
+ if (length % __vm_page_size)
+ {
+ printf ("incg data return: bad length size %d\n", length);
+ goto release_out;
+ }
+ if (offset % __vm_page_size)
+ {
+ printf ("incg data return: misaligned request\n");
+ goto release_out;
+ }
+
+ if (! dirty)
+ goto release_out;
+
+ if (p->pager_state != NORMAL)
+ {
+ printf ("pager in wrong state for write\n");
+ goto release_out;
+ }
+
+ npages = length / __vm_page_size;
+ pagerrs = alloca (npages * sizeof (error_t));
+
+ _pager_block_termination (p); /* until we are done with the pagemap
+ when the write completes. */
+
+ _pager_pagemap_resize (p, offset + length);
+
+ pm_entries = &p->pagemap[offset / __vm_page_size];
+
+ /* Mark these pages as being paged out. */
+#if 0
+ if (initializing)
+ {
+ assert (npages <= 32);
+ for (i = 0; i < npages; i++)
+ {
+ if (pm_entries[i] & PM_INIT)
+ omitdata |= 1 << i;
+ else
+ pm_entries[i] |= PM_PAGINGOUT | PM_INIT;
+ }
+ }
+ 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
+ might come in while we do the I/O; in that case there
+ would be a new entry on p->lock_requests and we must
+ make sure we don't decrement it. So we have to keep
+ track independently of which lock requests we incremented. */
+ lock_list = 0;
+ for (lr = p->lock_requests; lr; lr = lr->next)
+ if (offset < lr->end && offset + length >= lr->start)
+ {
+ ll = alloca (sizeof (struct lock_list));
+ ll->lr = lr;
+ ll->next = lock_list;
+ lock_list = ll;
+ lr->pending_writes++;
+ }
+
+ /* Let someone else in. */
+ _pager_release_seqno (p, seqno);
+ mutex_unlock (&p->interlock);
+
+ /* 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++)
+ if (!(omitdata & (1 << 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_entries = &p->pagemap[offset / __vm_page_size];
+
+ for (i = 0; i < npages; i++)
+ {
+ if (omitdata & (1 << i))
+ continue;
+
+ 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
+ munmap ((caddr_t) (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)
+ if (!--ll->lr->pending_writes && !ll->lr->locks_pending)
+ wakeup = 1;
+ if (wakeup)
+ condition_broadcast (&p->wakeup);
+
+ _pager_allow_termination (p);
+
+ mutex_unlock (&p->interlock);
+
+ ports_port_deref (p);
+ return 0;
+
+ release_out:
+ _pager_release_seqno (p, seqno);
+ mutex_unlock (&p->interlock);
+ ports_port_deref (p);
+ return 0;
+}
+
+/* Implement pageout call back as described by <mach/memory_object.defs>. */
+kern_return_t
+_pager_seqnos_memory_object_data_return (mach_port_t object,
+ mach_port_seqno_t seqno,
+ mach_port_t control,
+ vm_offset_t offset,
+ pointer_t data,
+ vm_size_t length,
+ int dirty,
+ int kcopy)
+{
+ return _pager_do_write_request (object, seqno, control, offset, data,
+ length, dirty, kcopy, 0);
+}
diff --git a/libpager/data-unlock.c b/libpager/data-unlock.c
new file mode 100644
index 00000000..a4ef0600
--- /dev/null
+++ b/libpager/data-unlock.c
@@ -0,0 +1,90 @@
+/* Implementation of memory_object_data_unlock for pager library
+ Copyright (C) 1994, 1995 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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_S.h"
+#include <stdio.h>
+
+/* 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,
+ mach_port_seqno_t seqno,
+ mach_port_t control,
+ vm_offset_t offset,
+ vm_size_t length,
+ vm_prot_t access)
+{
+ struct pager *p;
+ volatile int err;
+
+ p = ports_lookup_port (0, object, _pager_class);
+ if (!p)
+ return EOPNOTSUPP;
+
+ mutex_lock (&p->interlock);
+ _pager_wait_for_seqno (p, seqno);
+ _pager_release_seqno (p, seqno);
+ mutex_unlock (&p->interlock);
+
+ if (p->pager_state != NORMAL)
+ {
+ printf ("pager in wrong state for unlock\n");
+ goto out;
+ }
+
+ if (control != p->memobjcntl)
+ {
+ printf ("incg data unlock: wrong control port\n");
+ goto out;
+ }
+ /* The only thing we ever block is writes */
+ if ((access & VM_PROT_WRITE) == 0)
+ {
+ printf ("incg data unlock: not unlock writes\n");
+ goto out;
+ }
+ if (offset % __vm_page_size)
+ {
+ printf ("incg data unlock: misaligned request\n");
+ goto out;
+ }
+ if (length != __vm_page_size)
+ {
+ printf ("incg data unlock: bad length size %d\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,
+ VM_PROT_NONE, 0);
+ else
+ {
+ /* Flush the page, and set a bit so that m_o_data_request knows
+ to issue an error. */
+ _pager_lock_object (p, offset, length, MEMORY_OBJECT_RETURN_NONE, 1,
+ VM_PROT_WRITE, 1);
+ _pager_mark_next_request_error (p, offset, length, err);
+ }
+ out:
+ ports_port_deref (p);
+ return 0;
+}
+
diff --git a/libpager/demuxer.c b/libpager/demuxer.c
new file mode 100644
index 00000000..f233d1c0
--- /dev/null
+++ b/libpager/demuxer.c
@@ -0,0 +1,36 @@
+/* Demuxer for pager library
+ Copyright (C) 1994, 1995 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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_S.h"
+#include "notify_S.h"
+
+/* Demultiplex a single message directed at a pager port; INP is the
+ message received; fille OUTP with the reply. */
+int
+pager_demuxer (mach_msg_header_t *inp,
+ mach_msg_header_t *outp)
+{
+ extern int _pager_seqnos_memory_object_server (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));
+}
+
diff --git a/libpager/dropweak.c b/libpager/dropweak.c
new file mode 100644
index 00000000..54f16b60
--- /dev/null
+++ b/libpager/dropweak.c
@@ -0,0 +1,29 @@
+/*
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "priv.h"
+
+void
+_pager_real_dropweak (void *arg)
+{
+ struct pager *p = arg;
+
+ pager_dropweak (p->upi);
+}
diff --git a/libpager/get-upi.c b/libpager/get-upi.c
new file mode 100644
index 00000000..e9e92924
--- /dev/null
+++ b/libpager/get-upi.c
@@ -0,0 +1,27 @@
+/*
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "priv.h"
+
+struct user_pager_info *
+pager_get_upi (struct pager *p)
+{
+ return p->upi;
+}
diff --git a/libpager/inhibit-term.c b/libpager/inhibit-term.c
new file mode 100644
index 00000000..222bad5e
--- /dev/null
+++ b/libpager/inhibit-term.c
@@ -0,0 +1,35 @@
+/* Locks to inhibit termination races for pager library
+ Copyright (C) 1994 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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"
+
+/* Prevent this memory object from being terminated. */
+/* Must be called with interlock held. */
+void
+_pager_block_termination (struct pager *p)
+{
+ p->noterm++;
+}
+
+/* Allow termination again. */
+/* Must be called with interlock held. */
+void
+_pager_allow_termination (struct pager *p)
+{
+ if (!--p->noterm && p->termwaiting)
+ condition_broadcast (&p->wakeup);
+}
diff --git a/libpager/lock-completed.c b/libpager/lock-completed.c
new file mode 100644
index 00000000..1810959f
--- /dev/null
+++ b/libpager/lock-completed.c
@@ -0,0 +1,68 @@
+/* Implementation of memory_object_lock_completed for pager library
+ Copyright (C) 1994, 1995, 1996 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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_S.h"
+#include <stdio.h>
+
+/* The kernel calls this (as described in <mach/memory_object.defs>)
+ when a memory_object_lock_request call has completed. Read this
+ in combination with lock-object.c. */
+kern_return_t
+_pager_seqnos_memory_object_lock_completed (mach_port_t object,
+ mach_port_seqno_t seqno,
+ mach_port_t control,
+ vm_offset_t offset,
+ vm_size_t length)
+{
+ error_t err = 0;
+ struct pager *p;
+ struct lock_request *lr;
+
+ p = ports_lookup_port (0, object, _pager_class);
+ if (!p)
+ return EOPNOTSUPP;
+
+ mutex_lock (&p->interlock);
+ _pager_wait_for_seqno (p, seqno);
+
+ if (control != p->memobjcntl)
+ {
+ printf ("lock_completed: bad control port\n");
+ err = EPERM;
+ goto out;
+ }
+
+ mach_port_deallocate (mach_task_self (), control);
+
+ for (lr = p->lock_requests; lr; lr = lr->next)
+ if (lr->start == offset && lr->end == offset + length)
+ {
+ if (lr->locks_pending)
+ --lr->locks_pending;
+ if (!lr->locks_pending && !lr->pending_writes)
+ condition_broadcast (&p->wakeup);
+ break;
+ }
+
+ out:
+ _pager_release_seqno (p, seqno);
+ mutex_unlock (&p->interlock);
+ ports_port_deref (p);
+
+ return err;
+}
diff --git a/libpager/lock-object.c b/libpager/lock-object.c
new file mode 100644
index 00000000..5182eff8
--- /dev/null
+++ b/libpager/lock-object.c
@@ -0,0 +1,105 @@
+/* Synchronous wrapper for memory_object_lock_request
+ Copyright (C) 1993, 1994, 1996, 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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"
+
+/* Request a lock from the kernel on pager P. Parameters OFFSET,
+ SIZE, SHOULD_RETURN, SHOULD_FLUSH, and LOCK_VALUE are as for
+ memory_object_lock_request. If SYNC is set, then wait for the
+ operation to fully complete before returning. */
+void
+_pager_lock_object (struct pager *p,
+ vm_offset_t offset,
+ vm_size_t size,
+ int should_return,
+ int should_flush,
+ vm_prot_t lock_value,
+ int sync)
+{
+ int i;
+ struct lock_request *lr = 0;
+
+ mutex_lock (&p->interlock);
+ if (p->pager_state != NORMAL)
+ {
+ mutex_unlock (&p->interlock);
+ return;
+ }
+
+ if (sync)
+ {
+ for (lr = p->lock_requests; lr; lr = lr->next)
+ if (lr->start == offset && lr->end == offset + size)
+ {
+ lr->locks_pending++;
+ lr->threads_waiting++;
+ break;
+ }
+ if (!lr)
+ {
+ lr = malloc (sizeof (struct lock_request));
+ lr->start = offset;
+ lr->end = offset + size;
+ lr->pending_writes = 0;
+ lr->locks_pending = 1;
+ lr->threads_waiting = 1;
+ lr->next = p->lock_requests;
+ if (lr->next)
+ lr->next->prevp = &lr->next;
+ lr->prevp = &p->lock_requests;
+ p->lock_requests = lr;
+ }
+ }
+
+ memory_object_lock_request (p->memobjcntl, offset, size, should_return,
+ should_flush, lock_value,
+ sync ? p->port.port_right : MACH_PORT_NULL);
+
+ if (sync)
+ {
+ while (lr->locks_pending || lr->pending_writes)
+ condition_wait (&p->wakeup, &p->interlock);
+
+ if (! --lr->threads_waiting)
+ {
+ *lr->prevp = lr->next;
+ if (lr->next)
+ lr->next->prevp = lr->prevp;
+ free (lr);
+ }
+
+ if (should_flush)
+ {
+ vm_offset_t pm_offs = offset / __vm_page_size;
+
+ _pager_pagemap_resize (p, offset + size);
+ if (p->pagemapsize > pm_offs)
+ {
+ char *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;
+ }
+ }
+ }
+
+ mutex_unlock (&p->interlock);
+}
diff --git a/libpager/mark-error.c b/libpager/mark-error.c
new file mode 100644
index 00000000..8b031479
--- /dev/null
+++ b/libpager/mark-error.c
@@ -0,0 +1,122 @@
+/* Recording errors for pager library
+ 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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"
+
+
+int _pager_page_errors[] = {KERN_SUCCESS, ENOSPC, EIO, EDQUOT};
+
+/* Some error has happened indicating that the page cannot be written.
+ (Usually this is ENOSPC or EDQOUT.) On the next pagein which
+ requests write access, return the error to the kernel. (This is
+ screwy because of the rules associated with m_o_lock_request.)
+ Currently the only errors permitted are ENOSPC, EIO, and EDQUOT. */
+void
+_pager_mark_next_request_error(struct pager *pager,
+ vm_address_t offset,
+ vm_size_t length,
+ error_t error)
+{
+ int page_error;
+ char *p;
+
+ offset /= __vm_page_size;
+ length /= __vm_page_size;
+
+ switch (error)
+ {
+ case 0:
+ page_error = PAGE_NOERR;
+ break;
+ case ENOSPC:
+ page_error = PAGE_ENOSPC;
+ break;
+ case EIO:
+ default:
+ page_error = PAGE_EIO;
+ break;
+ case EDQUOT:
+ page_error = PAGE_EDQUOT;
+ break;
+ }
+
+ for (p = pager->pagemap + offset; p < pager->pagemap + offset + length; p++)
+ *p = SET_PM_NEXTERROR (*p, page_error);
+}
+
+/* We are returning a pager error to the kernel. Write down
+ in the pager what that error was so that the exception handling
+ routines can find out. (This is only necessary because the
+ XP interface is not completely implemented in the kernel.)
+ Again, only ENOSPC, EIO, and EDQUOT are permitted. */
+void
+_pager_mark_object_error(struct pager *pager,
+ vm_address_t offset,
+ vm_size_t length,
+ error_t error)
+{
+ int page_error = 0;
+ char *p;
+
+ offset /= __vm_page_size;
+ length /= __vm_page_size;
+
+ switch (error)
+ {
+ case 0:
+ page_error = PAGE_NOERR;
+ break;
+ case ENOSPC:
+ page_error = PAGE_ENOSPC;
+ break;
+ case EIO:
+ default:
+ page_error = PAGE_EIO;
+ break;
+ case EDQUOT:
+ page_error = PAGE_EDQUOT;
+ break;
+ }
+
+ for (p = pager->pagemap + offset; p < pager->pagemap + offset + length; p++)
+ *p = SET_PM_ERROR (*p, page_error);
+}
+
+/* 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)
+{
+ error_t err;
+
+ mutex_lock (&p->interlock);
+
+ 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/no-senders.c b/libpager/no-senders.c
new file mode 100644
index 00000000..3c2400c4
--- /dev/null
+++ b/libpager/no-senders.c
@@ -0,0 +1,43 @@
+/* Called when a nosenders notification happens
+ Copyright (C) 1994, 1995 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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 <mach/notify.h>
+
+error_t
+_pager_do_seqnos_mach_notify_no_senders (mach_port_t notify,
+ mach_port_seqno_t seqno,
+ mach_port_mscount_t mscount)
+{
+ struct pager *p = ports_lookup_port (0, notify, _pager_class);
+
+ if (!p)
+ return EOPNOTSUPP;
+
+ mutex_lock (&p->interlock);
+ _pager_wait_for_seqno (p, seqno);
+ _pager_release_seqno (p, seqno);
+ mutex_unlock (&p->interlock);
+
+ ports_no_senders (p, mscount);
+
+ ports_port_deref (p);
+ return 0;
+}
+
+
diff --git a/libpager/notify-stubs.c b/libpager/notify-stubs.c
new file mode 100644
index 00000000..728163e4
--- /dev/null
+++ b/libpager/notify-stubs.c
@@ -0,0 +1,75 @@
+/*
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#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)),
+ mach_port_t name
+ __attribute__ ((unused)))
+{
+ return 0;
+}
+
+error_t
+_pager_do_seqnos_mach_notify_msg_accepted (mach_port_t notify
+ __attribute__ ((unused)),
+ mach_port_seqno_t seqno
+ __attribute__ ((unused)),
+ mach_port_t name
+ __attribute__ ((unused)))
+{
+ return 0;
+}
+
+error_t
+_pager_do_seqnos_mach_notify_port_destroyed (mach_port_t notify
+ __attribute__ ((unused)),
+ mach_port_seqno_t seqno
+ __attribute__ ((unused)),
+ mach_port_t name
+ __attribute__ ((unused)))
+{
+ return 0;
+}
+
+error_t
+_pager_do_seqnos_mach_notify_send_once (mach_port_t notify
+ __attribute__ ((unused)),
+ mach_port_seqno_t seqno
+ __attribute__ ((unused)))
+{
+ return 0;
+}
+
+error_t
+_pager_do_seqnos_mach_notify_dead_name (mach_port_t notify
+ __attribute__ ((unused)),
+ mach_port_seqno_t seqno
+ __attribute__ ((unused)),
+ mach_port_t name
+ __attribute__ ((unused)))
+{
+ return 0;
+}
diff --git a/libpager/object-create.c b/libpager/object-create.c
new file mode 100644
index 00000000..c8dfe6de
--- /dev/null
+++ b/libpager/object-create.c
@@ -0,0 +1,73 @@
+/* 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-init.c b/libpager/object-init.c
new file mode 100644
index 00000000..eeb50993
--- /dev/null
+++ b/libpager/object-init.c
@@ -0,0 +1,79 @@
+/* Implementation of memory_object_init for pager library
+ Copyright (C) 1994, 1995, 1996 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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_S.h"
+#include <stdio.h>
+
+/* Implement the object initialiation call as described in
+ <mach/memory_object.defs>. */
+kern_return_t
+_pager_seqnos_memory_object_init (mach_port_t object,
+ mach_port_seqno_t seqno,
+ mach_port_t control,
+ mach_port_t name,
+ vm_size_t pagesize)
+{
+ struct pager *p;
+
+ p = ports_lookup_port (0, object, _pager_class);
+ if (!p)
+ return EOPNOTSUPP;
+
+ mutex_lock (&p->interlock);
+ _pager_wait_for_seqno (p, seqno);
+
+ if (pagesize != __vm_page_size)
+ {
+ printf ("incg init: bad page size");
+ goto out;
+ }
+
+ if (p->pager_state != NOTINIT)
+ {
+#ifdef KERNEL_INIT_RACE
+ struct pending_init *i = malloc (sizeof (struct pending_init));
+ printf ("pager out-of-sequence init\n");
+ i->control = control;
+ i->name = name;
+
+ i->next = 0;
+ if (p->init_tail)
+ p->init_tail->next = i;
+ else
+ p->init_head = i;
+ p->init_tail = i;
+#else
+ printf ("pager dup init\n");
+#endif
+ goto out;
+ }
+
+ p->memobjcntl = control;
+ p->memobjname = name;
+
+ memory_object_ready (control, p->may_cache, p->copy_strategy);
+
+ p->pager_state = NORMAL;
+
+ out:
+ _pager_release_seqno (p, seqno);
+ mutex_unlock (&p->interlock);
+ ports_port_deref (p);
+
+ return 0;
+}
diff --git a/libpager/object-terminate.c b/libpager/object-terminate.c
new file mode 100644
index 00000000..4315cbbb
--- /dev/null
+++ b/libpager/object-terminate.c
@@ -0,0 +1,133 @@
+/* Implementation of memory_object_terminate for pager library
+ Copyright (C) 1994, 1995, 1996, 1999 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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_S.h"
+#include <stdio.h>
+
+/* Implement the object termination call from the kernel as described
+ in <mach/memory_object.defs>. */
+kern_return_t
+_pager_seqnos_memory_object_terminate (mach_port_t object,
+ mach_port_seqno_t seqno,
+ mach_port_t control,
+ mach_port_t name)
+{
+ struct pager *p;
+
+ p = ports_lookup_port (0, object, _pager_class);
+ if (!p)
+ return EOPNOTSUPP;
+
+ mutex_lock (&p->interlock);
+ _pager_wait_for_seqno (p, seqno);
+
+ if (control != p->memobjcntl)
+ {
+ printf ("incg terminate: wrong control port");
+ goto out;
+ }
+ if (name != p->memobjname)
+ {
+ printf ("incg terminate: wrong name port");
+ goto out;
+ }
+
+ while (p->noterm)
+ {
+ p->termwaiting = 1;
+ 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
+ if (p->init_head)
+ {
+ struct pending_init *i = p->init_head;
+ p->init_head = i->next;
+ if (!i->next)
+ p->init_tail = 0;
+ p->memobjcntl = i->control;
+ p->memobjname = i->name;
+ memory_object_ready (i->control, p->may_cache, p->copy_strategy);
+ p->pager_state = NORMAL;
+ free (i);
+ }
+#endif
+
+ out:
+ _pager_release_seqno (p, seqno);
+ mutex_unlock (&p->interlock);
+ ports_port_deref (p);
+
+ return 0;
+}
+
+/* Shared code for termination from memory_object_terminate and
+ no-senders. The pager must be locked. This routine will
+ deallocate all the ports and memory that pager P references. */
+void
+_pager_free_structure (struct pager *p)
+{
+ int wakeup;
+ struct lock_request *lr;
+ struct attribute_request *ar;
+
+ wakeup = 0;
+ for (lr = p->lock_requests; lr; lr = lr->next)
+ {
+ lr->locks_pending = 0;
+ if (!lr->pending_writes)
+ wakeup = 1;
+ }
+ for (ar = p->attribute_requests; ar; ar = ar->next)
+ {
+ ar->attrs_pending = 0;
+ wakeup = 1;
+ }
+
+ if (wakeup)
+ condition_broadcast (&p->wakeup);
+
+ 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)
+ {
+ munmap (p->pagemap, p->pagemapsize);
+ p->pagemapsize = 0;
+ p->pagemap = 0;
+ }
+
+ p->pager_state = NOTINIT;
+}
diff --git a/libpager/offer-page.c b/libpager/offer-page.c
new file mode 100644
index 00000000..0d62da6a
--- /dev/null
+++ b/libpager/offer-page.c
@@ -0,0 +1,52 @@
+/* Wrapper for unsolicited memory_object_data_supply
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+
+#include "priv.h"
+
+void
+pager_offer_page (struct pager *p,
+ int precious,
+ int writelock,
+ vm_offset_t offset,
+ vm_address_t buf)
+{
+ mutex_lock (&p->interlock);
+
+ if (_pager_pagemap_resize (p, offset + vm_page_size))
+ {
+ char *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);
+ }
+
+ mutex_unlock (&p->interlock);
+}
+
diff --git a/libpager/pagemap.c b/libpager/pagemap.c
new file mode 100644
index 00000000..c6d924c7
--- /dev/null
+++ b/libpager/pagemap.c
@@ -0,0 +1,46 @@
+/* Pagemap manipulation for pager library
+ Copyright (C) 1994, 1997, 1999 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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 <string.h>
+
+/* Grow the pagemap of pager P as necessary to deal with address OFF */
+error_t
+_pager_pagemap_resize (struct pager *p, vm_address_t off)
+{
+ error_t err = 0;
+
+ off /= __vm_page_size;
+
+ if (p->pagemapsize < off)
+ {
+ void *newaddr;
+ int newsize = round_page (off);
+
+ newaddr = mmap (0, newsize, 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);
+ p->pagemap = newaddr;
+ p->pagemapsize = newsize;
+ }
+ }
+
+ return err;
+}
diff --git a/libpager/pager-attr.c b/libpager/pager-attr.c
new file mode 100644
index 00000000..cbc1533f
--- /dev/null
+++ b/libpager/pager-attr.c
@@ -0,0 +1,98 @@
+/* Changing pager attributes synchronously
+ Copyright (C) 1994, 1996 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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 <assert.h>
+
+/* Change the attributes of the memory object underlying pager P.
+ Args MAY_CACHE and COPY_STRATEGY are as for
+ memory_object_change_atributes. Wait for the kernel to report completion
+ off WAIT is set.*/
+void
+pager_change_attributes (struct pager *p,
+ boolean_t may_cache,
+ memory_object_copy_strategy_t copy_strategy,
+ int wait)
+{
+ struct attribute_request *ar = 0;
+
+ mutex_lock (&p->interlock);
+
+ /* If there's nothing to do we might be able to return. However,
+ if the user asked us to wait, and there are pending changes,
+ then we have to do the work anyway because we must follow the
+ pending change. */
+ if (p->may_cache == may_cache && p->copy_strategy == copy_strategy
+ && ! (p->attribute_requests && wait))
+ {
+ mutex_unlock (&p->interlock);
+ return;
+ }
+
+ p->may_cache = may_cache;
+ p->copy_strategy = copy_strategy;
+
+ if (p->pager_state == NOTINIT)
+ {
+ mutex_unlock (&p->interlock);
+ return;
+ }
+
+ if (wait)
+ {
+ for (ar = p->attribute_requests; ar; ar = ar->next)
+ if (ar->may_cache == may_cache
+ && ar->copy_strategy == copy_strategy)
+ {
+ ar->attrs_pending++;
+ ar->threads_waiting++;
+ break;
+ }
+ if (!ar)
+ {
+ ar = malloc (sizeof (struct attribute_request));
+ ar->may_cache = may_cache;
+ ar->copy_strategy = copy_strategy;
+ ar->attrs_pending = 1;
+ ar->threads_waiting = 1;
+ ar->next = p->attribute_requests;
+ if (ar->next)
+ ar->next->prevp = &ar->next;
+ ar->prevp = &p->attribute_requests;
+ p->attribute_requests = ar;
+ }
+ }
+
+ memory_object_change_attributes (p->memobjcntl, may_cache, copy_strategy,
+ wait ? p->port.port_right : MACH_PORT_NULL);
+
+ if (wait)
+ {
+ while (ar->attrs_pending)
+ condition_wait (&p->wakeup, &p->interlock);
+
+ if (! --ar->threads_waiting)
+ {
+ *ar->prevp = ar->next;
+ if (ar->next)
+ ar->next->prevp = ar->prevp;
+ free (ar);
+ }
+ }
+
+ mutex_unlock (&p->interlock);
+}
diff --git a/libpager/pager-create.c b/libpager/pager-create.c
new file mode 100644
index 00000000..26d1aad2
--- /dev/null
+++ b/libpager/pager-create.c
@@ -0,0 +1,64 @@
+/* Pager creation
+ Copyright (C) 1994, 1995, 1996 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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"
+
+/* Create and return a new pager with user info UPI. */
+struct pager *
+pager_create (struct user_pager_info *upi,
+ struct port_bucket *bucket,
+ boolean_t may_cache,
+ memory_object_copy_strategy_t copy_strategy)
+{
+ struct pager *p;
+
+ errno = ports_create_port (_pager_class, bucket, sizeof (struct pager), &p);
+ if (errno)
+ return 0;
+
+ p->upi = upi;
+ p->pager_state = NOTINIT;
+ mutex_init (&p->interlock);
+ condition_init (&p->wakeup);
+ p->lock_requests = 0;
+ p->attribute_requests = 0;
+ p->may_cache = may_cache;
+ p->copy_strategy = copy_strategy;
+ p->memobjcntl = MACH_PORT_NULL;
+ p->memobjname = MACH_PORT_NULL;
+ p->seqno = -1;
+ p->noterm = 0;
+ p->termwaiting = 0;
+ p->waitingforseqno = 0;
+ p->pagemap = 0;
+ p->pagemapsize = 0;
+
+ return p;
+}
+
+
+/* This causes the function to be run at startup by compiler magic. */
+static void create_class (void) __attribute__ ((constructor));
+
+static void
+create_class ()
+{
+ _pager_class = ports_create_class (_pager_clean, _pager_real_dropweak);
+ (void) &create_class; /* Avoid warning */
+}
+
+
diff --git a/libpager/pager-flush.c b/libpager/pager-flush.c
new file mode 100644
index 00000000..55a76de6
--- /dev/null
+++ b/libpager/pager-flush.c
@@ -0,0 +1,45 @@
+/* Functions for flushing data
+ Copyright (C) 1994, 1996 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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"
+
+/* Have the kernel flush all pages in the pager; if WAIT is set, then
+ wait for them to be finally expunged before returning. */
+void
+pager_flush (struct pager *p, int wait)
+{
+ vm_address_t offset;
+ vm_size_t len;
+
+ pager_report_extent (p->upi, &offset, &len);
+
+ _pager_lock_object (p, offset, len, MEMORY_OBJECT_RETURN_NONE, 1,
+ VM_PROT_NO_CHANGE, wait);
+}
+
+
+/* Have the kernel write back some pages of a pager from OFFSET to
+ OFFSET+SIZE; if WAIT is set, then wait for them to be finally
+ written before returning. */
+void
+pager_flush_some (struct pager *p, vm_address_t offset,
+ vm_size_t size, int wait)
+{
+ _pager_lock_object (p, offset, size, MEMORY_OBJECT_RETURN_NONE, 1,
+ VM_PROT_NO_CHANGE, wait);
+}
+
diff --git a/libpager/pager-memcpy.c b/libpager/pager-memcpy.c
new file mode 100644
index 00000000..ed63c247
--- /dev/null
+++ b/libpager/pager-memcpy.c
@@ -0,0 +1,107 @@
+/* Fault-safe copy into or out of pager-backed memory.
+ Copyright (C) 1996,97,99,2000 Free Software Foundation, Inc.
+ Written by Roland McGrath.
+
+ This program 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.
+
+ This program 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 "pager.h"
+#include <sys/mman.h>
+#include <hurd/sigpreempt.h>
+#include <assert.h>
+
+/* Try to copy *SIZE bytes between the region OTHER points to
+ and the region at OFFSET in the pager indicated by PAGER and MEMOBJ.
+ If PROT is VM_PROT_READ, copying is from the pager to OTHER;
+ if PROT contains VM_PROT_WRITE, copying is from OTHER into the pager.
+ *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;
+
+ error_t copy (struct hurd_signal_preemptor *preemptor)
+ {
+ while (to_copy > 0)
+ {
+ size_t pageoff = offset & (vm_page_size - 1);
+
+ if (window)
+ /* Deallocate the old window. */
+ munmap ((caddr_t) window, windowsize);
+
+ /* Map in and copy a standard-sized window, unless that is
+ more than the total left to be copied. */
+
+ if (windowsize > pageoff + to_copy)
+ windowsize = pageoff + to_copy;
+
+ 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;
+
+ /* Realign the fault preemptor for the new mapping window. */
+ preemptor->first = window;
+ preemptor->last = window + windowsize;
+
+ if (prot == VM_PROT_READ)
+ memcpy (other, (const void *) window + pageoff,
+ windowsize - pageoff);
+ else
+ memcpy ((void *) window + pageoff, other, windowsize - pageoff);
+
+ offset += windowsize - pageoff;
+ other += windowsize - pageoff;
+ to_copy -= windowsize - pageoff;
+ }
+ return 0;
+ }
+
+ jmp_buf buf;
+ void fault (int signo, long int sigcode, struct sigcontext *scp)
+ {
+ assert (scp->sc_error == EKERN_MEMORY_ERROR);
+ err = pager_get_error (pager, sigcode - window + offset);
+ to_copy -= sigcode - window;
+ longjmp (buf, 1);
+ }
+
+ if (to_copy == 0)
+ /* Short-circuit return if nothing to do.
+ ERR would not be initialized by the copy loop in this case. */
+ return 0;
+
+ if (setjmp (buf) == 0)
+ hurd_catch_signal (sigmask (SIGSEGV) | sigmask (SIGBUS),
+ window, window + windowsize,
+ &copy, (sighandler_t) &fault);
+
+ if (window)
+ munmap ((caddr_t) window, windowsize);
+
+ *size -= to_copy;
+
+ return err;
+}
diff --git a/libpager/pager-port.c b/libpager/pager-port.c
new file mode 100644
index 00000000..e5d10457
--- /dev/null
+++ b/libpager/pager-port.c
@@ -0,0 +1,26 @@
+/* Return the port corresponding to a pager.
+ Copyright (C) 1993, 1994 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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"
+
+/* Return the port (receive right) corresponding to a pager. It is
+ essential that a new send right be created from this port. */
+mach_port_t
+pager_get_port (struct pager *p)
+{
+ return ports_get_right (p);
+}
diff --git a/libpager/pager-return.c b/libpager/pager-return.c
new file mode 100644
index 00000000..b1013059
--- /dev/null
+++ b/libpager/pager-return.c
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "priv.h"
+
+/* Have all dirty pages written back, and also flush the contents of
+ the kernel's cache. */
+void
+pager_return (struct pager *p, int wait)
+{
+ vm_address_t offset;
+ vm_size_t len;
+
+ pager_report_extent (p->upi, &offset, &len);
+
+ _pager_lock_object (p, offset, len, MEMORY_OBJECT_RETURN_ALL, 1,
+ VM_PROT_NO_CHANGE, wait);
+}
+
+void
+pager_return_some (struct pager *p, vm_address_t offset,
+ vm_size_t size, int wait)
+{
+ _pager_lock_object (p, offset, size, MEMORY_OBJECT_RETURN_ALL, 1,
+ VM_PROT_NO_CHANGE, wait);
+}
+
diff --git a/libpager/pager-shutdown.c b/libpager/pager-shutdown.c
new file mode 100644
index 00000000..b729b3f2
--- /dev/null
+++ b/libpager/pager-shutdown.c
@@ -0,0 +1,33 @@
+/* Pager shutdown in pager library
+ Copyright (C) 1994, 1995 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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 <mach/notify.h>
+
+/* Shutdown pager P and prevent any future paging activity on it. */
+void
+pager_shutdown (struct pager *p)
+{
+ /* Sync and flush pager */
+ pager_sync (p, 1);
+ pager_flush (p, 1);
+ mutex_lock (&p->interlock);
+ p->pager_state = SHUTDOWN;
+ ports_destroy_right (p);
+ mutex_unlock (&p->interlock);
+}
+
diff --git a/libpager/pager-sync.c b/libpager/pager-sync.c
new file mode 100644
index 00000000..d98a3ac8
--- /dev/null
+++ b/libpager/pager-sync.c
@@ -0,0 +1,45 @@
+/* Functions for sync.
+ Copyright (C) 1994, 1996 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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"
+
+/* Have the kernel write back all dirty pages in the pager; if
+ WAIT is set, then wait for them to be finally written before
+ returning. */
+void
+pager_sync (struct pager *p, int wait)
+{
+ vm_address_t offset;
+ vm_size_t len;
+
+ pager_report_extent (p->upi, &offset, &len);
+
+ _pager_lock_object (p, offset, len, MEMORY_OBJECT_RETURN_ALL, 0,
+ VM_PROT_NO_CHANGE, wait);
+}
+
+
+/* Have the kernel write back some pages of a pager; if WAIT is set,
+ then wait for them to be finally written before returning. */
+void
+pager_sync_some (struct pager *p, vm_address_t offset,
+ vm_size_t size, int wait)
+{
+ _pager_lock_object (p, offset, size, MEMORY_OBJECT_RETURN_ALL, 0,
+ VM_PROT_NO_CHANGE, wait);
+}
+
diff --git a/libpager/pager.h b/libpager/pager.h
new file mode 100644
index 00000000..d3f1162c
--- /dev/null
+++ b/libpager/pager.h
@@ -0,0 +1,195 @@
+/* Definitions for multi-threaded pager library
+ 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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. */
+
+
+#ifndef _HURD_PAGER_
+#define _HURD_PAGER_
+
+#include <hurd/ports.h>
+
+/* This declaration exists to place struct user_pager_info in the proper
+ scope. */
+struct user_pager_info;
+
+/* This de-muxer function is for use within libports_demuxer. */
+/* INP is a message we've received; OUTP will be filled in with
+ a reply message. */
+int pager_demuxer (mach_msg_header_t *inp,
+ mach_msg_header_t *outp);
+
+/* Create a new pager. The pager will have a port created for it
+ (using libports, in BUCKET) and will be immediately ready
+ to receive requests. U_PAGER will be provided to later calls to
+ pager_find_address. The pager will have one user reference
+ 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. On errors, return null and set errno. */
+struct pager *
+pager_create (struct user_pager_info *u_pager,
+ struct port_bucket *bucket,
+ boolean_t may_cache,
+ memory_object_copy_strategy_t copy_strategy);
+
+/* Return the user_pager_info struct associated with a pager. */
+struct user_pager_info *
+pager_get_upi (struct pager *p);
+
+/* Sync data from pager PAGER to backing store; wait for
+ all the writes to complete iff WAIT is set. */
+void
+pager_sync (struct pager *pager,
+ int wait);
+
+/* Sync some data (starting at START, for LEN bytes) from pager PAGER
+ to backing store. Wait for all the writes to complete iff WAIT is
+ set. */
+void
+pager_sync_some (struct pager *pager,
+ vm_address_t start,
+ vm_size_t len,
+ int wait);
+
+/* Flush data from the kernel for pager PAGER and force any pending
+ delayed copies. Wait for all pages to be flushed iff WAIT is set. */
+void
+pager_flush (struct pager *pager,
+ int wait);
+
+
+/* Flush some data (starting at START, for LEN bytes) for pager PAGER
+ from the kernel. Wait for all pages to be flushed iff WAIT is set. */
+void
+pager_flush_some (struct pager *pager,
+ vm_address_t start,
+ vm_size_t len,
+ int wait);
+
+/* Flush data from the kernel for pager PAGER and force any pending
+ delayed copies. Wait for all pages to be flushed iff WAIT is set.
+ Have the kernel write back modifications. */
+void
+pager_return (struct pager *pager,
+ int wait);
+
+
+/* Flush some data (starting at START, for LEN bytes) for pager PAGER
+ from the kernel. Wait for all pages to be flushed iff WAIT is set.
+ Have the kernel write back modifications. */
+void
+pager_return_some (struct pager *pager,
+ vm_address_t start,
+ vm_size_t len,
+ int wait);
+
+/* Offer a page of data to the kernel. If PRECIOUS is set, then this
+ page will be paged out at some future point, otherwise it might be
+ dropped by the kernel. If the page is currently in core, the
+ kernel might ignore this call. */
+void
+pager_offer_page (struct pager *pager,
+ int precious,
+ int writelock,
+ vm_offset_t page,
+ vm_address_t buf);
+
+/* Change the attributes of the memory object underlying pager PAGER.
+ Args MAY_CACHE and COPY_STRATEGY are as for
+ memory_object_change_atributes. Wait for the kernel to report completion
+ off WAIT is set.*/
+void
+pager_change_attributes (struct pager *pager,
+ boolean_t may_cache,
+ memory_object_copy_strategy_t copy_strategy,
+ int wait);
+
+/* Return the port (receive right) for requests to the pager. It is
+ absolutely necessary that a new send right be created from this
+ receive right. */
+mach_port_t
+pager_get_port (struct pager *pager);
+
+/* Force termination of a pager. After this returns, no
+ more paging requests on the pager will be honored, and the
+ pager will be deallocated. (The actual deallocation might
+ occur asynchronously if there are currently outstanding paging
+ requests that will complete first.) */
+void
+pager_shutdown (struct pager *pager);
+
+/* Return the error code of the last page error for pager P at address ADDR;
+ this will be deleted when the kernel interface is fixed. */
+error_t
+pager_get_error (struct pager *p, vm_address_t addr);
+
+/* Try to copy *SIZE bytes between the region OTHER points to
+ and the region at OFFSET in the pager indicated by PAGER and MEMOBJ.
+ If PROT is VM_PROT_READ, copying is from the pager to OTHER;
+ if PROT contains VM_PROT_WRITE, copying is from OTHER into the pager.
+ *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);
+
+/* 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. */
+error_t
+pager_read_page (struct user_pager_info *pager,
+ vm_offset_t page,
+ vm_address_t *buf,
+ int *write_lock);
+
+/* The user must define this function. For pager PAGER, synchronously
+ write one page from BUF to offset PAGE. In addition, mfree
+ (or equivalent) BUF. The only permissable error returns are EIO,
+ EDQUOT, and ENOSPC. */
+error_t
+pager_write_page (struct user_pager_info *pager,
+ vm_offset_t page,
+ vm_address_t buf);
+
+/* The user must define this function. A page should be made writable. */
+error_t
+pager_unlock_page (struct user_pager_info *pager,
+ vm_offset_t address);
+
+/* The user must define this function. It should report back (in
+ *OFFSET and *SIZE the minimum valid address the pager will accept
+ and the size of the object. */
+error_t
+pager_report_extent (struct user_pager_info *pager,
+ vm_address_t *offset,
+ vm_size_t *size);
+
+/* The user must define this function. This is called when a pager is
+ being deallocated after all extant send rights have been destroyed. */
+void
+pager_clear_user_data (struct user_pager_info *pager);
+
+/* The use must define this function. This will be called when the ports
+ library wants to drop weak references. The pager library creates no
+ weak references itself. If the user doesn't either, then it's OK for
+ this function to do nothing. */
+void
+pager_dropweak (struct user_pager_info *p);
+
+#endif
diff --git a/libpager/priv.h b/libpager/priv.h
new file mode 100644
index 00000000..0232e3e8
--- /dev/null
+++ b/libpager/priv.h
@@ -0,0 +1,146 @@
+/* Private data for pager library.
+ Copyright (C) 1994,95,96,97,99 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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 <mach.h>
+#include <hurd.h>
+#include <sys/mman.h>
+#include "pager.h"
+#include <hurd/ports.h>
+
+/* Define this if you think the kernel is sending memory_object_init
+ out of sequence with memory_object_terminate. */
+/* #undef KERNEL_INIT_RACE */
+
+struct pager
+{
+ struct port_info port;
+ struct user_pager_info *upi;
+
+ enum
+ {
+ NOTINIT, /* before memory_object_init */
+ 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;
+
+ int noterm; /* number of threads blocking termination */
+
+ struct pager *next, **pprev;
+
+ 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;
+};
+
+struct lock_request
+{
+ struct lock_request *next, **prevp;
+ vm_address_t start, end;
+ int pending_writes;
+ int locks_pending;
+ int threads_waiting;
+};
+
+struct attribute_request
+{
+ struct attribute_request *next, **prevp;
+ boolean_t may_cache;
+ memory_object_copy_strategy_t copy_strategy;
+ int threads_waiting;
+ int attrs_pending;
+};
+
+#ifdef KERNEL_INIT_RACE
+struct pending_init
+{
+ mach_port_t control;
+ mach_port_t name;
+ struct pending_init *next;
+};
+#endif
+
+enum page_errors
+{
+ PAGE_NOERR,
+ PAGE_ENOSPC,
+ PAGE_EIO,
+ PAGE_EDQUOT,
+};
+
+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 */
+
+/* These take values of enum page_errors */
+
+/* Doesn't belong here; this is the error that should have been passed
+ through m_o_data_error to the user but isn't; this lets internal use
+ of the pager know what the error is. */
+#define PM_ERROR(byte) (((byte) & 0xc) >> 2)
+#define SET_PM_ERROR(byte,err) (((byte) & ~0xc) | ((err) << 2))
+
+/* Issue this error on next data_request, but only if it asks for
+ write access. */
+#define PM_NEXTERROR(byte) ((byte) & 0x3)
+#define SET_PM_NEXTERROR(byte,err) (((byte) & ~0x3) | (err))
+
+struct port_class *_pager_class;
+
+
+void _pager_wait_for_seqno (struct pager *, int);
+void _pager_release_seqno (struct pager *, int);
+void _pager_block_termination (struct pager *);
+void _pager_allow_termination (struct pager *);
+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,
+ vm_size_t, error_t);
+void _pager_lock_object (struct pager *, vm_offset_t, vm_size_t, int, int,
+ vm_prot_t, int);
+void _pager_free_structure (struct pager *);
+void _pager_clean (void *arg);
+void _pager_real_dropweak (void *arg);
diff --git a/libpager/seqnos.c b/libpager/seqnos.c
new file mode 100644
index 00000000..94cce93b
--- /dev/null
+++ b/libpager/seqnos.c
@@ -0,0 +1,49 @@
+/* Sequence number synchronization routines for pager library
+ Copyright (C) 1994 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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 <assert.h>
+
+/* The message with seqno SEQNO has just been dequeued for pager P;
+ wait until all preceding messages have had a chance and then
+ return. */
+void
+_pager_wait_for_seqno (struct pager *p,
+ int seqno)
+{
+ while (seqno != p->seqno + 1)
+ {
+ p->waitingforseqno = 1;
+ condition_wait (&p->wakeup, &p->interlock);
+ }
+}
+
+
+/* Allow the next message for pager P (potentially blocked in
+ _pager_wait_for_seqno) to be handled. */
+void
+_pager_release_seqno (struct pager *p,
+ int seqno)
+{
+ assert (seqno == p->seqno + 1);
+ p->seqno = seqno;
+ if (p->waitingforseqno)
+ {
+ p->waitingforseqno = 0;
+ condition_broadcast (&p->wakeup);
+ }
+}
diff --git a/libpager/stubs.c b/libpager/stubs.c
new file mode 100644
index 00000000..b455699e
--- /dev/null
+++ b/libpager/stubs.c
@@ -0,0 +1,59 @@
+ /* Unused memory object interface stubs
+ Copyright (C) 1994 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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_S.h"
+#include <stdio.h>
+
+kern_return_t
+_pager_seqnos_memory_object_copy (mach_port_t old,
+ mach_port_seqno_t seq,
+ memory_object_control_t old_ctl,
+ vm_offset_t off,
+ vm_size_t len,
+ mach_port_t new)
+{
+ printf ("m_o_copy called\n");
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+_pager_seqnos_memory_object_data_write (mach_port_t old,
+ mach_port_seqno_t seq,
+ mach_port_t ctl,
+ vm_offset_t off,
+ pointer_t data,
+ vm_size_t data_cnt)
+{
+ printf ("m_o_data_write called\n");
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+_pager_seqnos_memory_object_supply_completed (mach_port_t obj,
+ mach_port_seqno_t seq,
+ mach_port_t ctl,
+ vm_offset_t off,
+ vm_size_t len,
+ kern_return_t result,
+ vm_offset_t err_off)
+{
+ printf ("m_o_supply_completed called\n");
+ return EOPNOTSUPP;
+}
+