diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2005-05-17 19:01:07 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2005-05-17 19:01:07 (GMT) |
commit | 9b4c1ce9f6e79cf3194b3777813365a623688c47 (patch) | |
tree | c28c7fcf1c9fb58011a46602ab48b54179375c18 | |
parent | 2afe0fcda114dd398e518d9f1242307f06b72fbc (diff) | |
download | hdf5-9b4c1ce9f6e79cf3194b3777813365a623688c47.zip hdf5-9b4c1ce9f6e79cf3194b3777813365a623688c47.tar.gz hdf5-9b4c1ce9f6e79cf3194b3777813365a623688c47.tar.bz2 |
[svn-r10750] Purpose:
New feature.
Description:
Add "memory pool" internal data structure. This set of routines is
designed to add a way to allocate small pieces of information for a particular
purpose and then free all the pieces at once (i.e. without having to free each
piece individually). Memory pools are also good for localizing lots of small
allocations that logically belong together.
For example, if you were constructing a temporary linked list, you could
create a new memory pool, allocate all the nodes for the list from the memory
pool and when you were done with the list, just destroy the pool instead of
tracking through the list and freeing each block independently.
Platforms tested:
FreeBSD 4.11 (sleipnir)
h5committest
-rw-r--r-- | MANIFEST | 4 | ||||
-rw-r--r-- | src/H5MP.c | 468 | ||||
-rw-r--r-- | src/H5MPpkg.h | 105 | ||||
-rw-r--r-- | src/H5MPprivate.h | 45 | ||||
-rw-r--r-- | src/H5MPtest.c | 236 | ||||
-rwxr-xr-x | src/Makefile.am | 17 | ||||
-rw-r--r-- | src/Makefile.in | 47 | ||||
-rw-r--r-- | test/Makefile.am | 2 | ||||
-rw-r--r-- | test/Makefile.in | 44 | ||||
-rw-r--r-- | test/pool.c | 775 |
10 files changed, 1679 insertions, 64 deletions
@@ -891,7 +891,10 @@ ./src/H5MM.c ./src/H5MMprivate.h ./src/H5MMpublic.h +./src/H5MP.c +./src/H5MPpkg.h ./src/H5MPprivate.h +./src/H5MPtest.c ./src/H5O.c ./src/H5Oattr.c ./src/H5Obogus.c @@ -1039,6 +1042,7 @@ ./test/gen_old_mtime.c _DO_NOT_DISTRIBUTE_ ./test/gen_new_mtime.c _DO_NOT_DISTRIBUTE_ ./test/gen_new_super.c _DO_NOT_DISTRIBUTE_ +./test/pool.c ./test/set_extent.c ./test/sheap.c ./test/stab.c diff --git a/src/H5MP.c b/src/H5MP.c new file mode 100644 index 0000000..490b38a --- /dev/null +++ b/src/H5MP.c @@ -0,0 +1,468 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5MP.c + * May 2 2005 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Implements memory pools. (Similar to Apache's APR + * memory pools) + * + * Please see the documentation in: + * doc/html/TechNotes/MemoryPools.html for a full description + * of how they work, etc. + * + *------------------------------------------------------------------------- + */ + +#define H5MP_PACKAGE /*suppress error about including H5MPpkg */ + +/* Private headers */ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5MPpkg.h" /* Memory Pools */ + +/****************/ +/* Local Macros */ +/****************/ + +/* Minimum sized block */ +#define H5MP_MIN_BLOCK (H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)) + H5MP_BLOCK_ALIGNMENT) + +/* First block in page */ +#define H5MP_PAGE_FIRST_BLOCK(p) \ + (H5MP_page_blk_t *)((unsigned char *)(p) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t))) + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/********************************/ +/* Package Variable Definitions */ +/********************************/ + + +/********************/ +/* Static Variables */ +/********************/ + +/* Declare a free list to manage the H5MP_pool_t struct */ +H5FL_DEFINE(H5MP_pool_t); + + + +/*------------------------------------------------------------------------- + * Function: H5MP_create + * + * Purpose: Create a new memory pool + * + * Return: Pointer to the memory pool "header" on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 2 2005 + * + *------------------------------------------------------------------------- + */ +H5MP_pool_t * +H5MP_create (size_t page_size, unsigned flags) +{ + H5MP_pool_t *mp; /* New memory pool header */ + H5MP_pool_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5MP_create, NULL) + + /* Allocate space for the pool header */ + if (NULL==(mp = H5FL_MALLOC(H5MP_pool_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for memory pool header") + + /* Assign information */ + mp->page_size = H5MP_BLOCK_ALIGN(page_size); + mp->flags = flags; + + /* Initialize information */ + mp->free_size = 0; + mp->first = NULL; + mp->max_size = mp->page_size - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)); + + /* Create factory for pool pages */ + if((mp->page_fac=H5FL_fac_init(page_size))==NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_CANTINIT, NULL, "can't create page factory") + + /* Set return value */ + ret_value = mp; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MP_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5MP_new_page + * + * Purpose: Allocate new page for a memory pool + * + * Return: Pointer to the page allocated on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 4 2005 + * + *------------------------------------------------------------------------- + */ +static H5MP_page_t * +H5MP_new_page(H5MP_pool_t *mp, size_t page_size) +{ + H5MP_page_t *new_page; /* New page created */ + H5MP_page_blk_t *first_blk; /* Pointer to first block in page */ + H5MP_page_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5MP_new_page) + + /* Sanity check */ + HDassert(mp); + HDassert(page_size >= mp->page_size); + + /* Allocate page */ + if(page_size > mp->page_size) { + if(NULL == (new_page = H5MM_malloc(page_size))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for page") + new_page->free_size = page_size - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)); + new_page->fac_alloc = FALSE; + } /* end if */ + else { + if((new_page = H5FL_FAC_MALLOC(mp->page_fac)) == NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for page") + new_page->free_size = mp->max_size; + new_page->fac_alloc = TRUE; + } /* end else */ +#ifdef QAK +HDfprintf(stderr,"%s: Allocating new page = %p\n", FUNC, new_page); +#endif /* QAK */ + + /* Initialize page information */ + first_blk = H5MP_PAGE_FIRST_BLOCK(new_page); + first_blk->size = new_page->free_size; + first_blk->page = new_page; + first_blk->is_free = TRUE; + first_blk->prev = NULL; + first_blk->next = NULL; + + /* Insert into page list */ + new_page->prev = NULL; + new_page->next = mp->first; + if(mp->first) + mp->first->prev = new_page; + mp->first = new_page; + + /* Account for new free space */ + new_page->free_blk = first_blk; + mp->free_size += new_page->free_size; + + /* Assign return value */ + ret_value = new_page; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MP_new_page() */ + + +/*------------------------------------------------------------------------- + * Function: H5MP_malloc + * + * Purpose: Allocate space in a memory pool + * + * Return: Pointer to the space allocated on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 2 2005 + * + *------------------------------------------------------------------------- + */ +void * +H5MP_malloc (H5MP_pool_t *mp, size_t request) +{ + H5MP_page_t *alloc_page = NULL; /* Page to allocate space from */ + H5MP_page_blk_t *alloc_free; /* Pointer to free space in page */ + size_t needed; /* Size requested, plus block header and alignment */ + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5MP_malloc, NULL) + + /* Sanity check */ + HDassert(mp); + HDassert(request > 0); + + /* Compute actual size needed */ + needed = H5MP_BLOCK_ALIGN(request) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)); +#ifdef QAK +HDfprintf(stderr,"%s: sizeof(H5MP_page_blk_t) = %Zu\n", FUNC, sizeof(H5MP_page_blk_t)); +HDfprintf(stderr,"%s: request = %Zu, needed = %Zu\n", FUNC, request, needed); +#endif /* QAK */ + + /* See if the request can be handled by existing free space */ + if(needed <= mp->free_size) { + size_t pool_free_avail; /* Amount of free space possibly available in pool */ + + /* Locate page with enough free space */ + alloc_page = mp->first; + pool_free_avail = mp->free_size; + while(alloc_page && pool_free_avail >= needed) { + /* If we found a page with enough free space, search for large + * enough free block on that page */ + if(alloc_page->free_size >= needed) { + size_t page_free_avail; /* Amount of free space possibly available */ + + /* Locate large enough block */ + alloc_free = alloc_page->free_blk; + page_free_avail = alloc_page->free_size; + while(alloc_free && page_free_avail >= needed) { + if(alloc_free->is_free) { + /* If we found a large enough block, leave now */ + if(alloc_free->size >= needed) + goto found; /* Needed to escape double "while" loop */ + + /* Decrement amount of potential space left */ + page_free_avail -= alloc_free->size; + } /* end if */ + + /* Go to next block */ + alloc_free = alloc_free->next; + } /* end while */ + } /* end if */ + + /* Decrement amount of potential space left */ + pool_free_avail -= alloc_page->free_size; + + /* Go to next page */ + alloc_page = alloc_page->next; + } /* end while */ + } /* end if */ + + { + size_t page_size; /* Size of page needed */ + + /* Check if the request is too large for a standard page */ + page_size = (needed > mp->max_size) ? + (needed + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t))) : mp->page_size; + + /* Allocate new page */ + if(NULL == (alloc_page = H5MP_new_page(mp, page_size))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for page") + + /* Set the block to allocate from */ + alloc_free = alloc_page->free_blk; + } /* end block */ + + /* Allocate space in page */ +found: + + /* Sanity check */ + HDassert(alloc_page); + HDassert(alloc_free); + + /* Check if we can subdivide the free space */ + if(alloc_free->size > (needed + H5MP_MIN_BLOCK)) { + H5MP_page_blk_t *new_free; /* New free block created */ + + /* Carve out new free block after block to allocate */ + new_free = (H5MP_page_blk_t *)(((unsigned char *)alloc_free) + needed); + + /* Link into existing lists */ + new_free->next = alloc_free->next; + if(alloc_free->next) + alloc_free->next->prev = new_free; + new_free->prev = alloc_free; + alloc_free->next = new_free; + + /* Set blocks' information */ + new_free->size = alloc_free->size - needed; + new_free->is_free = TRUE; + new_free->page = alloc_free->page; + alloc_free->size = needed; + alloc_free->is_free = FALSE; + } /* end if */ + else { + /* Use whole free space block for new block */ + alloc_free->is_free = FALSE; + } /* end else */ + + /* Update page & pool's free size information */ + alloc_page->free_size -= alloc_free->size; + if(alloc_page->free_blk == alloc_free) + alloc_page->free_blk = alloc_free->next; + mp->free_size -= alloc_free->size; + + /* Set new space pointer for the return value */ + ret_value = ((unsigned char *)alloc_free) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)); +#ifdef QAK +HDfprintf(stderr,"%s: Allocating space from page, ret_value = %p\n", FUNC, ret_value); +#endif /* QAK */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MP_malloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5MP_free + * + * Purpose: Release space in a memory pool + * + * Return: NULL on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 3 2005 + * + * Note: Should we release pages that have no used blocks? + * + *------------------------------------------------------------------------- + */ +void * +H5MP_free (H5MP_pool_t *mp, void *spc) +{ + H5MP_page_blk_t *spc_blk; /* Block for space to free */ + H5MP_page_t *spc_page; /* Page containing block to free */ + void *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOFUNC(H5MP_free) + + /* Sanity check */ + HDassert(mp); + HDassert(spc); + + /* Get block header for space to free */ + spc_blk = (H5MP_page_blk_t *)(((unsigned char *)spc) - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t))); + + /* Mark block as free */ + HDassert(spc_blk->is_free == FALSE); + spc_blk->is_free = TRUE; + + /* Add it's space to the amount of free space in the page & pool */ + spc_page = spc_blk->page; +#ifdef QAK +HDfprintf(stderr,"%s: Freeing from page = %p\n", "H5MP_free", spc_page); +#endif /* QAK */ + spc_page->free_size += spc_blk->size; + mp->free_size += spc_blk->size; + + /* Move page with newly freed space to front of list of pages in pool */ + if(spc_page != mp->first) { + /* Remove page from list */ + spc_page->prev->next = spc_page->next; + if(spc_page->next) + spc_page->next->prev = spc_page->prev; + + /* Insert page at beginning of list */ + spc_page->prev = NULL; + spc_page->next = mp->first; + mp->first->prev = spc_page; + mp->first = spc_page; + } /* end if */ + + /* Check if block can be merged with free space after it on page */ + if(spc_blk->next != NULL) { + H5MP_page_blk_t *next_blk; /* Block following space to free */ + + next_blk = spc_blk->next; + HDassert(next_blk->prev == spc_blk); + if(next_blk->is_free) { + spc_blk->size += next_blk->size; + spc_blk->next = next_blk->next; + } /* end if */ + } /* end if */ + + /* Check if block can be merged with free space before it on page */ + if(spc_blk->prev != NULL) { + H5MP_page_blk_t *prev_blk; /* Block before space to free */ + + prev_blk = spc_blk->prev; + HDassert(prev_blk->next == spc_blk); + if(prev_blk->is_free) { + prev_blk->size += spc_blk->size; + prev_blk->next = spc_blk->next; + } /* end if */ + } /* end if */ + + /* Check if the block freed becomes the first free block on the page */ + if(spc_page->free_blk == NULL || spc_blk < spc_page->free_blk) + spc_page->free_blk = spc_blk; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MP_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5MP_close + * + * Purpose: Release all memory for a pool and destroy pool + * + * Return: Non-negative on success/negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 3 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5MP_close (H5MP_pool_t *mp) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5MP_close, FAIL) + + /* Release memory for pool pages */ + if(mp->first != NULL) { + H5MP_page_t *page, *next_page; /* Pointer to pages in pool */ + + /* Iterate through pages, releasing them */ + page = mp->first; + while(page) { + next_page = page->next; + + /* Free the page appropriately */ + if(page->fac_alloc) + H5FL_FAC_FREE(mp->page_fac,page); + else + H5MM_xfree(page); + + page = next_page; + } /* end while */ + } /* end if */ + + /* Release page factory */ + if(mp->page_fac) + if(H5FL_fac_term(mp->page_fac)<0) + HGOTO_ERROR (H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy page factory") + + /* Free the memory pool itself */ + H5FL_FREE(H5MP_pool_t, mp); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MP_close() */ + diff --git a/src/H5MPpkg.h b/src/H5MPpkg.h new file mode 100644 index 0000000..3dc4bab --- /dev/null +++ b/src/H5MPpkg.h @@ -0,0 +1,105 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Monday, May 2, 2005 + * + * Purpose: This file contains declarations which are visible only within + * the H5MP package. Source files outside the H5MP package should + * include H5MPprivate.h instead. + */ +#ifndef H5MP_PACKAGE +#error "Do not include this file outside the H5MP package!" +#endif + +#ifndef _H5MPpkg_H +#define _H5MPpkg_H + +/* Get package's private header */ +#include "H5MPprivate.h" /* Memory Pools */ + +/* Other private headers needed by this file */ +#include "H5FLprivate.h" /* Free Lists */ + +/**************************/ +/* Package Private Macros */ +/**************************/ + +/* Alignment macros */ +/* (Ideas from Apache APR :-) */ + +/* Default alignment necessary */ +#define H5MP_BLOCK_ALIGNMENT 8 + +/* General alignment macro */ +/* (this only works for aligning to power of 2 boundary) */ +#define H5MP_ALIGN(x, a) \ + (((x) + ((size_t)(a)) - 1) & ~(((size_t)(a)) - 1)) + +/* Default alignment */ +#define H5MP_BLOCK_ALIGN(x) H5MP_ALIGN(x, H5MP_BLOCK_ALIGNMENT) + + +/****************************/ +/* Package Private Typedefs */ +/****************************/ + +/* Free block in pool */ +typedef struct H5MP_page_blk_t { + size_t size; /* Size of block (includes this H5MP_page_blk_t info) */ + unsigned is_free:1; /* Flag to indicate the block is free */ + struct H5MP_page_t *page; /* Pointer to page block is located in */ + struct H5MP_page_blk_t *prev; /* Pointer to previous block in page */ + struct H5MP_page_blk_t *next; /* Pointer to next block in page */ +} H5MP_page_blk_t; + +/* Memory pool page */ +typedef struct H5MP_page_t { + size_t free_size; /* Total amount of free space in page */ + unsigned fac_alloc:1; /* Flag to indicate the page was allocated by the pool's factory */ + H5MP_page_blk_t *free_blk; /* Pointer to first free block in page */ + struct H5MP_page_t *next; /* Pointer to next page in pool */ + struct H5MP_page_t *prev; /* Pointer to previous page in pool */ +} H5MP_page_t; + +/* Memory pool header */ +struct H5MP_pool_t { + H5FL_fac_head_t *page_fac; /* Free-list factory for pages */ + size_t page_size; /* Page size for pool */ + size_t free_size; /* Total amount of free space in pool */ + size_t max_size; /* Maximum block that will fit in a standard page */ + H5MP_page_t *first; /* Pointer to first page in pool */ + unsigned flags; /* Bit flags for pool settings */ +}; + + +/*****************************************/ +/* Package Private Variable Declarations */ +/*****************************************/ + + +/******************************/ +/* Package Private Prototypes */ +/******************************/ +#ifdef H5MP_TESTING +H5_DLL herr_t H5MP_get_pool_free_size (const H5MP_pool_t *mp, size_t *free_size); +H5_DLL htri_t H5MP_pool_is_free_size_correct(const H5MP_pool_t *mp); +H5_DLL herr_t H5MP_get_pool_first_page(const H5MP_pool_t *mp, H5MP_page_t **page); +H5_DLL herr_t H5MP_get_page_free_size(const H5MP_page_t *mp, size_t *page); +H5_DLL herr_t H5MP_get_page_next_page(const H5MP_page_t *page, H5MP_page_t **next_page); +#endif /* H5MP_TESTING */ + +#endif /* _H5MPpkg_H */ + diff --git a/src/H5MPprivate.h b/src/H5MPprivate.h index fbe4df1..92249aa 100644 --- a/src/H5MPprivate.h +++ b/src/H5MPprivate.h @@ -12,11 +12,50 @@ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* - * Header file for private definitions of the MPE instrumentation. +/*------------------------------------------------------------------------- + * + * Created: H5MPprivate.h + * May 2 2005 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Private header for memory pool routines. + * + *------------------------------------------------------------------------- */ + #ifndef _H5MPprivate_H #define _H5MPprivate_H +/* Include package's public header (not yet) */ +/* #include "H5MPpublic.h" */ + +/* Private headers needed by this file */ + + +/**************************/ +/* Library Private Macros */ +/**************************/ + +/* Pool creation flags */ +/* Default settings */ +#define H5MP_FLG_DEFAULT 0 +#define H5MP_PAGE_SIZE_DEFAULT 4096 /* (bytes) */ + + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +/* Memory pool header (defined in H5MPpkg.c) */ +typedef struct H5MP_pool_t H5MP_pool_t; + + +/***************************************/ +/* Library-private Function Prototypes */ +/***************************************/ +H5_DLL H5MP_pool_t *H5MP_create (size_t page_size, unsigned flags); +H5_DLL void * H5MP_malloc (H5MP_pool_t *mp, size_t request); +H5_DLL void * H5MP_free (H5MP_pool_t *mp, void *spc); +H5_DLL herr_t H5MP_close (H5MP_pool_t *mp); -#endif +#endif /* _H5MPprivate_H */ diff --git a/src/H5MPtest.c b/src/H5MPtest.c new file mode 100644 index 0000000..7962457 --- /dev/null +++ b/src/H5MPtest.c @@ -0,0 +1,236 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Tuesday, May 3, 2005 + * + * Purpose: Memory pool testing functions. + */ + +#define H5MP_PACKAGE /*suppress error about including H5MPpkg */ +#define H5MP_TESTING /*include H5MP testing funcs*/ + +/* Private headers */ +#include "H5private.h" /* Generic Functions */ +#include "H5MPpkg.h" /* Memory Pools */ +#include "H5Eprivate.h" /* Error handling */ + +/* Static Prototypes */ + +/* Package variables */ + + +/*------------------------------------------------------------------------- + * Function: H5MP_get_pool_free_size + * + * Purpose: Retrieve the total amount of free space in entire pool + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, May 3, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5MP_get_pool_free_size(const H5MP_pool_t *mp, size_t *free_size) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MP_get_pool_free_size) + + /* Check arguments. */ + HDassert(mp); + HDassert(free_size); + + /* Get memory pool's free space */ + *free_size = mp->free_size; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5MP_get_pool_free_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5MP_get_pool_first_page + * + * Purpose: Retrieve the first page in a memory pool + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, May 3, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5MP_get_pool_first_page(const H5MP_pool_t *mp, H5MP_page_t **page) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MP_get_pool_first_page) + + /* Check arguments. */ + HDassert(mp); + HDassert(page); + + /* Get memory pool's first page */ + *page = mp->first; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5MP_get_pool_first_page() */ + + +/*------------------------------------------------------------------------- + * Function: H5MP_pool_is_free_size_correct + * + * Purpose: Check that the free space reported in each page corresponds + * to the free size in each page and that the free space in the + * free blocks for a page corresponds with the free space for + * the page. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Wednesday, May 3, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5MP_pool_is_free_size_correct(const H5MP_pool_t *mp) +{ + H5MP_page_t *page; /* Pointer to current page */ + size_t pool_free; /* Size of pages' free space */ + htri_t ret_value = TRUE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MP_pool_is_free_size_correct) + + /* Check arguments. */ + HDassert(mp); + + /* Iterate through pages, checking the free size & accumulating the + * free space for all the pages */ + page = mp->first; + pool_free = 0; + while(page != NULL) { + H5MP_page_blk_t *blk; /* Pointer to current free block */ + size_t page_free; /* Size of blocks on free list */ + + /* Iterate through the blocks in page, accumulating free space */ + blk = (H5MP_page_blk_t *)((unsigned char *)page + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t))); + page_free = 0; + while(blk != NULL) { + if(blk->is_free) + page_free += blk->size; + blk = blk->next; + } /* end while */ + + /* Check that the free space from the blocks on the free list + * corresponds to space in page */ +#ifdef QAK +HDfprintf(stderr,"%s: page_free = %Zu, page->free_size = %Zu\n", "H5MP_pool_is_free_size_correct", page_free, page->free_size); +#endif /* QAK */ + if(page_free != page->free_size) + HGOTO_DONE (FALSE) + + /* Increment the amount of free space in pool */ + pool_free += page->free_size; + + /* Advance to next page */ + page = page->next; + } /* end while */ + + /* Check that the free space from the pages + * corresponds to free space in pool */ +#ifdef QAK +HDfprintf(stderr,"%s: pool_free = %Zu, mp->free_size = %Zu\n", "H5MP_pool_is_free_size_correct", pool_free, mp->free_size); +#endif /* QAK */ + if(pool_free != mp->free_size) + HGOTO_DONE (FALSE) + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MP_pool_is_free_size_correct() */ + + +/*------------------------------------------------------------------------- + * Function: H5MP_get_page_free_size + * + * Purpose: Retrieve the amount of free space in given page + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, May 3, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5MP_get_page_free_size(const H5MP_page_t *page, size_t *free_size) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MP_get_page_free_size) + + /* Check arguments. */ + HDassert(page); + HDassert(free_size); + + /* Get memory page's free space */ + *free_size = page->free_size; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5MP_get_page_free_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5MP_get_page_next_page + * + * Purpose: Retrieve the next page in the pool + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, May 3, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5MP_get_page_next_page(const H5MP_page_t *page, H5MP_page_t **next_page) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MP_get_page_next_page) + + /* Check arguments. */ + HDassert(page); + HDassert(next_page); + + /* Get next memory page */ + *next_page = page->next; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5MP_get_page_next_page() */ + diff --git a/src/Makefile.am b/src/Makefile.am index 50128e2..ec21d50 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -52,7 +52,9 @@ libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2cache.c H5B2dbg.c \ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \ H5FDstream.c H5FL.c H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c \ H5G.c H5Gent.c H5Gnode.c H5Gstab.c \ - H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c H5O.c \ + H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \ + H5MP.c H5MPtest.c \ + H5O.c \ H5Oattr.c H5Obogus.c \ H5Ocont.c H5Odtype.c H5Oefl.c H5Ofill.c H5Olayout.c H5Omtime.c \ H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c H5Ostab.c \ @@ -78,19 +80,6 @@ include_HEADERS =H5public.h H5Apublic.h H5ACpublic.h H5Bpublic.h H5B2public.h \ H5SHpublic.h \ H5Tpublic.h H5Zpublic.h H5pubconf.h hdf5.h H5api_adpt.h -# Private headers -#noinst_HEADERS =H5private.h H5Aprivate.h H5Apkg.h H5ACprivate.h H5Bprivate.h \ -# H5B2private.h \ -# H5BTprivate.h \ -# H5Dprivate.h H5Eprivate.h H5Fprivate.h H5FDprivate.h H5FLprivate.h \ -# H5FOprivate.h H5FSprivate.h H5Gprivate.h H5Gpkg.h \ -# H5HGprivate.h H5HLprivate.h H5HPprivate.h H5Iprivate.h H5MFprivate.h \ -# H5MMprivate.h H5Oprivate.h H5Opkg.h H5Pprivate.h H5Ppkg.h \ -# H5Rprivate.h H5RCprivate.h H5RSprivate.h H5Sprivate.h H5SHprivate.h \ -# H5STprivate.h \ -# H5Tprivate.h H5Tpkg.h H5TSprivate.h H5Vprivate.h \ -# H5Zprivate.h H5Zpkg.h H5config.h - # install libhdf5.settings in lib directory settingsdir=$(libdir) settings_DATA=libhdf5.settings diff --git a/src/Makefile.in b/src/Makefile.in index f9fc0c9..050139d 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -92,20 +92,20 @@ am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5B2.lo \ H5FDstdio.lo H5FDstream.lo H5FL.lo H5FO.lo H5FP.lo \ H5FPclient.lo H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo \ H5Gnode.lo H5Gstab.lo H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo \ - H5HP.lo H5I.lo H5MF.lo H5MM.lo H5O.lo H5Oattr.lo H5Obogus.lo \ - H5Ocont.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Olayout.lo \ - H5Omtime.lo H5Oname.lo H5Onull.lo H5Opline.lo H5Osdspace.lo \ - H5Oshared.lo H5Ostab.lo H5P.lo H5Pdcpl.lo H5Pdxpl.lo \ - H5Pfapl.lo H5Pfcpl.lo H5Ptest.lo H5R.lo H5RC.lo H5RS.lo H5S.lo \ - H5Sall.lo H5Shyper.lo H5Smpio.lo H5Snone.lo H5Spoint.lo \ - H5Sselect.lo H5Stest.lo H5SH.lo H5SHcache.lo H5SHdbg.lo \ - H5SL.lo H5ST.lo H5T.lo H5Tarray.lo H5Tbit.lo H5Tcommit.lo \ - H5Tcompound.lo H5Tconv.lo H5Tcset.lo H5Tenum.lo H5Tfields.lo \ - H5Tfixed.lo H5Tfloat.lo H5Tinit.lo H5Tnative.lo H5Toffset.lo \ - H5Topaque.lo H5Torder.lo H5Tpad.lo H5Tprecis.lo H5Tstrpad.lo \ - H5Tvlen.lo H5TS.lo H5V.lo H5Z.lo H5Zdeflate.lo \ - H5Zfletcher32.lo H5Znbit.lo H5Zshuffle.lo H5Zszip.lo \ - H5Zscaleoffset.lo H5Ztrans.lo + H5HP.lo H5I.lo H5MF.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \ + H5Oattr.lo H5Obogus.lo H5Ocont.lo H5Odtype.lo H5Oefl.lo \ + H5Ofill.lo H5Olayout.lo H5Omtime.lo H5Oname.lo H5Onull.lo \ + H5Opline.lo H5Osdspace.lo H5Oshared.lo H5Ostab.lo H5P.lo \ + H5Pdcpl.lo H5Pdxpl.lo H5Pfapl.lo H5Pfcpl.lo H5Ptest.lo H5R.lo \ + H5RC.lo H5RS.lo H5S.lo H5Sall.lo H5Shyper.lo H5Smpio.lo \ + H5Snone.lo H5Spoint.lo H5Sselect.lo H5Stest.lo H5SH.lo \ + H5SHcache.lo H5SHdbg.lo H5SL.lo H5ST.lo H5T.lo H5Tarray.lo \ + H5Tbit.lo H5Tcommit.lo H5Tcompound.lo H5Tconv.lo H5Tcset.lo \ + H5Tenum.lo H5Tfields.lo H5Tfixed.lo H5Tfloat.lo H5Tinit.lo \ + H5Tnative.lo H5Toffset.lo H5Topaque.lo H5Torder.lo H5Tpad.lo \ + H5Tprecis.lo H5Tstrpad.lo H5Tvlen.lo H5TS.lo H5V.lo H5Z.lo \ + H5Zdeflate.lo H5Zfletcher32.lo H5Znbit.lo H5Zshuffle.lo \ + H5Zszip.lo H5Zscaleoffset.lo H5Ztrans.lo libhdf5_la_OBJECTS = $(am_libhdf5_la_OBJECTS) PROGRAMS = $(noinst_PROGRAMS) H5detect_SOURCES = H5detect.c @@ -369,7 +369,9 @@ libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2cache.c H5B2dbg.c \ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \ H5FDstream.c H5FL.c H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c \ H5G.c H5Gent.c H5Gnode.c H5Gstab.c \ - H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c H5O.c \ + H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \ + H5MP.c H5MPtest.c \ + H5O.c \ H5Oattr.c H5Obogus.c \ H5Ocont.c H5Odtype.c H5Oefl.c H5Ofill.c H5Olayout.c H5Omtime.c \ H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c H5Ostab.c \ @@ -396,19 +398,6 @@ include_HEADERS = H5public.h H5Apublic.h H5ACpublic.h H5Bpublic.h H5B2public.h \ H5Tpublic.h H5Zpublic.h H5pubconf.h hdf5.h H5api_adpt.h -# Private headers -#noinst_HEADERS =H5private.h H5Aprivate.h H5Apkg.h H5ACprivate.h H5Bprivate.h \ -# H5B2private.h \ -# H5BTprivate.h \ -# H5Dprivate.h H5Eprivate.h H5Fprivate.h H5FDprivate.h H5FLprivate.h \ -# H5FOprivate.h H5FSprivate.h H5Gprivate.h H5Gpkg.h \ -# H5HGprivate.h H5HLprivate.h H5HPprivate.h H5Iprivate.h H5MFprivate.h \ -# H5MMprivate.h H5Oprivate.h H5Opkg.h H5Pprivate.h H5Ppkg.h \ -# H5Rprivate.h H5RCprivate.h H5RSprivate.h H5Sprivate.h H5SHprivate.h \ -# H5STprivate.h \ -# H5Tprivate.h H5Tpkg.h H5TSprivate.h H5Vprivate.h \ -# H5Zprivate.h H5Zpkg.h H5config.h - # install libhdf5.settings in lib directory settingsdir = $(libdir) settings_DATA = libhdf5.settings @@ -580,6 +569,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5I.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MF.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MM.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MP.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MPtest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5O.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Oattr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Obogus.Plo@am__quote@ diff --git a/test/Makefile.am b/test/Makefile.am index ed903c8..4a700a4 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -30,7 +30,7 @@ check_SCRIPTS = $(TEST_SCRIPT) # These are our main targets. They should be listed in the order to be # executed, generally most specific tests to least specific tests. TEST_PROG=testhdf5 lheap ohdr stab gheap cache btree2 blocktrack sheap \ - hyperslab istore bittests dt_atomic \ + pool hyperslab istore bittests dt_atomic \ dtypes dsets cmpd_dset extend external links unlink big mtime \ fillval mount flush1 flush2 enum \ set_extent ttsafe stream_test \ diff --git a/test/Makefile.in b/test/Makefile.in index c6623ff..d360fef 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -29,7 +29,7 @@ # # HDF5 Library Test Makefile(.in) # -SOURCES = $(libh5test_la_SOURCES) big.c bittests.c blocktrack.c btree2.c cache.c cmpd_dset.c dangle.c dsets.c dt_atomic.c dtransform.c dtypes.c enum.c err_compat.c error_test.c extend.c external.c file_handle.c filename.c fillval.c flush1.c flush2.c getname.c gheap.c hyperslab.c istore.c lheap.c links.c mount.c mtime.c ntypes.c ohdr.c reserved.c set_extent.c sheap.c stab.c stream_test.c $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c +SOURCES = $(libh5test_la_SOURCES) big.c bittests.c blocktrack.c btree2.c cache.c cmpd_dset.c dangle.c dsets.c dt_atomic.c dtransform.c dtypes.c enum.c err_compat.c error_test.c extend.c external.c file_handle.c filename.c fillval.c flush1.c flush2.c getname.c gheap.c hyperslab.c istore.c lheap.c links.c mount.c mtime.c ntypes.c ohdr.c pool.c reserved.c set_extent.c sheap.c stab.c stream_test.c $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -72,16 +72,16 @@ am_libh5test_la_OBJECTS = h5test.lo testframe.lo libh5test_la_OBJECTS = $(am_libh5test_la_OBJECTS) am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \ stab$(EXEEXT) gheap$(EXEEXT) cache$(EXEEXT) btree2$(EXEEXT) \ - blocktrack$(EXEEXT) sheap$(EXEEXT) hyperslab$(EXEEXT) \ - istore$(EXEEXT) bittests$(EXEEXT) dt_atomic$(EXEEXT) \ - dtypes$(EXEEXT) dsets$(EXEEXT) cmpd_dset$(EXEEXT) \ - extend$(EXEEXT) external$(EXEEXT) links$(EXEEXT) \ - unlink$(EXEEXT) big$(EXEEXT) mtime$(EXEEXT) fillval$(EXEEXT) \ - mount$(EXEEXT) flush1$(EXEEXT) flush2$(EXEEXT) enum$(EXEEXT) \ - set_extent$(EXEEXT) ttsafe$(EXEEXT) stream_test$(EXEEXT) \ - getname$(EXEEXT) file_handle$(EXEEXT) ntypes$(EXEEXT) \ - dangle$(EXEEXT) dtransform$(EXEEXT) filename$(EXEEXT) \ - reserved$(EXEEXT) + blocktrack$(EXEEXT) sheap$(EXEEXT) pool$(EXEEXT) \ + hyperslab$(EXEEXT) istore$(EXEEXT) bittests$(EXEEXT) \ + dt_atomic$(EXEEXT) dtypes$(EXEEXT) dsets$(EXEEXT) \ + cmpd_dset$(EXEEXT) extend$(EXEEXT) external$(EXEEXT) \ + links$(EXEEXT) unlink$(EXEEXT) big$(EXEEXT) mtime$(EXEEXT) \ + fillval$(EXEEXT) mount$(EXEEXT) flush1$(EXEEXT) \ + flush2$(EXEEXT) enum$(EXEEXT) set_extent$(EXEEXT) \ + ttsafe$(EXEEXT) stream_test$(EXEEXT) getname$(EXEEXT) \ + file_handle$(EXEEXT) ntypes$(EXEEXT) dangle$(EXEEXT) \ + dtransform$(EXEEXT) filename$(EXEEXT) reserved$(EXEEXT) big_SOURCES = big.c big_OBJECTS = big.$(OBJEXT) big_LDADD = $(LDADD) @@ -206,6 +206,10 @@ ohdr_SOURCES = ohdr.c ohdr_OBJECTS = ohdr.$(OBJEXT) ohdr_LDADD = $(LDADD) ohdr_DEPENDENCIES = libh5test.la $(am__DEPENDENCIES_1) +pool_SOURCES = pool.c +pool_OBJECTS = pool.$(OBJEXT) +pool_LDADD = $(LDADD) +pool_DEPENDENCIES = libh5test.la $(am__DEPENDENCIES_1) reserved_SOURCES = reserved.c reserved_OBJECTS = reserved.$(OBJEXT) reserved_LDADD = $(LDADD) @@ -266,17 +270,17 @@ SOURCES = $(libh5test_la_SOURCES) big.c bittests.c blocktrack.c \ dtransform.c dtypes.c enum.c err_compat.c error_test.c \ extend.c external.c file_handle.c filename.c fillval.c \ flush1.c flush2.c getname.c gheap.c hyperslab.c istore.c \ - lheap.c links.c mount.c mtime.c ntypes.c ohdr.c reserved.c \ - set_extent.c sheap.c stab.c stream_test.c $(testhdf5_SOURCES) \ - testmeta.c $(ttsafe_SOURCES) unlink.c + lheap.c links.c mount.c mtime.c ntypes.c ohdr.c pool.c \ + reserved.c set_extent.c sheap.c stab.c stream_test.c \ + $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c DIST_SOURCES = $(libh5test_la_SOURCES) big.c bittests.c blocktrack.c \ btree2.c cache.c cmpd_dset.c dangle.c dsets.c dt_atomic.c \ dtransform.c dtypes.c enum.c err_compat.c error_test.c \ extend.c external.c file_handle.c filename.c fillval.c \ flush1.c flush2.c getname.c gheap.c hyperslab.c istore.c \ - lheap.c links.c mount.c mtime.c ntypes.c ohdr.c reserved.c \ - set_extent.c sheap.c stab.c stream_test.c $(testhdf5_SOURCES) \ - testmeta.c $(ttsafe_SOURCES) unlink.c + lheap.c links.c mount.c mtime.c ntypes.c ohdr.c pool.c \ + reserved.c set_extent.c sheap.c stab.c stream_test.c \ + $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -495,7 +499,7 @@ check_SCRIPTS = $(TEST_SCRIPT) # These are our main targets. They should be listed in the order to be # executed, generally most specific tests to least specific tests. TEST_PROG = testhdf5 lheap ohdr stab gheap cache btree2 blocktrack sheap \ - hyperslab istore bittests dt_atomic \ + pool hyperslab istore bittests dt_atomic \ dtypes dsets cmpd_dset extend external links unlink big mtime \ fillval mount flush1 flush2 enum \ set_extent ttsafe stream_test \ @@ -704,6 +708,9 @@ ntypes$(EXEEXT): $(ntypes_OBJECTS) $(ntypes_DEPENDENCIES) ohdr$(EXEEXT): $(ohdr_OBJECTS) $(ohdr_DEPENDENCIES) @rm -f ohdr$(EXEEXT) $(LINK) $(ohdr_LDFLAGS) $(ohdr_OBJECTS) $(ohdr_LDADD) $(LIBS) +pool$(EXEEXT): $(pool_OBJECTS) $(pool_DEPENDENCIES) + @rm -f pool$(EXEEXT) + $(LINK) $(pool_LDFLAGS) $(pool_OBJECTS) $(pool_LDADD) $(LIBS) reserved$(EXEEXT): $(reserved_OBJECTS) $(reserved_DEPENDENCIES) @rm -f reserved$(EXEEXT) $(LINK) $(reserved_LDFLAGS) $(reserved_OBJECTS) $(reserved_LDADD) $(LIBS) @@ -770,6 +777,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mtime.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntypes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ohdr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reserved.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_extent.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sheap.Po@am__quote@ diff --git a/test/pool.c b/test/pool.c new file mode 100644 index 0000000..5170c77 --- /dev/null +++ b/test/pool.c @@ -0,0 +1,775 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Tuesday, May 3, 2005 + */ +#include "h5test.h" + +/* + * This file needs to access private datatypes from the H5MP package. + * This file also needs to access the memory pool testing code. + */ +#define H5MP_PACKAGE +#define H5MP_TESTING +#include "H5MPpkg.h" /* Memory Pools */ + +/* Other private headers that this test requires */ + +/* Local macros */ +#define MPOOL_PAGE_SIZE H5MP_PAGE_SIZE_DEFAULT +#define MPOOL_FLAGS H5MP_FLG_DEFAULT +#define MPOOL_NUM_NORMAL_BLOCKS 15 +#define MPOOL_NORMAL_BLOCK 512 +#define MPOOL_LARGE_BLOCK (MPOOL_PAGE_SIZE * 3) +#define MPOOL_NUM_SMALL_BLOCKS 64 +#define MPOOL_SMALL_BLOCK 1 +#define MPOOL_NUM_RANDOM 10*1024 +#define MPOOL_RANDOM_MAX_SIZE (MPOOL_PAGE_SIZE * 2) + + +/*------------------------------------------------------------------------- + * Function: test_create + * + * Purpose: Test trivial creating & closing memory pool + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, May 3, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_create(void) +{ + H5MP_pool_t *mp; /* Memory pool */ + H5MP_page_t *page; /* Memory pool page */ + size_t free_size; /* Free size in pool */ + + /* + * Test memory pool creation + */ + TESTING("memory pool creation"); + + /* Create a memory pool */ + if (NULL == (mp = H5MP_create(MPOOL_PAGE_SIZE, MPOOL_FLAGS))) + TEST_ERROR + + /* Check free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != 0) + TEST_ERROR + + /* Check first page */ + if (H5MP_get_pool_first_page(mp, &page) < 0) + TEST_ERROR; + if(page != NULL) + TEST_ERROR + + /* Close the memory pool */ + if (H5MP_close(mp) < 0) + TEST_ERROR + + PASSED(); + + return 0; + +error: + H5E_BEGIN_TRY { + } H5E_END_TRY; + return 1; +} /* test_create() */ + + +/*------------------------------------------------------------------------- + * Function: test_close_one + * + * Purpose: Tests closing pool with one block allocated + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Friday, May 6, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_close_one(void) +{ + H5MP_pool_t *mp; /* Memory pool */ + void *spc1; /* Pointer to space allocated */ + + /* + * Test memory pool closing + */ + TESTING("closing pool with blocks still allocated in one page"); + + /* Create a memory pool */ + if (NULL == (mp = H5MP_create(MPOOL_PAGE_SIZE, MPOOL_FLAGS))) + TEST_ERROR + + /* Allocate space in pool */ + if (NULL == (spc1 = H5MP_malloc(mp, MPOOL_NORMAL_BLOCK))) + TEST_ERROR + + /* Close the memory pool */ + if (H5MP_close(mp) < 0) + TEST_ERROR + + PASSED(); + + return 0; + +error: + H5E_BEGIN_TRY { + } H5E_END_TRY; + return 1; +} /* test_close_one() */ + + +/*------------------------------------------------------------------------- + * Function: test_allocate_first + * + * Purpose: Tests allocating first block in pool + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, May 3, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_allocate_first(void) +{ + H5MP_pool_t *mp; /* Memory pool */ + H5MP_page_t *page; /* Memory pool page */ + size_t free_size; /* Free size in pool */ + void *spc; /* Pointer to space allocated */ + + /* + * Test memory pool allocation + */ + TESTING("allocating first block in pool"); + + /* Create a memory pool */ + if (NULL == (mp = H5MP_create(MPOOL_PAGE_SIZE, MPOOL_FLAGS))) + TEST_ERROR + + /* Allocate space in pool */ + if (NULL == (spc = H5MP_malloc(mp, MPOOL_NORMAL_BLOCK))) + TEST_ERROR + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != MPOOL_PAGE_SIZE - (H5MP_BLOCK_ALIGN(MPOOL_NORMAL_BLOCK) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)))) + TEST_ERROR + + /* Get first page */ + if (H5MP_get_pool_first_page(mp, &page) < 0) + TEST_ERROR; + if(page == NULL) + TEST_ERROR + + /* Check page's free space */ + if (H5MP_get_page_free_size(page, &free_size) < 0) + TEST_ERROR; + if(free_size != MPOOL_PAGE_SIZE - (H5MP_BLOCK_ALIGN(MPOOL_NORMAL_BLOCK) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Check next page */ + if (H5MP_get_page_next_page(page, &page) < 0) + TEST_ERROR; + if(page != NULL) + TEST_ERROR + + /* Free space in pool */ + H5MP_free(mp, spc); + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != MPOOL_PAGE_SIZE - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Close the memory pool */ + if (H5MP_close(mp) < 0) + TEST_ERROR + + PASSED(); + + TESTING("allocating large first block in pool"); + + /* Create a memory pool */ + if (NULL == (mp = H5MP_create(MPOOL_PAGE_SIZE, MPOOL_FLAGS))) + TEST_ERROR + + /* Allocate space in pool */ + if (NULL == (spc = H5MP_malloc(mp, MPOOL_LARGE_BLOCK))) + TEST_ERROR + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != 0) + TEST_ERROR + + /* Get first page */ + if (H5MP_get_pool_first_page(mp, &page) < 0) + TEST_ERROR; + if(page == NULL) + TEST_ERROR + + /* Check page's free space */ + if (H5MP_get_page_free_size(page, &free_size) < 0) + TEST_ERROR; + if(free_size != 0) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Check next page */ + if (H5MP_get_page_next_page(page, &page) < 0) + TEST_ERROR; + if(page != NULL) + TEST_ERROR + + /* Free space in pool */ + H5MP_free(mp, spc); + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != MPOOL_LARGE_BLOCK + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Close the memory pool */ + if (H5MP_close(mp) < 0) + TEST_ERROR + + PASSED(); + + return 0; + +error: + H5E_BEGIN_TRY { + } H5E_END_TRY; + return 1; +} /* test_allocate_first() */ + + +/*------------------------------------------------------------------------- + * Function: test_allocate_split + * + * Purpose: Tests allocating block in pool that requires splitting + * existing block + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, May 3, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_allocate_split(void) +{ + H5MP_pool_t *mp; /* Memory pool */ + size_t free_size; /* Free size in pool */ + void *spc1; /* Pointer to space allocated */ + void *spc2; /* Pointer to space allocated */ + + /* + * Test memory pool allocation + */ + TESTING("splitting block in pool"); + + /* Create a memory pool */ + if (NULL == (mp = H5MP_create(MPOOL_PAGE_SIZE, MPOOL_FLAGS))) + TEST_ERROR + + /* Allocate space in pool */ + if (NULL == (spc1 = H5MP_malloc(mp, MPOOL_NORMAL_BLOCK))) + TEST_ERROR + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != MPOOL_PAGE_SIZE - (H5MP_BLOCK_ALIGN(MPOOL_NORMAL_BLOCK) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Allocate more space in pool */ + if (NULL == (spc2 = H5MP_malloc(mp, MPOOL_NORMAL_BLOCK))) + TEST_ERROR + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != MPOOL_PAGE_SIZE - (((H5MP_BLOCK_ALIGN(MPOOL_NORMAL_BLOCK) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t))) * 2) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Free first block in pool */ + H5MP_free(mp, spc1); + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != MPOOL_PAGE_SIZE - (H5MP_BLOCK_ALIGN(MPOOL_NORMAL_BLOCK) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Free second block in pool (should merge with first block) */ + H5MP_free(mp, spc2); + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != MPOOL_PAGE_SIZE - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Close the memory pool */ + if (H5MP_close(mp) < 0) + TEST_ERROR + + PASSED(); + + return 0; + +error: + H5E_BEGIN_TRY { + } H5E_END_TRY; + return 1; +} /* test_allocate_split() */ + + +/*------------------------------------------------------------------------- + * Function: test_allocate_many_small + * + * Purpose: Tests allocating many small blocks in a pool + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, May 6, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_allocate_many_small(void) +{ + H5MP_pool_t *mp; /* Memory pool */ + size_t free_size; /* Free size in pool */ + void *spc[MPOOL_NUM_SMALL_BLOCKS]; /* Pointers to space allocated */ + int i; /* Local index variable */ + + /* + * Test memory pool allocation + */ + TESTING("allocating many small blocks"); + + /* Create a memory pool */ + if (NULL == (mp = H5MP_create(MPOOL_PAGE_SIZE, MPOOL_FLAGS))) + TEST_ERROR + + /* Allocate space in pool */ + for (i = 0; i < MPOOL_NUM_SMALL_BLOCKS; i++) + if (NULL == (spc[i] = H5MP_malloc(mp, MPOOL_SMALL_BLOCK))) + TEST_ERROR + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != MPOOL_PAGE_SIZE - (((H5MP_BLOCK_ALIGN(MPOOL_SMALL_BLOCK) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t))) * MPOOL_NUM_SMALL_BLOCKS) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Free blocks in pool */ + /* (Tests free block merging with block after it */ + for(i = (MPOOL_NUM_SMALL_BLOCKS - 1); i >= 0; i--) + H5MP_free(mp, spc[i]); + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != MPOOL_PAGE_SIZE - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Close the memory pool */ + if (H5MP_close(mp) < 0) + TEST_ERROR + + PASSED(); + + return 0; + +error: + H5E_BEGIN_TRY { + } H5E_END_TRY; + return 1; +} /* test_allocate_many_small() */ + + +/*------------------------------------------------------------------------- + * Function: test_allocate_new_page + * + * Purpose: Tests allocating block in pool that requires allocating + * new page + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Friday, May 6, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_allocate_new_page(void) +{ + H5MP_pool_t *mp; /* Memory pool */ + size_t free_size; /* Free size in pool */ + size_t u; /* Local index variable */ + void *spc[MPOOL_NUM_NORMAL_BLOCKS]; /* Pointer to space allocated */ + void *spc1; /* Pointer to space allocated */ + void *spc2; /* Pointer to space allocated */ + + /* + * Test memory pool allocation + */ + TESTING("allocate normal-sized block in new page"); + + /* Create a memory pool */ + if (NULL == (mp = H5MP_create(MPOOL_PAGE_SIZE, MPOOL_FLAGS))) + TEST_ERROR + + /* Allocate space in pool */ + for(u = 0; u < MPOOL_NUM_NORMAL_BLOCKS; u++) + if (NULL == (spc[u] = H5MP_malloc(mp, MPOOL_NORMAL_BLOCK))) + TEST_ERROR + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != (MPOOL_PAGE_SIZE * 3) - (((H5MP_BLOCK_ALIGN(MPOOL_NORMAL_BLOCK) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t))) * MPOOL_NUM_NORMAL_BLOCKS) + (H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)) * 3))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Free blocks in pool */ + /* (Free alternating blocks, in two passes, which tests block merging w/both neighbors) */ + for(u = 0; u < MPOOL_NUM_NORMAL_BLOCKS; u+=2) + H5MP_free(mp, spc[u]); + for(u = 1; u < MPOOL_NUM_NORMAL_BLOCKS; u+=2) + H5MP_free(mp, spc[u]); + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != ((MPOOL_PAGE_SIZE - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t))) * 3)) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Close the memory pool */ + if (H5MP_close(mp) < 0) + TEST_ERROR + + PASSED(); + + TESTING("allocate large-sized block in new page"); + + /* Create a memory pool */ + if (NULL == (mp = H5MP_create(MPOOL_PAGE_SIZE, MPOOL_FLAGS))) + TEST_ERROR + + /* Allocate space in pool */ + /* (Normal sized block) */ + if (NULL == (spc1 = H5MP_malloc(mp, MPOOL_NORMAL_BLOCK))) + TEST_ERROR + /* (Larger sized block) */ + if (NULL == (spc2 = H5MP_malloc(mp, MPOOL_LARGE_BLOCK))) + TEST_ERROR + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != MPOOL_PAGE_SIZE - (H5MP_BLOCK_ALIGN(MPOOL_NORMAL_BLOCK) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Free blocks in pool */ + H5MP_free(mp, spc1); + H5MP_free(mp, spc2); + + /* Check pool's free space */ + if (H5MP_get_pool_free_size(mp, &free_size) < 0) + TEST_ERROR; + if(free_size != ((MPOOL_PAGE_SIZE - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t))) + + MPOOL_LARGE_BLOCK + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Close the memory pool */ + if (H5MP_close(mp) < 0) + TEST_ERROR + + PASSED(); + + return 0; + +error: + H5E_BEGIN_TRY { + } H5E_END_TRY; + return 1; +} /* test_allocate_new_page() */ + + +/*------------------------------------------------------------------------- + * Function: test_allocate_random + * + * Purpose: Tests allocating random sized blocks in pool + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Friday, May 6, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_allocate_random(void) +{ + H5MP_pool_t *mp; /* Memory pool */ + size_t u; /* Local index variable */ + time_t curr_time; /* Current time, for seeding random number generator */ + size_t *blk_size = NULL; /* Pointer to block sizes */ + void **spc = NULL; /* Pointer to space allocated */ + size_t swap_idx; /* Location to swap with when shuffling */ + void *swap_ptr; /* Pointer to swap when shuffling */ + + /* + * Test memory pool allocation + */ + TESTING("allocate many random sized blocks"); + + /* Initialize random number seed */ + curr_time=HDtime(NULL); +#ifdef QAK +curr_time=1115412944; +HDfprintf(stderr,"curr_time=%lu\n",(unsigned long)curr_time); +#endif /* QAK */ + HDsrandom((unsigned long)curr_time); + + /* Create a memory pool */ + if (NULL == (mp = H5MP_create(MPOOL_PAGE_SIZE, MPOOL_FLAGS))) + TEST_ERROR + + /* Allocate space for the block sizes */ + if(NULL == (blk_size = HDmalloc(sizeof(size_t) * MPOOL_NUM_RANDOM))) + TEST_ERROR + + /* Allocate space for the block pointers */ + if(NULL == (spc = HDmalloc(sizeof(void *) * MPOOL_NUM_RANDOM))) + TEST_ERROR + + /* Initialize the block sizes with random values */ + for(u = 0; u < MPOOL_NUM_RANDOM; u++) + blk_size[u] = (size_t)(HDrandom() % MPOOL_RANDOM_MAX_SIZE) + 1; + + /* Allocate space in pool */ + for(u = 0; u < MPOOL_NUM_RANDOM; u++) + if (NULL == (spc[u] = H5MP_malloc(mp, blk_size[u]))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Shuffle pointers to free */ + for(u = 0; u < MPOOL_NUM_RANDOM; u++) { + swap_idx = (size_t)(HDrandom() % (MPOOL_NUM_RANDOM - u)) + u; + swap_ptr = spc[u]; + spc[u] = spc[swap_idx]; + spc[swap_idx] = swap_ptr; + } /* end for */ + + /* Free blocks in pool */ + for(u = 0; u < MPOOL_NUM_RANDOM; u++) + H5MP_free(mp, spc[u]); + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Initialize the block sizes with random values */ + for(u = 0; u < MPOOL_NUM_RANDOM; u++) + blk_size[u] = (size_t)(HDrandom() % MPOOL_RANDOM_MAX_SIZE) + 1; + + /* Allocate space in pool (again) */ + /* (Leave allocated to test closing pool with many blocks still allocated) */ + for(u = 0; u < MPOOL_NUM_RANDOM; u++) + if (NULL == (spc[u] = H5MP_malloc(mp, blk_size[u]))) + TEST_ERROR + + /* Check that free space totals match */ + if (H5MP_pool_is_free_size_correct(mp) <= 0) + TEST_ERROR; + + /* Close the memory pool */ + if (H5MP_close(mp) < 0) + TEST_ERROR + + /* Free memory for block sizes & pointers */ + HDfree(blk_size); + HDfree(spc); + + PASSED(); + + return 0; + +error: + if(blk_size) + HDfree(blk_size); + if(spc) + HDfree(spc); + H5E_BEGIN_TRY { + } H5E_END_TRY; + return 1; +} /* test_allocate_random() */ + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: Test the memory pool code + * + * Return: Success: + * + * Failure: + * + * Programmer: Quincey Koziol + * Tuesday, May 3, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +main(void) +{ + int nerrors=0; + + /* Reset library */ + h5_reset(); + + /* Test memory pool creation */ + nerrors += test_create(); + + /* Test memory pool space closing */ + nerrors += test_close_one(); + + /* Test memory pool space allocation */ + nerrors += test_allocate_first(); + nerrors += test_allocate_split(); + nerrors += test_allocate_many_small(); + nerrors += test_allocate_new_page(); + nerrors += test_allocate_random(); + + if (nerrors) goto error; + puts("All memory pool tests passed."); + return 0; + +error: + puts("*** TESTS FAILED ***"); + H5E_BEGIN_TRY { + } H5E_END_TRY; + return 1; +} + |