You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by dr...@apache.org on 2001/05/15 01:01:28 UTC
cvs commit: apr/memory/unix apr_sms.c apr_sms_std.c apr_sms_tracking.c Makefile.in
dreid 01/05/14 16:01:27
Modified: memory/unix Makefile.in
Added: memory/unix apr_sms.c apr_sms_std.c apr_sms_tracking.c
Log:
Add the renamed memory files to APR.
apr_sms.c used to be apr_memory_system.c
apr_sms_std.c used to be apr_standard_memory_system.c
apr_sms_tracking.c used to be apr_tracking_memory_system.c
Alter Makefile.in to actually build the new files.
Revision Changes Path
1.3 +3 -3 apr/memory/unix/Makefile.in
Index: Makefile.in
===================================================================
RCS file: /home/cvs/apr/memory/unix/Makefile.in,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Makefile.in 2001/05/09 16:30:21 1.2
+++ Makefile.in 2001/05/14 23:01:25 1.3
@@ -1,7 +1,7 @@
-TARGETS = apr_memory_system.lo \
- apr_tracking_memory_system.lo \
- apr_standard_memory_system.lo
+TARGETS = apr_sms.lo \
+ apr_sms_std.lo \
+ apr_sms_tracking.lo
# bring in rules.mk for standard functionality
@INCLUDE_RULES@
1.1 apr/memory/unix/apr_sms.c
Index: apr_sms.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/>.
*/
/* This code kindly donated to APR by
* Elrond <el...@samba-tng.org>
* Luke Kenneth Casson Leighton <lk...@samba-tng.org>
* Sander Striker <st...@samba-tng.org>
*
* May 2001
*/
#include "apr.h"
#include "apr_general.h"
#include "apr_memory_system.h"
#include <stdlib.h>
#include <assert.h>
#include <memory.h> /* strikerXXX: had to add this for windows to stop
* complaining, please autoconf the include stuff
*/
/*
* private structure defenitions
*/
struct apr_sms_cleanup
{
struct apr_sms_cleanup *next;
void *data;
apr_status_t (*cleanup_fn)(void *);
};
/*
* memory allocation functions
*/
APR_DECLARE(void *) apr_sms_malloc(apr_sms_t *mem_sys,
apr_size_t size)
{
#ifdef APR_ASSERT_MEMORY
assert(mem_sys);
assert(mem_sys->malloc_fn);
#endif
if (!mem_sys || !mem_sys->malloc_fn)
return NULL;
if (size == 0)
return NULL;
return mem_sys->malloc_fn(mem_sys, size);
}
APR_DECLARE(void *) apr_sms_calloc(apr_sms_t *mem_sys,
apr_size_t size)
{
#ifdef APR_ASSERT_MEMORY
assert(mem_sys);
assert(mem_sys->malloc_fn);
assert(mem_sys->calloc_fn);
#endif
if (size == 0)
return NULL;
if (mem_sys->calloc_fn == NULL){
/* Assumption - if we don't have calloc we have
* malloc, might be bogus...
*/
void *mem = mem_sys->malloc_fn(mem_sys, size);
memset(mem, '\0', size);
return mem;
} else
return mem_sys->calloc_fn(mem_sys, size);
}
APR_DECLARE(void *) apr_sms_realloc(apr_sms_t *mem_sys, void *mem,
apr_size_t size)
{
#ifdef APR_ASSERT_MEMORY
assert(mem_sys);
assert(mem_sys->realloc_fn);
#endif
if (mem == NULL)
return apr_sms_malloc(mem_sys, size);
if (size == 0)
{
apr_sms_free(mem_sys, mem);
return NULL;
}
return mem_sys->realloc_fn(mem_sys, mem, size);
}
APR_DECLARE(apr_status_t) apr_sms_free(apr_sms_t *mem_sys,
void *mem)
{
#ifdef APR_ASSERT_MEMORY
assert(mem_sys->free_fn);
#endif
if (!mem_sys)
return APR_EMEMSYS;
if (mem == NULL)
return APR_EINVAL;
if (mem_sys->free_fn != NULL)
return mem_sys->free_fn(mem_sys, mem);
return APR_SUCCESS;
}
/*
* memory system functions
*/
static int apr_sms_is_tracking(apr_sms_t *mem_sys)
{
/*
* The presense of a reset function gives us the clue that this is a
* tracking memory system.
*/
return mem_sys->reset_fn != NULL;
}
APR_DECLARE(apr_sms_t *) apr_sms_create(void *memory,
apr_sms_t *parent_mem_sys)
{
apr_sms_t *mem_sys;
if (memory == NULL)
return NULL;
/* Just typecast it, and clear it */
mem_sys = (apr_sms_t *)memory;
memset(mem_sys, '\0', sizeof(apr_sms_t));
/* Initialize the parent and accounting memory system pointers */
mem_sys->parent_mem_sys = parent_mem_sys;
mem_sys->accounting_mem_sys = mem_sys;
if (parent_mem_sys != NULL)
{
if ((mem_sys->sibling_mem_sys =
parent_mem_sys->child_mem_sys) != NULL)
{
mem_sys->sibling_mem_sys->ref_mem_sys =
&mem_sys->sibling_mem_sys;
}
mem_sys->ref_mem_sys =
&parent_mem_sys->child_mem_sys;
parent_mem_sys->child_mem_sys = mem_sys;
}
/* This seems a bit redundant, but we're not taking chances */
else
{
mem_sys->ref_mem_sys = NULL;
mem_sys->sibling_mem_sys = NULL;
mem_sys->child_mem_sys = NULL;
}
return mem_sys;
}
#ifdef APR_MEMORY_ASSERT
APR_DECLARE(void) apr_sms_assert(apr_sms_t *mem_sys)
{
apr_sms_t *parent;
/*
* A memory system without a malloc won't do us much good
*/
assert(mem_sys->malloc_fn != NULL);
/*
* Check to see if this is either a non-tracking or
* a tracking memory system. It has to have at least a free
* or destroy function. And to avoid half implementations
* we require reset to be present when destroy is.
*/
assert(mem_sys->free_fn != NULL ||
(mem_sys->destroy_fn != NULL &&
mem_sys->reset_fn != NULL));
assert(mem_sys->destroy_fn == NULL ||
mem_sys->reset_fn != NULL);
assert(mem_sys->reset_fn == NULL ||
mem_sys->destroy_fn != NULL);
/*
* Make sure all accounting memory dies with the memory system.
* To be more specific, make sure the accounting memort system
* is either the memory system itself or a direct child.
*/
assert(mem_sys->accounting_mem_sys == mem_sys ||
mem_sys->accounting_mem_sys->parent_mem_sys ==
mem_sys);
/*
* A non-tracking memory system can be the child of
* another non-tracking memory system if there are no
* tracking ancestors, but in that specific case we issue a
* warning.
*/
if (mem_sys->parent_mem_sys == NULL)
return;
parent = mem_sys
while (parent)
{
if (apr_sms_is_tracking(parent))
return; /* Tracking memory system found, return satisfied ;-) */
parent = parent->parent_mem_sys;
}
/* issue a warning:
* WARNING: A non-tracking memory system was created without a tracking
* parent.
*/
}
#endif /* APR_MEMORY_ASSERT */
/*
* LOCAL FUNCTION used in:
* - apr_sms_do_child_cleanups
* - apr_sms_reset
* - apr_sms_destroy
*
* Call all the cleanup routines registered with a memory system.
*/
static void apr_sms_do_cleanups(apr_sms_t *mem_sys)
{
struct apr_sms_cleanup *cleanup;
cleanup = mem_sys->cleanups;
while (cleanup)
{
cleanup->cleanup_fn(cleanup->data);
cleanup = cleanup->next;
}
}
/*
* LOCAL FUNCTION used in:
* - apr_sms_reset
* - apr_sms_destroy
*
* This not only calls do_cleanups, but also calls the pre_destroy(!)
*/
static void apr_sms_do_child_cleanups(apr_sms_t *mem_sys)
{
if (mem_sys == NULL)
return;
mem_sys = mem_sys->child_mem_sys;
while (mem_sys)
{
apr_sms_do_child_cleanups(mem_sys);
apr_sms_do_cleanups(mem_sys);
if (mem_sys->pre_destroy_fn != NULL)
mem_sys->pre_destroy_fn(mem_sys);
mem_sys = mem_sys->sibling_mem_sys;
}
}
APR_DECLARE(apr_status_t) apr_sms_reset(apr_sms_t *mem_sys)
{
if (!mem_sys)
return APR_EMEMSYS;
if (!mem_sys->reset_fn)
return APR_EINVAL; /* Not sure if this is right... */
/*
* Run the cleanups of all child memory systems _including_
* the accounting memory system.
*/
apr_sms_do_child_cleanups(mem_sys);
/* Run all cleanups, the memory will be freed by the reset */
apr_sms_do_cleanups(mem_sys);
mem_sys->cleanups = NULL;
/* We don't have any child memory systems after the reset */
mem_sys->child_mem_sys = NULL;
/* Reset the accounting memory system to ourselves, any
* child memory system _including_ the accounting memory
* system will be destroyed by the reset
* strikerXXX: Maybe this should be the responsibility of
* the reset function(?).
*/
mem_sys->accounting_mem_sys = mem_sys;
/* Let the memory system handle the actual reset */
return mem_sys->reset_fn(mem_sys);
}
APR_DECLARE(apr_status_t) apr_sms_destroy(apr_sms_t *mem_sys)
{
apr_sms_t *child_mem_sys;
apr_sms_t *sibling_mem_sys;
struct apr_sms_cleanup *cleanup;
struct apr_sms_cleanup *next_cleanup;
if (!mem_sys)
return APR_EMEMSYS;
if (apr_sms_is_tracking(mem_sys))
{
/*
* Run the cleanups of all child memory systems _including_
* the accounting memory system.
*/
apr_sms_do_child_cleanups(mem_sys);
/* Run all cleanups, the memory will be freed by the destroy */
apr_sms_do_cleanups(mem_sys);
}
else
{
if (mem_sys->accounting_mem_sys != mem_sys)
{
child_mem_sys = mem_sys->accounting_mem_sys;
/*
* Remove the accounting memory system from the memory systems
* child list (we will explicitly destroy it later in this block).
*/
if (child_mem_sys->sibling_mem_sys != NULL)
child_mem_sys->sibling_mem_sys->ref_mem_sys =
child_mem_sys->ref_mem_sys;
*child_mem_sys->ref_mem_sys =
child_mem_sys->sibling_mem_sys;
/* Set this fields so destroy will work */
child_mem_sys->ref_mem_sys = NULL;
child_mem_sys->sibling_mem_sys = NULL;
}
/* Visit all children and destroy them */
child_mem_sys = mem_sys->child_mem_sys;
while (child_mem_sys != NULL)
{
sibling_mem_sys = child_mem_sys->sibling_mem_sys;
apr_sms_destroy(child_mem_sys);
child_mem_sys = sibling_mem_sys;
}
/*
* If the accounting memory system _is_ tracking, we also know that it is
* not the memory system itself.
*/
if (apr_sms_is_tracking(mem_sys->accounting_mem_sys))
{
/*
* Run all cleanups, the memory will be freed by the destroying of the
* accounting memory system.
*/
apr_sms_do_cleanups(mem_sys);
/* Destroy the accounting memory system */
apr_sms_destroy(mem_sys->accounting_mem_sys);
/*
* Set the accounting memory system back to the parent memory system
* just in case...
*/
mem_sys->accounting_mem_sys = mem_sys;
}
else
{
/* Run all cleanups, free'ing memory as we go */
cleanup = mem_sys->cleanups;
while (cleanup)
{
cleanup->cleanup_fn(cleanup->data);
next_cleanup = cleanup->next;
apr_sms_free(mem_sys->accounting_mem_sys,
cleanup);
cleanup = next_cleanup;
}
if (mem_sys->accounting_mem_sys != mem_sys)
{
/* Destroy the accounting memory system */
apr_sms_destroy(mem_sys->accounting_mem_sys);
/*
* Set the accounting memory system back to the parent memory system
* just in case...
*/
mem_sys->accounting_mem_sys = mem_sys;
}
}
}
/* Remove the memory system from the parent memory systems child list */
if (mem_sys->sibling_mem_sys != NULL)
mem_sys->sibling_mem_sys->ref_mem_sys =
mem_sys->ref_mem_sys;
if (mem_sys->ref_mem_sys != NULL)
*mem_sys->ref_mem_sys = mem_sys->sibling_mem_sys;
/* Call the pre-destroy if present */
if (mem_sys->pre_destroy_fn != NULL)
mem_sys->pre_destroy_fn(mem_sys);
/* 1 - If we have a self destruct, use it */
if (mem_sys->destroy_fn != NULL)
return mem_sys->destroy_fn(mem_sys);
/* 2 - If we don't have a parent, free using ourselves */
else if (mem_sys->parent_mem_sys == NULL)
return mem_sys->free_fn(mem_sys, mem_sys);
/* 3 - If we do have a parent and it has a free function, use it */
else if (mem_sys->parent_mem_sys->free_fn != NULL)
return apr_sms_free(mem_sys->parent_mem_sys, mem_sys);
/* 4 - Assume we are the child of a tracking memory system, and do nothing */
#ifdef APR_ASSERT_MEMORY
mem_sys = mem_sys->parent_mem_sys;
while (mem_sys)
{
if (apr_sms_is_tracking(mem_sys))
return APR_SUCCESS;
mem_sys = mem_sys->parent_mem_sys;
}
assert(0); /* Made the wrong assumption, so we assert */
#endif /* APR_MEMORY_ASSERT */
return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_sms_is_ancestor(apr_sms_t *a,
apr_sms_t *b)
{
#ifdef APR_ASSERT_MEMORY
assert(a != NULL);
assert(b != NULL);
#endif
if (!b)
return APR_EINVAL;
while (b && b != a)
b = b->parent_mem_sys;
/* APR_SUCCESS = 0, so if they agree we should return that... */
return !(b == a);
}
APR_DECLARE(void) apr_sms_threadsafe_lock(apr_sms_t *mem_sys)
{
#ifdef APR_ASSERT_MEMORY
assert(mem_sys != NULL);
#endif
if (!mem_sys)
return;
if (mem_sys->threadsafe_lock_fn != NULL)
mem_sys->threadsafe_lock_fn(mem_sys);
}
APR_DECLARE(void) apr_sms_threadsafe_unlock(apr_sms_t *mem_sys)
{
#ifdef APR_ASSERT_MEMORY
assert(mem_sys != NULL);
#endif
if (!mem_sys)
return;
if (mem_sys->threadsafe_unlock_fn != NULL)
mem_sys->threadsafe_unlock_fn(mem_sys);
}
/*
* memory system cleanup management functions
*/
APR_DECLARE(apr_status_t)
apr_sms_cleanup_register(apr_sms_t *mem_sys, void *data,
apr_status_t (*cleanup_fn)(void *))
{
struct apr_sms_cleanup *cleanup;
#ifdef APR_ASSERT_MEMORY
assert(mem_sys->accounting_mem_sys != NULL);
#endif
if (!mem_sys)
return APR_EMEMSYS;
if (cleanup_fn == NULL)
return APR_EINVAL;
cleanup = (struct apr_sms_cleanup *)
apr_sms_malloc(mem_sys->accounting_mem_sys,
sizeof(struct apr_sms_cleanup));
if (cleanup == NULL)
return APR_ENOMEM;
cleanup->data = data;
cleanup->cleanup_fn = cleanup_fn;
cleanup->next = mem_sys->cleanups;
mem_sys->cleanups = cleanup;
return APR_SUCCESS;
}
APR_DECLARE(apr_status_t)
apr_sms_cleanup_unregister(apr_sms_t *mem_sys, void *data,
apr_status_t (*cleanup_fn)(void *))
{
struct apr_sms_cleanup *cleanup;
struct apr_sms_cleanup **cleanup_ref;
#ifdef APR_ASSERT_MEMORY
assert(mem_sys->accounting_mem_sys != NULL);
#endif
if (!mem_sys)
return APR_EMEMSYS;
cleanup = mem_sys->cleanups;
cleanup_ref = &mem_sys->cleanups;
while (cleanup)
{
if (cleanup->data == data && cleanup->cleanup_fn == cleanup_fn)
{
*cleanup_ref = cleanup->next;
mem_sys = mem_sys->accounting_mem_sys;
if (mem_sys->free_fn != NULL)
apr_sms_free(mem_sys, cleanup);
return APR_SUCCESS;
}
cleanup_ref = &cleanup->next;
cleanup = cleanup->next;
}
/* The cleanup function should have been registered previously */
return APR_ENOCLEANUP;
}
APR_DECLARE(apr_status_t)
apr_sms_cleanup_run(apr_sms_t *mem_sys, void *data,
apr_status_t (*cleanup_fn)(void *))
{
apr_sms_cleanup_unregister(mem_sys, data, cleanup_fn);
return cleanup_fn(data);
}
1.1 apr/memory/unix/apr_sms_std.c
Index: apr_sms_std.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/>.
*/
/* This code kindly donated to APR by
* Elrond <el...@samba-tng.org>
* Luke Kenneth Casson Leighton <lk...@samba-tng.org>
* Sander Striker <st...@samba-tng.org>
*
* May 2001
*/
#include "apr.h"
#include "apr_private.h"
#include "apr_memory_system.h"
#include <stdlib.h>
#include <assert.h>
/*
* standard memory system
*/
static void * apr_sms_std_malloc(apr_sms_t *mem_sys,
apr_size_t size)
{
return malloc(size);
}
static void * apr_sms_std_calloc(apr_sms_t *mem_sys,
apr_size_t size)
{
#if HAVE_CALLOC
return calloc(1, size);
#else
void *mem;
mem = malloc(size);
memset(mem, '\0', size);
return mem;
#endif
}
static void * apr_sms_std_realloc(apr_sms_t *mem_sys,
void *mem, apr_size_t size)
{
return realloc(mem, size);
}
static apr_status_t apr_sms_std_free(apr_sms_t *mem_sys,
void *mem)
{
free(mem);
return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_sms_std_create(apr_sms_t **mem_sys)
{
apr_sms_t *new_mem_sys;
assert(mem_sys != NULL);
*mem_sys = NULL;
/* should we be using apr_sms_calloc now we have it??? */
new_mem_sys = apr_sms_create(malloc(sizeof(apr_sms_t)),
NULL);
if (new_mem_sys == NULL)
return APR_ENOMEM;
new_mem_sys->malloc_fn = apr_sms_std_malloc;
new_mem_sys->calloc_fn = apr_sms_std_calloc;
new_mem_sys->realloc_fn = apr_sms_std_realloc;
new_mem_sys->free_fn = apr_sms_std_free;
/* as we're not a tracking memory module, i.e. we don't keep
* track of our allocations, we don't have apr_sms_reset or
* apr_sms_destroy functions.
*/
apr_sms_assert(new_mem_sys);
*mem_sys = new_mem_sys;
return APR_SUCCESS;
}
1.1 apr/memory/unix/apr_sms_tracking.c
Index: apr_sms_tracking.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/>.
*/
/* This code kindly donated to APR by
* Elrond <el...@samba-tng.org>
* Luke Kenneth Casson Leighton <lk...@samba-tng.org>
* Sander Striker <st...@samba-tng.org>
*
* May 2001
*/
#include "apr.h"
#include "apr_general.h"
#include "apr_private.h"
#include "apr_tracking_memory_system.h"
#include <stdlib.h>
#include <assert.h>
/*
* Simple tracking memory system
*/
/* INTERNALLY USED STRUCTURES */
typedef struct apr_track_node_t
{
struct apr_track_node_t *next;
struct apr_track_node_t **ref;
} apr_track_node_t;
typedef struct apr_sms_tracking_t
{
apr_sms_t header;
apr_track_node_t *nodes;
} apr_sms_tracking_t;
static void * apr_sms_tracking_malloc(apr_sms_t *mem_sys,
apr_size_t size)
{
apr_sms_tracking_t *tms;
apr_track_node_t *node;
assert (mem_sys != NULL);
tms = (apr_sms_tracking_t *)mem_sys;
node = apr_sms_malloc(mem_sys->parent_mem_sys,
size + sizeof(apr_track_node_t));
if (node == NULL)
return NULL;
node->next = tms->nodes;
tms->nodes = node;
node->ref = &tms->nodes;
if (node->next != NULL)
node->next->ref = &node->next;
node++;
return (void *)node;
}
static void * apr_sms_tracking_calloc(apr_sms_t *mem_sys,
apr_size_t size)
{
apr_sms_tracking_t *tms;
apr_track_node_t *node;
assert (mem_sys != NULL);
tms = (apr_sms_tracking_t *)mem_sys;
node = apr_sms_calloc(mem_sys->parent_mem_sys,
size + sizeof(apr_track_node_t));
if (node == NULL)
return NULL;
node->next = tms->nodes;
tms->nodes = node;
node->ref = &tms->nodes;
if (node->next != NULL)
node->next->ref = &node->next;
node++;
return (void *)node;
}
static void * apr_sms_tracking_realloc(apr_sms_t *mem_sys,
void *mem, apr_size_t size)
{
apr_sms_tracking_t *tms;
apr_track_node_t *node;
assert (mem_sys != NULL);
tms = (apr_sms_tracking_t *)mem_sys;
node = (apr_track_node_t *)mem;
if (node != NULL)
{
node--;
*(node->ref) = node->next;
}
node = apr_sms_realloc(mem_sys->parent_mem_sys,
node, size + sizeof(apr_track_node_t));
if (node == NULL)
return NULL;
node->next = tms->nodes;
tms->nodes = node;
node->ref = &tms->nodes;
if (node->next != NULL)
node->next->ref = &node->next;
node++;
return (void *)node;
}
static apr_status_t apr_sms_tracking_free(apr_sms_t *mem_sys,
void *mem)
{
apr_track_node_t *node;
assert (mem_sys != NULL);
assert (mem != NULL);
node = (apr_track_node_t *)mem;
node--;
*(node->ref) = node->next;
if (node->next != NULL)
node->next->ref = node->ref;
return apr_sms_free(mem_sys->parent_mem_sys, node);
}
static apr_status_t apr_sms_tracking_reset(apr_sms_t *mem_sys)
{
apr_sms_tracking_t *tms;
apr_track_node_t *node;
apr_status_t rv;
assert (mem_sys != NULL);
tms = (apr_sms_tracking_t *)mem_sys;
while (tms->nodes != NULL)
{
node = tms->nodes;
*(node->ref) = node->next;
if (node->next != NULL)
node->next->ref = node->ref;
if ((rv = apr_sms_free(mem_sys->parent_mem_sys,
node)) != APR_SUCCESS)
return rv;
}
return APR_SUCCESS;
}
static apr_status_t apr_sms_tracking_destroy(apr_sms_t *mem_sys)
{
apr_status_t rv;
/* If this is NULL we won't blow up as it should be caught at the
* next level down and then passed back to us...
*/
#ifdef APR_ASSERT_MEMORY
assert (mem_sys->parent_mem_sys != NULL);
#endif
if (!mem_sys)
return APR_EMEMSYS;
if ((rv = apr_sms_tracking_reset(mem_sys)) != APR_SUCCESS)
return rv;
return apr_sms_free(mem_sys->parent_mem_sys, mem_sys);
}
APR_DECLARE(apr_status_t) apr_sms_tracking_create(apr_sms_t **mem_sys,
apr_sms_t *pms)
{
apr_sms_t *new_mem_sys, *tmpms;
apr_sms_tracking_t *tms;
assert (mem_sys != NULL);
assert (pms != NULL);
*mem_sys = NULL;
/* changed this to 2 stages to make easier to follow...
* should we be using apr_sms_calloc now we have it?
*/
tmpms = apr_sms_malloc(pms, sizeof(apr_sms_tracking_t));
new_mem_sys = apr_sms_create(tmpms, pms);
if (new_mem_sys == NULL)
return APR_ENOMEM;
new_mem_sys->malloc_fn = apr_sms_tracking_malloc;
new_mem_sys->calloc_fn = apr_sms_tracking_calloc;
new_mem_sys->realloc_fn = apr_sms_tracking_realloc;
new_mem_sys->free_fn = apr_sms_tracking_free;
new_mem_sys->reset_fn = apr_sms_tracking_reset;
new_mem_sys->destroy_fn = apr_sms_tracking_destroy;
tms = (apr_sms_tracking_t *)new_mem_sys;
tms->nodes = NULL;
apr_sms_assert(new_mem_sys);
*mem_sys = new_mem_sys;
return APR_SUCCESS;
}