Friday, April 14, 2017

Alignment strikes back

Previous post was about alignment problems in Smallapack matrix inversion. Let us look at another one that crippled the jpeg plugin for 64 bits windows flavour of opensmalltalk Virtual Machine (issue 119).

The problem originate at win64 requirement for jmp_buf type used in setjmp/longjmp: it must be 16-bytes aligned. I couldn't find a reference to this requirement, but there is a definition in some header that ensure such alignment. Appropriate cygwin grep in /usr/x86_64-w64-mingw32/sys-root/mingw/include will reveal:

setjmp.h:  typedef _JBTYPE jmp_buf[_JBLEN];
setjmp.h:  typedef SETJMP_FLOAT128 _JBTYPE;
setjmp.h:  typedef _CRT_ALIGN(16) struct _SETJMP_FLOAT128 {

With such definitions, the C compiler will manage to properly align the data, so we don't have to worry... Or do we?

We use setjmp/longjmp for the purpose of error handling (and properly quiting the primitive). But we had the brilliant idea to put such jmp_buf member in a structure (see JPEGReadWriter2Plugin/Error.c).

The layout of the structure cannot vary for each instance, so if we want one member to be aligned on 16bytes boundary, the sole solution is to align the whole structure itself to 16bytes boundary, and fill enough gaps between members. Alas, both gcc and clang fail to do so. I don't know if I should report a bug for that.

Imposing that requirement to our own structure, in a portable and future-proof way is less than obvious. So the workaround was rather to use a pointer on a jmp_buf - see pull request #120.

This kind of bug is pretty tricky, but if you have to implement some VM parts in C, what do you expect?

No comments:

Post a Comment