From 58cf0c0fc108d7252e418808cc505b8ca91304b2 Mon Sep 17 00:00:00 2001 From: Ben Supnik Date: Sat, 18 Apr 2020 20:43:26 -0400 Subject: [PATCH] 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 --- kiss_fft.c | 6 ++++-- kiss_fft.h | 4 ++++ tools/kiss_fftnd.c | 27 +++++++++++++++------------ tools/kiss_fftndr.c | 24 ++++++++++++++++-------- tools/kiss_fftr.c | 2 ++ 5 files changed, 41 insertions(+), 22 deletions(-) diff --git a/kiss_fft.c b/kiss_fft.c index 5614838..9548c4f 100644 --- a/kiss_fft.c +++ b/kiss_fft.c @@ -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_ALIGN_CHECK(mem) + kiss_fft_cfg st=NULL; - size_t memneeded = sizeof(struct kiss_fft_state) - + sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/ + size_t memneeded = KISS_FFT_ALIGN_SIZE_UP(sizeof(struct kiss_fft_state) + + sizeof(kiss_fft_cpx)*(nfft-1)); /* twiddle factors*/ if ( lenmem==NULL ) { st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded ); diff --git a/kiss_fft.h b/kiss_fft.h index ed6e24a..305b015 100644 --- a/kiss_fft.h +++ b/kiss_fft.h @@ -37,11 +37,15 @@ extern "C" { # define kiss_fft_scalar __m128 # ifndef KISS_FFT_MALLOC # 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 # ifndef KISS_FFT_FREE # define KISS_FFT_FREE _mm_free # endif #else +# define KISS_FFT_ALIGN_CHECK(ptr) +# define KISS_FFT_ALIGN_SIZE_UP(size) (size) # ifndef KISS_FFT_MALLOC # define KISS_FFT_MALLOC malloc # endif diff --git a/tools/kiss_fftnd.c b/tools/kiss_fftnd.c index cf38f86..1376493 100644 --- a/tools/kiss_fftnd.c +++ b/tools/kiss_fftnd.c @@ -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_FFT_ALIGN_CHECK(mem) + kiss_fftnd_cfg st = NULL; int i; int dimprod=1; - size_t memneeded = sizeof(struct kiss_fftnd_state); - char * ptr; + size_t memneeded = KISS_FFT_ALIGN_SIZE_UP(sizeof(struct kiss_fftnd_state)); + char * ptr = NULL; for (i=0;istates[i] */ dimprod *= dims[i]; } - memneeded += sizeof(int) * ndims;/* st->dims */ - memneeded += sizeof(void*) * ndims;/* st->states */ - memneeded += sizeof(kiss_fft_cpx) * dimprod; /* st->tmpbuf */ + memneeded += KISS_FFT_ALIGN_SIZE_UP(sizeof(int) * ndims);/* st->dims */ + memneeded += KISS_FFT_ALIGN_SIZE_UP(sizeof(void*) * ndims);/* st->states */ + memneeded += KISS_FFT_ALIGN_SIZE_UP(sizeof(kiss_fft_cpx) * dimprod); /* st->tmpbuf */ if (lenmem == NULL) {/* allocate for the caller*/ - st = (kiss_fftnd_cfg) malloc (memneeded); + ptr = (char *) malloc (memneeded); } else { /* initialize supplied buffer if big enough */ if (*lenmem >= memneeded) - st = (kiss_fftnd_cfg) mem; + ptr = (char *) mem; *lenmem = memneeded; /*tell caller how big struct is (or would be) */ } - if (!st) + if (!ptr) return NULL; /*malloc failed or buffer too small */ + st = (kiss_fftnd_cfg) ptr; st->dimprod = dimprod; st->ndims = ndims; - ptr=(char*)(st+1); + ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(struct kiss_fftnd_state)); st->states = (kiss_fft_cfg *)ptr; - ptr += sizeof(void*) * ndims; + ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(void*) * ndims); st->dims = (int*)ptr; - ptr += sizeof(int) * ndims; + ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(int) * ndims); 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= memneeded) - st = (kiss_fftndr_cfg)mem; + ptr = (char *)mem; *lenmem = memneeded; } - if (st==NULL) + if (ptr==NULL) return NULL; + + st = (kiss_fftndr_cfg) ptr; memset( st , 0 , memneeded); + ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(struct kiss_fftndr_state)); st->dimReal = dimReal; st->dimOther = dimOther; - st->cfg_r = kiss_fftr_alloc( dimReal,inverse_fft,st+1,&nr); - st->cfg_nd = kiss_fftnd_alloc(dims,ndims-1,inverse_fft, ((char*) st->cfg_r)+nr,&nd); - st->tmpbuf = (char*)st->cfg_nd + nd; + st->cfg_r = kiss_fftr_alloc( dimReal,inverse_fft,ptr,&nr); + ptr += KISS_FFT_ALIGN_SIZE_UP(nr); + 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; } diff --git a/tools/kiss_fftr.c b/tools/kiss_fftr.c index 8102132..5d74425 100644 --- a/tools/kiss_fftr.c +++ b/tools/kiss_fftr.c @@ -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_FFT_ALIGN_CHECK(mem) + int i; kiss_fftr_cfg st = NULL; size_t subsize = 0, memneeded;