alignment fixing for USE_SIMD - all memory allocations are rounded

up to 16-byte boundaries.  This fixes crashes where the sub-buffers
for complex FFTs end up unaligned violating compiler expectations
This commit is contained in:
Ben Supnik 2020-04-18 20:43:26 -04:00
parent 33d9ad3bad
commit 58cf0c0fc1
5 changed files with 41 additions and 22 deletions

View File

@ -332,9 +332,11 @@ void kf_factor(int n,int * facbuf)
* */ * */
kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem ) kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem )
{ {
KISS_FFT_ALIGN_CHECK(mem)
kiss_fft_cfg st=NULL; kiss_fft_cfg st=NULL;
size_t memneeded = sizeof(struct kiss_fft_state) size_t memneeded = KISS_FFT_ALIGN_SIZE_UP(sizeof(struct kiss_fft_state)
+ sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/ + sizeof(kiss_fft_cpx)*(nfft-1)); /* twiddle factors*/
if ( lenmem==NULL ) { if ( lenmem==NULL ) {
st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded ); st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded );

View File

@ -37,11 +37,15 @@ extern "C" {
# define kiss_fft_scalar __m128 # define kiss_fft_scalar __m128
# ifndef KISS_FFT_MALLOC # ifndef KISS_FFT_MALLOC
# define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16) # define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16)
# define KISS_FFT_ALIGN_CHECK(ptr) assert((((uintptr_t) ptr) & 0xF) == 0);
# define KISS_FFT_ALIGN_SIZE_UP(size) ((size + 15UL) & ~0xFUL)
# endif # endif
# ifndef KISS_FFT_FREE # ifndef KISS_FFT_FREE
# define KISS_FFT_FREE _mm_free # define KISS_FFT_FREE _mm_free
# endif # endif
#else #else
# define KISS_FFT_ALIGN_CHECK(ptr)
# define KISS_FFT_ALIGN_SIZE_UP(size) (size)
# ifndef KISS_FFT_MALLOC # ifndef KISS_FFT_MALLOC
# define KISS_FFT_MALLOC malloc # define KISS_FFT_MALLOC malloc
# endif # endif

View File

@ -19,11 +19,13 @@ struct kiss_fftnd_state{
kiss_fftnd_cfg kiss_fftnd_alloc(const int *dims,int ndims,int inverse_fft,void*mem,size_t*lenmem) kiss_fftnd_cfg kiss_fftnd_alloc(const int *dims,int ndims,int inverse_fft,void*mem,size_t*lenmem)
{ {
KISS_FFT_ALIGN_CHECK(mem)
kiss_fftnd_cfg st = NULL; kiss_fftnd_cfg st = NULL;
int i; int i;
int dimprod=1; int dimprod=1;
size_t memneeded = sizeof(struct kiss_fftnd_state); size_t memneeded = KISS_FFT_ALIGN_SIZE_UP(sizeof(struct kiss_fftnd_state));
char * ptr; char * ptr = NULL;
for (i=0;i<ndims;++i) { for (i=0;i<ndims;++i) {
size_t sublen=0; size_t sublen=0;
@ -31,32 +33,33 @@ kiss_fftnd_cfg kiss_fftnd_alloc(const int *dims,int ndims,int inverse_fft,void*m
memneeded += sublen; /* st->states[i] */ memneeded += sublen; /* st->states[i] */
dimprod *= dims[i]; dimprod *= dims[i];
} }
memneeded += sizeof(int) * ndims;/* st->dims */ memneeded += KISS_FFT_ALIGN_SIZE_UP(sizeof(int) * ndims);/* st->dims */
memneeded += sizeof(void*) * ndims;/* st->states */ memneeded += KISS_FFT_ALIGN_SIZE_UP(sizeof(void*) * ndims);/* st->states */
memneeded += sizeof(kiss_fft_cpx) * dimprod; /* st->tmpbuf */ memneeded += KISS_FFT_ALIGN_SIZE_UP(sizeof(kiss_fft_cpx) * dimprod); /* st->tmpbuf */
if (lenmem == NULL) {/* allocate for the caller*/ if (lenmem == NULL) {/* allocate for the caller*/
st = (kiss_fftnd_cfg) malloc (memneeded); ptr = (char *) malloc (memneeded);
} else { /* initialize supplied buffer if big enough */ } else { /* initialize supplied buffer if big enough */
if (*lenmem >= memneeded) if (*lenmem >= memneeded)
st = (kiss_fftnd_cfg) mem; ptr = (char *) mem;
*lenmem = memneeded; /*tell caller how big struct is (or would be) */ *lenmem = memneeded; /*tell caller how big struct is (or would be) */
} }
if (!st) if (!ptr)
return NULL; /*malloc failed or buffer too small */ return NULL; /*malloc failed or buffer too small */
st = (kiss_fftnd_cfg) ptr;
st->dimprod = dimprod; st->dimprod = dimprod;
st->ndims = ndims; st->ndims = ndims;
ptr=(char*)(st+1); ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(struct kiss_fftnd_state));
st->states = (kiss_fft_cfg *)ptr; st->states = (kiss_fft_cfg *)ptr;
ptr += sizeof(void*) * ndims; ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(void*) * ndims);
st->dims = (int*)ptr; st->dims = (int*)ptr;
ptr += sizeof(int) * ndims; ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(int) * ndims);
st->tmpbuf = (kiss_fft_cpx*)ptr; st->tmpbuf = (kiss_fft_cpx*)ptr;
ptr += sizeof(kiss_fft_cpx) * dimprod; ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(kiss_fft_cpx) * dimprod);
for (i=0;i<ndims;++i) { for (i=0;i<ndims;++i) {
size_t len; size_t len;

View File

@ -29,36 +29,44 @@ static int prod(const int *dims, int ndims)
kiss_fftndr_cfg kiss_fftndr_alloc(const int *dims,int ndims,int inverse_fft,void*mem,size_t*lenmem) kiss_fftndr_cfg kiss_fftndr_alloc(const int *dims,int ndims,int inverse_fft,void*mem,size_t*lenmem)
{ {
KISS_FFT_ALIGN_CHECK(mem)
kiss_fftndr_cfg st = NULL; kiss_fftndr_cfg st = NULL;
size_t nr=0 , nd=0,ntmp=0; size_t nr=0 , nd=0,ntmp=0;
int dimReal = dims[ndims-1]; int dimReal = dims[ndims-1];
int dimOther = prod(dims,ndims-1); int dimOther = prod(dims,ndims-1);
size_t memneeded; size_t memneeded;
char * ptr = NULL;
(void)kiss_fftr_alloc(dimReal,inverse_fft,NULL,&nr); (void)kiss_fftr_alloc(dimReal,inverse_fft,NULL,&nr);
(void)kiss_fftnd_alloc(dims,ndims-1,inverse_fft,NULL,&nd); (void)kiss_fftnd_alloc(dims,ndims-1,inverse_fft,NULL,&nd);
ntmp = ntmp =
MAX( 2*dimOther , dimReal+2) * sizeof(kiss_fft_scalar) // freq buffer for one pass MAX( 2*dimOther , dimReal+2) * sizeof(kiss_fft_scalar) // freq buffer for one pass
+ dimOther*(dimReal+2) * sizeof(kiss_fft_scalar); // large enough to hold entire input in case of in-place + dimOther*(dimReal+2) * sizeof(kiss_fft_scalar); // large enough to hold entire input in case of in-place
memneeded = sizeof( struct kiss_fftndr_state ) + nr + nd + ntmp; memneeded = KISS_FFT_ALIGN_SIZE_UP(sizeof( struct kiss_fftndr_state )) + KISS_FFT_ALIGN_SIZE_UP(nr) + KISS_FFT_ALIGN_SIZE_UP(nd) + KISS_FFT_ALIGN_SIZE_UP(ntmp);
if (lenmem==NULL) { if (lenmem==NULL) {
st = (kiss_fftndr_cfg) malloc(memneeded); ptr = (char*) malloc(memneeded);
}else{ }else{
if (*lenmem >= memneeded) if (*lenmem >= memneeded)
st = (kiss_fftndr_cfg)mem; ptr = (char *)mem;
*lenmem = memneeded; *lenmem = memneeded;
} }
if (st==NULL) if (ptr==NULL)
return NULL; return NULL;
st = (kiss_fftndr_cfg) ptr;
memset( st , 0 , memneeded); memset( st , 0 , memneeded);
ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(struct kiss_fftndr_state));
st->dimReal = dimReal; st->dimReal = dimReal;
st->dimOther = dimOther; st->dimOther = dimOther;
st->cfg_r = kiss_fftr_alloc( dimReal,inverse_fft,st+1,&nr); st->cfg_r = kiss_fftr_alloc( dimReal,inverse_fft,ptr,&nr);
st->cfg_nd = kiss_fftnd_alloc(dims,ndims-1,inverse_fft, ((char*) st->cfg_r)+nr,&nd); ptr += KISS_FFT_ALIGN_SIZE_UP(nr);
st->tmpbuf = (char*)st->cfg_nd + nd; st->cfg_nd = kiss_fftnd_alloc(dims,ndims-1,inverse_fft, ptr,&nd);
ptr += KISS_FFT_ALIGN_SIZE_UP(nd);
st->tmpbuf = ptr;
return st; return st;
} }

View File

@ -20,6 +20,8 @@ struct kiss_fftr_state{
kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem) kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
{ {
KISS_FFT_ALIGN_CHECK(mem)
int i; int i;
kiss_fftr_cfg st = NULL; kiss_fftr_cfg st = NULL;
size_t subsize = 0, memneeded; size_t subsize = 0, memneeded;