You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by je...@apache.org on 2001/07/01 08:23:10 UTC

cvs commit: apr/include apr_sms_trivial.h

jerenkrantz    01/06/30 23:23:10

  Modified:    memory/unix Makefile.in
               test     testmem.c
  Added:       memory/unix apr_sms_trivial.c
               include  apr_sms_trivial.h
  Log:
  Get apr_sms_trivial into APR and add the appropriate things to testmem.
  This should be similar to the current pool code in its method of
  allocation and having freelists.
  
  testmem was including "apr_sms_trivial.h", so instead of removing that
  line, I went the long way and added trivial SMS.  I added the code to
  testmem.
  
  Sander still doesn't have his CVS access (although his account is setup?).
  This is based off of his submission to dev@apr from a few weeks ago - he
  might have a newer version locally that he hasn't posted.
  
  Submitted by:	Sander Striker
  Reviewed by:	Justin Erenkrantz
  
  Revision  Changes    Path
  1.5       +2 -1      apr/memory/unix/Makefile.in
  
  Index: Makefile.in
  ===================================================================
  RCS file: /home/cvs/apr/memory/unix/Makefile.in,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Makefile.in	2001/06/13 14:12:03	1.4
  +++ Makefile.in	2001/07/01 06:23:09	1.5
  @@ -2,7 +2,8 @@
   TARGETS = apr_sms.lo \
             apr_sms_std.lo \
             apr_sms_tracking.lo \
  -          apr_sms_blocks.lo
  +          apr_sms_blocks.lo \
  +          apr_sms_trivial.lo
   
   # bring in rules.mk for standard functionality
   @INCLUDE_RULES@
  
  
  
  1.1                  apr/memory/unix/apr_sms_trivial.c
  
  Index: apr_sms_trivial.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.h"
  #include "apr_general.h"
  #include "apr_private.h"
  #include "apr_sms.h"
  #include "apr_sms_trivial.h"
  #include "apr_lock.h"
  
  static const char *module_identity = "TRIVIAL";
  
  /*
   * Simple trivial memory system
   */
  
  
  /* INTERNALLY USED STRUCTURES */
  
  typedef struct block_t
  {
      struct node_t  *node;
  } block_t;
  
  typedef struct node_t
  {
      struct node_t  *next;
      struct node_t  *prev;
      char           *first_avail;
      apr_size_t      avail_size;
      apr_uint16_t    count;
  } node_t;
  
  typedef struct apr_sms_trivial_t
  {
      apr_sms_t            sms_hdr;
      node_t               used_sentinel;
      node_t               free_sentinel;
      node_t              *self;
      apr_size_t           min_alloc;
      apr_size_t           min_free;
      apr_size_t           max_free;
      apr_lock_t          *lock;
  } apr_sms_trivial_t;
  
  #define SIZEOF_BLOCK_T   APR_ALIGN_DEFAULT(sizeof(block_t))
  #define SIZEOF_NODE_T    APR_ALIGN_DEFAULT(sizeof(node_t))
  #define SIZEOF_TRIVIAL_T APR_ALIGN_DEFAULT(sizeof(apr_sms_trivial_t))
  
  #define BLOCK_T(mem)     ((block_t *)(mem))
  #define NODE_T(mem)      ((node_t *)(mem))
  #define TRIVIAL_T(sms)   ((apr_sms_trivial_t *)(sms))
  
  /* Magic numbers :) */
  
  #define MIN_ALLOC  0x2000 
  #define MIN_FREE   0x1000
  #define MAX_FREE  0x80000 
  
  static void *apr_sms_trivial_malloc(apr_sms_t *sms,
                                       apr_size_t size)
  {
      node_t *node, *sentinel;
      apr_size_t node_size;
      void *mem;
  
      /* Round up the size to the next 8 byte boundary */
      size = APR_ALIGN_DEFAULT(size) + SIZEOF_BLOCK_T;
  
      if (TRIVIAL_T(sms)->lock)
          apr_lock_acquire(TRIVIAL_T(sms)->lock);
      
      node = TRIVIAL_T(sms)->used_sentinel.prev;
  
      if (node->avail_size >= size) {
          mem = node->first_avail;
          node->avail_size -= size;
          node->first_avail += size;
          node->count++;
  
          if (TRIVIAL_T(sms)->lock)
              apr_lock_release(TRIVIAL_T(sms)->lock);
      
          BLOCK_T(mem)->node = node;
          mem = (char *)mem + SIZEOF_BLOCK_T;
  
          return mem;
      }
  
      /* reset the 'last' block, it will be replaced soon */
      node->avail_size += node->first_avail - ((char *)node + SIZEOF_NODE_T);
      node->first_avail = (char *)node + SIZEOF_NODE_T;
  
      /* browse the free list for a useable block */
      sentinel = &TRIVIAL_T(sms)->free_sentinel;
      sentinel->avail_size = size;
  
      node = sentinel->next;
      while (node->avail_size < size)
          node = node->next;
  
      if (node != sentinel) {
          node->prev->next = node->next;
          node->next->prev = node->prev;
  
          node->prev = TRIVIAL_T(sms)->used_sentinel.prev;
          node->prev->next = node;
          node->next = &TRIVIAL_T(sms)->used_sentinel;
          TRIVIAL_T(sms)->used_sentinel.prev = node;
          
          if (node != TRIVIAL_T(sms)->self)
              TRIVIAL_T(sms)->max_free += node->avail_size;
  
          mem = node->first_avail;
          node->avail_size -= size;
          node->first_avail += size;
          node->count = 1;
  
          if (TRIVIAL_T(sms)->lock)
              apr_lock_release(TRIVIAL_T(sms)->lock);
  
          BLOCK_T(mem)->node = node;
          mem = (char *)mem + SIZEOF_BLOCK_T;
  
          return mem;
      }
      
      /* we have to allocate a new block from our parent */
      node_size = size + TRIVIAL_T(sms)->min_free;
      if (node_size < TRIVIAL_T(sms)->min_alloc)
          node_size = TRIVIAL_T(sms)->min_alloc;
      
      node = apr_sms_malloc(sms->parent, node_size);
      if (!node) {
          node = TRIVIAL_T(sms)->used_sentinel.prev;
          node->first_avail += node->avail_size;
          node->avail_size = 0;
  
          if (TRIVIAL_T(sms)->lock)
              apr_lock_release(TRIVIAL_T(sms)->lock);
          
          return NULL;
      }
  
      node->prev = TRIVIAL_T(sms)->used_sentinel.prev;
      node->prev->next = node;
      node->next = &TRIVIAL_T(sms)->used_sentinel;
      TRIVIAL_T(sms)->used_sentinel.prev = node;
      
      mem = node->first_avail = (char *)node + SIZEOF_NODE_T;
      node->first_avail += size;
      node->avail_size = node_size - (node->first_avail - (char *)node);
      node->count = 1;
  
      if (TRIVIAL_T(sms)->lock)
          apr_lock_release(TRIVIAL_T(sms)->lock);
  
      BLOCK_T(mem)->node = node;
      mem = (char *)mem + SIZEOF_BLOCK_T;
      
      return mem;
  }
  
  static apr_status_t apr_sms_trivial_free(apr_sms_t *sms, void *mem)
  {
      node_t *node;
  
      node = BLOCK_T((char *)mem - SIZEOF_BLOCK_T)->node;
  
      if (TRIVIAL_T(sms)->lock)
          apr_lock_acquire(TRIVIAL_T(sms)->lock);
  
      node->count--;
  
      if (node->count) {
          if (TRIVIAL_T(sms)->lock)
              apr_lock_release(TRIVIAL_T(sms)->lock);
  
          return APR_SUCCESS;
      }
  
      node->avail_size += node->first_avail - ((char *)node + SIZEOF_NODE_T);
      node->first_avail = (char *)node + SIZEOF_NODE_T;
      
      if (TRIVIAL_T(sms)->used_sentinel.prev != node) {
          node->next->prev = node->prev;
          node->prev->next = node->next;
  
          if (sms->parent->free_fn &&
              node->avail_size > TRIVIAL_T(sms)->max_free &&
              node != TRIVIAL_T(sms)->self) {
              if (TRIVIAL_T(sms)->lock)
                  apr_lock_release(TRIVIAL_T(sms)->lock);
  
              return apr_sms_free(sms->parent, node);
          }
          
          node->prev = TRIVIAL_T(sms)->free_sentinel.prev;
          node->prev->next = node;
          node->next = &TRIVIAL_T(sms)->free_sentinel;
          TRIVIAL_T(sms)->free_sentinel.prev = node;
  
          if (node != TRIVIAL_T(sms)->self)
              TRIVIAL_T(sms)->max_free -= node->avail_size;
      }
  
      if (TRIVIAL_T(sms)->lock)
          apr_lock_release(TRIVIAL_T(sms)->lock);
  
      return APR_SUCCESS;
  }
  
  static apr_status_t apr_sms_trivial_reset(apr_sms_t *sms)
  {
      node_t *node, *prev, *used_sentinel, *free_sentinel;
   
      if (TRIVIAL_T(sms)->lock)
          apr_lock_acquire(TRIVIAL_T(sms)->lock);
  
      used_sentinel = &TRIVIAL_T(sms)->used_sentinel;
      free_sentinel = &TRIVIAL_T(sms)->free_sentinel;
  
      node = TRIVIAL_T(sms)->self;
      node->avail_size += node->first_avail - ((char *)node + SIZEOF_NODE_T);
      node->first_avail = (char *)node + SIZEOF_NODE_T;
      node->count = 0;
      node->prev->next = node->next;
      node->next->prev = node->prev;
      
      node = used_sentinel->prev;
      node->avail_size += node->first_avail - ((char *)node + SIZEOF_NODE_T);
      node->first_avail = (char *)node + SIZEOF_NODE_T;
      
      if (sms->parent->free_fn) {
          used_sentinel->avail_size = TRIVIAL_T(sms)->min_alloc;
          while (TRIVIAL_T(sms)->max_free > TRIVIAL_T(sms)->min_alloc) {
              if (node->avail_size <= TRIVIAL_T(sms)->max_free) {
                  if (node == used_sentinel)
                      break;
              
                  TRIVIAL_T(sms)->max_free -= node->avail_size;
                  node->prev->next = node->next;
                  node->next->prev = node->prev;
          
                  prev = node->prev;
              
                  node->next = free_sentinel->next;
                  free_sentinel->next = node;
                  node->next->prev = node;
                  node->prev = free_sentinel;
  
                  node = prev;
              }
              else
                  node = node->prev;
          }
          
          used_sentinel->prev->next = NULL;
          while ((node = used_sentinel->next) != NULL) {
              used_sentinel->next = node->next;
              apr_sms_free(sms->parent, node);
          }
      }
      else {
          node = used_sentinel->prev;
          node->next = free_sentinel->next;
          node->next->prev = node;
  
          node = used_sentinel->next;
          node->prev = free_sentinel;
          free_sentinel->next = node;
      }
          
      node = TRIVIAL_T(sms)->self;
      node->next = node->prev = used_sentinel;
      used_sentinel->next = used_sentinel->prev = node;
  
      if (TRIVIAL_T(sms)->lock)
          apr_lock_release(TRIVIAL_T(sms)->lock);
  
      return APR_SUCCESS;
  }
  
  static apr_status_t apr_sms_trivial_pre_destroy(apr_sms_t *sms)
  {
      /* This function WILL always be called.  However, be aware that the
       * main sms destroy function knows that it's not wise to try and destroy
       * the same piece of memory twice, so the destroy function in a child won't
       * neccesarily be called.  To guarantee we destroy the lock it's therefore
       * destroyed here.
       */
          
      if (TRIVIAL_T(sms)->lock) {
          apr_lock_acquire(TRIVIAL_T(sms)->lock);
          apr_lock_destroy(TRIVIAL_T(sms)->lock);
          TRIVIAL_T(sms)->lock = NULL;
      }
      
      return APR_SUCCESS;    
  }
  
  static apr_status_t apr_sms_trivial_destroy(apr_sms_t *sms)
  {
      apr_sms_trivial_t *tms;
      node_t *node, *next;
  
      tms = TRIVIAL_T(sms);
      node = tms->self;
      node->next->prev = node->prev;
      node->prev->next = node->next;
  
      tms->free_sentinel.prev->next = NULL;
      tms->used_sentinel.prev->next = tms->free_sentinel.next;
      
      node = tms->used_sentinel.next;
      while (node) {
          next = node->next;
          apr_sms_free(sms->parent, node);
          node = next;
      }
  
      apr_sms_free(sms->parent, sms);
  
      return APR_SUCCESS;
  }
  
  
  APR_DECLARE(apr_status_t) apr_sms_trivial_create(apr_sms_t **sms, 
                                                    apr_sms_t *pms)
  {
      return apr_sms_trivial_create_ex(sms, pms, MIN_ALLOC, MIN_FREE, MAX_FREE);
  }
  
  APR_DECLARE(apr_status_t) apr_sms_trivial_create_ex(apr_sms_t **sms, 
                                                      apr_sms_t *pms,
                                                      apr_size_t min_alloc,
                                                      apr_size_t min_free,
                                                      apr_size_t max_free)
  {
      apr_sms_t *new_sms;
      apr_sms_trivial_t *tms;
      node_t *node;
      apr_status_t rv;
  
      *sms = NULL;
      
      min_alloc = APR_ALIGN_DEFAULT(min_alloc);
      min_free  = APR_ALIGN_DEFAULT(min_free);
  
      /* We're not a top level module, ie we have a parent, so
       * we allocate the memory for the structure from our parent.
       * This is safe as we shouldn't outlive our parent...
       */
  
      new_sms = apr_sms_calloc(pms, min_alloc);
      if (!new_sms)
          return APR_ENOMEM;
  
      if ((rv = apr_sms_init(new_sms, pms)) != APR_SUCCESS)
          return rv;
  
      new_sms->malloc_fn      = apr_sms_trivial_malloc;
      new_sms->free_fn        = apr_sms_trivial_free;
      new_sms->reset_fn       = apr_sms_trivial_reset;
      new_sms->pre_destroy_fn = apr_sms_trivial_pre_destroy;
      new_sms->destroy_fn     = apr_sms_trivial_destroy;
      new_sms->identity       = module_identity;
  
      node = (node_t *)((char *)new_sms + SIZEOF_TRIVIAL_T);
      node->first_avail = (char *)node + SIZEOF_NODE_T;
      node->avail_size  = min_alloc - SIZEOF_TRIVIAL_T - SIZEOF_NODE_T;
      node->count       = 0;
  
      tms = TRIVIAL_T(new_sms);
      tms->min_alloc   = min_alloc;
      tms->min_free    = min_free;
      tms->max_free    = max_free;
      tms->self        = node;
      
      node->next = node->prev = &tms->used_sentinel;
      tms->used_sentinel.next = tms->used_sentinel.prev = node;
      tms->free_sentinel.next = tms->free_sentinel.prev = &tms->free_sentinel;
     
      apr_sms_assert(new_sms);
  
      *sms = new_sms;
      return APR_SUCCESS;
  }
  
  
  
  1.8       +10 -2     apr/test/testmem.c
  
  Index: testmem.c
  ===================================================================
  RCS file: /home/cvs/apr/test/testmem.c,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- testmem.c	2001/06/21 00:39:22	1.7
  +++ testmem.c	2001/07/01 06:23:10	1.8
  @@ -84,7 +84,7 @@
       apr_time_t howlong;
   } _test_;
   
  -#define T_QTY 4 /* how many tests do we have?? */
  +#define T_QTY 5 /* how many tests do we have?? */
   static _test_ t[T_QTY];
   
   static void its_an_sms(apr_sms_t *ams, _test_ *t, char *name, int lt)
  @@ -434,7 +434,7 @@
   
   int main(int argc, char **argv)
   {
  -    apr_sms_t *ams, *bms, *dms;
  +    apr_sms_t *ams, *bms, *dms, *tms;
       apr_pool_t *pool;
       int i;
       
  @@ -452,12 +452,15 @@
                    apr_sms_tracking_create(&bms, ams))
       STD_TEST_NEQ("    Creating a 64 byte block system",
                    apr_sms_blocks_create(&dms, ams, 64))
  +    STD_TEST_NEQ("    Creating a trivial system",
  +                 apr_sms_trivial_create(&tms, ams))
   
       its_a_pool(pool, &t[0], "Pool code",     1);
       its_an_sms(ams,  &t[1], "Standard sms",  1);
       t[1].reset_fn = NULL;
       its_an_sms(bms,  &t[2], "Tracking sms",  1);
       its_an_sms(dms,  &t[3], "Blocks sms",    0);
  +    its_an_sms(tms,  &t[4], "Trivial sms",   1);
           
       printf("Checking sms identities...\n");
       TEST_NEQ("    Checking identity of standard memory system",
  @@ -469,6 +472,9 @@
       TEST_NEQ("    Checking the identity of blocks memory system",
                strcmp(apr_sms_identity(dms), "BLOCKS"), 0,
                "OK", "Not BLOCKS")
  +    TEST_NEQ("    Checking the identity of trivial memory system",
  +             strcmp(apr_sms_identity(tms), "TRIVIAL"), 0,
  +             "OK", "Not TRIVIAL")
   
       printf("Big allocation test...\n");
       for (i = 0; i < T_QTY; i++) {
  @@ -508,6 +514,8 @@
       
       printf("Destroying the memory...\n");
   
  +    STD_TEST_NEQ("Trying to destroy the trivial memory system",
  +                 apr_sms_destroy(tms))
       STD_TEST_NEQ("Trying to destroy the tracking memory system",
                    apr_sms_destroy(bms))
       STD_TEST_NEQ("Trying to destroy the block memory system",
  
  
  
  1.1                  apr/include/apr_sms_trivial.h
  
  Index: apr_sms_trivial.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_SMS_TRIVIAL_H
  #define APR_SMS_TRIVIAL_H
  
  #include "apr.h"
  #include "apr_sms.h"
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /**
   * @package APR trivial memory system
   */
  
  /**
   * Create a pool like malloc/free/reset memory system
   * @param mem_sys A pointer to the returned apr_sms_t*
   * @param pms The parent memory system, used to allocate the memory
   *            that we will be trivial.
   * @deffunc apr_status_t apr_sms_trivial_create(apr_sms_t **mem_sys,
   *                                               apr_sms_t *pms);
   */
  APR_DECLARE(apr_status_t) apr_sms_trivial_create(apr_sms_t **sms,
                                                    apr_sms_t *pms);
  
  /**
   * Create a pool like malloc/free/reset memory system
   * @param mem_sys A pointer to the returned apr_sms_t*
   * @param pms The parent memory system, used to allocate the memory
   *            that we will be trivial.
   * @param min_alloc The minimal blocksize to allocate when getting
   *                  memory from the parent
   * @param min_free  The minimal amount of memory to make sure is
   *                  free in an allocated block from the parent 
   * @param max_free  The amount of memory the sms may hold on to
   * @deffunc apr_status_t apr_sms_trivial_create_ex(apr_sms_t **mem_sys,
   *                                                 apr_sms_t *pms,
   *                                                 apr_size_t min_alloc,
   *                                                 apr_size_t min_free,
   *                                                 apr_size_t max_free);
   */
  APR_DECLARE(apr_status_t) apr_sms_trivial_create_ex(apr_sms_t **sms,
                                                      apr_sms_t *pms,
                                                      apr_size_t min_alloc,
                                                      apr_size_t min_free,
                                                      apr_size_t max_free);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* !APR_SMS_TRIVIAL_H */
  
  
  

Re: cvs commit: apr/include apr_sms_trivial.h

Posted by David Reid <dr...@jetnet.co.uk>.
> > I think with the testmem and Ian's testpool, I think we are close to 
> > having a decent testing environment that is outside of the "real" 
> > world.  The only thing I'm waiting on now is David's implementation of
> > apr_pool_t as a SMS.  =)  

OK, OK, it's on it's way :)  Patience is a virtue!

> We need some decent debugging :)

Yes, we do!  First steps on the way real soon now!

> 
> > I was shocked that trivial was 102-103% of 
> > the pool code (based on testmem results).  This is *without* 
> > multi-threaded/unlocked allocation, which is where I believe that we're
> 
> There is a lock in the sms framework that is enabled by default. It is
> acquired when apr_sms_reset is called. This lock has to be dynamically
> created as the rest of the locks. I have a decent scheme in mind which
> I will post Real Soon Now(tm).
> 
> If you disable the lock creation in apr_sms_create() [or, wait, we
> moved it to apr_sms_post_init()] you should get better results. Also,
> if you increase the MAX_FREE to a lot bigger you come closer to pools,
> which doesn't free memory at all. With sms, you give it back to the
> parent, which may hold on to it itself, or may give it back to the
> system (which means that when a box has low load, the memory use
> will go down).
> 
> > going to see a benefit from SMS long-term.  -- justin
> 
> Yes. Btw, I'm doing some last mods on an sms which I called threads_sms.
> It is to be the parent sms of the smss that are in different threads.
> It is based on trivial and has some nice properties when it comes to
> locking. I'm hoping this will be a speed improvement in a threaded
> environment. I will have to commit some groundwork for use later on
> for that though.

Cool.

david



RE: cvs commit: apr/include apr_sms_trivial.h

Posted by Sander Striker <st...@apache.org>.
[...]
>> We probably need to take a look at the list handling and see if
>> we can speed this up a bit.
> 
> Yeah, I tried trying to walk through the sentinel code last night and my
> brain just wasn't parsing the code.  It does need to be looked at with a
> fine-toothed comb.  I might get around to it later this afternoon.  It
> almost calls for pencil and paper to sketch out what the code is doing.

Please do. I wrote the code when I was very 'in focus'. I should have added
more comments, but didn't get around to it. I do know that the sentinels
do there job quite well with respect to eliminating checks. Let me know
what your findings are and if you see room for speed improvements.

> > Also, the values need tweaking (MAX_FREE, MIN_ALLOC, MIN_FREE). But
> > I think we should wait with that until we have a good testing
> > environment.
> 
> I wonder if you even need the MAX_FREE, MIN_ALLOC, and MIN_FREE stuff.
> Shouldn't we just leave those to the parent SMS?  That makes more sense
> to me.  I'm not really sold on the trivial SMS doing this sort of thing.
> (This sort of thing is WHY we have SMS in the first place, IMHO.)

No, the smss are layered. The parent sms could be the std_sms, which just
does malloc/free. In trivial you do almost exactly what pools do, but you
maintain a private free list. The MIN_FREE and MIN_ALLOC come from the
pools code. I did an apr_sms_trivial_create_ex() to be able to specify
these values at runtime (in case you don't like the defaults you get with
the apr_sms_trivial_create). See below for a note on the MAX_FREE define.

> I think with the testmem and Ian's testpool, I think we are close to 
> having a decent testing environment that is outside of the "real" 
> world.  The only thing I'm waiting on now is David's implementation of
> apr_pool_t as a SMS.  =)  

We need some decent debugging :)

> I was shocked that trivial was 102-103% of 
> the pool code (based on testmem results).  This is *without* 
> multi-threaded/unlocked allocation, which is where I believe that we're

There is a lock in the sms framework that is enabled by default. It is
acquired when apr_sms_reset is called. This lock has to be dynamically
created as the rest of the locks. I have a decent scheme in mind which
I will post Real Soon Now(tm).

If you disable the lock creation in apr_sms_create() [or, wait, we
moved it to apr_sms_post_init()] you should get better results. Also,
if you increase the MAX_FREE to a lot bigger you come closer to pools,
which doesn't free memory at all. With sms, you give it back to the
parent, which may hold on to it itself, or may give it back to the
system (which means that when a box has low load, the memory use
will go down).

> going to see a benefit from SMS long-term.  -- justin

Yes. Btw, I'm doing some last mods on an sms which I called threads_sms.
It is to be the parent sms of the smss that are in different threads.
It is based on trivial and has some nice properties when it comes to
locking. I'm hoping this will be a speed improvement in a threaded
environment. I will have to commit some groundwork for use later on
for that though.

Sander


Re: cvs commit: apr/include apr_sms_trivial.h

Posted by Justin Erenkrantz <je...@ebuilt.com>.
On Sun, Jul 01, 2001 at 02:56:13PM +0200, Sander Striker wrote:
> >   This is based off of his submission to dev@apr from a few weeks ago - he
> >   might have a newer version locally that he hasn't posted.
> 
> There were only minor diffs between my local version and the one
> posted earlier. Just committed those.

Cool.

> There was one fix, but Justin already caught that. Thx :)

Hehe.  =)  Yeah, I added that return value.

> We probably need to take a look at the list handling and see if
> we can speed this up a bit.

Yeah, I tried trying to walk through the sentinel code last night and my
brain just wasn't parsing the code.  It does need to be looked at with a
fine-toothed comb.  I might get around to it later this afternoon.  It
almost calls for pencil and paper to sketch out what the code is doing.

> Also, the values need tweaking (MAX_FREE, MIN_ALLOC, MIN_FREE). But
> I think we should wait with that until we have a good testing
> environment.

I wonder if you even need the MAX_FREE, MIN_ALLOC, and MIN_FREE stuff.
Shouldn't we just leave those to the parent SMS?  That makes more sense
to me.  I'm not really sold on the trivial SMS doing this sort of thing.
(This sort of thing is WHY we have SMS in the first place, IMHO.)

I think with the testmem and Ian's testpool, I think we are close to 
having a decent testing environment that is outside of the "real" 
world.  The only thing I'm waiting on now is David's implementation of
apr_pool_t as a SMS.  =)  I was shocked that trivial was 102-103% of 
the pool code (based on testmem results).  This is *without* 
multi-threaded/unlocked allocation, which is where I believe that we're 
going to see a benefit from SMS long-term.  -- justin


RE: cvs commit: apr/include apr_sms_trivial.h

Posted by Sander Striker <st...@apache.org>.
>   This is based off of his submission to dev@apr from a few weeks ago - he
>   might have a newer version locally that he hasn't posted.

There were only minor diffs between my local version and the one
posted earlier. Just committed those.

There was one fix, but Justin already caught that. Thx :)

We probably need to take a look at the list handling and see if
we can speed this up a bit.

Also, the values need tweaking (MAX_FREE, MIN_ALLOC, MIN_FREE). But
I think we should wait with that until we have a good testing
environment.

Sander


RE: cvs commit: apr/include apr_sms_trivial.h

Posted by rb...@covalent.net.
Sander,  the CVS commit messages are moderated, and this was the first
time you committed something from that account.  So, I had to approve the
commit message.  Sorry it took me so long.  :-)

Ryan

On Sun, 1 Jul 2001, Sander Striker wrote:

> Actually, my cvs is working as of yesterday. I commited
> something and didn't see my commit msg appear, so I
> decided to wait with the rest. 7 hours later the commit
> msg did appear and I had chosen today to commit the
> rest :)
>
> I have a local newer version which I will commit today :)
>
> Sander
>
>
> > jerenkrantz    01/06/30 23:23:10
> >
> >   Modified:    memory/unix Makefile.in
> >                test     testmem.c
> >   Added:       memory/unix apr_sms_trivial.c
> >                include  apr_sms_trivial.h
> >   Log:
> >   Get apr_sms_trivial into APR and add the appropriate things to testmem.
> >   This should be similar to the current pool code in its method of
> >   allocation and having freelists.
> >
> >   testmem was including "apr_sms_trivial.h", so instead of removing that
> >   line, I went the long way and added trivial SMS.  I added the code to
> >   testmem.
> >
> >   Sander still doesn't have his CVS access (although his account
> > is setup?).
> >   This is based off of his submission to dev@apr from a few weeks ago - he
> >   might have a newer version locally that he hasn't posted.
> >
> >   Submitted by:	Sander Striker
> >   Reviewed by:	Justin Erenkrantz
>
>
>


_____________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
Covalent Technologies			rbb@covalent.net
-----------------------------------------------------------------------------


RE: cvs commit: apr/include apr_sms_trivial.h

Posted by Sander Striker <st...@apache.org>.
Actually, my cvs is working as of yesterday. I commited
something and didn't see my commit msg appear, so I
decided to wait with the rest. 7 hours later the commit
msg did appear and I had chosen today to commit the
rest :)

I have a local newer version which I will commit today :)

Sander


> jerenkrantz    01/06/30 23:23:10
>
>   Modified:    memory/unix Makefile.in
>                test     testmem.c
>   Added:       memory/unix apr_sms_trivial.c
>                include  apr_sms_trivial.h
>   Log:
>   Get apr_sms_trivial into APR and add the appropriate things to testmem.
>   This should be similar to the current pool code in its method of
>   allocation and having freelists.
>
>   testmem was including "apr_sms_trivial.h", so instead of removing that
>   line, I went the long way and added trivial SMS.  I added the code to
>   testmem.
>
>   Sander still doesn't have his CVS access (although his account
> is setup?).
>   This is based off of his submission to dev@apr from a few weeks ago - he
>   might have a newer version locally that he hasn't posted.
>
>   Submitted by:	Sander Striker
>   Reviewed by:	Justin Erenkrantz