only use atomic operations if the compiler supports them

This commit is contained in:
Joel Dice 2009-11-19 19:32:54 -07:00
parent 07f40a07e1
commit 5f5cc57d12
2 changed files with 22 additions and 1 deletions

View File

@ -63,6 +63,11 @@ typedef uint64_t uintptr_t;
# include "stdint.h"
# if (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
# define USE_ATOMIC_OPERATIONS
# define COMPARE_AND_SWAP __sync_bool_compare_and_swap
# endif
# define LIKELY(v) __builtin_expect((v) != 0, true)
# define UNLIKELY(v) __builtin_expect((v) != 0, false)
@ -325,13 +330,15 @@ markBit(uintptr_t* map, unsigned i)
map[wordOf(i)] |= static_cast<uintptr_t>(1) << bitOf(i);
}
#ifdef USE_ATOMIC_OPERATIONS
inline void
markBitAtomic(uintptr_t* map, unsigned i)
{
uintptr_t* p = map + wordOf(i);
uintptr_t v = static_cast<uintptr_t>(1) << bitOf(i);
while (not __sync_bool_compare_and_swap(p, *p, *p | v)) { }
while (not COMPARE_AND_SWAP(p, *p, *p | v)) { }
}
#endif
inline void
clearBit(uintptr_t* map, unsigned i)

View File

@ -303,12 +303,14 @@ class Segment {
if (child) child->set(p, v);
}
#ifdef USE_ATOMIC_OPERATIONS
void markAtomic(void* p) {
assert(segment->context, bitsPerRecord == 1);
markBitAtomic(data, indexOf(p));
assert(segment->context, getBit(data, indexOf(p)));
if (child) child->markAtomic(p);
}
#endif
unsigned get(void* p) {
return getBits(data, bitsPerRecord, indexOf(p));
@ -1816,6 +1818,10 @@ class MyHeap: public Heap {
virtual void mark(void* p, unsigned offset, unsigned count) {
if (needsMark(p)) {
#ifndef USE_ATOMIC_OPERATIONS
ACQUIRE(c.lock);
#endif
if (c.client->isFixed(p)) {
Fixie* f = fixie(p);
assert(&c, offset == 0 or f->hasMask);
@ -1830,7 +1836,11 @@ class MyHeap: public Heap {
}
dirty = true;
#ifdef USE_ATOMIC_OPERATIONS
markBitAtomic(f->mask(), offset + i);
#else
markBit(f->mask(), offset + i);
#endif
assert(&c, getBit(f->mask(), offset + i));
}
}
@ -1848,7 +1858,11 @@ class MyHeap: public Heap {
for (unsigned i = 0; i < count; ++i) {
void** target = static_cast<void**>(p) + offset + i;
if (targetNeedsMark(mask(*target))) {
#ifdef USE_ATOMIC_OPERATIONS
map->markAtomic(target);
#else
map->set(target);
#endif
}
}
}