"Hallvard B Furuseth" <h.b.furuseth@[EMAIL PROTECTED]
> wrote in message
news:hbf.20081007bpkh@[EMAIL PROTECTED]
> Hello again... thanks for the answers so far:
>
> Dave Butenhof writes:
>>Hallvard B Furuseth wrote:
>>> What do POSIX and other thread APIs have to say about memory layout
>>> of data accessed by different treads? E.g.:
>>>
>>> struct Foo {
>>> pthread_mutex_t ma, mb;
>>> int a, b; /* protected by ma and mb respectively */
>>> int c; /* not mutex-protected, only accessed by 1 thread */
>>> };
>> (...)
>> Generally int will be safe. Although on some machines, an UNALIGNED int
>> is legal but not necessarily atomic.
>
>> Both C and C++ are working now on detailed memory models that will nail
>> down standard and ****table answers to this sort of
>> question. Unfortunately it's all well below the level that could be
>> resolved in POSIX.
>>
>> As David Schwartz suggested, however, you're generally going to be
>> better off keeping independently accessed data as "distinct objects"
>> rather than compacting them into a common container. If you keep them
>> distinctly separate, you have a much better chance that your code, the
>> compiler, the memory allocator in your runtime, and the hardware will
>> all get along.
>
> Makes sense. What would you do if you want data structures with
> differently-protected data in the same struct though?
Here is possible contrived solution:
struct data {
int part1;
char l2pad1[L2_CACHE_LINE_SIZE - sizeof(int)];
int part2;
char l2pad2[L2_CACHE_LINE_SIZE - sizeof(int)];
int part3;
char l2pad3[L2_CACHE_LINE_SIZE - sizeof(int)];
};
If you align this struct on a cache line boundary `data::part1/2/3' will
never be false-shared with each other.
> Ensure at least
> <void* and int>-sized padding/alignment, or maybe insert the data in a
> union with a mutex which hopefully gets aligned sensibly, or more?
>
> As you say, false sharing can often make it best to keep them apart in
> memory anyway. But not always - e.g. with write-seldom/read-often, the
> extra indirection to move between two parts of an object might cost more
> - in either runtime or coding/maintenance.
[...]
Here are some general guidelines:
http://groups.google.com/group/comp.programming.threads/browse_frm/thread/7030f8ac1610a709
http://groups.google.com/group/comp.programming.threads/msg/8036dc8a380718ad
As for ensuring that mutex's are not false-shared with the data they
protect, well, here is what I do on Windows:
http://groups.google.com/group/comp.programming.threads/msg/88bd832858072802
The CRITICAL_SECTION data-structure is not padded up to a l2 cache-line.
So
I simply wrap it in a union, and use the alignment hack code found here:
http://groups.google.com/group/comp.lang.c/msg/be7e0d0e97c5e1d9
Dynamic allocation is performed using a custom malloc function; an example
of this can be found here:
http://webpages.charter.net/appcore/appcore/src/appcore_c.html
(look at the last two functions in the file
(ac_malloc_aligned/ac_calloc_aligned).


|