Skip to content

Commit

Permalink
volk: adding volk_malloc and volk_free functions to handle allocation…
Browse files Browse the repository at this point in the history
… of aligned memory.
  • Loading branch information
trondeau committed Jan 16, 2014
1 parent 07ed547 commit 6b19c5d
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 0 deletions.
1 change: 1 addition & 0 deletions volk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ install(FILES
${CMAKE_BINARY_DIR}/include/volk/volk_cpu.h
${CMAKE_BINARY_DIR}/include/volk/volk_config_fixed.h
${CMAKE_BINARY_DIR}/include/volk/volk_typedefs.h
${CMAKE_SOURCE_DIR}/include/volk/volk_malloc.h
DESTINATION include/volk
COMPONENT "volk_devel"
)
Expand Down
66 changes: 66 additions & 0 deletions volk/include/volk/volk_malloc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* -*- c -*- */
/*
* Copyright 2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio 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.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/

#ifndef INCLUDED_VOLK_MALLOC_H
#define INCLUDED_VOLK_MALLOC_H

#include <volk/volk_common.h>
#include <stdlib.h>

__VOLK_DECL_BEGIN

/*!
* \brief Allocate \p size bytes of data aligned to \p alignment.
*
* \details
* Because we don't have a standard method to allocate buffers in
* memory that are guaranteed to be on an alignment, VOLK handles this
* itself. The volk_malloc function behaves like malloc in that it
* returns a pointer to the allocated memory. However, it also takes
* in an alignment specfication, which is usually something like 16 or
* 32 to ensure that the aligned memory is located on a particular
* byte boundary for use with SIMD.
*
* Internally, the volk_malloc first checks if the compiler is C11
* compliant and uses the new aligned_alloc method. If not, it checks
* if the system is POSIX compliant and uses posix_memalign. If that
* fails, volk_malloc handles the memory allocation and alignment
* internally.
*
* Because of the ways in which volk_malloc may allocate memory, it is
* important to always free volk_malloc pointers using volk_free.
*
* \param size The number of bytes to allocate.
* \param alignment The byte alignment of the allocated memory.
* \return pointer to aligned memory.
*/
VOLK_API void *volk_malloc(size_t size, size_t alignment);

/*!
* \brief Free's memory allocated by volk_malloc.
* \param aptr The aligned pointer allocaed by volk_malloc.
*/
VOLK_API void volk_free(void *aptr);

__VOLK_DECL_END

#endif /* INCLUDED_VOLK_MALLOC_H */
1 change: 1 addition & 0 deletions volk/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ endif()
list(APPEND volk_sources
${CMAKE_CURRENT_SOURCE_DIR}/volk_prefs.c
${CMAKE_CURRENT_SOURCE_DIR}/volk_rank_archs.c
${CMAKE_CURRENT_SOURCE_DIR}/volk_malloc.c
${volk_gen_sources}
)

Expand Down
176 changes: 176 additions & 0 deletions volk/lib/volk_malloc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/* -*- c -*- */
/*
* Copyright 2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio 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.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/

#include <volk/volk_malloc.h>
#include <stdio.h>
#include <stdlib.h>

/*
* For #defines used to determine support for allocation functions,
* see: http://linux.die.net/man/3/aligned_alloc
*/

// Disabling use of aligned_alloc. This function requires that size be
// a multiple of alignment, which is too restrictive for many uses of
// VOLK.

//// If we are using C11 standard, use the aligned_alloc
//#ifdef _ISOC11_SOURCE
//
//void *volk_malloc(size_t size, size_t alignment)
//{
// void *ptr = aligned_alloc(alignment, size);
// if(ptr == NULL) {
// fprintf(stderr, "VOLK: Error allocating memory (aligned_alloc)\n");
// }
// return ptr;
//}
//
//void volk_free(void *ptr)
//{
// free(ptr);
//}
//
//#else // _ISOC11_SOURCE

// Otherwise, test if we are a POSIX or X/Open system
// This only has a restriction that alignment be a power of 2.
#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600

void *volk_malloc(size_t size, size_t alignment)
{
void *ptr;
int err = posix_memalign(&ptr, alignment, size);
if(err == 0) {
return ptr;
}
else {
fprintf(stderr, "VOLK: Error allocating memory (posix_memalign: %d)\n", err);
return NULL;
}
}

void volk_free(void *ptr)
{
free(ptr);
}

// No standard handlers; we'll do it ourselves.
#else // _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600

typedef struct mbuf_t {
void *orig;
void *align;
struct mbuf_t *next;
} mbuf;

/*
Keep track of the pointers we've allocated. We hold a linked list
from volk_first_ptr to volk_last_ptr and the number of allocated
pointers. When allocating a new pointer, we create the pointer with
malloc, find how it is misaligned, and create a new pointer at the
alignment boundary. Both of these are stored in the linked list data
structure. When free, we are passed the aligned pointer and use that
to look up the original pointer, which we use to actually free the
entire allocated memory.
*/
unsigned int volk_nptrs = 0;
mbuf* volk_first_ptr = NULL;
mbuf* volk_last_ptr = NULL;

void*
volk_malloc(size_t size, size_t alignment)
{
// Allocate memory plus enough extra to adjust alignment
void *ptr = malloc(size + (alignment - 1));
if(ptr == NULL) {
free(ptr);
fprintf(stderr, "VOLK: Error allocating memory (malloc)\n");
return NULL;
}

// Find and return the first aligned boundary of the pointer
void *aptr = ptr;
if((unsigned long)ptr % alignment != 0)
aptr = ptr + (alignment - ((unsigned long)ptr % alignment));

// Store original pointer and aligned pointers
mbuf *n = (mbuf*)malloc(sizeof(mbuf));
n->orig = ptr;
n->align = aptr;
n->next = NULL;
if(volk_first_ptr == NULL) {
volk_first_ptr = n;
}
else {
volk_last_ptr->next = n;
}
volk_last_ptr = n;
volk_nptrs++;

return aptr;
}

void volk_free(void *ptr)
{
unsigned long aptr = (unsigned long)ptr;
mbuf *prev = volk_first_ptr;
mbuf *p = volk_first_ptr;

// Look for the aligned pointer until we either find it or have
// walked the entire list of allocated pointers
while(p != NULL) {
if((unsigned long)(p->align) == aptr) {
// If the memory is found at the first pointer, move this
// pointer to the next in the list
if(p == volk_first_ptr) {
if(volk_first_ptr == volk_last_ptr)
volk_last_ptr = NULL;
volk_first_ptr = p->next;
}
// Otherwise, link the previous to the following to skip the
// struct we're deleting.
else {
if(p == volk_last_ptr)
volk_last_ptr = prev;
prev->next = p->next;
}

// Free the original pointer to remove all memory allocated
free((void*)p->orig);
volk_nptrs--;

// Free the struct to clean up all memory and exit
free(p);

return;
}
// Not found, update our pointers to look at the next in the list
prev = p;
p = p->next;
}
fprintf(stderr, "VOLK: tried to free a non-VOLK pointer\n");
}

#endif // _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600

//#endif // _ISOC11_SOURCE
1 change: 1 addition & 0 deletions volk/tmpl/volk.tmpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <volk/volk_config_fixed.h>
#include <volk/volk_common.h>
#include <volk/volk_complex.h>
#include <volk/volk_malloc.h>

#include <stdlib.h>
#include <stdbool.h>
Expand Down

0 comments on commit 6b19c5d

Please sign in to comment.