1

I'm doing some cell broadband engine programming, and I've come across a strange thing I can't explain, while investigating a segmentation fault, based on the following code:

struct SPU_DATA
{
    unsigned char *i;
    unsigned char *o;
    unsigned int width;
    unsigned int height;
    unsigned int bpp;
    char padding[108];
} __attribute__((aligned(128)));

When I output the size of this struct to the console on the ppu, the value 256 is output. However, when I output the size on an spu, it comes out as 128, which is what's expected.

I can't find a reason for this. Any ideas?

Ian Young
  • 1,712
  • 1
  • 16
  • 33
  • 2
    Perhaps ints and pointers are 64 bit on the ppu? – Kenney Dec 03 '15 at 22:15
  • An interesting point, which I hadn't considered – Ian Young Dec 03 '15 at 22:16
  • 1
    It could also be 1013 bytes or any other value. There is no guarantee types other than `char` have a specific size or there is no padding. If you rely on a specific layout, (de)serialise from/to a `char []`. Anything else is recipe for undefined behaviour. And `char` is not necessarily 8 bits either. – too honest for this site Dec 03 '15 at 22:18
  • 1
    @IanYoung That's most likely the case. If sizeof(int) is 8 then it can't fit with 128 bytes. So it would align with another 128 bytes. – P.P Dec 03 '15 at 22:20
  • ints are the same size, but a pointer is 8 bytes, which is pushing it over the 128 Byte alignment. – Ian Young Dec 03 '15 at 22:32
  • 1
    @Olaf Usually the implementation does guarantee such things, even though the language does not. – user253751 Dec 03 '15 at 22:32
  • @immibis: You are wrong. While it is right due to the alignment, `1013` is really not possible, any multple of 128 actually is. Anyway, relying on a specific layout of a struct is bad practice. You forget it is not just the layout, but also endianes and representation. All that may be avoided with correct serialisation or - except for endianess - a packed `struct` and fixed-width types from `stdint.h`. There are more architectures than just x86/64 – too honest for this site Dec 03 '15 at 23:01
  • 1
    @Olaf I'm wrong that implementations usually define struct layout? – user253751 Dec 03 '15 at 23:24
  • @immibis: It normally is defined by the PCS/ABI of the target platform. An implementation just does conform to this. But I actually understood your comment such that an implementation does guarantee there is e.g. no padding. Sorry if I missunderstood you. – too honest for this site Dec 03 '15 at 23:41

1 Answers1

1

After some additional reading I discovered the following: the ppu-g++ compiler seems to default to 64 bit, which means that pointer values will occupy 8 bytes in memory. This can lead to inconsistancies in data values send to the SPU program for DMA transfer.

To prevent such problems, instead of storing a pointer in the struct, you should store an unsigned long long, which contains the value of the pointer, like so:

struct SPU_DATA
{
    unsigned long long i;
    unsigned long long o;
    unsigned int width;
    unsigned int height;
    unsigned int bpp;
    char padding[108];
} __attribute__((aligned(128)));

In this way the pointer value will not be truncated, and the correct effective address of data sent to the SPU program will be correct, preventing further problems in the case of 64bit PPU programs running 32bit SPU programs.

Ian Young
  • 1,712
  • 1
  • 16
  • 33