diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..3813ff8ac --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "zmalloc.h": "c" + } +} \ No newline at end of file diff --git a/src/Makefile b/src/Makefile index adf32d557..680e3866b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -119,7 +119,7 @@ ifeq ($(uname_S),DragonFly) else # All the other OSes (notably Linux) FINAL_LDFLAGS+= -rdynamic - FINAL_LIBS+=-ldl -pthread -lrt + FINAL_LIBS+=-ldl -pthread -lrt -lmemkind endif endif endif @@ -164,11 +164,11 @@ endif REDIS_SERVER_NAME=redis-server REDIS_SENTINEL_NAME=redis-sentinel -REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o acl.o +REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o acl.o storage.o REDIS_CLI_NAME=redis-cli -REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o siphash.o crc16.o +REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o siphash.o crc16.o storage.o REDIS_BENCHMARK_NAME=redis-benchmark -REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o zmalloc.o redis-benchmark.o +REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o zmalloc.o redis-benchmark.o storage.o REDIS_CHECK_RDB_NAME=redis-check-rdb REDIS_CHECK_AOF_NAME=redis-check-aof diff --git a/src/acl.c b/src/acl.c index ecaae9268..b37b4719a 100644 --- a/src/acl.c +++ b/src/acl.c @@ -146,7 +146,7 @@ void ACLListFreeSds(void *item) { * If the user with such name already exists NULL is returned. */ user *ACLCreateUser(const char *name, size_t namelen) { if (raxFind(Users,(unsigned char*)name,namelen) != raxNotFound) return NULL; - user *u = zmalloc(sizeof(*u)); + user *u = zmalloc(sizeof(*u), MALLOC_LOCAL); u->name = sdsnewlen(name,namelen); u->flags = 0; u->allowed_subcommands = NULL; @@ -267,7 +267,7 @@ void ACLAddAllowedSubcommand(user *u, unsigned long id, const char *sub) { * this user, we have to allocate the subcommands array. */ if (u->allowed_subcommands == NULL) { u->allowed_subcommands = zcalloc(USER_COMMAND_BITS_COUNT * - sizeof(sds*)); + sizeof(sds*), MALLOC_LOCAL); } /* We also need to enlarge the allocation pointing to the diff --git a/src/adlist.c b/src/adlist.c index ec5f8bbf4..359262521 100644 --- a/src/adlist.c +++ b/src/adlist.c @@ -42,7 +42,7 @@ list *listCreate(void) { struct list *list; - if ((list = zmalloc(sizeof(*list))) == NULL) + if ((list = zmalloc(sizeof(*list), MALLOC_SHARED)) == NULL) return NULL; list->head = list->tail = NULL; list->len = 0; @@ -89,7 +89,7 @@ list *listAddNodeHead(list *list, void *value) { listNode *node; - if ((node = zmalloc(sizeof(*node))) == NULL) + if ((node = zmalloc(sizeof(*node), MALLOC_SHARED)) == NULL) return NULL; node->value = value; if (list->len == 0) { @@ -115,7 +115,7 @@ list *listAddNodeTail(list *list, void *value) { listNode *node; - if ((node = zmalloc(sizeof(*node))) == NULL) + if ((node = zmalloc(sizeof(*node), MALLOC_SHARED)) == NULL) return NULL; node->value = value; if (list->len == 0) { @@ -134,7 +134,7 @@ list *listAddNodeTail(list *list, void *value) list *listInsertNode(list *list, listNode *old_node, void *value, int after) { listNode *node; - if ((node = zmalloc(sizeof(*node))) == NULL) + if ((node = zmalloc(sizeof(*node), MALLOC_SHARED)) == NULL) return NULL; node->value = value; if (after) { @@ -187,7 +187,7 @@ listIter *listGetIterator(list *list, int direction) { listIter *iter; - if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL; + if ((iter = zmalloc(sizeof(*iter), MALLOC_SHARED)) == NULL) return NULL; if (direction == AL_START_HEAD) iter->next = list->head; else diff --git a/src/ae.c b/src/ae.c index 53629ef77..7f59aecf1 100644 --- a/src/ae.c +++ b/src/ae.c @@ -64,9 +64,9 @@ aeEventLoop *aeCreateEventLoop(int setsize) { aeEventLoop *eventLoop; int i; - if ((eventLoop = zmalloc(sizeof(*eventLoop))) == NULL) goto err; - eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize); - eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize); + if ((eventLoop = zmalloc(sizeof(*eventLoop), MALLOC_LOCAL)) == NULL) goto err; + eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize, MALLOC_LOCAL); + eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize, MALLOC_LOCAL); if (eventLoop->events == NULL || eventLoop->fired == NULL) goto err; eventLoop->setsize = setsize; eventLoop->lastTime = time(NULL); @@ -212,7 +212,7 @@ long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds, long long id = eventLoop->timeEventNextId++; aeTimeEvent *te; - te = zmalloc(sizeof(*te)); + te = zmalloc(sizeof(*te), MALLOC_LOCAL); if (te == NULL) return AE_ERR; te->id = id; aeAddMillisecondsToNow(milliseconds,&te->when_sec,&te->when_ms); diff --git a/src/ae_epoll.c b/src/ae_epoll.c index 410aac70d..298bcf6ce 100644 --- a/src/ae_epoll.c +++ b/src/ae_epoll.c @@ -37,10 +37,10 @@ typedef struct aeApiState { } aeApiState; static int aeApiCreate(aeEventLoop *eventLoop) { - aeApiState *state = zmalloc(sizeof(aeApiState)); + aeApiState *state = zmalloc(sizeof(aeApiState), MALLOC_LOCAL); if (!state) return -1; - state->events = zmalloc(sizeof(struct epoll_event)*eventLoop->setsize); + state->events = zmalloc(sizeof(struct epoll_event)*eventLoop->setsize, MALLOC_LOCAL); if (!state->events) { zfree(state); return -1; diff --git a/src/ae_evport.c b/src/ae_evport.c index 5c317becb..7b7fbe28e 100644 --- a/src/ae_evport.c +++ b/src/ae_evport.c @@ -74,7 +74,7 @@ typedef struct aeApiState { static int aeApiCreate(aeEventLoop *eventLoop) { int i; - aeApiState *state = zmalloc(sizeof(aeApiState)); + aeApiState *state = zmalloc(sizeof(aeApiState), MALLOC_LOCAL); if (!state) return -1; state->portfd = port_create(); diff --git a/src/ae_kqueue.c b/src/ae_kqueue.c index 6796f4ceb..36148bf58 100644 --- a/src/ae_kqueue.c +++ b/src/ae_kqueue.c @@ -42,7 +42,7 @@ static int aeApiCreate(aeEventLoop *eventLoop) { aeApiState *state = zmalloc(sizeof(aeApiState)); if (!state) return -1; - state->events = zmalloc(sizeof(struct kevent)*eventLoop->setsize); + state->events = zmalloc(sizeof(struct kevent)*eventLoop->setsize, MALLOC_LOCAL); if (!state->events) { zfree(state); return -1; diff --git a/src/ae_select.c b/src/ae_select.c index c039a8ea3..7e6746aae 100644 --- a/src/ae_select.c +++ b/src/ae_select.c @@ -40,7 +40,7 @@ typedef struct aeApiState { } aeApiState; static int aeApiCreate(aeEventLoop *eventLoop) { - aeApiState *state = zmalloc(sizeof(aeApiState)); + aeApiState *state = zmalloc(sizeof(aeApiState), MALLOC_LOCAL); if (!state) return -1; FD_ZERO(&state->rfds); diff --git a/src/aof.c b/src/aof.c index 46ae58324..ed9da54ef 100644 --- a/src/aof.c +++ b/src/aof.c @@ -143,7 +143,7 @@ void aofRewriteBufferAppend(unsigned char *s, unsigned long len) { if (len) { /* First block to allocate, or need another block. */ int numblocks; - block = zmalloc(sizeof(*block)); + block = zmalloc(sizeof(*block), MALLOC_LOCAL); block->free = AOF_RW_BUF_BLOCK_SIZE; block->used = 0; listAddNodeTail(server.aof_rewrite_buf_blocks,block); @@ -627,7 +627,7 @@ void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int a /* In Redis commands are always executed in the context of a client, so in * order to load the append only file we need to create a fake client. */ struct client *createFakeClient(void) { - struct client *c = zmalloc(sizeof(*c)); + struct client *c = zmalloc(sizeof(*c), MALLOC_LOCAL); selectDb(c,0); c->fd = -1; @@ -752,7 +752,7 @@ int loadAppendOnlyFile(char *filename) { argc = atoi(buf+1); if (argc < 1) goto fmterr; - argv = zmalloc(sizeof(robj*)*argc); + argv = zmalloc(sizeof(robj*)*argc, MALLOC_LOCAL); fakeClient->argc = argc; fakeClient->argv = argv; diff --git a/src/bio.c b/src/bio.c index 2af684570..13662197e 100644 --- a/src/bio.c +++ b/src/bio.c @@ -129,7 +129,7 @@ void bioInit(void) { } void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) { - struct bio_job *job = zmalloc(sizeof(*job)); + struct bio_job *job = zmalloc(sizeof(*job), MALLOC_LOCAL); job->time = time(NULL); job->arg1 = arg1; diff --git a/src/bitops.c b/src/bitops.c index 8d03a7699..e2b53169a 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -621,9 +621,9 @@ void bitopCommand(client *c) { /* Lookup keys, and store pointers to the string objects into an array. */ numkeys = c->argc - 3; - src = zmalloc(sizeof(unsigned char*) * numkeys); - len = zmalloc(sizeof(long) * numkeys); - objects = zmalloc(sizeof(robj*) * numkeys); + src = zmalloc(sizeof(unsigned char*) * numkeys, MALLOC_LOCAL); + len = zmalloc(sizeof(long) * numkeys, MALLOC_LOCAL); + objects = zmalloc(sizeof(robj*) * numkeys, MALLOC_LOCAL); for (j = 0; j < numkeys; j++) { o = lookupKeyRead(c->db,c->argv[j+3]); /* Handle non-existing keys as empty strings. */ diff --git a/src/blocked.c b/src/blocked.c index f9e196626..24d674935 100644 --- a/src/blocked.c +++ b/src/blocked.c @@ -513,7 +513,7 @@ void blockForKeys(client *c, int btype, robj **keys, int numkeys, mstime_t timeo * is NULL for lists and sorted sets, or the stream ID for streams. */ void *key_data = NULL; if (btype == BLOCKED_STREAM) { - key_data = zmalloc(sizeof(streamID)); + key_data = zmalloc(sizeof(streamID), MALLOC_SHARED); memcpy(key_data,ids+j,sizeof(streamID)); } @@ -596,7 +596,7 @@ void signalKeyAsReady(redisDb *db, robj *key) { if (dictFind(db->ready_keys,key) != NULL) return; /* Ok, we need to queue this key into server.ready_keys. */ - rl = zmalloc(sizeof(*rl)); + rl = zmalloc(sizeof(*rl), MALLOC_SHARED); rl->key = key; rl->db = db; incrRefCount(key); diff --git a/src/cluster.c b/src/cluster.c index 1a3a348b5..bd04646d0 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -119,7 +119,7 @@ int clusterLoadConfig(char *filename) { * * To simplify we allocate 1024+CLUSTER_SLOTS*128 bytes per line. */ maxline = 1024+CLUSTER_SLOTS*128; - line = zmalloc(maxline); + line = zmalloc(maxline, MALLOC_LOCAL); while(fgets(line,maxline,fp) != NULL) { int argc; sds *argv; @@ -429,7 +429,7 @@ void clusterUpdateMyselfFlags(void) { void clusterInit(void) { int saveconf = 0; - server.cluster = zmalloc(sizeof(clusterState)); + server.cluster = zmalloc(sizeof(clusterState), MALLOC_LOCAL); server.cluster->myself = NULL; server.cluster->currentEpoch = 0; server.cluster->state = CLUSTER_FAIL; @@ -587,7 +587,7 @@ void clusterReset(int hard) { * -------------------------------------------------------------------------- */ clusterLink *createClusterLink(clusterNode *node) { - clusterLink *link = zmalloc(sizeof(*link)); + clusterLink *link = zmalloc(sizeof(*link), MALLOC_LOCAL); link->ctime = mstime(); link->sndbuf = sdsempty(); link->rcvbuf = sdsempty(); @@ -692,7 +692,7 @@ unsigned int keyHashSlot(char *key, int keylen) { * The node is created and returned to the user, but it is not automatically * added to the nodes hash table. */ clusterNode *createClusterNode(char *nodename, int flags) { - clusterNode *node = zmalloc(sizeof(*node)); + clusterNode *node = zmalloc(sizeof(*node), MALLOC_LOCAL); if (nodename) memcpy(node->name, nodename, CLUSTER_NAMELEN); @@ -749,7 +749,7 @@ int clusterNodeAddFailureReport(clusterNode *failing, clusterNode *sender) { } /* Otherwise create a new report. */ - fr = zmalloc(sizeof(*fr)); + fr = zmalloc(sizeof(*fr), MALLOC_LOCAL); fr->node = sender; fr->time = mstime(); listAddNodeTail(l,fr); @@ -2401,7 +2401,7 @@ void clusterSendPing(clusterLink *link, int type) { /* Note: clusterBuildMessageHdr() expects the buffer to be always at least * sizeof(clusterMsg) or more. */ if (totlen < (int)sizeof(clusterMsg)) totlen = sizeof(clusterMsg); - buf = zcalloc(totlen); + buf = zcalloc(totlen, MALLOC_LOCAL); hdr = (clusterMsg*) buf; /* Populate the header. */ @@ -2538,7 +2538,7 @@ void clusterSendPublish(clusterLink *link, robj *channel, robj *message) { if (totlen < sizeof(buf)) { payload = buf; } else { - payload = zmalloc(totlen); + payload = zmalloc(totlen, MALLOC_LOCAL); memcpy(payload,hdr,sizeof(*hdr)); hdr = (clusterMsg*) payload; } @@ -2607,7 +2607,7 @@ void clusterSendModule(clusterLink *link, uint64_t module_id, uint8_t type, if (totlen < sizeof(buf)) { heapbuf = buf; } else { - heapbuf = zmalloc(totlen); + heapbuf = zmalloc(totlen, MALLOC_LOCAL); memcpy(heapbuf,hdr,sizeof(*hdr)); hdr = (clusterMsg*) heapbuf; } @@ -4277,7 +4277,7 @@ NULL /* CLUSTER ADDSLOTS [slot] ... */ /* CLUSTER DELSLOTS [slot] ... */ int j, slot; - unsigned char *slots = zmalloc(CLUSTER_SLOTS); + unsigned char *slots = zmalloc(CLUSTER_SLOTS, MALLOC_LOCAL); int del = !strcasecmp(c->argv[1]->ptr,"delslots"); memset(slots,0,CLUSTER_SLOTS); @@ -4546,7 +4546,7 @@ NULL unsigned int keys_in_slot = countKeysInSlot(slot); if (maxkeys > keys_in_slot) maxkeys = keys_in_slot; - keys = zmalloc(sizeof(robj*)*maxkeys); + keys = zmalloc(sizeof(robj*)*maxkeys, MALLOC_LOCAL); numkeys = getKeysInSlot(slot, keys, maxkeys); addReplyArrayLen(c,numkeys); for (j = 0; j < numkeys; j++) { @@ -5008,7 +5008,7 @@ migrateCachedSocket* migrateGetSocket(client *c, robj *host, robj *port, long ti } /* Add to the cache and return it to the caller. */ - cs = zmalloc(sizeof(*cs)); + cs = zmalloc(sizeof(*cs), MALLOC_LOCAL); cs->fd = fd; cs->last_dbid = -1; cs->last_use_time = server.unixtime; @@ -5256,7 +5256,7 @@ try_again: * to propagate the MIGRATE as a DEL command (if no COPY option was given). * We allocate num_keys+1 because the additional argument is for "DEL" * command name itself. */ - if (!copy) newargv = zmalloc(sizeof(robj*)*(num_keys+1)); + if (!copy) newargv = zmalloc(sizeof(robj*)*(num_keys+1), MALLOC_LOCAL); for (j = 0; j < num_keys; j++) { if (syncReadLine(cs->fd, buf2, sizeof(buf2), timeout) <= 0) { diff --git a/src/config.c b/src/config.c index 91bbdee72..be1c45235 100644 --- a/src/config.c +++ b/src/config.c @@ -159,8 +159,8 @@ void queueLoadModule(sds path, sds *argv, int argc) { int i; struct moduleLoadQueueEntry *loadmod; - loadmod = zmalloc(sizeof(struct moduleLoadQueueEntry)); - loadmod->argv = zmalloc(sizeof(robj*)*argc); + loadmod = zmalloc(sizeof(struct moduleLoadQueueEntry), MALLOC_LOCAL); + loadmod->argv = zmalloc(sizeof(robj*)*argc, MALLOC_LOCAL); loadmod->path = sdsnew(path); loadmod->argc = argc; for (i = 0; i < argc; i++) { @@ -1672,7 +1672,7 @@ void rewriteConfigMarkAsProcessed(struct rewriteConfigState *state, const char * * If the old file does not exist at all, an empty state is returned. */ struct rewriteConfigState *rewriteConfigReadOldFile(char *path) { FILE *fp = fopen(path,"r"); - struct rewriteConfigState *state = zmalloc(sizeof(*state)); + struct rewriteConfigState *state = zmalloc(sizeof(*state), MALLOC_LOCAL); char buf[CONFIG_MAX_LINE+1]; int linenum = -1; diff --git a/src/core.REMOVED.git-id b/src/core.REMOVED.git-id new file mode 100644 index 000000000..251962f07 --- /dev/null +++ b/src/core.REMOVED.git-id @@ -0,0 +1 @@ +f6027990a0231d80395d15f8f867d3a31eea285d \ No newline at end of file diff --git a/src/db.c b/src/db.c index f59ae8406..b44975b40 100644 --- a/src/db.c +++ b/src/db.c @@ -1200,7 +1200,7 @@ int *getKeysUsingCommandTable(struct redisCommand *cmd,robj **argv, int argc, in last = cmd->lastkey; if (last < 0) last = argc+last; - keys = zmalloc(sizeof(int)*((last - cmd->firstkey)+1)); + keys = zmalloc(sizeof(int)*((last - cmd->firstkey)+1), MALLOC_SHARED); for (j = cmd->firstkey; j <= last; j += cmd->keystep) { if (j >= argc) { /* Modules commands, and standard commands with a not fixed number @@ -1267,7 +1267,7 @@ int *zunionInterGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *nu /* Keys in z{union,inter}store come from two places: * argv[1] = storage key, * argv[3...n] = keys to intersect */ - keys = zmalloc(sizeof(int)*(num+1)); + keys = zmalloc(sizeof(int)*(num+1), MALLOC_SHARED); /* Add all key positions for argv[3...n] to keys[] */ for (i = 0; i < num; i++) keys[i] = 3+i; @@ -1293,7 +1293,7 @@ int *evalGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) return NULL; } - keys = zmalloc(sizeof(int)*num); + keys = zmalloc(sizeof(int)*num, MALLOC_SHARED); *numkeys = num; /* Add all key positions for argv[3...n] to keys[] */ @@ -1314,7 +1314,7 @@ int *sortGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) UNUSED(cmd); num = 0; - keys = zmalloc(sizeof(int)*2); /* Alloc 2 places for the worst case. */ + keys = zmalloc(sizeof(int)*2, MALLOC_SHARED); /* Alloc 2 places for the worst case. */ keys[num++] = 1; /* is always present. */ @@ -1372,7 +1372,7 @@ int *migrateGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkey } } - keys = zmalloc(sizeof(int)*num); + keys = zmalloc(sizeof(int)*num, MALLOC_SHARED); for (i = 0; i < num; i++) keys[i] = first+i; *numkeys = num; return keys; @@ -1405,7 +1405,7 @@ int *georadiusGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numk * argv[1] = key, * argv[5...n] = stored key if present */ - keys = zmalloc(sizeof(int) * num); + keys = zmalloc(sizeof(int) * num, MALLOC_SHARED); /* Add all key positions to keys[] */ keys[0] = 1; @@ -1454,7 +1454,7 @@ int *xreadGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) num /= 2; /* We have half the keys as there are arguments because there are also the IDs, one per key. */ - keys = zmalloc(sizeof(int) * num); + keys = zmalloc(sizeof(int) * num, MALLOC_SHARED); for (i = streams_pos+1; i < argc-num; i++) keys[i-streams_pos-1] = i; *numkeys = num; return keys; @@ -1471,7 +1471,7 @@ void slotToKeyUpdateKey(robj *key, int add) { size_t keylen = sdslen(key->ptr); server.cluster->slots_keys_count[hashslot] += add ? 1 : -1; - if (keylen+2 > 64) indexed = zmalloc(keylen+2); + if (keylen+2 > 64) indexed = zmalloc(keylen+2, MALLOC_SHARED); indexed[0] = (hashslot >> 8) & 0xff; indexed[1] = hashslot & 0xff; memcpy(indexed+2,key->ptr,keylen); diff --git a/src/debug.c b/src/debug.c index a98bc61ad..d544d8832 100644 --- a/src/debug.c +++ b/src/debug.c @@ -345,7 +345,7 @@ NULL restartServer(flags,delay); addReplyError(c,"failed to restart the server. Check server logs."); } else if (!strcasecmp(c->argv[1]->ptr,"oom")) { - void *ptr = zmalloc(ULONG_MAX); /* Should trigger an out of memory. */ + void *ptr = zmalloc(ULONG_MAX, MALLOC_LOCAL); /* Should trigger an out of memory. */ zfree(ptr); addReply(c,shared.ok); } else if (!strcasecmp(c->argv[1]->ptr,"assert")) { diff --git a/src/defrag.c b/src/defrag.c index d67b6e253..7729c594c 100644 --- a/src/defrag.c +++ b/src/defrag.c @@ -72,8 +72,8 @@ void* activeDefragAlloc(void *ptr) { /* move this allocation to a new allocation. * make sure not to use the thread cache. so that we don't get back the same * pointers we try to free */ - size = zmalloc_size(ptr); - newptr = zmalloc_no_tcache(size); + size = zmalloc_size(ptr, MALLOC_LOCAL); + newptr = zmalloc_no_tcache(size, MALLOC_LOCAL); memcpy(newptr, ptr, size); zfree_no_tcache(ptr); return newptr; diff --git a/src/dict.c b/src/dict.c index 2cf9d4839..3560eb3d3 100644 --- a/src/dict.c +++ b/src/dict.c @@ -111,7 +111,7 @@ static void _dictReset(dictht *ht) dict *dictCreate(dictType *type, void *privDataPtr) { - dict *d = zmalloc(sizeof(*d)); + dict *d = zmalloc(sizeof(*d), MALLOC_SHARED); _dictInit(d,type,privDataPtr); return d; @@ -160,7 +160,7 @@ int dictExpand(dict *d, unsigned long size) /* Allocate the new hash table and initialize all pointers to NULL */ n.size = realsize; n.sizemask = realsize-1; - n.table = zcalloc(realsize*sizeof(dictEntry*)); + n.table = zcalloc(realsize*sizeof(dictEntry*), MALLOC_SHARED); n.used = 0; /* Is this the first initialization? If so it's not really a rehashing @@ -307,7 +307,7 @@ dictEntry *dictAddRaw(dict *d, void *key, dictEntry **existing) * system it is more likely that recently added entries are accessed * more frequently. */ ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0]; - entry = zmalloc(sizeof(*entry)); + entry = zmalloc(sizeof(*entry), MALLOC_SHARED); entry->next = ht->table[index]; ht->table[index] = entry; ht->used++; @@ -541,7 +541,7 @@ long long dictFingerprint(dict *d) { dictIterator *dictGetIterator(dict *d) { - dictIterator *iter = zmalloc(sizeof(*iter)); + dictIterator *iter = zmalloc(sizeof(*iter), MALLOC_LOCAL); iter->d = d; iter->table = 0; diff --git a/src/evict.c b/src/evict.c index 773916ce8..cd033e62f 100644 --- a/src/evict.c +++ b/src/evict.c @@ -140,7 +140,7 @@ void evictionPoolAlloc(void) { struct evictionPoolEntry *ep; int j; - ep = zmalloc(sizeof(*ep)*EVPOOL_SIZE); + ep = zmalloc(sizeof(*ep)*EVPOOL_SIZE, MALLOC_LOCAL); for (j = 0; j < EVPOOL_SIZE; j++) { ep[j].idle = 0; ep[j].key = NULL; diff --git a/src/geo.c b/src/geo.c index 91a0421f5..1c792255e 100644 --- a/src/geo.c +++ b/src/geo.c @@ -51,7 +51,7 @@ int zslValueLteMax(double value, zrangespec *spec); /* Create a new array of geoPoints. */ geoArray *geoArrayCreate(void) { - geoArray *ga = zmalloc(sizeof(*ga)); + geoArray *ga = zmalloc(sizeof(*ga), MALLOC_SHARED); /* It gets allocated on first geoArrayAppend() call. */ ga->array = NULL; ga->buckets = 0; @@ -413,7 +413,7 @@ void geoaddCommand(client *c) { int elements = (c->argc - 2) / 3; int argc = 2+elements*2; /* ZADD key score ele ... */ - robj **argv = zcalloc(argc*sizeof(robj*)); + robj **argv = zcalloc(argc*sizeof(robj*), MALLOC_LOCAL); argv[0] = createRawStringObject("zadd",4); argv[1] = c->argv[1]; /* key */ incrRefCount(argv[1]); diff --git a/src/intset.c b/src/intset.c index 4445a5ca6..4cf15f4db 100644 --- a/src/intset.c +++ b/src/intset.c @@ -95,7 +95,7 @@ static void _intsetSet(intset *is, int pos, int64_t value) { /* Create an empty intset. */ intset *intsetNew(void) { - intset *is = zmalloc(sizeof(intset)); + intset *is = zmalloc(sizeof(intset), MALLOC_SHARED); is->encoding = intrev32ifbe(INTSET_ENC_INT16); is->length = 0; return is; diff --git a/src/latency.c b/src/latency.c index 33aa1245b..5b4610993 100644 --- a/src/latency.c +++ b/src/latency.c @@ -102,7 +102,7 @@ void latencyAddSample(char *event, mstime_t latency) { /* Create the time series if it does not exist. */ if (ts == NULL) { - ts = zmalloc(sizeof(*ts)); + ts = zmalloc(sizeof(*ts), MALLOC_SHARED); ts->idx = 0; ts->max = 0; memset(ts->samples,0,sizeof(ts->samples)); diff --git a/src/listpack_malloc.h b/src/listpack_malloc.h index 401ab6f74..4c0317528 100644 --- a/src/listpack_malloc.h +++ b/src/listpack_malloc.h @@ -39,7 +39,7 @@ #ifndef LISTPACK_ALLOC_H #define LISTPACK_ALLOC_H #include "zmalloc.h" -#define lp_malloc zmalloc +#define lp_malloc(size) zmalloc(size, MALLOC_SHARED) #define lp_realloc zrealloc #define lp_free zfree #endif diff --git a/src/lolwut5.c b/src/lolwut5.c index 8408b378d..b247cfb13 100644 --- a/src/lolwut5.c +++ b/src/lolwut5.c @@ -71,10 +71,10 @@ void lwTranslatePixelsGroup(int byte, char *output) { /* Allocate and return a new canvas of the specified size. */ lwCanvas *lwCreateCanvas(int width, int height) { - lwCanvas *canvas = zmalloc(sizeof(*canvas)); + lwCanvas *canvas = zmalloc(sizeof(*canvas), MALLOC_SHARED); canvas->width = width; canvas->height = height; - canvas->pixels = zmalloc(width*height); + canvas->pixels = zmalloc(width*height, MALLOC_SHARED); memset(canvas->pixels,0,width*height); return canvas; } diff --git a/src/module.c b/src/module.c index 8954fcdf0..b06493a1b 100644 --- a/src/module.c +++ b/src/module.c @@ -280,7 +280,7 @@ void RM_FreeDict(RedisModuleCtx *ctx, RedisModuleDict *d); * and in general is taken into account as memory allocated by Redis. * You should avoid using malloc(). */ void *RM_Alloc(size_t bytes) { - return zmalloc(bytes); + return zmalloc(bytes, MALLOC_LOCAL); } /* Use like calloc(). Memory allocated with this function is reported in @@ -288,7 +288,7 @@ void *RM_Alloc(size_t bytes) { * and in general is taken into account as memory allocated by Redis. * You should avoid using calloc() directly. */ void *RM_Calloc(size_t nmemb, size_t size) { - return zcalloc(nmemb*size); + return zcalloc(nmemb*size, MALLOC_LOCAL); } /* Use like realloc() for memory obtained with RedisModule_Alloc(). */ @@ -354,7 +354,7 @@ void *RM_PoolAlloc(RedisModuleCtx *ctx, size_t bytes) { if (left < bytes) { size_t blocksize = REDISMODULE_POOL_ALLOC_MIN_SIZE; if (blocksize < bytes) blocksize = bytes; - b = zmalloc(sizeof(*b) + blocksize); + b = zmalloc(sizeof(*b) + blocksize, MALLOC_LOCAL); b->size = blocksize; b->used = 0; b->next = ctx->pa_head; @@ -668,10 +668,10 @@ int RM_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc c * * Note that we use the Redis command table 'getkeys_proc' in order to * pass a reference to the command proxy structure. */ - cp = zmalloc(sizeof(*cp)); + cp = zmalloc(sizeof(*cp), MALLOC_LOCAL); cp->module = ctx->module; cp->func = cmdfunc; - cp->rediscmd = zmalloc(sizeof(*rediscmd)); + cp->rediscmd = zmalloc(sizeof(*rediscmd), MALLOC_LOCAL); cp->rediscmd->name = cmdname; cp->rediscmd->proc = RedisModuleCommandDispatcher; cp->rediscmd->arity = -1; @@ -695,7 +695,7 @@ void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int api RedisModule *module; if (ctx->module != NULL) return; - module = zmalloc(sizeof(*module)); + module = zmalloc(sizeof(*module), MALLOC_LOCAL); module->name = sdsnew((char*)name); module->ver = ver; module->apiver = apiver; @@ -1470,7 +1470,7 @@ void *RM_OpenKey(RedisModuleCtx *ctx, robj *keyname, int mode) { } /* Setup the key handle. */ - kp = zmalloc(sizeof(*kp)); + kp = zmalloc(sizeof(*kp), MALLOC_LOCAL); kp->ctx = ctx; kp->db = ctx->client->db; kp->key = keyname; @@ -2392,7 +2392,7 @@ int RM_HashGet(RedisModuleKey *key, int flags, ...) { * is processed as needed. Initially we just make sure to set the right * reply type, which is extremely cheap to do. */ RedisModuleCallReply *moduleCreateCallReplyFromProto(RedisModuleCtx *ctx, sds proto) { - RedisModuleCallReply *reply = zmalloc(sizeof(*reply)); + RedisModuleCallReply *reply = zmalloc(sizeof(*reply), MALLOC_LOCAL); reply->ctx = ctx; reply->proto = proto; reply->protolen = sdslen(proto); @@ -2482,7 +2482,7 @@ void moduleParseCallReply_Array(RedisModuleCallReply *reply) { return; } - reply->val.array = zmalloc(sizeof(RedisModuleCallReply)*arraylen); + reply->val.array = zmalloc(sizeof(RedisModuleCallReply)*arraylen, MALLOC_LOCAL); reply->len = arraylen; for (j = 0; j < arraylen; j++) { RedisModuleCallReply *ele = reply->val.array+j; @@ -2996,7 +2996,7 @@ moduleType *RM_CreateDataType(RedisModuleCtx *ctx, const char *name, int encver, moduleTypeFreeFunc free; } *tms = (struct typemethods*) typemethods_ptr; - moduleType *mt = zcalloc(sizeof(*mt)); + moduleType *mt = zcalloc(sizeof(*mt), MALLOC_LOCAL); mt->id = id; mt->module = ctx->module; mt->rdb_load = tms->rdb_load; @@ -3393,7 +3393,7 @@ void RM_EmitAOF(RedisModuleIO *io, const char *cmdname, const char *fmt, ...) { RedisModuleCtx *RM_GetContextFromIO(RedisModuleIO *io) { if (io->ctx) return io->ctx; /* Can't have more than one... */ RedisModuleCtx ctxtemplate = REDISMODULE_CTX_INIT; - io->ctx = zmalloc(sizeof(RedisModuleCtx)); + io->ctx = zmalloc(sizeof(RedisModuleCtx), MALLOC_LOCAL); *(io->ctx) = ctxtemplate; io->ctx->module = io->type->module; io->ctx->client = NULL; @@ -3530,7 +3530,7 @@ RedisModuleBlockedClient *RM_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc int islua = c->flags & CLIENT_LUA; int ismulti = c->flags & CLIENT_MULTI; - c->bpop.module_blocked_handle = zmalloc(sizeof(RedisModuleBlockedClient)); + c->bpop.module_blocked_handle = zmalloc(sizeof(RedisModuleBlockedClient), MALLOC_LOCAL); RedisModuleBlockedClient *bc = c->bpop.module_blocked_handle; /* We need to handle the invalid operation of calling modules blocking @@ -3780,7 +3780,7 @@ int RM_BlockedClientDisconnected(RedisModuleCtx *ctx) { * TODO: thread safe contexts do not inherit the blocked client * selected database. */ RedisModuleCtx *RM_GetThreadSafeContext(RedisModuleBlockedClient *bc) { - RedisModuleCtx *ctx = zmalloc(sizeof(*ctx)); + RedisModuleCtx *ctx = zmalloc(sizeof(*ctx), MALLOC_LOCAL); RedisModuleCtx empty = REDISMODULE_CTX_INIT; memcpy(ctx,&empty,sizeof(empty)); if (bc) { @@ -3880,7 +3880,7 @@ void moduleReleaseGIL(void) { * See https://redis.io/topics/notifications for more information. */ int RM_SubscribeToKeyspaceEvents(RedisModuleCtx *ctx, int types, RedisModuleNotificationFunc callback) { - RedisModuleKeyspaceSubscriber *sub = zmalloc(sizeof(*sub)); + RedisModuleKeyspaceSubscriber *sub = zmalloc(sizeof(*sub), MALLOC_LOCAL); sub->module = ctx->module; sub->event_mask = types; sub->notify_callback = callback; @@ -4017,7 +4017,7 @@ void RM_RegisterClusterMessageReceiver(RedisModuleCtx *ctx, uint8_t type, RedisM /* Not found, let's add it. */ if (callback) { - r = zmalloc(sizeof(*r)); + r = zmalloc(sizeof(*r), MALLOC_LOCAL); r->module_id = module_id; r->module = ctx->module; r->callback = callback; @@ -4069,14 +4069,14 @@ char **RM_GetClusterNodesList(RedisModuleCtx *ctx, size_t *numnodes) { if (!server.cluster_enabled) return NULL; size_t count = dictSize(server.cluster->nodes); - char **ids = zmalloc((count+1)*REDISMODULE_NODE_ID_LEN); + char **ids = zmalloc((count+1)*REDISMODULE_NODE_ID_LEN, MALLOC_LOCAL); dictIterator *di = dictGetIterator(server.cluster->nodes); dictEntry *de; int j = 0; while((de = dictNext(di)) != NULL) { clusterNode *node = dictGetVal(de); if (node->flags & (CLUSTER_NODE_NOADDR|CLUSTER_NODE_HANDSHAKE)) continue; - ids[j] = zmalloc(REDISMODULE_NODE_ID_LEN); + ids[j] = zmalloc(REDISMODULE_NODE_ID_LEN, MALLOC_LOCAL); memcpy(ids[j],node->name,REDISMODULE_NODE_ID_LEN); j++; } @@ -4269,7 +4269,7 @@ int moduleTimerHandler(struct aeEventLoop *eventLoop, long long id, void *client * the specified function using `data` as argument. The returned timer ID can be * used to get information from the timer or to stop it before it fires. */ RedisModuleTimerID RM_CreateTimer(RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data) { - RedisModuleTimer *timer = zmalloc(sizeof(*timer)); + RedisModuleTimer *timer = zmalloc(sizeof(*timer), MALLOC_LOCAL); timer->module = ctx->module; timer->callback = callback; timer->data = data; @@ -4367,7 +4367,7 @@ int RM_GetTimerInfo(RedisModuleCtx *ctx, RedisModuleTimerID id, uint64_t *remain * Next / Prev dictionary iterator calls. */ RedisModuleDict *RM_CreateDict(RedisModuleCtx *ctx) { - struct RedisModuleDict *d = zmalloc(sizeof(*d)); + struct RedisModuleDict *d = zmalloc(sizeof(*d), MALLOC_LOCAL); d->rax = raxNew(); if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_DICT,d); return d; @@ -4467,7 +4467,7 @@ int RM_DictDel(RedisModuleDict *d, RedisModuleString *key, void *oldval) { * REDISMODULE_ERR at the first call, otherwise they'll produce elements. */ RedisModuleDictIter *RM_DictIteratorStartC(RedisModuleDict *d, const char *op, void *key, size_t keylen) { - RedisModuleDictIter *di = zmalloc(sizeof(*di)); + RedisModuleDictIter *di = zmalloc(sizeof(*di), MALLOC_LOCAL); di->dict = d; raxStart(&di->ri,d->rax); raxSeek(&di->ri,op,key,keylen); diff --git a/src/multi.c b/src/multi.c index 71090d8ed..720ec90e2 100644 --- a/src/multi.c +++ b/src/multi.c @@ -63,7 +63,7 @@ void queueMultiCommand(client *c) { mc = c->mstate.commands+c->mstate.count; mc->cmd = c->cmd; mc->argc = c->argc; - mc->argv = zmalloc(sizeof(robj*)*c->argc); + mc->argv = zmalloc(sizeof(robj*)*c->argc, MALLOC_LOCAL); memcpy(mc->argv,c->argv,sizeof(robj*)*c->argc); for (j = 0; j < c->argc; j++) incrRefCount(mc->argv[j]); @@ -253,7 +253,7 @@ void watchForKey(client *c, robj *key) { } listAddNodeTail(clients,c); /* Add the new key to the list of keys watched by this client */ - wk = zmalloc(sizeof(*wk)); + wk = zmalloc(sizeof(*wk), MALLOC_SHARED); wk->key = key; wk->db = c->db; incrRefCount(key); diff --git a/src/networking.c b/src/networking.c index 9e62cb6be..b853da5bd 100644 --- a/src/networking.c +++ b/src/networking.c @@ -57,7 +57,7 @@ size_t getStringObjectSdsUsedMemory(robj *o) { /* Client.reply list dup and free methods. */ void *dupClientReplyValue(void *o) { clientReplyBlock *old = o; - clientReplyBlock *buf = zmalloc(sizeof(clientReplyBlock) + old->size); + clientReplyBlock *buf = zmalloc(sizeof(clientReplyBlock) + old->size, MALLOC_LOCAL); memcpy(buf, o, sizeof(clientReplyBlock) + old->size); return buf; } @@ -83,7 +83,7 @@ void linkClient(client *c) { } client *createClient(int fd) { - client *c = zmalloc(sizeof(client)); + client *c = zmalloc(sizeof(client), MALLOC_LOCAL); /* passing -1 as fd it is possible to create a non connected client. * This is useful since all the commands needs to be executed @@ -281,7 +281,7 @@ void _addReplyProtoToList(client *c, const char *s, size_t len) { /* Create a new node, make sure it is allocated to at * least PROTO_REPLY_CHUNK_BYTES */ size_t size = len < PROTO_REPLY_CHUNK_BYTES? PROTO_REPLY_CHUNK_BYTES: len; - tail = zmalloc(size + sizeof(clientReplyBlock)); + tail = zmalloc(size + sizeof(clientReplyBlock), MALLOC_LOCAL); /* take over the allocation's internal fragmentation */ tail->size = zmalloc_usable(tail) - sizeof(clientReplyBlock); tail->used = len; @@ -460,7 +460,7 @@ void setDeferredAggregateLen(client *c, void *node, long length, char prefix) { listDelNode(c->reply,ln); } else { /* Create a new node */ - clientReplyBlock *buf = zmalloc(lenstr_len + sizeof(clientReplyBlock)); + clientReplyBlock *buf = zmalloc(lenstr_len + sizeof(clientReplyBlock), MALLOC_LOCAL); /* Take over the allocation's internal fragmentation */ buf->size = zmalloc_usable(buf) - sizeof(clientReplyBlock); buf->used = lenstr_len; @@ -1333,7 +1333,7 @@ int processInlineBuffer(client *c) { /* Setup argv array on client structure */ if (argc) { if (c->argv) zfree(c->argv); - c->argv = zmalloc(sizeof(robj*)*argc); + c->argv = zmalloc(sizeof(robj*)*argc, MALLOC_LOCAL); } /* Create redis objects for all arguments. */ @@ -1345,7 +1345,7 @@ int processInlineBuffer(client *c) { sdsfree(argv[j]); } } - zfree(argv); + sds_free(argv); return C_OK; } @@ -1431,7 +1431,7 @@ int processMultibulkBuffer(client *c) { /* Setup argv array on client structure */ if (c->argv) zfree(c->argv); - c->argv = zmalloc(sizeof(robj*)*c->multibulklen); + c->argv = zmalloc(sizeof(robj*)*c->multibulklen, MALLOC_LOCAL); } serverAssertWithInfo(c,NULL,c->multibulklen > 0); @@ -2123,7 +2123,7 @@ void rewriteClientCommandVector(client *c, int argc, ...) { int j; robj **argv; /* The new argument vector */ - argv = zmalloc(sizeof(robj*)*argc); + argv = zmalloc(sizeof(robj*)*argc, MALLOC_LOCAL); va_start(ap,argc); for (j = 0; j < argc; j++) { robj *a; diff --git a/src/object.c b/src/object.c index ec0bd02ee..ddd50b553 100644 --- a/src/object.c +++ b/src/object.c @@ -39,7 +39,7 @@ /* ===================== Creation and parsing of objects ==================== */ robj *createObject(int type, void *ptr) { - robj *o = zmalloc(sizeof(*o)); + robj *o = salloc_obj(); //zmalloc(sizeof(*o), MALLOC_SHARED); o->type = type; o->encoding = OBJ_ENCODING_RAW; o->ptr = ptr; @@ -82,7 +82,7 @@ robj *createRawStringObject(const char *ptr, size_t len) { * an object where the sds string is actually an unmodifiable string * allocated in the same chunk as the object itself. */ robj *createEmbeddedStringObject(const char *ptr, size_t len) { - robj *o = zmalloc(sizeof(robj)+sizeof(struct sdshdr8)+len+1); + robj *o = zmalloc(sizeof(robj)+sizeof(struct sdshdr8)+len+1, MALLOC_SHARED); struct sdshdr8 *sh = (void*)(o+1); o->type = OBJ_STRING; @@ -247,7 +247,7 @@ robj *createHashObject(void) { } robj *createZsetObject(void) { - zset *zs = zmalloc(sizeof(*zs)); + zset *zs = zmalloc(sizeof(*zs), MALLOC_SHARED); robj *o; zs->dict = dictCreate(&zsetDictType,NULL); @@ -272,7 +272,7 @@ robj *createStreamObject(void) { } robj *createModuleObject(moduleType *mt, void *value) { - moduleValue *mv = zmalloc(sizeof(*mv)); + moduleValue *mv = zmalloc(sizeof(*mv), MALLOC_SHARED); mv->type = mt; mv->value = value; return createObject(OBJ_MODULE,mv); @@ -362,7 +362,10 @@ void decrRefCount(robj *o) { case OBJ_STREAM: freeStreamObject(o); break; default: serverPanic("Unknown object type"); break; } - zfree(o); + if (o->type == OBJ_STRING && o->encoding == OBJ_ENCODING_EMBSTR) + zfree(o); + else + sfree_obj(o); } else { if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0"); if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount--; @@ -945,7 +948,7 @@ struct redisMemOverhead *getMemoryOverheadData(void) { size_t mem_total = 0; size_t mem = 0; size_t zmalloc_used = zmalloc_used_memory(); - struct redisMemOverhead *mh = zcalloc(sizeof(*mh)); + struct redisMemOverhead *mh = zcalloc(sizeof(*mh), MALLOC_LOCAL); mh->total_allocated = zmalloc_used; mh->startup_allocated = server.initial_memory_usage; diff --git a/src/pubsub.c b/src/pubsub.c index 994dd9734..a7ee67400 100644 --- a/src/pubsub.c +++ b/src/pubsub.c @@ -209,7 +209,7 @@ int pubsubSubscribePattern(client *c, robj *pattern) { pubsubPattern *pat; listAddNodeTail(c->pubsub_patterns,pattern); incrRefCount(pattern); - pat = zmalloc(sizeof(*pat)); + pat = zmalloc(sizeof(*pat), MALLOC_LOCAL); pat->pattern = getDecodedObject(pattern); pat->client = c; listAddNodeTail(server.pubsub_patterns,pat); diff --git a/src/quicklist.c b/src/quicklist.c index 7b5484116..ea0a2ae77 100644 --- a/src/quicklist.c +++ b/src/quicklist.c @@ -94,7 +94,7 @@ static const size_t optimization_level[] = {4096, 8192, 16384, 32768, 65536}; quicklist *quicklistCreate(void) { struct quicklist *quicklist; - quicklist = zmalloc(sizeof(*quicklist)); + quicklist = zmalloc(sizeof(*quicklist), MALLOC_SHARED); quicklist->head = quicklist->tail = NULL; quicklist->len = 0; quicklist->count = 0; @@ -137,7 +137,7 @@ quicklist *quicklistNew(int fill, int compress) { REDIS_STATIC quicklistNode *quicklistCreateNode(void) { quicklistNode *node; - node = zmalloc(sizeof(*node)); + node = zmalloc(sizeof(*node), MALLOC_SHARED); node->zl = NULL; node->count = 0; node->sz = 0; @@ -184,7 +184,7 @@ REDIS_STATIC int __quicklistCompressNode(quicklistNode *node) { if (node->sz < MIN_COMPRESS_BYTES) return 0; - quicklistLZF *lzf = zmalloc(sizeof(*lzf) + node->sz); + quicklistLZF *lzf = zmalloc(sizeof(*lzf) + node->sz, MALLOC_SHARED); /* Cancel if compression fails or doesn't compress small enough */ if (((lzf->sz = lzf_compress(node->zl, node->sz, lzf->compressed, @@ -217,7 +217,7 @@ REDIS_STATIC int __quicklistDecompressNode(quicklistNode *node) { node->attempted_compress = 0; #endif - void *decompressed = zmalloc(node->sz); + void *decompressed = zmalloc(node->sz, MALLOC_SHARED); quicklistLZF *lzf = (quicklistLZF *)node->zl; if (lzf_decompress(lzf->compressed, lzf->sz, decompressed, node->sz) == 0) { /* Someone requested decompress, but we can't decompress. Not good. */ @@ -799,7 +799,7 @@ REDIS_STATIC quicklistNode *_quicklistSplitNode(quicklistNode *node, int offset, size_t zl_sz = node->sz; quicklistNode *new_node = quicklistCreateNode(); - new_node->zl = zmalloc(zl_sz); + new_node->zl = zmalloc(zl_sz, MALLOC_SHARED); /* Copy original ziplist so we can split it */ memcpy(new_node->zl, node->zl, zl_sz); @@ -1048,7 +1048,7 @@ int quicklistCompare(unsigned char *p1, unsigned char *p2, int p2_len) { quicklistIter *quicklistGetIterator(const quicklist *quicklist, int direction) { quicklistIter *iter; - iter = zmalloc(sizeof(*iter)); + iter = zmalloc(sizeof(*iter), MALLOC_LOCAL); if (direction == AL_START_HEAD) { iter->current = quicklist->head; @@ -1195,10 +1195,10 @@ quicklist *quicklistDup(quicklist *orig) { if (current->encoding == QUICKLIST_NODE_ENCODING_LZF) { quicklistLZF *lzf = (quicklistLZF *)current->zl; size_t lzf_sz = sizeof(*lzf) + lzf->sz; - node->zl = zmalloc(lzf_sz); + node->zl = zmalloc(lzf_sz, MALLOC_SHARED); memcpy(node->zl, current->zl, lzf_sz); } else if (current->encoding == QUICKLIST_NODE_ENCODING_RAW) { - node->zl = zmalloc(current->sz); + node->zl = zmalloc(current->sz, MALLOC_SHARED); memcpy(node->zl, current->zl, current->sz); } @@ -1372,7 +1372,7 @@ int quicklistPopCustom(quicklist *quicklist, int where, unsigned char **data, REDIS_STATIC void *_quicklistSaver(unsigned char *data, unsigned int sz) { unsigned char *vstr; if (data) { - vstr = zmalloc(sz); + vstr = zmalloc(sz, MALLOC_SHARED); memcpy(vstr, data, sz); return vstr; } diff --git a/src/rax_malloc.h b/src/rax_malloc.h index 9295985c6..a5aea44d9 100644 --- a/src/rax_malloc.h +++ b/src/rax_malloc.h @@ -38,7 +38,7 @@ #ifndef RAX_ALLOC_H #define RAX_ALLOC_H #include "zmalloc.h" -#define rax_malloc zmalloc +#define rax_malloc(size) zmalloc(size, MALLOC_SHARED) #define rax_realloc zrealloc #define rax_free zfree #endif diff --git a/src/rdb.c b/src/rdb.c index 351b90774..32a3df1d5 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -32,6 +32,7 @@ #include "zipmap.h" #include "endianconv.h" #include "stream.h" +#include "storage.h" #include #include @@ -284,7 +285,7 @@ void *rdbLoadIntegerObject(rio *rdb, int enctype, int flags, size_t *lenptr) { char buf[LONG_STR_SIZE], *p; int len = ll2string(buf,sizeof(buf),val); if (lenptr) *lenptr = len; - p = plain ? zmalloc(len) : sdsnewlen(SDS_NOINIT,len); + p = plain ? zmalloc(len, MALLOC_SHARED) : sdsnewlen(SDS_NOINIT,len); memcpy(p,buf,len); return p; } else if (encode) { @@ -345,7 +346,7 @@ ssize_t rdbSaveLzfStringObject(rio *rdb, unsigned char *s, size_t len) { /* We require at least four bytes compression for this to be worth it */ if (len <= 4) return 0; outlen = len-4; - if ((out = zmalloc(outlen+1)) == NULL) return 0; + if ((out = zmalloc(outlen+1, MALLOC_LOCAL)) == NULL) return 0; comprlen = lzf_compress(s, len, out, outlen); if (comprlen == 0) { zfree(out); @@ -368,11 +369,11 @@ void *rdbLoadLzfStringObject(rio *rdb, int flags, size_t *lenptr) { if ((clen = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL; if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL; - if ((c = zmalloc(clen)) == NULL) goto err; + if ((c = zmalloc(clen, MALLOC_SHARED)) == NULL) goto err; /* Allocate our target according to the uncompressed size. */ if (plain) { - val = zmalloc(len); + val = zmalloc(len, MALLOC_SHARED); } else { val = sdsnewlen(SDS_NOINIT,len); } @@ -501,7 +502,7 @@ void *rdbGenericLoadStringObject(rio *rdb, int flags, size_t *lenptr) { if (len == RDB_LENERR) return NULL; if (plain || sds) { - void *buf = plain ? zmalloc(len) : sdsnewlen(SDS_NOINIT,len); + void *buf = plain ? zmalloc(len, MALLOC_SHARED) : sdsnewlen(SDS_NOINIT,len); if (lenptr) *lenptr = len; if (len && rioRead(rdb,buf,len) == 0) { if (plain) @@ -1290,10 +1291,12 @@ int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) { openChildInfoPipe(); start = ustime(); + handle_prefork(); if ((childpid = fork()) == 0) { int retval; /* Child */ + handle_postfork(0); closeListeningSockets(0); redisSetProcTitle("redis-rdb-bgsave"); retval = rdbSave(filename,rsi); @@ -1312,6 +1315,7 @@ int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) { exitFromChild((retval == C_OK) ? 0 : 1); } else { /* Parent */ + handle_postfork(childpid); server.stat_fork_time = ustime()-start; server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */ latencyAddSampleIfNeeded("fork",server.stat_fork_time/1000); @@ -2141,7 +2145,7 @@ void backgroundSaveDoneHandlerSocket(int exitcode, int bysignal) { * If the process returned an error, consider the list of slaves that * can continue to be empty, so that it's just a special case of the * normal code path. */ - ok_slaves = zmalloc(sizeof(uint64_t)); /* Make space for the count. */ + ok_slaves = zmalloc(sizeof(uint64_t), MALLOC_LOCAL); /* Make space for the count. */ ok_slaves[0] = 0; if (!bysignal && exitcode == 0) { int readlen = sizeof(uint64_t); @@ -2258,11 +2262,11 @@ int rdbSaveToSlavesSockets(rdbSaveInfo *rsi) { /* Collect the file descriptors of the slaves we want to transfer * the RDB to, which are i WAIT_BGSAVE_START state. */ - fds = zmalloc(sizeof(int)*listLength(server.slaves)); + fds = zmalloc(sizeof(int)*listLength(server.slaves), MALLOC_LOCAL); /* We also allocate an array of corresponding client IDs. This will * be useful for the child process in order to build the report * (sent via unix pipe) that will be sent to the parent. */ - clientids = zmalloc(sizeof(uint64_t)*listLength(server.slaves)); + clientids = zmalloc(sizeof(uint64_t)*listLength(server.slaves), MALLOC_LOCAL); numfds = 0; listRewind(server.slaves,&li); @@ -2326,7 +2330,7 @@ int rdbSaveToSlavesSockets(rdbSaveInfo *rsi) { * can match the report with a specific slave, and 'error' is * set to 0 if the replication process terminated with a success * or the error code if an error occurred. */ - void *msg = zmalloc(sizeof(uint64_t)*(1+2*numfds)); + void *msg = zmalloc(sizeof(uint64_t)*(1+2*numfds), MALLOC_LOCAL); uint64_t *len = msg; uint64_t *ids = len+1; int j, msglen; diff --git a/src/redis-benchmark.c b/src/redis-benchmark.c index d30879dc4..716c492df 100644 --- a/src/redis-benchmark.c +++ b/src/redis-benchmark.c @@ -45,6 +45,7 @@ #include "hiredis.h" #include "adlist.h" #include "zmalloc.h" +#include "storage.h" #define UNUSED(V) ((void) V) #define RANDPTR_INITIAL_SIZE 8 @@ -315,7 +316,7 @@ static void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask) { * Even when cloning another client, prefix commands are applied if needed.*/ static client createClient(char *cmd, size_t len, client from) { int j; - client c = zmalloc(sizeof(struct _client)); + client c = zmalloc(sizeof(struct _client), MALLOC_LOCAL); if (config.hostsocket == NULL) { c->context = redisConnectNonBlock(config.hostip,config.hostport); @@ -379,7 +380,7 @@ static client createClient(char *cmd, size_t len, client from) { if (from) { c->randlen = from->randlen; c->randfree = 0; - c->randptr = zmalloc(sizeof(char*)*c->randlen); + c->randptr = zmalloc(sizeof(char*)*c->randlen, MALLOC_LOCAL); /* copy the offsets. */ for (j = 0; j < (int)c->randlen; j++) { c->randptr[j] = c->obuf + (from->randptr[j]-from->obuf); @@ -391,7 +392,7 @@ static client createClient(char *cmd, size_t len, client from) { c->randlen = 0; c->randfree = RANDPTR_INITIAL_SIZE; - c->randptr = zmalloc(sizeof(char*)*c->randfree); + c->randptr = zmalloc(sizeof(char*)*c->randfree, MALLOC_LOCAL); while ((p = strstr(p,"__rand_int__")) != NULL) { if (c->randfree == 0) { c->randptr = zrealloc(c->randptr,sizeof(char*)*c->randlen*2); @@ -652,6 +653,8 @@ int main(int argc, const char **argv) { client c; + storage_init(); + srandom(time(NULL)); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); @@ -684,7 +687,7 @@ int main(int argc, const char **argv) { argc -= i; argv += i; - config.latency = zmalloc(sizeof(long long)*config.requests); + config.latency = zmalloc(sizeof(long long)*config.requests, MALLOC_LOCAL); if (config.keepalive == 0) { printf("WARNING: keepalive disabled, you probably need 'echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse' for Linux and 'sudo sysctl -w net.inet.tcp.msl=1000' for Mac OS X in order to use a lot of clients/requests\n"); @@ -716,7 +719,7 @@ int main(int argc, const char **argv) { } /* Run default benchmark suite. */ - data = zmalloc(config.datasize+1); + data = zmalloc(config.datasize+1, MALLOC_LOCAL); do { memset(data,'x',config.datasize); data[config.datasize] = '\0'; diff --git a/src/redis-check-aof.c b/src/redis-check-aof.c index c4d5a225e..a79adb946 100644 --- a/src/redis-check-aof.c +++ b/src/redis-check-aof.c @@ -82,7 +82,7 @@ int readString(FILE *fp, char** target) { /* Increase length to also consume \r\n */ len += 2; - *target = (char*)zmalloc(len); + *target = (char*)zmalloc(len, MALLOC_LOCAL); if (!readBytes(fp,*target,len)) { return 0; } diff --git a/src/redis-cli.c b/src/redis-cli.c index 93290e5ed..91deac496 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -55,6 +55,7 @@ #include "help.h" #include "anet.h" #include "ae.h" +#include "storage.h" #define UNUSED(V) ((void) V) @@ -477,11 +478,11 @@ static void cliInitHelp(void) { helpEntry tmp; helpEntriesLen = len = commandslen+groupslen; - helpEntries = zmalloc(sizeof(helpEntry)*len); + helpEntries = zmalloc(sizeof(helpEntry)*len, MALLOC_LOCAL); for (i = 0; i < groupslen; i++) { tmp.argc = 1; - tmp.argv = zmalloc(sizeof(sds)); + tmp.argv = zmalloc(sizeof(sds), MALLOC_LOCAL); tmp.argv[0] = sdscatprintf(sdsempty(),"@%s",commandGroups[i]); tmp.full = tmp.argv[0]; tmp.type = CLI_HELP_GROUP; @@ -532,13 +533,13 @@ static void cliIntegrateHelp(void) { helpEntry *new = helpEntries+(helpEntriesLen-1); new->argc = 1; - new->argv = zmalloc(sizeof(sds)); + new->argv = zmalloc(sizeof(sds), MALLOC_LOCAL); new->argv[0] = sdsnew(cmdname); new->full = new->argv[0]; new->type = CLI_HELP_COMMAND; sdstoupper(new->argv[0]); - struct commandHelp *ch = zmalloc(sizeof(*ch)); + struct commandHelp *ch = zmalloc(sizeof(*ch), MALLOC_LOCAL); ch->name = new->argv[0]; ch->params = sdsempty(); int args = llabs(entry->element[1]->integer); @@ -1171,7 +1172,7 @@ static int cliSendCommand(int argc, char **argv, long repeat) { } /* Setup argument length */ - argvlen = zmalloc(argc*sizeof(size_t)); + argvlen = zmalloc(argc*sizeof(size_t), MALLOC_LOCAL); for (j = 0; j < argc; j++) argvlen[j] = sdslen(argv[j]); @@ -1590,7 +1591,7 @@ static int confirmWithYes(char *msg) { /* Turn the plain C strings into Sds strings */ static char **convertToSds(int count, char** args) { int j; - char **sds = zmalloc(sizeof(char*)*count); + char **sds = zmalloc(sizeof(char*)*count, MALLOC_LOCAL); for(j = 0; j < count; j++) sds[j] = sdsnew(args[j]); @@ -1872,7 +1873,7 @@ static int evalMode(int argc, char **argv) { } /* Create our argument vector */ - argv2 = zmalloc(sizeof(sds)*(argc+3)); + argv2 = zmalloc(sizeof(sds)*(argc+3), MALLOC_LOCAL); argv2[0] = sdsnew("EVAL"); argv2[1] = script; for (j = 0; j < argc; j++) { @@ -2193,7 +2194,7 @@ static void freeClusterManager(void) { } static clusterManagerNode *clusterManagerNewNode(char *ip, int port) { - clusterManagerNode *node = zmalloc(sizeof(*node)); + clusterManagerNode *node = zmalloc(sizeof(*node), MALLOC_LOCAL); node->context = NULL; node->name = NULL; node->ip = ip; @@ -2228,7 +2229,7 @@ static int clusterManagerCheckRedisReply(clusterManagerNode *n, if (!r || (is_err = (r->type == REDIS_REPLY_ERROR))) { if (is_err) { if (err != NULL) { - *err = zmalloc((r->len + 1) * sizeof(char)); + *err = zmalloc((r->len + 1) * sizeof(char), MALLOC_LOCAL); strcpy(*err, r->str); } else CLUSTER_MANAGER_PRINT_REPLY_ERROR(n, r->str); } @@ -2374,7 +2375,7 @@ static redisReply *clusterManagerGetNodeRedisInfo(clusterManagerNode *node, if (info == NULL) return NULL; if (info->type == REDIS_REPLY_ERROR) { if (err != NULL) { - *err = zmalloc((info->len + 1) * sizeof(char)); + *err = zmalloc((info->len + 1) * sizeof(char), MALLOC_LOCAL); strcpy(*err, info->str); } freeReplyObject(info); @@ -2451,7 +2452,7 @@ static int clusterManagerGetAntiAffinityScore(clusterManagerNodeArray *ipnodes, int node_len = cluster_manager.nodes->len; clusterManagerNode **offending_p = NULL; if (offending != NULL) { - *offending = zcalloc(node_len * sizeof(clusterManagerNode*)); + *offending = zcalloc(node_len * sizeof(clusterManagerNode*), MALLOC_LOCAL); offending_p = *offending; } /* For each set of nodes in the same host, split by @@ -2541,7 +2542,7 @@ static void clusterManagerOptimizeAntiAffinity(clusterManagerNodeArray *ipnodes, clusterManagerNode *first = offenders[rand_idx], *second = NULL; clusterManagerNode **other_replicas = zcalloc((node_len - 1) * - sizeof(*other_replicas)); + sizeof(*other_replicas), MALLOC_LOCAL); int other_replicas_count = 0; listIter li; listNode *ln; @@ -2769,8 +2770,8 @@ static int clusterManagerAddSlots(clusterManagerNode *node, char**err) int success = 1; /* First two args are used for the command itself. */ int argc = node->slots_count + 2; - sds *argv = zmalloc(argc * sizeof(*argv)); - size_t *argvlen = zmalloc(argc * sizeof(*argvlen)); + sds *argv = zmalloc(argc * sizeof(*argv), MALLOC_LOCAL); + size_t *argvlen = zmalloc(argc * sizeof(*argvlen), MALLOC_LOCAL); argv[0] = "CLUSTER"; argv[1] = "ADDSLOTS"; argvlen[0] = 7; @@ -2869,7 +2870,7 @@ static int clusterManagerSetSlot(clusterManagerNode *node1, if (reply->type == REDIS_REPLY_ERROR) { success = 0; if (err != NULL) { - *err = zmalloc((reply->len + 1) * sizeof(char)); + *err = zmalloc((reply->len + 1) * sizeof(char), MALLOC_LOCAL); strcpy(*err, reply->str); } else CLUSTER_MANAGER_PRINT_REPLY_ERROR(node1, reply->str); goto cleanup; @@ -2983,8 +2984,8 @@ static int clusterManagerCompareKeysValues(clusterManagerNode *n1, { size_t i, argc = keys_reply->elements + 2; static const char *hash_zero = "0000000000000000000000000000000000000000"; - char **argv = zcalloc(argc * sizeof(char *)); - size_t *argv_len = zcalloc(argc * sizeof(size_t)); + char **argv = zcalloc(argc * sizeof(char *), MALLOC_LOCAL); + size_t *argv_len = zcalloc(argc * sizeof(size_t), MALLOC_LOCAL); argv[0] = "DEBUG"; argv_len[0] = 5; argv[1] = "DIGEST-VALUE"; @@ -3051,8 +3052,8 @@ static redisReply *clusterManagerMigrateKeysInReply(clusterManagerNode *source, if (config.auth) c += 2; size_t argc = c + reply->elements; size_t i, offset = 6; // Keys Offset - argv = zcalloc(argc * sizeof(char *)); - argv_len = zcalloc(argc * sizeof(size_t)); + argv = zcalloc(argc * sizeof(char *), MALLOC_LOCAL); + argv_len = zcalloc(argc * sizeof(size_t), MALLOC_LOCAL); char portstr[255]; char timeoutstr[255]; snprintf(portstr, 10, "%d", target->port); @@ -3130,7 +3131,7 @@ static int clusterManagerMigrateKeysInSlot(clusterManagerNode *source, if (reply->type == REDIS_REPLY_ERROR) { success = 0; if (err != NULL) { - *err = zmalloc((reply->len + 1) * sizeof(char)); + *err = zmalloc((reply->len + 1) * sizeof(char), MALLOC_LOCAL); strcpy(*err, reply->str); CLUSTER_MANAGER_PRINT_REPLY_ERROR(source, *err); } @@ -3142,7 +3143,7 @@ static int clusterManagerMigrateKeysInSlot(clusterManagerNode *source, freeReplyObject(reply); break; } - if (verbose) dots = zmalloc((count+1) * sizeof(char)); + if (verbose) dots = zmalloc((count+1) * sizeof(char), MALLOC_LOCAL); /* Calling MIGRATE command. */ migrate_reply = clusterManagerMigrateKeysInReply(source, target, reply, 0, timeout, @@ -3242,7 +3243,7 @@ static int clusterManagerMigrateKeysInSlot(clusterManagerNode *source, if (!success) { if (migrate_reply != NULL) { if (err) { - *err = zmalloc((migrate_reply->len + 1) * sizeof(char)); + *err = zmalloc((migrate_reply->len + 1) * sizeof(char), MALLOC_LOCAL); strcpy(*err, migrate_reply->str); } printf("\n"); @@ -3318,7 +3319,7 @@ static int clusterManagerMoveSlot(clusterManagerNode *source, if (r->type == REDIS_REPLY_ERROR) { success = 0; if (err != NULL) { - *err = zmalloc((r->len + 1) * sizeof(char)); + *err = zmalloc((r->len + 1) * sizeof(char), MALLOC_LOCAL); strcpy(*err, r->str); CLUSTER_MANAGER_PRINT_REPLY_ERROR(n, *err); } @@ -3347,7 +3348,7 @@ static int clusterManagerFlushNodeConfig(clusterManagerNode *node, char **err) { node->replicate); if (reply == NULL || (is_err = (reply->type == REDIS_REPLY_ERROR))) { if (is_err && err != NULL) { - *err = zmalloc((reply->len + 1) * sizeof(char)); + *err = zmalloc((reply->len + 1) * sizeof(char), MALLOC_LOCAL); strcpy(*err, reply->str); } success = 0; @@ -3715,7 +3716,7 @@ static sds clusterManagerGetConfigSignature(clusterManagerNode *node) { zrealloc(node_configs, (node_count * sizeof(char *))); /* Make room for '|' separators. */ tot_size += (sizeof(char) * (c - 1)); - char *cfg = zmalloc((sizeof(char) * tot_size) + 1); + char *cfg = zmalloc((sizeof(char) * tot_size) + 1, MALLOC_LOCAL); memcpy(cfg, nodename, name_len); char *sp = cfg + name_len; *(sp++) = ':'; @@ -4641,7 +4642,7 @@ static clusterManagerNode *clusterNodeForResharding(char *id, static list *clusterManagerComputeReshardTable(list *sources, int numslots) { list *moved = listCreate(); int src_count = listLength(sources), i = 0, tot_slots = 0, j; - clusterManagerNode **sorted = zmalloc(src_count * sizeof(*sorted)); + clusterManagerNode **sorted = zmalloc(src_count * sizeof(*sorted), MALLOC_LOCAL); listIter li; listNode *ln; listRewind(sources, &li); @@ -4662,7 +4663,7 @@ static list *clusterManagerComputeReshardTable(list *sources, int numslots) { int slot = node->slots[j]; if (!slot) continue; if (count >= max || (int)listLength(moved) >= numslots) break; - clusterManagerReshardTableItem *item = zmalloc(sizeof(*item)); + clusterManagerReshardTableItem *item = zmalloc(sizeof(*item), MALLOC_LOCAL); item->source = node; item->slot = j; listAddNodeTail(moved, item); @@ -4720,7 +4721,7 @@ static void clusterManagerLog(int level, const char* fmt, ...) { static void clusterManagerNodeArrayInit(clusterManagerNodeArray *array, int alloc_len) { - array->nodes = zcalloc(alloc_len * sizeof(clusterManagerNode*)); + array->nodes = zcalloc(alloc_len * sizeof(clusterManagerNode*), MALLOC_LOCAL); array->alloc = array->nodes; array->len = alloc_len; array->count = 0; @@ -4861,9 +4862,9 @@ static int clusterManagerCommandCreate(int argc, char **argv) { clusterManagerLogInfo(">>> Performing hash slots allocation " "on %d nodes...\n", node_len); int interleaved_len = 0, ip_count = 0; - clusterManagerNode **interleaved = zcalloc(node_len*sizeof(**interleaved)); - char **ips = zcalloc(node_len * sizeof(char*)); - clusterManagerNodeArray *ip_nodes = zcalloc(node_len * sizeof(*ip_nodes)); + clusterManagerNode **interleaved = zcalloc(node_len*sizeof(**interleaved), MALLOC_LOCAL); + char **ips = zcalloc(node_len * sizeof(char*), MALLOC_LOCAL); + clusterManagerNodeArray *ip_nodes = zcalloc(node_len * sizeof(*ip_nodes), MALLOC_LOCAL); listIter li; listNode *ln; listRewind(cluster_manager.nodes, &li); @@ -5500,7 +5501,7 @@ static int clusterManagerCommandRebalance(int argc, char **argv) { nodes_involved++; listAddNodeTail(involved, n); } - weightedNodes = zmalloc(nodes_involved * sizeof(clusterManagerNode *)); + weightedNodes = zmalloc(nodes_involved * sizeof(clusterManagerNode *), MALLOC_LOCAL); if (weightedNodes == NULL) goto cleanup; /* Check cluster, only proceed if it looks sane. */ clusterManagerCheckCluster(1); @@ -5845,7 +5846,7 @@ static int clusterManagerCommandCall(int argc, char **argv) { if (!clusterManagerLoadInfoFromNode(refnode, 0)) return 0; argc--; argv++; - size_t *argvlen = zmalloc(argc*sizeof(size_t)); + size_t *argvlen = zmalloc(argc*sizeof(size_t), MALLOC_LOCAL); clusterManagerLogInfo(">>> Calling"); for (i = 0; i < argc; i++) { argvlen[i] = strlen(argv[i]); @@ -6841,7 +6842,7 @@ static char *getInfoField(char *info, char *field) { n1 = strchr(p,'\r'); n2 = strchr(p,','); if (n2 && n2 < n1) n1 = n2; - result = zmalloc(sizeof(char)*(n1-p)+1); + result = zmalloc(sizeof(char)*(n1-p)+1, MALLOC_LOCAL); memcpy(result,p,(n1-p)); result[n1-p] = '\0'; return result; @@ -7175,6 +7176,7 @@ static void intrinsicLatencyMode(void) { int main(int argc, char **argv) { int firstarg; + storage_init(); config.hostip = sdsnew("127.0.0.1"); config.hostport = 6379; config.hostsocket = NULL; diff --git a/src/replication.c b/src/replication.c index 3bc42d62a..103af2691 100644 --- a/src/replication.c +++ b/src/replication.c @@ -76,7 +76,7 @@ char *replicationGetSlaveName(client *c) { void createReplicationBacklog(void) { serverAssert(server.repl_backlog == NULL); - server.repl_backlog = zmalloc(server.repl_backlog_size); + server.repl_backlog = zmalloc(server.repl_backlog_size, MALLOC_LOCAL); server.repl_backlog_histlen = 0; server.repl_backlog_idx = 0; @@ -105,7 +105,7 @@ void resizeReplicationBacklog(long long newsize) { * worse often we need to alloc additional space before freeing the * old buffer. */ zfree(server.repl_backlog); - server.repl_backlog = zmalloc(server.repl_backlog_size); + server.repl_backlog = zmalloc(server.repl_backlog_size, MALLOC_LOCAL); server.repl_backlog_histlen = 0; server.repl_backlog_idx = 0; /* Next byte we have is... the next since the buffer is empty. */ diff --git a/src/rio.c b/src/rio.c index c9c76b8f2..0f44b017d 100644 --- a/src/rio.c +++ b/src/rio.c @@ -267,8 +267,8 @@ void rioInitWithFdset(rio *r, int *fds, int numfds) { int j; *r = rioFdsetIO; - r->io.fdset.fds = zmalloc(sizeof(int)*numfds); - r->io.fdset.state = zmalloc(sizeof(int)*numfds); + r->io.fdset.fds = zmalloc(sizeof(int)*numfds, MALLOC_LOCAL); + r->io.fdset.state = zmalloc(sizeof(int)*numfds, MALLOC_LOCAL); memcpy(r->io.fdset.fds,fds,sizeof(int)*numfds); for (j = 0; j < numfds; j++) r->io.fdset.state[j] = 0; r->io.fdset.numfds = numfds; diff --git a/src/scripting.c b/src/scripting.c index f6df38400..3b3b996e0 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -1866,7 +1866,7 @@ sds *ldbReplParseCommand(int *argcp) { if (*argcp <= 0 || *argcp > 1024) goto protoerr; /* Parse each argument. */ - argv = zmalloc(sizeof(sds)*(*argcp)); + argv = zmalloc(sizeof(sds)*(*argcp), MALLOC_LOCAL); argc = 0; while(argc < *argcp) { if (*p != '$') goto protoerr; diff --git a/src/sds.c b/src/sds.c index 330c955e8..a87173d94 100644 --- a/src/sds.c +++ b/src/sds.c @@ -96,7 +96,7 @@ sds sdsnewlen(const void *init, size_t initlen) { int hdrlen = sdsHdrSize(type); unsigned char *fp; /* flags pointer. */ - sh = s_malloc(hdrlen+initlen+1); + sh = s_malloc(hdrlen+initlen+1, MALLOC_SHARED); if (init==SDS_NOINIT) init = NULL; else if (!init) @@ -234,7 +234,7 @@ sds sdsMakeRoomFor(sds s, size_t addlen) { } else { /* Since the header size changes, need to move the string forward, * and can't use realloc */ - newsh = s_malloc(hdrlen+newlen+1); + newsh = s_malloc(hdrlen+newlen+1, MALLOC_SHARED); if (newsh == NULL) return NULL; memcpy((char*)newsh+hdrlen, s, len+1); s_free(sh); @@ -273,7 +273,7 @@ sds sdsRemoveFreeSpace(sds s) { if (newsh == NULL) return NULL; s = (char*)newsh+oldhdrlen; } else { - newsh = s_malloc(hdrlen+len+1); + newsh = s_malloc(hdrlen+len+1, MALLOC_SHARED); if (newsh == NULL) return NULL; memcpy((char*)newsh+hdrlen, s, len+1); s_free(sh); @@ -523,7 +523,7 @@ sds sdscatvprintf(sds s, const char *fmt, va_list ap) { /* We try to start using a static buffer for speed. * If not possible we revert to heap allocation. */ if (buflen > sizeof(staticbuf)) { - buf = s_malloc(buflen); + buf = s_malloc(buflen, MALLOC_SHARED); if (buf == NULL) return NULL; } else { buflen = sizeof(staticbuf); @@ -539,7 +539,7 @@ sds sdscatvprintf(sds s, const char *fmt, va_list ap) { if (buf[buflen-2] != '\0') { if (buf != staticbuf) s_free(buf); buflen *= 2; - buf = s_malloc(buflen); + buf = s_malloc(buflen, MALLOC_SHARED); if (buf == NULL) return NULL; continue; } @@ -816,7 +816,7 @@ sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *c if (seplen < 1 || len < 0) return NULL; - tokens = s_malloc(sizeof(sds)*slots); + tokens = s_malloc(sizeof(sds)*slots, MALLOC_SHARED); if (tokens == NULL) return NULL; if (len == 0) { @@ -1044,7 +1044,7 @@ sds *sdssplitargs(const char *line, int *argc) { current = NULL; } else { /* Even on empty input string return something not NULL. */ - if (vector == NULL) vector = s_malloc(sizeof(void*)); + if (vector == NULL) vector = s_malloc(sizeof(void*), MALLOC_SHARED); return vector; } } @@ -1111,7 +1111,7 @@ sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen) { * the overhead of function calls. Here we define these wrappers only for * the programs SDS is linked to, if they want to touch the SDS internals * even if they use a different allocator. */ -void *sds_malloc(size_t size) { return s_malloc(size); } +void *sds_malloc(size_t size) { return s_malloc(size, MALLOC_SHARED); } void *sds_realloc(void *ptr, size_t size) { return s_realloc(ptr,size); } void sds_free(void *ptr) { s_free(ptr); } diff --git a/src/sdsalloc.h b/src/sdsalloc.h index 531d41929..cb814acce 100644 --- a/src/sdsalloc.h +++ b/src/sdsalloc.h @@ -37,6 +37,10 @@ * to use the default libc allocator). */ #include "zmalloc.h" -#define s_malloc zmalloc -#define s_realloc zrealloc -#define s_free zfree +#include "storage.h" +//#define s_malloc zmalloc +#define s_malloc salloc +//#define s_realloc zrealloc +#define s_realloc srealloc +//#define s_free zfree +#define s_free sfree diff --git a/src/sentinel.c b/src/sentinel.c index 4d03c9c12..7add1e744 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -341,7 +341,7 @@ static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) { return C_ERR; /* Create container for context and r/w events */ - e = (redisAeEvents*)zmalloc(sizeof(*e)); + e = (redisAeEvents*)zmalloc(sizeof(*e), MALLOC_LOCAL); e->context = ac; e->loop = loop; e->fd = c->fd; @@ -549,7 +549,7 @@ sentinelAddr *createSentinelAddr(char *hostname, int port) { errno = ENOENT; return NULL; } - sa = zmalloc(sizeof(*sa)); + sa = zmalloc(sizeof(*sa), MALLOC_LOCAL); sa->ip = sdsnew(ip); sa->port = port; return sa; @@ -559,7 +559,7 @@ sentinelAddr *createSentinelAddr(char *hostname, int port) { sentinelAddr *dupSentinelAddr(sentinelAddr *src) { sentinelAddr *sa; - sa = zmalloc(sizeof(*sa)); + sa = zmalloc(sizeof(*sa), MALLOC_LOCAL); sa->ip = sdsnew(src->ip); sa->port = src->port; return sa; @@ -703,10 +703,10 @@ void sentinelScheduleScriptExecution(char *path, ...) { va_end(ap); argv[0] = sdsnew(path); - sj = zmalloc(sizeof(*sj)); + sj = zmalloc(sizeof(*sj), MALLOC_LOCAL); sj->flags = SENTINEL_SCRIPT_NONE; sj->retry_num = 0; - sj->argv = zmalloc(sizeof(char*)*(argc+1)); + sj->argv = zmalloc(sizeof(char*)*(argc+1), MALLOC_LOCAL); sj->start_time = 0; sj->pid = 0; memcpy(sj->argv,argv,sizeof(char*)*(argc+1)); @@ -950,7 +950,7 @@ void sentinelCallClientReconfScript(sentinelRedisInstance *master, int role, cha /* Create a not yet connected link object. */ instanceLink *createInstanceLink(void) { - instanceLink *link = zmalloc(sizeof(*link)); + instanceLink *link = zmalloc(sizeof(*link), MALLOC_LOCAL); link->refcount = 1; link->disconnected = 1; @@ -1200,7 +1200,7 @@ sentinelRedisInstance *createSentinelRedisInstance(char *name, int flags, char * } /* Create the instance object. */ - ri = zmalloc(sizeof(*ri)); + ri = zmalloc(sizeof(*ri), MALLOC_LOCAL); /* Note that all the instances are started in the disconnected state, * the event loop will take care of connecting them. */ ri->flags = flags; @@ -4091,7 +4091,7 @@ int compareSlavesForPromotion(const void *a, const void *b) { sentinelRedisInstance *sentinelSelectSlave(sentinelRedisInstance *master) { sentinelRedisInstance **instance = - zmalloc(sizeof(instance[0])*dictSize(master->slaves)); + zmalloc(sizeof(instance[0])*dictSize(master->slaves), MALLOC_LOCAL); sentinelRedisInstance *selected = NULL; int instances = 0; dictIterator *di; diff --git a/src/server.c b/src/server.c index 1df63f65f..62b37dfa1 100644 --- a/src/server.c +++ b/src/server.c @@ -33,6 +33,7 @@ #include "bio.h" #include "latency.h" #include "atomicvar.h" +#include "storage.h" #include #include @@ -2729,7 +2730,7 @@ void initServer(void) { strerror(errno)); exit(1); } - server.db = zmalloc(sizeof(redisDb)*server.dbnum); + server.db = zmalloc(sizeof(redisDb)*server.dbnum, MALLOC_LOCAL); /* Open the TCP listening socket for the user commands. */ if (server.port != 0 && @@ -3066,7 +3067,7 @@ void alsoPropagate(struct redisCommand *cmd, int dbid, robj **argv, int argc, if (server.loading) return; /* No propagation during loading. */ - argvcopy = zmalloc(sizeof(robj*)*argc); + argvcopy = zmalloc(sizeof(robj*)*argc, MALLOC_LOCAL); for (j = 0; j < argc; j++) { argvcopy[j] = argv[j]; incrRefCount(argv[j]); @@ -4481,7 +4482,7 @@ void usage(void) { void redisAsciiArt(void) { #include "asciilogo.h" - char *buf = zmalloc(1024*16); + char *buf = zmalloc(1024*16, MALLOC_LOCAL); char *mode; if (server.cluster_enabled) mode = "cluster"; @@ -4739,6 +4740,8 @@ int main(int argc, char **argv) { struct timeval tv; int j; + storage_init(); + #ifdef REDIS_TEST if (argc == 3 && !strcasecmp(argv[1], "test")) { if (!strcasecmp(argv[2], "ziplist")) { @@ -4789,7 +4792,7 @@ int main(int argc, char **argv) { /* Store the executable path and arguments in a safe place in order * to be able to restart the server later. */ server.executable = getAbsolutePath(argv[0]); - server.exec_argv = zmalloc(sizeof(char*)*(argc+1)); + server.exec_argv = zmalloc(sizeof(char*)*(argc+1), MALLOC_LOCAL); server.exec_argv[argc] = NULL; for (j = 0; j < argc; j++) server.exec_argv[j] = zstrdup(argv[j]); diff --git a/src/slowlog.c b/src/slowlog.c index 1d715e39b..b6041f096 100644 --- a/src/slowlog.c +++ b/src/slowlog.c @@ -46,12 +46,12 @@ * Incrementing the ref count of all the objects retained is up to * this function. */ slowlogEntry *slowlogCreateEntry(client *c, robj **argv, int argc, long long duration) { - slowlogEntry *se = zmalloc(sizeof(*se)); + slowlogEntry *se = zmalloc(sizeof(*se), MALLOC_LOCAL); int j, slargc = argc; if (slargc > SLOWLOG_ENTRY_MAX_ARGC) slargc = SLOWLOG_ENTRY_MAX_ARGC; se->argc = slargc; - se->argv = zmalloc(sizeof(robj*)*slargc); + se->argv = zmalloc(sizeof(robj*)*slargc, MALLOC_LOCAL); for (j = 0; j < slargc; j++) { /* Logging too many arguments is a useless memory waste, so we stop * at SLOWLOG_ENTRY_MAX_ARGC, but use the last argument to specify diff --git a/src/sort.c b/src/sort.c index 8608cd8b3..7ae794501 100644 --- a/src/sort.c +++ b/src/sort.c @@ -36,7 +36,7 @@ zskiplistNode* zslGetElementByRank(zskiplist *zsl, unsigned long rank); redisSortOperation *createSortOperation(int type, robj *pattern) { - redisSortOperation *so = zmalloc(sizeof(*so)); + redisSortOperation *so = zmalloc(sizeof(*so), MALLOC_LOCAL); so->type = type; so->pattern = pattern; return so; @@ -340,7 +340,7 @@ void sortCommand(client *c) { } /* Load the sorting vector with all the objects to sort */ - vector = zmalloc(sizeof(redisSortObject)*vectorlen); + vector = zmalloc(sizeof(redisSortObject)*vectorlen, MALLOC_LOCAL); j = 0; if (sortval->type == OBJ_LIST && dontsort) { diff --git a/src/sparkline.c b/src/sparkline.c index 0a986883d..e18ce98fd 100644 --- a/src/sparkline.c +++ b/src/sparkline.c @@ -55,7 +55,7 @@ static int label_margin_top = 1; /* Create a new sequence. */ struct sequence *createSparklineSequence(void) { - struct sequence *seq = zmalloc(sizeof(*seq)); + struct sequence *seq = zmalloc(sizeof(*seq), MALLOC_LOCAL); seq->length = 0; seq->samples = NULL; return seq; @@ -99,7 +99,7 @@ sds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, double relmax = seq->max - seq->min; int steps = charset_len*rows; int row = 0; - char *chars = zmalloc(len); + char *chars = zmalloc(len, MALLOC_LOCAL); int loop = 1; int opt_fill = flags & SPARKLINE_FILL; int opt_log = flags & SPARKLINE_LOG_SCALE; diff --git a/src/storage.c b/src/storage.c new file mode 100644 index 000000000..90009c2a8 --- /dev/null +++ b/src/storage.c @@ -0,0 +1,155 @@ +#include "server.h" + +#include +#include +#include +#include +#include +#include +#include +#include "storage.h" + +struct memkind *mkdisk = NULL; +static char *PMEM_DIR = "/mnt/btrfs_scratch/"; + + + +#define OBJECT_PAGE_BUFFER_SIZE 8192 //(size in objs) +struct object_page +{ + uint64_t allocmap[OBJECT_PAGE_BUFFER_SIZE/(8*sizeof(uint64_t))]; + robj rgobj[OBJECT_PAGE_BUFFER_SIZE]; + struct object_page *pnext; +}; +#define OBJ_PAGE_BITS_PER_WORD 64 +struct object_page *headObjpage = NULL; + +void storage_init() +{ + int errv = memkind_create_pmem(PMEM_DIR, 0, &mkdisk); + if (errv) + { + fprintf(stderr, "Memory pool creation failed: %d\n", errv); + exit(EXIT_FAILURE); + } + headObjpage = memkind_calloc(MEMKIND_HUGETLB, 1, sizeof(struct object_page)); +} + +int IdxAllocObject(struct object_page *page) +{ + for (size_t iword = 0; iword < OBJ_PAGE_BITS_PER_WORD; ++iword) + { + if ((page->allocmap[iword] + 1) != 0) + { + int ibit = 0; + uint64_t bitword = page->allocmap[iword]; + while (bitword & 1) + { + bitword >>= 1; + ++ibit; + } + page->allocmap[iword] |= 1 << ibit; + return (iword * OBJ_PAGE_BITS_PER_WORD) + ibit; + } + } + return -1; +} + +struct redisObject *salloc_obj() +{ + struct object_page *cur = headObjpage; + for (;;) + { + int idx = IdxAllocObject(cur); + if (idx >= 0) + { + return &cur->rgobj[idx]; + } + + if (cur->pnext == NULL) + { + cur->pnext = memkind_calloc(MEMKIND_HUGETLB, 1, sizeof(struct object_page)); + } + + cur = cur->pnext; + } +} +void sfree_obj(struct redisObject *obj) +{ + struct object_page *cur = headObjpage; + for (;;) + { + if (obj >= cur->rgobj && (obj < (cur->rgobj + OBJECT_PAGE_BUFFER_SIZE))) + { + // Its on this page + int idx = obj - cur->rgobj; + cur->allocmap[idx / OBJ_PAGE_BITS_PER_WORD] &= ~(1 << (idx % OBJ_PAGE_BITS_PER_WORD)); + break; + } + cur = cur->pnext; + } + return; +} + +void *salloc(size_t cb, enum MALLOC_CLASS class) +{ + switch (class) + { + case MALLOC_SHARED: + return memkind_malloc(mkdisk, cb); + default: + return memkind_malloc(MEMKIND_DEFAULT, cb); + } + return NULL; +} + +void *scalloc(size_t cb, size_t c, enum MALLOC_CLASS class) +{ + switch (class) + { + case MALLOC_SHARED: + return memkind_calloc(mkdisk, cb, c); + default: + return memkind_calloc(MEMKIND_DEFAULT, cb, c); + } + return NULL; +} + +void sfree(void *pv) +{ + memkind_free(NULL, pv); +} + +void *srealloc(void *pv, size_t cb) +{ + memkind_t kind = mkdisk; + return memkind_realloc(kind, pv, cb); +} + +int fdNew = -1; +void handle_prefork() +{ + memkind_tmpfile(PMEM_DIR, &fdNew); + if (ioctl(fdNew, FICLONE, memkind_fd(mkdisk)) == -1) + { + perror("failed to fork file"); + exit(EXIT_FAILURE); + } +} + +void handle_postfork(int pid) +{ + if (pid != 0) + { + // Parent, close fdNew + close(fdNew); + fdNew = -1; + } + else + { + int fdOriginal = memkind_fd(mkdisk); + memkind_pmem_remapfd(mkdisk, fdNew); + close(fdOriginal); + } + +} \ No newline at end of file diff --git a/src/storage.h b/src/storage.h new file mode 100644 index 000000000..ebb2d1c5e --- /dev/null +++ b/src/storage.h @@ -0,0 +1,23 @@ +#ifndef __STORAGE_H__ +#define __STORAGE_H__ + +enum MALLOC_CLASS +{ + MALLOC_LOCAL, + MALLOC_SHARED, +}; + +void storage_init(void); + +struct redisObject *salloc_obj(); +void sfree_obj(struct redisObject *obj); + +void *salloc(size_t cb, enum MALLOC_CLASS class); +void *scalloc(size_t cb, size_t c, enum MALLOC_CLASS class); +void sfree(void*); +void *srealloc(void *pv, size_t cb); + +void handle_prefork(); +void handle_postfork(int pid); + +#endif diff --git a/src/t_hash.c b/src/t_hash.c index d8aee6572..c94945a1f 100644 --- a/src/t_hash.c +++ b/src/t_hash.c @@ -322,7 +322,7 @@ unsigned long hashTypeLength(const robj *o) { } hashTypeIterator *hashTypeInitIterator(robj *subject) { - hashTypeIterator *hi = zmalloc(sizeof(hashTypeIterator)); + hashTypeIterator *hi = zmalloc(sizeof(hashTypeIterator), MALLOC_LOCAL); hi->subject = subject; hi->encoding = subject->encoding; diff --git a/src/t_list.c b/src/t_list.c index 451ffb4b5..143f672a4 100644 --- a/src/t_list.c +++ b/src/t_list.c @@ -82,7 +82,7 @@ unsigned long listTypeLength(const robj *subject) { /* Initialize an iterator at the specified index. */ listTypeIterator *listTypeInitIterator(robj *subject, long index, unsigned char direction) { - listTypeIterator *li = zmalloc(sizeof(listTypeIterator)); + listTypeIterator *li = zmalloc(sizeof(listTypeIterator), MALLOC_LOCAL); li->subject = subject; li->encoding = subject->encoding; li->direction = direction; diff --git a/src/t_set.c b/src/t_set.c index 61013dbcd..89b5cf70a 100644 --- a/src/t_set.c +++ b/src/t_set.c @@ -119,7 +119,7 @@ int setTypeIsMember(robj *subject, sds value) { } setTypeIterator *setTypeInitIterator(robj *subject) { - setTypeIterator *si = zmalloc(sizeof(setTypeIterator)); + setTypeIterator *si = zmalloc(sizeof(setTypeIterator), MALLOC_LOCAL); si->subject = subject; si->encoding = subject->encoding; if (si->encoding == OBJ_ENCODING_HT) { @@ -791,7 +791,7 @@ int qsortCompareSetsByRevCardinality(const void *s1, const void *s2) { void sinterGenericCommand(client *c, robj **setkeys, unsigned long setnum, robj *dstkey) { - robj **sets = zmalloc(sizeof(robj*)*setnum); + robj **sets = zmalloc(sizeof(robj*)*setnum, MALLOC_SHARED); setTypeIterator *si; robj *dstset = NULL; sds elesds; @@ -930,7 +930,7 @@ void sinterstoreCommand(client *c) { void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum, robj *dstkey, int op) { - robj **sets = zmalloc(sizeof(robj*)*setnum); + robj **sets = zmalloc(sizeof(robj*)*setnum, MALLOC_SHARED); setTypeIterator *si; robj *dstset = NULL; sds ele; diff --git a/src/t_stream.c b/src/t_stream.c index 1a5acac42..5fb14628b 100644 --- a/src/t_stream.c +++ b/src/t_stream.c @@ -50,7 +50,7 @@ size_t streamReplyWithRangeFromConsumerPEL(client *c, stream *s, streamID *start /* Create a new stream data structure. */ stream *streamNew(void) { - stream *s = zmalloc(sizeof(*s)); + stream *s = zmalloc(sizeof(*s), MALLOC_SHARED); s->rax = raxNew(); s->length = 0; s->last_id.ms = 0; @@ -1402,8 +1402,8 @@ void xreadCommand(client *c) { /* Parse the IDs and resolve the group name. */ if (streams_count > STREAMID_STATIC_VECTOR_LEN) - ids = zmalloc(sizeof(streamID)*streams_count); - if (groupname) groups = zmalloc(sizeof(streamCG*)*streams_count); + ids = zmalloc(sizeof(streamID)*streams_count, MALLOC_SHARED); + if (groupname) groups = zmalloc(sizeof(streamCG*)*streams_count, MALLOC_SHARED); for (int i = streams_arg + streams_count; i < c->argc; i++) { /* Specifying "$" as last-known-id means that the client wants to be @@ -1595,7 +1595,7 @@ cleanup: /* Cleanup. */ * time to the current time. The NACK consumer will be set to the one * specified as argument of the function. */ streamNACK *streamCreateNACK(streamConsumer *consumer) { - streamNACK *nack = zmalloc(sizeof(*nack)); + streamNACK *nack = zmalloc(sizeof(*nack), MALLOC_SHARED); nack->delivery_time = mstime(); nack->delivery_count = 1; nack->consumer = consumer; @@ -1628,7 +1628,7 @@ streamCG *streamCreateCG(stream *s, char *name, size_t namelen, streamID *id) { if (raxFind(s->cgroups,(unsigned char*)name,namelen) != raxNotFound) return NULL; - streamCG *cg = zmalloc(sizeof(*cg)); + streamCG *cg = zmalloc(sizeof(*cg), MALLOC_SHARED); cg->pel = raxNew(); cg->consumers = raxNew(); cg->last_id = *id; @@ -1661,7 +1661,7 @@ streamConsumer *streamLookupConsumer(streamCG *cg, sds name, int create) { sdslen(name)); if (consumer == raxNotFound) { if (!create) return NULL; - consumer = zmalloc(sizeof(*consumer)); + consumer = zmalloc(sizeof(*consumer), MALLOC_SHARED); consumer->name = sdsdup(name); consumer->pel = raxNew(); raxInsert(cg->consumers,(unsigned char*)name,sdslen(name), diff --git a/src/t_zset.c b/src/t_zset.c index 0427ee887..daeabcf93 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -70,7 +70,7 @@ int zslLexValueLteMax(sds value, zlexrangespec *spec); * The SDS string 'ele' is referenced by the node after the call. */ zskiplistNode *zslCreateNode(int level, double score, sds ele) { zskiplistNode *zn = - zmalloc(sizeof(*zn)+level*sizeof(struct zskiplistLevel)); + zmalloc(sizeof(*zn)+level*sizeof(struct zskiplistLevel), MALLOC_SHARED); zn->score = score; zn->ele = ele; return zn; @@ -81,7 +81,7 @@ zskiplist *zslCreate(void) { int j; zskiplist *zsl; - zsl = zmalloc(sizeof(*zsl)); + zsl = zmalloc(sizeof(*zsl), MALLOC_SHARED); zsl->level = 1; zsl->length = 0; zsl->header = zslCreateNode(ZSKIPLIST_MAXLEVEL,0,NULL); @@ -1182,7 +1182,7 @@ void zsetConvert(robj *zobj, int encoding) { if (encoding != OBJ_ENCODING_SKIPLIST) serverPanic("Unknown target encoding"); - zs = zmalloc(sizeof(*zs)); + zs = zmalloc(sizeof(*zs), MALLOC_SHARED); zs->dict = dictCreate(&zsetDictType,NULL); zs->zsl = zslCreate(); @@ -1590,7 +1590,7 @@ void zaddGenericCommand(client *c, int flags) { /* Start parsing all the scores, we need to emit any syntax error * before executing additions to the sorted set, as the command should * either execute fully or nothing at all. */ - scores = zmalloc(sizeof(double)*elements); + scores = zmalloc(sizeof(double)*elements, MALLOC_SHARED); for (j = 0; j < elements; j++) { if (getDoubleFromObjectOrReply(c,c->argv[scoreidx+j*2],&scores[j],NULL) != C_OK) goto cleanup; @@ -2203,7 +2203,7 @@ void zunionInterGenericCommand(client *c, robj *dstkey, int op) { } /* read keys to be used for input */ - src = zcalloc(sizeof(zsetopsrc) * setnum); + src = zcalloc(sizeof(zsetopsrc) * setnum, MALLOC_SHARED); for (i = 0, j = 3; i < setnum; i++, j++) { robj *obj = lookupKeyWrite(c->db,c->argv[j]); if (obj != NULL) { diff --git a/src/ziplist.c b/src/ziplist.c index 1579d1109..733e2e685 100644 --- a/src/ziplist.c +++ b/src/ziplist.c @@ -577,7 +577,7 @@ void zipEntry(unsigned char *p, zlentry *e) { /* Create a new empty ziplist. */ unsigned char *ziplistNew(void) { unsigned int bytes = ZIPLIST_HEADER_SIZE+1; - unsigned char *zl = zmalloc(bytes); + unsigned char *zl = zmalloc(bytes, MALLOC_SHARED); ZIPLIST_BYTES(zl) = intrev32ifbe(bytes); ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(ZIPLIST_HEADER_SIZE); ZIPLIST_LENGTH(zl) = 0; diff --git a/src/zipmap.c b/src/zipmap.c index 22bfa1a46..88e7f8706 100644 --- a/src/zipmap.c +++ b/src/zipmap.c @@ -94,7 +94,7 @@ /* Create a new empty zipmap. */ unsigned char *zipmapNew(void) { - unsigned char *zm = zmalloc(2); + unsigned char *zm = zmalloc(2, MALLOC_SHARED); zm[0] = 0; /* Length */ zm[1] = ZIPMAP_END; diff --git a/src/zmalloc.c b/src/zmalloc.c index 2482f512b..7d307bad7 100644 --- a/src/zmalloc.c +++ b/src/zmalloc.c @@ -70,6 +70,16 @@ void zlibc_free(void *ptr) { #define mallocx(size,flags) je_mallocx(size,flags) #define dallocx(ptr,flags) je_dallocx(ptr,flags) #endif +#include "storage.h" +#undef malloc +#undef calloc +#undef realloc +#undef free +#define malloc(size, type) salloc(size, type) +#define calloc(count, size, type) scalloc(count, size, type) +#define realloc(ptr, size) srealloc(ptr, size) +#define free(ptr) sfree(ptr) +//#define zmalloc_size(ptr) (sizeof(ptr)) #define update_zmalloc_stat_alloc(__n) do { \ size_t _n = (__n); \ @@ -95,8 +105,8 @@ static void zmalloc_default_oom(size_t size) { static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom; -void *zmalloc(size_t size) { - void *ptr = malloc(size+PREFIX_SIZE); +void *zmalloc(size_t size, enum MALLOC_CLASS class) { + void *ptr = malloc(size+PREFIX_SIZE, class); if (!ptr) zmalloc_oom_handler(size); #ifdef HAVE_MALLOC_SIZE @@ -127,8 +137,8 @@ void zfree_no_tcache(void *ptr) { } #endif -void *zcalloc(size_t size) { - void *ptr = calloc(1, size+PREFIX_SIZE); +void *zcalloc(size_t size, enum MALLOC_CLASS class) { + void *ptr = calloc(1, size+PREFIX_SIZE, class); if (!ptr) zmalloc_oom_handler(size); #ifdef HAVE_MALLOC_SIZE @@ -148,7 +158,7 @@ void *zrealloc(void *ptr, size_t size) { size_t oldsize; void *newptr; - if (ptr == NULL) return zmalloc(size); + if (ptr == NULL) return zmalloc(size, MALLOC_SHARED); #ifdef HAVE_MALLOC_SIZE oldsize = zmalloc_size(ptr); newptr = realloc(ptr,size); @@ -207,7 +217,7 @@ void zfree(void *ptr) { char *zstrdup(const char *s) { size_t l = strlen(s)+1; - char *p = zmalloc(l); + char *p = zmalloc(l, MALLOC_SHARED); memcpy(p,s,l); return p; diff --git a/src/zmalloc.h b/src/zmalloc.h index 6fb19b046..0692e64c2 100644 --- a/src/zmalloc.h +++ b/src/zmalloc.h @@ -35,7 +35,12 @@ #define __xstr(s) __str(s) #define __str(s) #s -#if defined(USE_TCMALLOC) +#if 1 + #define ZMALLOC_LIB ("custom") + #include "storage.h" + #undef USE_JEMALLOC + #define USE_MALLOC_CLASS 1 +#elif defined(USE_TCMALLOC) #define ZMALLOC_LIB ("tcmalloc-" __xstr(TC_VERSION_MAJOR) "." __xstr(TC_VERSION_MINOR)) #include #if (TC_VERSION_MAJOR == 1 && TC_VERSION_MINOR >= 6) || (TC_VERSION_MAJOR > 1) @@ -77,8 +82,8 @@ #define HAVE_DEFRAG #endif -void *zmalloc(size_t size); -void *zcalloc(size_t size); +void *zmalloc(size_t size, enum MALLOC_CLASS class); +void *zcalloc(size_t size, enum MALLOC_CLASS class); void *zrealloc(void *ptr, size_t size); void zfree(void *ptr); char *zstrdup(const char *s); diff --git a/utils/hashtable/rehashing.c b/utils/hashtable/rehashing.c index b57a9043a..ee4d10c2d 100644 --- a/utils/hashtable/rehashing.c +++ b/utils/hashtable/rehashing.c @@ -71,7 +71,7 @@ int sortPointers(const void *a, const void *b) { void stressGetKeys(dict *d, int times, int *perfect_run, int *approx_run) { int j; - dictEntry **des = zmalloc(sizeof(dictEntry*)*dictSize(d)); + dictEntry **des = zmalloc(sizeof(dictEntry*)*dictSize(d), MALLOC_SHARED); for (j = 0; j < times; j++) { int requested = rand() % (dictSize(d)+1); int returned = dictGetSomeKeys(d, des, requested);