Skip to content

Commit

Permalink
more portable refcount atomics
Browse files Browse the repository at this point in the history
Most credit to Dustin and Trond for showing me the way, though I have no way
of testing this myself.

These should probably just be defines...
  • Loading branch information
dormando committed Jan 10, 2012
1 parent f4983b2 commit 3b96138
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 8 deletions.
12 changes: 6 additions & 6 deletions items.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
rel_time_t oldest_live = settings.oldest_live;

search = tails[id];
if (search != NULL && (__sync_add_and_fetch(&search->refcount, 1) == 2)) {
if (search != NULL && (refcount_incr(&search->refcount) == 2)) {
if ((search->exptime != 0 && search->exptime < current_time)
|| (search->time < oldest_live)) { // dead by flush
STATS_LOCK();
Expand Down Expand Up @@ -147,13 +147,13 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
/* Initialize the item block: */
it->slabs_clsid = 0;
} else {
__sync_sub_and_fetch(&search->refcount, 1);
refcount_decr(&search->refcount);
}
} else {
/* If the LRU is empty or locked, attempt to allocate memory */
it = slabs_alloc(ntotal, id);
if (search != NULL)
__sync_sub_and_fetch(&search->refcount, 1);
refcount_decr(&search->refcount);
}

if (it == NULL) {
Expand Down Expand Up @@ -287,7 +287,7 @@ int do_item_link(item *it, const uint32_t hv) {
ITEM_set_cas(it, (settings.use_cas) ? get_cas_id() : 0);
assoc_insert(it, hv);
item_link_q(it);
__sync_add_and_fetch(&it->refcount, 1);
refcount_incr(&it->refcount);
pthread_mutex_unlock(&cache_lock);

return 1;
Expand Down Expand Up @@ -328,7 +328,7 @@ void do_item_remove(item *it) {
MEMCACHED_ITEM_REMOVE(ITEM_key(it), it->nkey, it->nbytes);
assert((it->it_flags & ITEM_SLABBED) == 0);

if (__sync_sub_and_fetch(&it->refcount, 1) == 0) {
if (refcount_decr(&it->refcount) == 0) {
item_free(it);
}
}
Expand Down Expand Up @@ -484,7 +484,7 @@ item *do_item_get(const char *key, const size_t nkey, const uint32_t hv) {
mutex_lock(&cache_lock);
item *it = assoc_find(key, nkey, hv);
if (it != NULL) {
__sync_add_and_fetch(&it->refcount, 1);
refcount_incr(&it->refcount);
/* Optimization for slab reassignment. prevents popular items from
* jamming in busy wait. Can only do this here to satisfy lock order
* of item_lock, cache_lock, slabs_lock. */
Expand Down
2 changes: 2 additions & 0 deletions memcached.h
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,8 @@ void item_update(item *it);

void item_lock(uint32_t hv);
void item_unlock(uint32_t hv);
unsigned short refcount_incr(unsigned short *refcount);
unsigned short refcount_decr(unsigned short *refcount);
void STATS_LOCK(void);
void STATS_UNLOCK(void);
void threadlocal_stats_reset(void);
Expand Down
4 changes: 2 additions & 2 deletions slabs.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ static int slab_rebalance_move(void) {
item *it = slab_rebal.slab_pos;
status = MOVE_PASS;
if (it->slabs_clsid != 255) {
refcount = __sync_add_and_fetch(&it->refcount, 1);
refcount = refcount_incr(&it->refcount);
if (refcount == 1) { /* item is unlinked, unused */
if (it->it_flags & ITEM_SLABBED) {
/* remove from slab freelist */
Expand Down Expand Up @@ -589,7 +589,7 @@ static int slab_rebalance_move(void) {
case MOVE_BUSY:
slab_rebal.busy_items++;
was_busy++;
__sync_sub_and_fetch(&it->refcount, 1);
refcount_decr(&it->refcount);
break;
case MOVE_PASS:
break;
Expand Down
38 changes: 38 additions & 0 deletions thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
#include <string.h>
#include <pthread.h>

#ifdef __sun
#include <atomic.h>
#endif

#define ITEMS_PER_ALLOC 64

/* An item in the connection queue. */
Expand Down Expand Up @@ -39,6 +43,10 @@ pthread_mutex_t cache_lock;
/* Connection lock around accepting new connections */
pthread_mutex_t conn_lock = PTHREAD_MUTEX_INITIALIZER;

#if !defined(__GNUC__) && !defined(__sun)
pthread_mutex_t atomics_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif

/* Lock for global stats */
static pthread_mutex_t stats_lock;

Expand Down Expand Up @@ -70,6 +78,36 @@ static pthread_cond_t init_cond;

static void thread_libevent_process(int fd, short which, void *arg);

inline unsigned short refcount_incr(unsigned short *refcount) {
#ifdef __GNUC__
return __sync_add_and_fetch(refcount, 1);
#elif defined(__sun)
return atomic_inc_ushort_nv(refcount);
#else
unsigned short res;
mutex_lock(&atomics_mutex);
*refcount++;
res = *refcount;
pthread_mutex_unlock(&atomics_mutex);
return res;
#endif
}

inline unsigned short refcount_decr(unsigned short *refcount) {
#ifdef __GNUC__
return __sync_sub_and_fetch(refcount, 1);
#elif defined(__sun)
return atomic_dec_ushort_nv(refcount);
#else
unsigned short res;
mutex_lock(&atomics_mutex);
*refcount--;
res = *refcount;
pthread_mutex_unlock(&atomics_mutex);
return res;
#endif
}

void item_lock(uint32_t hv) {
mutex_lock(&item_locks[hv & item_lock_mask]);
}
Expand Down

0 comments on commit 3b96138

Please sign in to comment.