|
Boost : |
From: Tyson Whitehead (twhitehe_at_[hidden])
Date: 2004-07-02 16:48:27
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
I believe there is a mistake in the 'details/lwm_gcc.hpp' and
'details/lwm_linux.hpp' (and possibly the other lightweight_mutex
implementation as well -- I haven't looked at them).
In both of these files we have a counter (m_.a_) that is initialized to 1.
The lock routine is implemented as follows:
while( !__exchange_and_add(&m_.a_, -1) ){
__atomic_add(&m_.a_, 1);
sched_yield();
}
The unlock as:
__atomic_add(&m_.a_, 1);
This works if there are only two contenders for the lock. It can fail if
there are three or more:
1- Thread one takes the lock, putting the counter at 0.
2- Thread two does the __exchange_and_add, fails the test, and then its time
time slice expires before the __atomic_add, leaving the counter at -1.
3- Thread three also takes the lock (because !-1 is false).
A simple solution is to initialize the counter to zero and replace the above
lock by:
while( __exchange_and_add(&m_.a_, 1) ){
__atomic_add(&m_.a_, -1);
sched_yield();
}
and the unlock by:
__atomic_add(&m_.a_, -1);
This would result in:
1- Thread one takes the lock, putting the counter at 1.
2- Thread two does the __exchange_and_add, fails the test, and then its time
slice expires before it can do the __atomic_add, leaving the counter at 2.
3- Thread cannot take the the lock (because 2 is true).
- -T
- --
Tyson Whitehead (-twhitehe_at_[hidden] -- WSC-)
Computer Engineer Dept. of Applied Mathematics,
Graduate Student- Applied Mathematics University of Western Ontario,
GnuPG Key ID# 0x8A2AB5D8 London, Ontario, Canada
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)
iD8DBQFA5dgwRXbLmIoqtdgRAmbyAJ0aZFZvxn5MXeXyNqSAI63o9EqddQCfTK9p
wFAoBbQueoo9hLNhXJtit44=
=SPra
-----END PGP SIGNATURE-----
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk