can a volatile int be used as a mutex

T

tiffini

Hi,

We have a lot of OS's to support. So we created a mutex class with sieze and release like so


class foo{

private:
volatile int m_lock;
public:
Sieze(){ while (m_lock==1) { sleep(1);};m_lock=1;};
Release(){m_lock=0;};
.... // constructors etc

}


Is this legal or do I have to use an OS type call? I thought that volatile guaranteed m_lock to be thread safe, meaning the variable m_lock could not be cashed in a register if the thread was swapped out for another thread.


thanks in advance

tif
 
D

Doug

tiffini said:
Hi,

We have a lot of OS's to support. So we created a mutex class with sieze and release like so


class foo{

private:
volatile int m_lock;
public:
Sieze(){ while (m_lock==1) { sleep(1);};m_lock=1;};
Release(){m_lock=0;};
... // constructors etc

}


Is this legal or do I have to use an OS type call? I thought that volatile guaranteed m_lock to be thread safe, meaning the variable m_lock could not be cashed in a register if the thread was swapped out for another thread.


thanks in advance

tif

Hiya,

I think this is OT here - maybe post to comp.programming.threads?

I'll try to answer anyway. I don't think this is correct, even on a
single processor.
Sieze(){ while (m_lock==1) { sleep(1);};m_lock=1;};

Imagine thread A checks m_lock, sees it is not 1 and decides to
continue, but then gets rescheduled (say its timeslice expired) before
it writes to m_lock.
A second thread then comes along and sees the same thing, because
thread A didn't get a chance to write to m_lock yet.
Result - two threads running in your code guarded by the mutex.

I think that if you want to build a lock then at some point you need
to use an arch-specific instruction. I could be wrong, though. The
guys in comp.programming.threads would know, and probably try to sell
you lock-free!

Doug
 
F

Fei Liu

tiffini said:
Hi,

We have a lot of OS's to support. So we created a mutex class with
sieze and release like so


class foo{

private:
volatile int m_lock;
public:
Sieze(){ while (m_lock==1) { sleep(1);};m_lock=1;};
Release(){m_lock=0;};
... // constructors etc

}


Is this legal or do I have to use an OS type call? I thought that
volatile guaranteed m_lock to be thread safe, meaning the variable
m_lock could not be cashed in a register if the thread was swapped out
for another thread.


thanks in advance

tif

Your test-and-set is not atomic and will fail miserably in
multi-threaded application.

Fei
 
P

peter koch

Hi,

We have a lot of OS's to support. So we created a mutex class with sieze and release like so

class foo{

private:
volatile int m_lock;
public:
Sieze(){ while (m_lock==1) { sleep(1);};m_lock=1;};
Release(){m_lock=0;};
... // constructors etc

}

Is this legal or do I have to use an OS type call? I thought that volatile guaranteed m_lock to be thread safe, > meaning the variable m_lock could not be cashed in a register if the thread was swapped out for another thread.
It is legal C++ but it will not do what you expect. As Doug noted,
your code will fail even when run on a single processor.
I will recommend that you use the OS features on whatever system you
happen to compile for and encapsulate the code in a class as you did
above.

/Peter
 
T

tiffini

Doug said:
Hiya,

I think this is OT here - maybe post to comp.programming.threads?

I'll try to answer anyway. I don't think this is correct, even on a
single processor.


Imagine thread A checks m_lock, sees it is not 1 and decides to
continue, but then gets rescheduled (say its timeslice expired) before
it writes to m_lock.
A second thread then comes along and sees the same thing, because
thread A didn't get a chance to write to m_lock yet.
Result - two threads running in your code guarded by the mutex.
I thought that the volatile key word is a lock between threads and cannot be cached in a register.
So the while(lock==1} is the atomic check. when each thread is swapped out for the next the register that holds the volatile variable will be written to memory. Then the other thread will read it and variable.

If this is not correct, can you explain how volatile keyword works?


thanks in advance

tiff
 
K

Kai-Uwe Bux

tiffini wrote:
[snip]
I thought that the volatile key word is a lock between threads and cannot
be cached in a register.
So the while(lock==1} is the atomic check. when each thread is swapped
out for the next the register that holds the volatile variable will be
written to memory. Then the other thread will read it and variable.

If this is not correct,

It is not correct: volatile is unrelated to threading. The standard does not
say anything about threading. In particular, it does not define the meaning
of "volatile" with regard to threading.
can you explain how volatile keyword works?

If data is declared volatile, then reads and writes to such data qualify as
observable behavior [1.9/6]. Consequently, such writes and reads cannot be
moved around sequence points, i.e., sequence points define a partial order
on such reads and writes and you can use that to make sure that some
read/write occurs before another read/write. However, such guarantees only
apply to the abstract machine, which as of now is single threaded.

However, the single threaded abstract machine does allow for certain
interrupts: signals. With regard to those, the standard says that volatile
sig_atomic_t data have well-defined values when the program is interrupted
by a signal. The handler can modify volatile sig_atomic_t data. Any attempt
to modify other data is undefined behavior. [1.9/9]

As far as I know, these are the only guarantees made by the standard.


Best

Kai-Uwe Bux
 
M

Marcus Kwok

tiffini said:
Hi,

We have a lot of OS's to support. So we created a mutex class with sieze and release like so


class foo{

private:
volatile int m_lock;
public:
Sieze(){ while (m_lock==1) { sleep(1);};m_lock=1;};
Release(){m_lock=0;};
... // constructors etc

}


Is this legal or do I have to use an OS type call? I thought that volatile guaranteed m_lock to be thread safe, meaning the variable m_lock could not be cashed in a register if the thread was swapped out for another thread.

This article may be useful for you too:
http://www.ddj.com/dept/cpp/184403766
 
B

Bluejack

This article may be useful for you too:http://www.ddj.com/dept/cpp/184403766

In it's initial explanation of volatile, I agree. As to the author's
implementation, I'm not so sure. I didn't go through it in detail, but
it looked a little suspicious as I was scanning it, and his conclusion
was hardly encouraging:

"A couple of projects I've been involved with use volatile and
LockingPtr to great effect. The code is clean and understandable. I
recall a couple of deadlocks, but I prefer deadlocks to race
conditions because they are so much easier to debug. There were
virtually no problems related to race conditions. But then you never
know."

Um. Yeah. I'll run right out and use that implementation! Not.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top