/******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2007, 2008 Gregory Bard * Copyright (C) 2008 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mmc.h" #ifdef __M4RI_ENABLE_MMC /** * The actual memory block cache. */ mmb_t m4ri_mmc_cache[__M4RI_MMC_NBLOCKS]; #endif // __M4RI_ENABLE_MMC /** * \brief Allocate size bytes. * * \param size Number of bytes. * * \return pointer to allocated memory block. */ void *m4ri_mmc_malloc(size_t size) { #ifdef __M4RI_ENABLE_MMC void *ret = NULL; #if __M4RI_HAVE_OPENMP #pragma omp critical (mmc) { #endif mmb_t *mm = m4ri_mmc_cache; if (size <= __M4RI_MMC_THRESHOLD) { for (int i = 0; i < __M4RI_MMC_NBLOCKS; ++i) { if(mm[i].size == size) { ret = mm[i].data; mm[i].data = NULL; mm[i].size = 0; break; } } } #if __M4RI_HAVE_OPENMP } #endif if (ret) return ret; else return m4ri_mm_malloc(size); #else // __M4RI_ENABLE_MMC return m4ri_mm_malloc(size); #endif // __M4RI_ENABLE_MMC } /** * \brief Free the data pointed to by condemned of the given size. * * \param condemned Pointer to memory. * \param size Number of bytes. */ void m4ri_mmc_free(void *condemned, size_t size) { #ifdef __M4RI_ENABLE_MMC #if __M4RI_HAVE_OPENMP #pragma omp critical (mmc) { #endif static int j = 0; mmb_t *mm = m4ri_mmc_cache; if (size < __M4RI_MMC_THRESHOLD) { for(int i = 0; i < __M4RI_MMC_NBLOCKS; ++i) { if(mm[i].size == 0) { mm[i].size = size; mm[i].data = condemned; goto done; } } m4ri_mm_free(mm[j].data); mm[j].size = size; mm[j].data = condemned; j = (j+1) % __M4RI_MMC_NBLOCKS; } else { m4ri_mm_free(condemned); } done: ; #if __M4RI_HAVE_OPENMP } #endif // __M4RI_HAVE_OPENMP #else // __M4RI_ENABLE_MMC m4ri_mm_free(condemned); #endif // __M4RI_ENABLE_MMC } /** * \brief Cleans up memory block cache. * * This function is called automatically when the shared library is unloaded. * * \warning Not thread safe. */ void m4ri_mmc_cleanup(void) { #ifdef __M4RI_ENABLE_MMC #if __M4RI_HAVE_OPENMP #pragma omp critical (mmc) { #endif mmb_t *mm = m4ri_mmc_cache; for(int i = 0; i < __M4RI_MMC_NBLOCKS; ++i) { if (mm[i].size) m4ri_mm_free(mm[i].data); mm[i].size = 0; } #if __M4RI_HAVE_OPENMP } #endif // __M4RI_HAVE_OPENMP #endif // __M4RI_ENABLE_MMC }