diff options
Diffstat (limited to 'libpager')
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, + ©, (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; +} + |