Hi,

I can't comment on exactly your issue, but I can give you an outline of 
the issues around volatile and mutexes.

Volatile:

When you declare a variable to be volatile it ensures that the compiler 
always loads that variable from memory and immediately stores it back to 
memory after any operation on it.

For example:

int flag;

while (flag){}

In the absence of the volatile keyword the compiler will optimise this to:

if (!flag) while (1) {}
[If the flag is not zero to start with then the compiler assumes that 
there's nothing that can make it zero, so there is no exit condition on 
the loop.]

Not all shared data needs to be declared volatile. Only if you want one 
thread to see the effect of another thread.

[Example, if one thread populates a buffer, and another thread will 
later read from that buffer, then you don't need to declare the contents 
of the buffer as volatile. The important word being later, if you expect 
the two threads to access the buffer at the same time, then you would 
probably need the volatile keyword]

Mutexes are there to ensure exclusive access.

You will typically need to use them if you are updating a variable, or 
if you are performing a complex operation that should appear 'atomic'

For example:

volatile int total;

mutex_lock();
total+=5;
mutex_unlock();

You need to do this to avoid a data race, where another thread could 
also be updating total:

Here's the situation without the mutex:

Thread 1    Thread 2
Read total  Read total
Add 5       Add 5
Write total Write total

So total would be incremented by 5 rather than 10.

An example of a complex operation would be:

mutex_lock();
My_account = My_account - bill;
Their_account = Their_account + bill;
mutex_unlock();

You could use two separate mutexes, but then there would be a state 
where the amount bill would have been removed from My_account, but not 
yet placed into Their_account (this may or may not be a problem).

===================================

In your case I think you are filling a structure, then passing this 
structure to another thread. It seems that the two (or more) threads are 
not simultaneously accessing the structure. So the program order 
guarantees mutually exclusive access. In your case I do not think that 
you need either mutexes or the volatile keyword. However, you might need 
something in the mechanism that enables the sharing of the buffer.

For example, if the buffer is shared as a pointer

buffer * my_buffer;

Thread1
  my_buffer = this_buffer;

Thread2
  while (my_buffer==0) {} /*Wait for next buffer*/

Then the pointer needs to be volatile.

Alternatively, if you are adding a new element onto a linked list of 
buffers, then you will probably need a mutex around the linked list to 
ensure that only one thread is adding or removing times from the list at 
a time.

BTW, you can use the Thread Analyzer in Sun Studio to detect dataraces 
in your application. http://developers.sun.com/sunstudio/

HTH,

Regards,

Darryl.




Bert Miemietz wrote:
> When using multiple threads in userspace together with global data structures
> (bss, data segment or heap)  the following is not clear to me:
> Guess only one thread fills and updates a more complex global data structure 
> (similar to a devices softstate if it was in the kernel) and multiple other
> threads shall access the data from this structure. 
> Do I really need a mutex, rw-lock or something of that kind around every 
> single
> access - be it read or write - to any member of this structure?
> Or would it be enough to declare the respective structure/members volatile.
> What makes me unsure about correct usage is the statement from the 
> "Multithreaded
> Programming Guide":
> "The synchronization primitives use special instructions that flush the store 
> buffers
> to cache...So, using locks around your shared data ensures memory 
> consistency."
> On the other hand "Writing Device Drivers" contains an example with a busy 
> flag
> not protected by a lock and using the volatile keyword instead.
> Several small code examples in "Multithreaded Programming Guide" access data
> that are not in the current threads stack without using locks.
> So, the case described in the beginning does not require a lock for correct 
> data in
> the structure since only one thread is doing updates. But when is the data 
> visible
> to other threads? Or which instruction causes the data to be written to memory
> so that a consumer using "volatile" sees the data? The same question would 
> occurr
> with a global data buffer being shared between several threads.
> In practice everything works fine with volatile but the manual says (as far 
> as I 
> understand it) that there might be problems.
> Any hint would be very useful.

-- 
Darryl Gove
Compiler Performance Engineering
Blog : http://blogs.sun.com/d/
Books: http://www.sun.com/books/catalog/solaris_app_programming.xml
        http://my.safaribooksonline.com/0595352510

Reply via email to