Make object refcounts atomic, technically it doesn't need to be currently but the semantics are complicated and error prone. This is much safer with little performance impact

Former-commit-id: e310d33c121550f69b1c06d101db0c3f944a7fb0
This commit is contained in:
John Sully 2019-07-18 15:49:12 -04:00
parent afa1a2e023
commit aa560582b4
4 changed files with 11 additions and 9 deletions

View File

@ -436,7 +436,7 @@ NULL
"Value at:%p refcount:%d " "Value at:%p refcount:%d "
"encoding:%s serializedlength:%zu " "encoding:%s serializedlength:%zu "
"lru:%d lru_seconds_idle:%llu%s", "lru:%d lru_seconds_idle:%llu%s",
(void*)val, val->refcount, (void*)val, static_cast<int>(val->refcount),
strenc, rdbSavedObjectLen(val), strenc, rdbSavedObjectLen(val),
val->lru, estimateObjectIdleTime(val)/1000, extra); val->lru, estimateObjectIdleTime(val)/1000, extra);
} else if (!strcasecmp(szFromObj(c->argv[1]),"sdslen") && c->argc == 3) { } else if (!strcasecmp(szFromObj(c->argv[1]),"sdslen") && c->argc == 3) {
@ -721,14 +721,14 @@ void _serverAssertPrintClientInfo(const client *c) {
arg = buf; arg = buf;
} }
serverLog(LL_WARNING,"client->argv[%d] = \"%s\" (refcount: %d)", serverLog(LL_WARNING,"client->argv[%d] = \"%s\" (refcount: %d)",
j, arg, c->argv[j]->refcount); j, arg, static_cast<int>(c->argv[j]->refcount));
} }
} }
void serverLogObjectDebugInfo(robj_roptr o) { void serverLogObjectDebugInfo(robj_roptr o) {
serverLog(LL_WARNING,"Object type: %d", o->type); serverLog(LL_WARNING,"Object type: %d", o->type);
serverLog(LL_WARNING,"Object encoding: %d", o->encoding); serverLog(LL_WARNING,"Object encoding: %d", o->encoding);
serverLog(LL_WARNING,"Object refcount: %d", o->refcount); serverLog(LL_WARNING,"Object refcount: %d", static_cast<int>(o->refcount));
if (o->type == OBJ_STRING && sdsEncodedObject(o)) { if (o->type == OBJ_STRING && sdsEncodedObject(o)) {
serverLog(LL_WARNING,"Object raw string len: %zu", sdslen(szFromObj(o))); serverLog(LL_WARNING,"Object raw string len: %zu", sdslen(szFromObj(o)));
if (sdslen(szFromObj(o)) < 4096) { if (sdslen(szFromObj(o)) < 4096) {

View File

@ -2290,6 +2290,7 @@ sds getAllClientsInfoString(int type) {
listRewind(g_pserver->clients,&li); listRewind(g_pserver->clients,&li);
while ((ln = listNext(&li)) != NULL) { while ((ln = listNext(&li)) != NULL) {
client = reinterpret_cast<struct client*>(listNodeValue(ln)); client = reinterpret_cast<struct client*>(listNodeValue(ln));
std::unique_lock<decltype(client->lock)> lock(client->lock);
if (type != -1 && getClientType(client) != type) continue; if (type != -1 && getClientType(client) != type) continue;
o = catClientInfoString(o,client); o = catClientInfoString(o,client);
o = sdscatlen(o,"\n",1); o = sdscatlen(o,"\n",1);

View File

@ -43,7 +43,7 @@ robj *createObject(int type, void *ptr) {
o->type = type; o->type = type;
o->encoding = OBJ_ENCODING_RAW; o->encoding = OBJ_ENCODING_RAW;
o->m_ptr = ptr; o->m_ptr = ptr;
o->refcount = 1; o->refcount.store(1, std::memory_order_relaxed);
o->mvcc_tstamp = OBJ_MVCC_INVALID; o->mvcc_tstamp = OBJ_MVCC_INVALID;
/* Set the LRU to the current lruclock (minutes resolution), or /* Set the LRU to the current lruclock (minutes resolution), or
@ -69,7 +69,7 @@ robj *createObject(int type, void *ptr) {
*/ */
robj *makeObjectShared(robj *o) { robj *makeObjectShared(robj *o) {
serverAssert(o->refcount == 1); serverAssert(o->refcount == 1);
o->refcount = OBJ_SHARED_REFCOUNT; o->refcount.store(OBJ_SHARED_REFCOUNT, std::memory_order_relaxed);
return o; return o;
} }
@ -91,7 +91,7 @@ robj *createEmbeddedStringObject(const char *ptr, size_t len) {
o->type = OBJ_STRING; o->type = OBJ_STRING;
o->encoding = OBJ_ENCODING_EMBSTR; o->encoding = OBJ_ENCODING_EMBSTR;
o->refcount = 1; o->refcount.store(1, std::memory_order_relaxed);
o->mvcc_tstamp = OBJ_MVCC_INVALID; o->mvcc_tstamp = OBJ_MVCC_INVALID;
if (g_pserver->maxmemory_policy & MAXMEMORY_FLAG_LFU) { if (g_pserver->maxmemory_policy & MAXMEMORY_FLAG_LFU) {
@ -352,7 +352,7 @@ void freeStreamObject(robj_roptr o) {
} }
void incrRefCount(robj_roptr o) { void incrRefCount(robj_roptr o) {
if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount++; if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount.fetch_add(1, std::memory_order_acquire);
} }
void decrRefCount(robj_roptr o) { void decrRefCount(robj_roptr o) {
@ -370,7 +370,7 @@ void decrRefCount(robj_roptr o) {
zfree(o.unsafe_robjcast()); zfree(o.unsafe_robjcast());
} else { } else {
if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0"); if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0");
if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount--; if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount.fetch_sub(1, std::memory_order_acquire);
} }
} }

View File

@ -709,13 +709,14 @@ typedef struct RedisModuleDigest {
#define OBJ_SHARED_REFCOUNT INT_MAX #define OBJ_SHARED_REFCOUNT INT_MAX
#define OBJ_MVCC_INVALID (0xFFFFFFFFFFFFFFFFULL) #define OBJ_MVCC_INVALID (0xFFFFFFFFFFFFFFFFULL)
typedef struct redisObject { typedef struct redisObject {
unsigned type:4; unsigned type:4;
unsigned encoding:4; unsigned encoding:4;
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
* LFU data (least significant 8 bits frequency * LFU data (least significant 8 bits frequency
* and most significant 16 bits access time). */ * and most significant 16 bits access time). */
mutable int refcount; mutable std::atomic<int> refcount;
uint64_t mvcc_tstamp; uint64_t mvcc_tstamp;
void *m_ptr; void *m_ptr;
} robj; } robj;