Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC - How to realign stack?

I try to build an application which uses pthreads and __m128 SSE type. According to GCC manual, default stack alignment is 16 bytes. In order to use __m128, the requirement is the 16-byte alignment.

My target CPU supports SSE. I use a GCC compiler which doesn't support runtime stack realignment (e.g. -mstackrealign). I cannot use any other GCC compiler version.

My test application looks like:

#include <xmmintrin.h>
#include <pthread.h>
void *f(void *x){
   __m128 y;
   ...
}
int main(void){
  pthread_t p;
  pthread_create(&p, NULL, f, NULL);
}

The application generates an exception and exits. After a simple debugging (printf "%p", &y), I found that the variable y is not 16-byte aligned.

My question is: how can I realign the stack properly (16-byte) without using any GCC flags and attributes (they don't help)? Should I use GCC inline Assembler within this thread function f()?

like image 611
psihodelia Avatar asked May 04 '10 12:05

psihodelia


2 Answers

Allocate on the stack an array that is 15-bytes larger than sizeof(__m128), and use the first aligned address in that array. If you need several, allocate them in an array with a single 15-byte margin for alignment.

I do not remember if allocating an unsigned char array makes you safe from strict aliasing optimizations by the compiler or if it only works only the other way round.

#include <stdint.h>

void *f(void *x)
{
   unsigned char y[sizeof(__m128)+15];
   __m128 *py = (__m128*) (((uintptr_t)&y) + 15) & ~(uintptr_t)15);
   ...
}
like image 114
Pascal Cuoq Avatar answered Sep 20 '22 00:09

Pascal Cuoq


This shouldn't be happening in the first place, but to work around the problem you can try:

void *f(void *x)
{
   __m128 y __attribute__ ((aligned (16)));
   ...
}
like image 44
Paul R Avatar answered Sep 20 '22 00:09

Paul R