bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Reworking libpager


From: Neal H Walfield
Subject: Reworking libpager
Date: 06 Apr 2002 15:46:51 -0500
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/21.1

I have been inspired by the following entries in the TODO file:

** libpager
*** Put user-defined fns into a callback struct passed to pager_create. !
*** Make libpager paging interface able to read/write multiple pages at once.

Attached is what I consider to be an interface that satisfies both of
these items in a fairly straight forward way.

When designing this, I decided that a small change of philosophy was
necessary to allow for efficient code.  In the current interface, when
a call back function is invoked, it is expected that the call back
function does some work and then eventually return some data to the
libpager callee.  The callee then reorganizes the data and sends it to
the kernel and updates some data structures.

This marshaling of data is too expensive especially when we start
working with multiple pages and file systems where the file system
block size is not the size of a page of memory.  What I suggest
instead is the following model: the call back function, rather than
returning the data to the callee, sends the data (in multiple chunks
if necessary) to other libpager functions.

I think that the comments reveal most of my decisions; if I were to
explain change each change here, I think I would only be repeating
myself.

If you have questions about anything that I have done, or if it is not
clear, please ask.

Comments welcome, thanks.


/* Definitions for multi-threaded pager library
   Copyright (C) 1994,95,96,97,99, 2002 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   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>

/* These declarations exists to place struct user_pager_info and
   struct pager in the proper scope.  */
struct user_pager_info;
struct pager;

struct pager_ops
{
  /* Read from PAGER's backing store, starting at page START, NPAGES
     pages.

     The data is to be provided using either pager_data_supply or
     pager_data_unavailable.

     If an error is encountered reading any pages, it is to be
     reported using pager_data_read_error.

     For each indicated page, the callee *must* call exactly one of
     the above methods; the pager library will not rerequest
     pages.  */
  error_t (*read)(struct pager *pager,
                  struct user_pager_info *upi,
                  off_t start, off_t npages);

  /* Synchronously write to PAGER's backing store the NPAGES pages
     pointed to be BUF starting at page START.

     If DEALLOC is set, BUF must be deallocate be the callee.

     If an error is encountered while writing the pages to the backing
     store, it must be reported using pager_data_write_error.  */
  error_t (*write)(struct pager *pager,
                   struct user_pager_info *upi,
                   off_t start, off_t npages,
                   void *buf, int dealloc);

  /* The NPAGES pages, starting at page START, should be made writable.

     Success is to be indicated using pager_data_unlock; errors using
     pager_data_unlock_error.  */
  error_t (*unlock)(struct pager *pager,
                    struct user_pager_info *upi,
                    off_t start, off_t npages);

  /* Report the first (normally zero) and last valid pages that the
     pager will accept and store them in START and *END
     respectively.  */
  error_t (*report_extent)(struct user_pager_info *upi,
                           off_t *start, off_t *end);

  /* The user may define this function.  If non-NULL, it is called
     when a pager is being deallocated after all extant send rights
     have been destroyed.  */
  void (*clear_user_data)(struct user_pager_info *upi);

  /* This is 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 or be set to NULL.  */
  void (*dropweak)(struct user_pager_info *upi);
};

/* 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), but associated with the OPS operation
   structure and will be immediately ready to receive requests.  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.  A block of memory of size
   UPI_SIZE for pager state will be allocated and provided to the call
   back functions or via pager_get_upi.  On errors, null is returned
   and sets errno is set.  */
struct pager *
pager_create (struct pager_ops *ops,
              size_t upi_size,
              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 *pager);

/* 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);

/* Return the error code of the last page error for pager PAGER at
   page PAGE; this will be deleted when the kernel interface is
   fixed.  */
error_t
pager_get_error (struct pager *pager, off_t page);

/* 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 page START, for NPAGES pages) from pager
   PAGER to backing store.  Wait for all the writes to complete iff
   WAIT is set.  */
void
pager_sync_some (struct pager *pager,
                 off_t start, off_t npages,
                 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 page START, for NPAGES pages) for pager
   PAGER from the kernel.  Wait for all pages to be flushed iff WAIT
   is set.  */
void
pager_flush_some (struct pager *pager,
                  off_t start, off_t npages,
                  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 page START, for NPAGES pages) 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,
                   off_t start, off_t npages,
                   int wait);

/* Offer the NPAGES pages from BUF to the kernel for pager PAGER
   starting at page START.  If PRECIOUS is set, then the pages will be
   paged out at some future point, otherwise they may be dropped with
   out notice.  IF READONLY is set, this data will be provided read
   only to the kernel.  In this case, any attempts to write to the
   pages will cause the PAGER->UNLOCK method to be called.  If DEALLOC
   is set, the buffer pointed to by BUF will be deallocated.

   NB: If the data is currently in core, the kernel may ignore this
   call.  As such, pager_flush_some should be called if the call was
   not in response to a PAGER->READ event.

   This function is normally called as a response to the PAGER->READ
   method.  */
void
pager_data_supply (struct pager *pager,
                   int precious, int readonly,
                   off_t start, off_t npages,
                   void *buf, int dealloc);

/* Indicate to the kernel that the NPAGES pages starting at START are
   unavailable and should be supplied as anonymous (i.e. zero)
   pages.

   This function is normally only called in response to the
   PAGER->READ method.  */
void
pager_data_unavailable (struct pager *pager,
                        off_t start, off_t npages);

/* Indicate that an error has occured while trying to read the NPAGES
   pages starting at page START from pager PAGER's backing store.  The
   only permissable values for ERROR are: EIO, EDQUOT, and ENOSPC (all
   others will be ignored and squashed to EIO).

   This is normally only called in response to the PAGER->READ
   method.  */
void
pager_data_read_error (struct pager *pager,
                       off_t start, off_t npages,
                       error_t error);

/* Indicate that an error has occured while trying to write the NPAGES
   pages starting at page START to pager PAGER's backing store.  The
   only permissable values for ERROR are: EIO, EDQUOT, and ENOSPC (all
   others will be ignored and squashed to EIO).

   This is normally only called in response to the PAGER->WRITE
   method.  */
void
pager_data_write_error (struct pager *pager,
                        off_t start, off_t npages,
                        error_t error);

/* Indicate that the NPAGES pages starting at page START in pager PAGER
   have been made writable.

   This is normally only called in response to the PAGER->UNLOCK
   method.  */
void
pager_data_unlock (struct pager *pager,
                   off_t start, off_t npages);

/* Indicate that an error has occured unlocking (i.e. making writable)
   the NPAGES pages starting at page START in pager PAGER.  The only
   permissable values for ERROR are: EIO, EDQUOT, and ENOSPC (all
   others will be ignored and squashed to EIO).

   This is normally only called in response to the PAGER->UNLOCK
   method.  */
void
pager_data_unlock_error (struct pager *pager,
                         off_t start, off_t npages,
                         error_t error);

/* Change the attributes of the memory object underlying pager PAGER.
   Args MAY_CACHE and COPY_STRATEGY are as for
   memory_object_change_attributes.  Wait for the kernel to report
   completion if WAIT is set.*/
void
pager_change_attributes (struct pager *pager,
                         boolean_t may_cache,
                         memory_object_copy_strategy_t copy_strategy,
                         int wait);

/* 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);

/* 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,
              off_t offset, void *other, size_t *size,
              vm_prot_t prot);

#endif



reply via email to

[Prev in Thread] Current Thread [Next in Thread]