Unix Programming - Worried About Alignment

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > March 2005 > Worried About Alignment





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Worried About Alignment
Michael B Allen

2005-03-22, 2:51 am

I wrote a memory allocator that aligns everything using the following
macros:

#define ALIGNMASK 1U
#define ALIGN(s) (((s) + ALIGNMASK) & ~ALIGNMASK)

This works fine on Intel but it chokes on alpha Tru64. So I changed
ALIGNMASK to:

#define ALIGNMASK ((unsigned long)7)

And voila it works fine. But this is all a little unsettling and have
a few questions.

1) In general what do I need to watch out for when working on a system
that requires this kind of alignment? Will the following code work? I
guess in this case it will only because the offset of bar within foo
will be aligned but are there cases that I should look out for?

struct bar {
char j;
};
struct foo {
char i;
struct bar;
};

struct foo foos[10];
struct bar *b = &foo[1].bar;
printf("%d\n", b->j);

Is there a macro that provides a suitable alignment value for a given
architecture so that I do not have to modify my ALIGNMASK or make it
some unnecessarily large value?

Otherwise, I forget what the suffixes for integers like 'U' are. I
believe 'U' stands for unsigned int. What about 'unsigned long'? What
is the proper suffix for a value that supports the same number of bits
as a pointer?

Finally IIRC size_t is supposed to be as large as the largest addressible
memory location. Can it therefore be used to compute a pointer using
size_t base address and relative values on a system like alpha Tru64?

Thanks,
Mike
Andrei Voropaev

2005-03-22, 7:52 am

On 2005-03-22, Michael B Allen <mba2000@ioplex.com> wrote:
> I wrote a memory allocator that aligns everything using the following
> macros:
>
> #define ALIGNMASK 1U
> #define ALIGN(s) (((s) + ALIGNMASK) & ~ALIGNMASK)
>
> This works fine on Intel but it chokes on alpha Tru64. So I changed
> ALIGNMASK to:
>
> #define ALIGNMASK ((unsigned long)7)
>
> And voila it works fine. But this is all a little unsettling and have
> a few questions.
>
> 1) In general what do I need to watch out for when working on a system
> that requires this kind of alignment? Will the following code work? I
> guess in this case it will only because the offset of bar within foo
> will be aligned but are there cases that I should look out for?
>
> struct bar {
> char j;
> };
> struct foo {
> char i;
> struct bar;
> };
>
> struct foo foos[10];
> struct bar *b = &foo[1].bar;
> printf("%d\n", b->j);


This code shall work perfectly because compiler will make the structures
to be the "aligned" size. Print out the sizeof(struct foo) or
sizeof(struct bar).

--
Minds, like parachutes, function best when open
Måns Rullgård

2005-03-22, 7:52 am

Michael B Allen <mba2000@ioplex.com> writes:

> I wrote a memory allocator that aligns everything using the following
> macros:
>
> #define ALIGNMASK 1U
> #define ALIGN(s) (((s) + ALIGNMASK) & ~ALIGNMASK)
>
> This works fine on Intel but it chokes on alpha Tru64. So I changed
> ALIGNMASK to:
>
> #define ALIGNMASK ((unsigned long)7)
>
> And voila it works fine. But this is all a little unsettling and have
> a few questions.
>
> 1) In general what do I need to watch out for when working on a system
> that requires this kind of alignment?


The dangerous thing is casting between different pointer types. The
compiler will ensure proper alignment when it knows the correct types,
but if an arbitrary point is cast into, for instance, a long *, all
bets are off.

> Will the following code work? I guess in this case it will only
> because the offset of bar within foo will be aligned but are there
> cases that I should look out for?
>
> struct bar {
> char j;
> };
> struct foo {
> char i;
> struct bar;
> };
>
> struct foo foos[10];
> struct bar *b = &foo[1].bar;
> printf("%d\n", b->j);


I only see 'char' types here, so there can be no problem. Maybe you
meant 'int j' in the struct bar. In this case, the compiler would add
proper padding in struct foo.

> Is there a macro that provides a suitable alignment value for a given
> architecture so that I do not have to modify my ALIGNMASK or make it
> some unnecessarily large value?


There's none that I know of. The size of the largest of the data
types (int, long, double, etc.) is usually sufficient. I've never
come across a case where an alignment larger than 8 was required (and
I've used Alpha a bit).

> Otherwise, I forget what the suffixes for integers like 'U' are. I
> believe 'U' stands for unsigned int. What about 'unsigned long'?


UL

> What is the proper suffix for a value that supports the same number
> of bits as a pointer?


I don't know a suffix specifically for this purpose. However, the
Linux kernel assumes that a long is always large enough to hold a
pointer, and this seems to work pretty well.

> Finally IIRC size_t is supposed to be as large as the largest
> addressible memory location. Can it therefore be used to compute a
> pointer using size_t base address and relative values on a system
> like alpha Tru64?


stdint.h defines intptr_t and uintptr_t, which seem like a better
choice. Why can't you use real pointers instead?

--
Måns Rullgård
mru@inprovide.com
Michael B Allen

2005-03-22, 6:08 pm

On Tue, 22 Mar 2005 05:13:27 -0500, Måns Rullgård wrote:

<snip very helpful stuff>

> stdint.h defines intptr_t and uintptr_t, which seem like a better
> choice. Why can't you use real pointers instead?


The memory allocator in question [1] is pointerless, meaning instead
of pointers it uses size_t offsets from the beginning of the arbitrary
chunk of memory backing the allocator. This permits me to use complex
ADTs with shared memory between multiple processes, create complex data
archives with mmap, allocate from stack memory, etc. For example:

int
myfn(void)
{
unsigned char chunk[0x7FFF];
struct allocator *al = suba_init(chunk, 0x7FFF, 1, 0);
struct hashmap map;

hashmap_init(&map, 0, hash_str, cmp_str, NULL, al);

/* use hashmap and allocator ... */

return 0; /* just return, no cleanup necessary */
}

So far my test cases look like they're working but you can understand
why I'm nervous :-> Do you see any problem with this sort of thing?

Thanks,
Mike

[1] http://www.google.com/search?q=suba+allocator
Måns Rullgård

2005-03-22, 6:08 pm

Michael B Allen <mba2000@ioplex.com> writes:

> On Tue, 22 Mar 2005 05:13:27 -0500, Måns Rullgård wrote:
>
> <snip very helpful stuff>
>
>
> The memory allocator in question [1] is pointerless, meaning instead
> of pointers it uses size_t offsets from the beginning of the arbitrary
> chunk of memory backing the allocator. This permits me to use complex
> ADTs with shared memory between multiple processes, create complex data
> archives with mmap, allocate from stack memory, etc. For example:


You should still use a pointer type to refer to the base address.
What you use for the offsets doesn't matter, as long as the range is
enough to cover the largest chunk you'll ever use. size_t should be
fine for this.

> So far my test cases look like they're working but you can understand
> why I'm nervous :-> Do you see any problem with this sort of thing?


I understand your concern. I'd suggest making it simple, and aligning
everything to 16 bytes. Allocating smaller pieces doesn't usually
make much sense anyway.

--
Måns Rullgård
mru@inprovide.com
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com