You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by wr...@apache.org on 2002/01/05 08:14:29 UTC

cvs commit: apr-util/misc apr_rmm.c Makefile.in

wrowe       02/01/04 23:14:29

  Modified:    .        CHANGES aprutil.dsp libaprutil.dsp
               misc     Makefile.in
  Added:       include  apr_rmm.h
               misc     apr_rmm.c
  Log:
    A minimalist relocatable memory manager.  When I suggest minimalist,
    it is -minimal-, still missing locking for allocation [that gets tricky,
    we can discuss on list], some get largest-available and get free space
    APIs, a get_management_overhead call [for determining the optimal
    preallocation size before creating a block of memory to manage]
    and a better-fit algorithm so we make best use of tight spaces.
  
    This also should grow a set of typesafe offset-protection wrappers,
    which I will introduce shortly.  Those have proven trickier than I
    had expected.
  
    While this is designed for Aaron's redesign of shm, it certainly
    isn't limited to that application.  It is great for serializing any
    sort of structures into files or between processes, or other
    persistant applications.
  
  Revision  Changes    Path
  1.47      +4 -0      apr-util/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apr-util/CHANGES,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -u -r1.46 -r1.47
  --- CHANGES	4 Jan 2002 21:54:49 -0000	1.46
  +++ CHANGES	5 Jan 2002 07:14:28 -0000	1.47
  @@ -1,5 +1,9 @@
   Changes with APR-util b1  
   
  +  *) Introduce the apr_rmm api, to allow relocatable memory management
  +     of address-independent data stores, such as shared memory.
  +     [William Rowe]
  +
     *) Rework and fix VPATH-build support.  [Justin Erenkrantz]
   
     *) Add support for Berkeley DB4.  [Justin Erenkrantz]
  
  
  
  1.36      +48 -32    apr-util/aprutil.dsp
  
  Index: aprutil.dsp
  ===================================================================
  RCS file: /home/cvs/apr-util/aprutil.dsp,v
  retrieving revision 1.35
  retrieving revision 1.36
  diff -u -r1.35 -r1.36
  --- aprutil.dsp	26 Dec 2001 21:45:39 -0000	1.35
  +++ aprutil.dsp	5 Jan 2002 07:14:28 -0000	1.36
  @@ -147,69 +147,81 @@
   # Begin Group "dbm"
   
   # PROP Default_Filter ""
  -# Begin Group "sdbm"
  +# Begin Source File
   
  -# PROP Default_Filter ""
  +SOURCE=.\dbm\apr_dbm.c
  +# End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm.c
  +SOURCE=.\dbm\apr_dbm_berkeleydb.c
   # End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm_hash.c
  +SOURCE=.\dbm\apr_dbm_gdbm.c
   # End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm_lock.c
  +SOURCE=.\dbm\apr_dbm_sdbm.c
   # End Source File
  +# End Group
  +# Begin Group "encoding"
  +
  +# PROP Default_Filter ""
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm_pair.c
  +SOURCE=.\encoding\apr_base64.c
   # End Source File
  +# End Group
  +# Begin Group "hooks"
  +
  +# PROP Default_Filter ""
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm_pair.h
  +SOURCE=.\hooks\apr_hooks.c
   # End Source File
  +# End Group
  +# Begin Group "misc"
  +
  +# PROP Default_Filter ""
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm_private.h
  +SOURCE=.\misc\apr_date.c
   # End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm_tune.h
  +SOURCE=.\misc\apr_rmm.c
   # End Source File
   # End Group
  +# Begin Group "sdbm"
  +
  +# PROP Default_Filter ""
   # Begin Source File
   
  -SOURCE=.\dbm\apr_dbm.c
  +SOURCE=.\dbm\sdbm\sdbm.c
   # End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\apr_dbm_berkeleydb.c
  +SOURCE=.\dbm\sdbm\sdbm_hash.c
   # End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\apr_dbm_gdbm.c
  +SOURCE=.\dbm\sdbm\sdbm_lock.c
   # End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\apr_dbm_sdbm.c
  +SOURCE=.\dbm\sdbm\sdbm_pair.c
   # End Source File
  -# End Group
  -# Begin Group "encoding"
  -
  -# PROP Default_Filter ""
   # Begin Source File
   
  -SOURCE=.\encoding\apr_base64.c
  +SOURCE=.\dbm\sdbm\sdbm_pair.h
   # End Source File
  -# End Group
  -# Begin Group "hooks"
  +# Begin Source File
   
  -# PROP Default_Filter ""
  +SOURCE=.\dbm\sdbm\sdbm_private.h
  +# End Source File
   # Begin Source File
   
  -SOURCE=.\hooks\apr_hooks.c
  +SOURCE=.\dbm\sdbm\sdbm_tune.h
   # End Source File
   # End Group
   # Begin Group "uri"
  @@ -228,14 +240,6 @@
   SOURCE=.\xml\apr_xml.c
   # End Source File
   # End Group
  -# Begin Group "misc"
  -
  -# PROP Default_Filter ""
  -# Begin Source File
  -
  -SOURCE=.\misc\apr_date.c
  -# End Source File
  -# End Group
   # End Group
   # Begin Group "Generated"
   
  @@ -374,11 +378,11 @@
   # End Source File
   # Begin Source File
   
  -SOURCE=.\include\apr_dbm.h
  +SOURCE=.\include\apr_date.h
   # End Source File
   # Begin Source File
   
  -SOURCE=.\include\apr_generic_hook.h
  +SOURCE=.\include\apr_dbm.h
   # End Source File
   # Begin Source File
   
  @@ -386,7 +390,19 @@
   # End Source File
   # Begin Source File
   
  +SOURCE=.\include\apr_md4.h
  +# End Source File
  +# Begin Source File
  +
   SOURCE=.\include\apr_optional.h
  +# End Source File
  +# Begin Source File
  +
  +SOURCE=.\include\apr_optional_hooks.h
  +# End Source File
  +# Begin Source File
  +
  +SOURCE=.\include\apr_rmm.h
   # End Source File
   # Begin Source File
   
  
  
  
  1.30      +48 -32    apr-util/libaprutil.dsp
  
  Index: libaprutil.dsp
  ===================================================================
  RCS file: /home/cvs/apr-util/libaprutil.dsp,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- libaprutil.dsp	26 Dec 2001 21:45:39 -0000	1.29
  +++ libaprutil.dsp	5 Jan 2002 07:14:28 -0000	1.30
  @@ -153,69 +153,81 @@
   # Begin Group "dbm"
   
   # PROP Default_Filter ""
  -# Begin Group "sdbm"
  +# Begin Source File
   
  -# PROP Default_Filter ""
  +SOURCE=.\dbm\apr_dbm.c
  +# End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm.c
  +SOURCE=.\dbm\apr_dbm_berkeleydb.c
   # End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm_hash.c
  +SOURCE=.\dbm\apr_dbm_gdbm.c
   # End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm_lock.c
  +SOURCE=.\dbm\apr_dbm_sdbm.c
   # End Source File
  +# End Group
  +# Begin Group "encoding"
  +
  +# PROP Default_Filter ""
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm_pair.c
  +SOURCE=.\encoding\apr_base64.c
   # End Source File
  +# End Group
  +# Begin Group "hooks"
  +
  +# PROP Default_Filter ""
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm_pair.h
  +SOURCE=.\hooks\apr_hooks.c
   # End Source File
  +# End Group
  +# Begin Group "misc"
  +
  +# PROP Default_Filter ""
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm_private.h
  +SOURCE=.\misc\apr_date.c
   # End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\sdbm\sdbm_tune.h
  +SOURCE=.\misc\apr_rmm.c
   # End Source File
   # End Group
  +# Begin Group "sdbm"
  +
  +# PROP Default_Filter ""
   # Begin Source File
   
  -SOURCE=.\dbm\apr_dbm.c
  +SOURCE=.\dbm\sdbm\sdbm.c
   # End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\apr_dbm_berkeleydb.c
  +SOURCE=.\dbm\sdbm\sdbm_hash.c
   # End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\apr_dbm_gdbm.c
  +SOURCE=.\dbm\sdbm\sdbm_lock.c
   # End Source File
   # Begin Source File
   
  -SOURCE=.\dbm\apr_dbm_sdbm.c
  +SOURCE=.\dbm\sdbm\sdbm_pair.c
   # End Source File
  -# End Group
  -# Begin Group "encoding"
  -
  -# PROP Default_Filter ""
   # Begin Source File
   
  -SOURCE=.\encoding\apr_base64.c
  +SOURCE=.\dbm\sdbm\sdbm_pair.h
   # End Source File
  -# End Group
  -# Begin Group "hooks"
  +# Begin Source File
   
  -# PROP Default_Filter ""
  +SOURCE=.\dbm\sdbm\sdbm_private.h
  +# End Source File
   # Begin Source File
   
  -SOURCE=.\hooks\apr_hooks.c
  +SOURCE=.\dbm\sdbm\sdbm_tune.h
   # End Source File
   # End Group
   # Begin Group "uri"
  @@ -234,14 +246,6 @@
   SOURCE=.\xml\apr_xml.c
   # End Source File
   # End Group
  -# Begin Group "misc"
  -
  -# PROP Default_Filter ""
  -# Begin Source File
  -
  -SOURCE=.\misc\apr_date.c
  -# End Source File
  -# End Group
   # End Group
   # Begin Group "Generated"
   
  @@ -380,11 +384,11 @@
   # End Source File
   # Begin Source File
   
  -SOURCE=.\include\apr_dbm.h
  +SOURCE=.\include\apr_date.h
   # End Source File
   # Begin Source File
   
  -SOURCE=.\include\apr_generic_hook.h
  +SOURCE=.\include\apr_dbm.h
   # End Source File
   # Begin Source File
   
  @@ -392,7 +396,19 @@
   # End Source File
   # Begin Source File
   
  +SOURCE=.\include\apr_md4.h
  +# End Source File
  +# Begin Source File
  +
   SOURCE=.\include\apr_optional.h
  +# End Source File
  +# Begin Source File
  +
  +SOURCE=.\include\apr_optional_hooks.h
  +# End Source File
  +# Begin Source File
  +
  +SOURCE=.\include\apr_rmm.h
   # End Source File
   # Begin Source File
   
  
  
  
  1.1                  apr-util/include/apr_rmm.h
  
  Index: apr_rmm.h
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  #ifndef APR_RMM_H
  #define APR_RMM_H
  /** 
   * @file apr_rmm.h
   * @brief APR Relocatable Memory Management Routines
   */
  /**
   * @defgroup APR_RMM Relocatable Memory Management Routines
   * @ingroup APR
   * @{
   */
  
  #include "apr.h"
  #include "apr_pools.h"
  #include "apr_errno.h"
  #include "apu.h"
  
  #ifdef __cplusplus
  extern "C" {
  #endif /* __cplusplus */
  
  /** Structure to access Relocatable, Managed Memory */
  typedef struct apr_rmm_t apr_rmm_t;
  
  /** Fundemental allocation unit, within a spcific apr_rmm_off_t */
  typedef apr_size_t   apr_rmm_off_t;
  
  /**
   * Initialize a relocatable memory block to be managed by the apr_rmm API.
   * @param rmm The relocatable memory block
   * @param membuf The block of relocateable memory to be managed
   * @param memsize The size of relocateable memory block to be managed
   * @param cont The pool to use for local storage and management
   */
  APU_DECLARE(apr_status_t) apr_rmm_init(apr_rmm_t **rmm, void* membuf,
                                         apr_size_t memsize, apr_pool_t *cont);
  
  /**
   * Destroy a managed memory block.
   * @param rmm The relocatable memory block to destroy
   */
  APU_DECLARE(apr_status_t) apr_shm_destroy(apr_rmm_t *rmm);
  
  /**
   * Attach to a relocatable memory block already managed by the apr_rmm API.
   * @param rmm The relocatable memory block
   * @param membuf The block of relocateable memory already under management
   * @param cont The pool to use for local storage and management
   */
  APU_DECLARE(apr_status_t) apr_rmm_attach(apr_rmm_t **rmm, void* membuf,
                                           apr_pool_t *cont);
  
  /**
   * Detach from the managed block of memory.
   * @param rmm The relocatable memory block to detach from
   */
  APU_DECLARE(apr_status_t) apr_rmm_detach(apr_rmm_t *rmm);
  
  /**
   * Allocate memory from the block of relocatable memory.
   * @param rmm The relocatable memory block
   * @param reqsize How much memory to allocate
   */
  APU_DECLARE(apr_rmm_off_t) apr_rmm_malloc(apr_rmm_t *rmm, apr_size_t reqsize);
  
  /**
   * Allocate memory from the block of relocatable memory and initialize it to zero.
   * @param rmm The relocatable memory block
   * @param reqsize How much memory to allocate
   */
  APU_DECLARE(apr_rmm_off_t) apr_rmm_calloc(apr_rmm_t *rmm, apr_size_t reqsize);
  
  /**
   * Free allocation returned by apr_rmm_malloc or apr_rmm_calloc.
   * @param rmm The relocatable memory block
   * @param entity The memory allocation to free
   */
  APU_DECLARE(apr_status_t) apr_rmm_free(apr_rmm_t *rmm, apr_rmm_off_t entity);
  
  /**
   * Retrieve the physical address of a relocatable allocation of memory
   * @param rmm The relocatable memory block
   * @param entity The memory allocation to free
   */
  APU_DECLARE(void *) apr_rmm_addr_get(apr_rmm_t *rmm, apr_rmm_off_t entity);
  
  /**
   * Compute the offset of a relocatable allocation of memory
   * @param rmm The relocatable memory block
   * @param entity The physical address to convert to an offset
   */
  APU_DECLARE(apr_rmm_off_t) apr_rmm_offset_get(apr_rmm_t *rmm, void* entity);
  
  #ifdef __cplusplus
  }
  #endif
  /** @} */
  #endif  /* ! APR_RMM_H */
  
  
  
  
  1.5       +1 -1      apr-util/misc/Makefile.in
  
  Index: Makefile.in
  ===================================================================
  RCS file: /home/cvs/apr-util/misc/Makefile.in,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Makefile.in	4 Jan 2002 21:54:50 -0000	1.4
  +++ Makefile.in	5 Jan 2002 07:14:29 -0000	1.5
  @@ -5,7 +5,7 @@
   top_srcdir=@abs_srcdir@
   INCLUDES=-I$(top_builddir)/include -I$(top_srcdir)/include @APR_INCLUDES@
   
  -TARGETS = apr_date.lo
  +TARGETS = apr_date.lo apr_rmm.lo
   CLEAN_TARGETS = 
   
   # bring in rules.mk for standard functionality
  
  
  
  1.1                  apr-util/misc/apr_rmm.c
  
  Index: apr_rmm.c
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  #include "apr_general.h"
  #include "apr_rmm.h"
  #include "apr_errno.h"
  #include "apr_lib.h"
  #include "apr_strings.h"
  
  typedef struct rmm_block_t {
      apr_size_t size;
      apr_rmm_off_t prev;
      apr_rmm_off_t next;
  } rmm_block_t;
  
  /* Always at our apr_rmm_off(0):
   */
  typedef struct rmm_hdr_block_t {
      apr_size_t abssize;
      apr_rmm_off_t /* rmm_block_t */ firstused;
      apr_rmm_off_t /* rmm_block_t */ firstfree;
  } rmm_hdr_block_t;
  
  typedef struct apr_rmm_t {
      apr_pool_t *p;
      rmm_hdr_block_t *base;
      apr_size_t size;
  } apr_rmm_t;
  
  #define MIN_BLK_SIZE 128
  
  static apr_rmm_off_t find_block_by_offset(apr_rmm_t *rmm, apr_rmm_off_t next, 
                                            apr_rmm_off_t find, int includes)
  {
      apr_rmm_off_t prev = 0;
  
      while (next) {
          struct rmm_block_t *blk = (rmm_block_t*)((char*)rmm->base + next);
  
  	if (find == next)
              return next;
  
          /* Overshot? */
          if (find < next)
              return includes ? prev : 0;
  
          prev = next;
  	next = blk->next;
      }
      return 0;
  }
  
  static apr_rmm_off_t find_block_of_size(apr_rmm_t *rmm, apr_size_t size)
  {
      apr_rmm_off_t next = rmm->base->firstfree;
      apr_rmm_off_t best = 0;
      apr_rmm_off_t bestsize = 0;
  
      while (next) {
          struct rmm_block_t *blk = (rmm_block_t*)((char*)rmm->base + next);
  
  	if (blk->size == size)
  	    return next;
  
          if (blk->size >= size) {
              /* XXX: sub optimal algorithm 
               * We need the most thorough best-fit logic, since we can
               * never grow our rmm, we are SOL when we hit the wall.
               */
              if (!bestsize || (blk->size < bestsize)) {
                  bestsize = blk->size;
                  best = next;
              }
          }
  
  	next = blk->next;
      }
  
      if (bestsize - size > MIN_BLK_SIZE) {
          struct rmm_block_t *blk = (rmm_block_t*)((char*)rmm->base + best);
          struct rmm_block_t *new = (rmm_block_t*)((char*)rmm->base + best + size);
  
          new->size = blk->size - size;
          new->next = blk->next;
          new->prev = best;
  
          blk->size = size;
          blk->next = best + size;
  
          if (new->next) {
              blk = (rmm_block_t*)((char*)rmm->base + blk->next);
              blk->prev = best + size;
          }
      }
  
      if (best) {
          return best;
      }
       
      return 0;
  }
  
  void move_block(apr_rmm_t *rmm, apr_rmm_off_t this, int free)
  {   
      struct rmm_block_t *blk = (rmm_block_t*)((char*)rmm->base + this);
  
      /* close the gap */
      if (blk->prev) {
          struct rmm_block_t *prev = (rmm_block_t*)((char*)rmm->base + blk->prev);
          prev->next = blk->next;
      }
      else {
          if (free) {
              rmm->base->firstused = blk->next;
          }
          else {
              rmm->base->firstfree = blk->next;
          }
      }
      if (blk->next) {
          struct rmm_block_t *next = (rmm_block_t*)((char*)rmm->base + blk->next);
          next->prev = blk->prev;
      }
  
      /* now find it in the other list, pushing it to the head if required */
      if (free) {
          blk->prev = find_block_by_offset(rmm, rmm->base->firstfree, this, 1);
          if (!blk->prev) {
              blk->next = rmm->base->firstfree;
              rmm->base->firstfree = this;
          }
      }
      else {
          blk->prev = find_block_by_offset(rmm, rmm->base->firstused, this, 1);
          if (!blk->prev) {
              blk->next = rmm->base->firstused;
              rmm->base->firstused = this;
          }
      }
  
      /* and open it up */
      if (blk->prev) {
          struct rmm_block_t *prev = (rmm_block_t*)((char*)rmm->base + blk->prev);
          blk->next = prev->next;
          prev->next = this;
      }
  
      if (blk->next) {
          struct rmm_block_t *next = (rmm_block_t*)((char*)rmm->base + blk->next);
          next->prev = this;
      }
  }
  
  APU_DECLARE(apr_status_t) apr_rmm_init(apr_rmm_t **rmm, void *base, apr_size_t size,
                                         apr_pool_t *p)
  {
      rmm_block_t *blk;
  
      (*rmm) = (apr_rmm_t *)apr_pcalloc(p, sizeof(apr_rmm_t));
      (*rmm)->p = p;
      (*rmm)->base = base;
      (*rmm)->size = size;
  
      (*rmm)->base->abssize = size;
      (*rmm)->base->firstused = 0;
      (*rmm)->base->firstfree = sizeof(rmm_hdr_block_t);
  
      blk = (rmm_block_t *)((char*)base + (*rmm)->base->firstfree);
  
      blk->size = size - (*rmm)->base->firstfree;
      blk->prev = 0;
      blk->next = 0;
  
      return APR_SUCCESS;
  }
  
  APU_DECLARE(apr_status_t) apr_rmm_destroy(apr_rmm_t *rmm)
  {
      rmm_block_t *blk;
  
      /* Blast it all --- no going back :) */
      if (rmm->base->firstused) {
          apr_rmm_off_t this = rmm->base->firstused;
          do {
              blk = (rmm_block_t *)((char*)rmm->base + this);
              this = blk->next;
              blk->next = blk->prev = 0;
          } while (this);
          rmm->base->firstused = 0;
      }
      if (rmm->base->firstfree) {
          apr_rmm_off_t this = rmm->base->firstfree;
          do {
              blk = (rmm_block_t *)((char*)rmm->base + this);
              this = blk->next;
              blk->next = blk->prev = 0;
          } while (this);
          rmm->base->firstfree = 0;
      }
      rmm->base->abssize = 0;
      rmm->size = 0;
      return APR_SUCCESS;
  }
  
  APU_DECLARE(apr_status_t) apr_rmm_attach(apr_rmm_t **rmm, void *base, 
                                           apr_pool_t *p)
  {
      /* sanity would be good here */
      (*rmm) = (apr_rmm_t *)apr_pcalloc(p, sizeof(apr_rmm_t));
      (*rmm)->p = p;
      (*rmm)->base = base;
      (*rmm)->size = (*rmm)->base->abssize;
  
      return APR_SUCCESS;
  }
  
  APU_DECLARE(apr_status_t) apr_rmm_detach(apr_rmm_t *rmm) 
  {
      /* A noop until we introduce locking/refcounts */
      return APR_SUCCESS;
  }
  
  APU_DECLARE(apr_rmm_off_t) apr_rmm_malloc(apr_rmm_t *rmm, apr_size_t reqsize)
  {
      apr_rmm_off_t this = find_block_of_size(rmm, reqsize + sizeof(rmm_block_t));
  
      if (this) {
          move_block(rmm, this, 0);
          this += sizeof(rmm_block_t);
      }
  
      return this;
  }
  
  APU_DECLARE(apr_rmm_off_t) apr_rmm_calloc(apr_rmm_t *rmm, apr_size_t reqsize)
  {
      apr_rmm_off_t this = find_block_of_size(rmm, reqsize + sizeof(rmm_block_t));
  
      if (this) {
          move_block(rmm, this, 0);
          this += sizeof(rmm_block_t);
          memset((char*)rmm->base + this, 0, reqsize);
      }
  
      return this;
  }
  
  APU_DECLARE(apr_status_t) apr_rmm_free(apr_rmm_t *rmm, apr_rmm_off_t this)
  {
      struct rmm_block_t *blk;
  
      /* A little sanity check is always healthy, especially here.
       * If we really cared, we could make this compile-time
       */
      if (this < sizeof(rmm_hdr_block_t) + sizeof(rmm_block_t)) {
          return APR_EINVAL;
      }
  
      this -= sizeof(rmm_block_t);
  
      blk = (rmm_block_t*)((char*)rmm->base + this);
  
      if (blk->prev) {
          struct rmm_block_t *prev = (rmm_block_t*)((char*)rmm->base + blk->prev);
          if (prev->next != this) {
              return APR_EINVAL;
          }
      }
      else {
          if (rmm->base->firstused != this) {
              return APR_EINVAL;
          }
      }
  
      if (blk->next) {
          struct rmm_block_t *next = (rmm_block_t*)((char*)rmm->base + blk->next);
          if (next->prev != this) {
              return APR_EINVAL;
          }
      }
  
      /* Ok, it remained [apparently] sane, so unlink it
       */
      move_block(rmm, this, 1);
      
      return APR_SUCCESS;
  }
  
  APU_DECLARE(void *) apr_rmm_addr_get(apr_rmm_t *rmm, apr_rmm_off_t entity) 
  {
      /* debug-sanity checking here would be good
       */
      return (void*)((char*)rmm->base + entity);
  }
  
  APU_DECLARE(apr_rmm_off_t) apr_rmm_offset_get(apr_rmm_t *rmm, void* entity)
  {
      /* debug, or always, sanity checking here would be good
       * since the primitive is apr_rmm_off_t, I don't mind penalizing
       * inverse conversions for safety, unless someone can prove that
       * there is no choice in some cases.
       */
      return ((char*)entity - (char*)rmm->base);
  }
  
  
  

Re: cvs commit: apr-util/misc apr_rmm.c Makefile.in

Posted by "William A. Rowe, Jr." <wr...@covalent.net>.
Some quick credits where credit is due, thanks to David for his very thorough
beos/apr_shmem.c implementation (and to whomever inspired that code), for at
least a good outline and little reminders of structure... and to Aaron, Justin,
Sander and Ian for sounding boards.

And if you want to float ideas or discuss apr design... we'd all like to invite 
you [again] to join us over at irc.openprojects.net, the #apr home hacking
channel :)  It really helped to coallesce some ideas [now open for discussion
and patching] before this was thrown out 1/2 thought out.

Warning to implementors; we will aquire a lock to go with this, and register
it with apr_rmm_init or apr_rmm_attach.  The first question; who is responsible
for creating the lock?

Some folks won't need locks at all (only the controlling process/thread would
ever alloc/dealloc.)  Some will need an intraprocess lock, since only the one
process (many of it's threads, however) will be messing with allocations.
And some will need full interprocess locks so everyone can get their fingers
dirty.

Since the actually apr_lock_t is location-process-dependent, we can't simply
throw the lock into the rmm memory space.  We need to pass in some descriptor
that apr_rmm_attach() can use to obtain it's own private copy of that same
lock.  Maybe it's time to look at an accessor API for serializing and 
recomposing apr types, to pass from process to process [Win32 needs this,
very badly.]

And if you object to the name apr_rmm, be warned, most alternatives were
real groaners :)

Bill


----- Original Message ----- 
From: <wr...@apache.org>
To: <ap...@apache.org>
Sent: Saturday, January 05, 2002 1:14 AM
Subject: cvs commit: apr-util/misc apr_rmm.c Makefile.in


> wrowe       02/01/04 23:14:29
> 
>   Modified:    .        CHANGES aprutil.dsp libaprutil.dsp
>                misc     Makefile.in
>   Added:       include  apr_rmm.h
>                misc     apr_rmm.c
>   Log:
>     A minimalist relocatable memory manager.  When I suggest minimalist,
>     it is -minimal-, still missing locking for allocation [that gets tricky,
>     we can discuss on list], some get largest-available and get free space
>     APIs, a get_management_overhead call [for determining the optimal
>     preallocation size before creating a block of memory to manage]
>     and a better-fit algorithm so we make best use of tight spaces.
>   
>     This also should grow a set of typesafe offset-protection wrappers,
>     which I will introduce shortly.  Those have proven trickier than I
>     had expected.
>   
>     While this is designed for Aaron's redesign of shm, it certainly
>     isn't limited to that application.  It is great for serializing any
>     sort of structures into files or between processes, or other
>     persistant applications.