Andrew Haley wrote:
Phil Endecott writes:
> Andrew Haley wrote:
> > this stuff really should be done by the compiler.
>
> Yes. I've filed a bug asking for a __sync_lock_test_and_set builtin:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33413
Surer, but the problem is that for most of the things we want to do
(lightweight locks, for example) __sync_lock_test_and_set() doesn't
really do what we need: we need compare_and_swap().
There are several factors, e.g.:
(a) Does your system's threading model allow a high-priority thread
that is in a spin lock to eventually be interrupted?
(b) Can you allow a sentinel value in your atomic type?
(c) Do you expect to hold locks for extended periods, or just for a few
instructions at a time?
In my case I'm implementing reference counts, and a solution using just
swap is possible. Calling the kernel-helper thing to get
compare-and-swap would add a lot of unnecessary overhead.
BTW you can do lightweight locks using just swap, something like this:
int mutex; // 1=locked, 0=unlocked
void lock() {
int x=1;
do {
swap(mutex,x); // if mutex was unlocked, it is now locked and x==0
// if mutex was locked, it is still locked and x==1
} while (x==1)
}
void unlock() {
mutex=0;
}
This requires that a thread that is in the spin loop will eventually be
pre-empted by the thread that holds the lock, and is only efficient if
the critical sections are short. If these conditions hold, it needs
far fewer instructions that the compare-and-swap kernel-helper version.
Regards,
Phil.