zmalloc.c 4.5 KB
Newer Older
A
antirez 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/* zmalloc - total amount of allocated memory aware version of malloc()
 *
 * Copyright (c) 2006-2009, Salvatore Sanfilippo <antirez at gmail dot com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Redis nor the names of its contributors may be used
 *     to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

31
#include <stdio.h>
A
antirez 已提交
32 33
#include <stdlib.h>
#include <string.h>
34
#include <pthread.h>
35
#include "config.h"
36

37 38 39 40 41 42
#if defined(__sun)
#define PREFIX_SIZE sizeof(long long)
#else
#define PREFIX_SIZE sizeof(size_t)
#endif

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
#define increment_used_memory(_n) do { \
    if (zmalloc_thread_safe) { \
        pthread_mutex_lock(&used_memory_mutex);  \
        used_memory += _n; \
        pthread_mutex_unlock(&used_memory_mutex); \
    } else { \
        used_memory += _n; \
    } \
} while(0)

#define decrement_used_memory(_n) do { \
    if (zmalloc_thread_safe) { \
        pthread_mutex_lock(&used_memory_mutex);  \
        used_memory -= _n; \
        pthread_mutex_unlock(&used_memory_mutex); \
    } else { \
        used_memory -= _n; \
    } \
} while(0)

A
antirez 已提交
63
static size_t used_memory = 0;
64
static int zmalloc_thread_safe = 0;
65
pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER;
A
antirez 已提交
66

67
static void zmalloc_oom(size_t size) {
68
    fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n",
69 70 71 72 73
        size);
    fflush(stderr);
    abort();
}

A
antirez 已提交
74
void *zmalloc(size_t size) {
75
    void *ptr = malloc(size+PREFIX_SIZE);
A
antirez 已提交
76

77
    if (!ptr) zmalloc_oom(size);
78
#ifdef HAVE_MALLOC_SIZE
79
    increment_used_memory(redis_malloc_size(ptr));
80 81
    return ptr;
#else
A
antirez 已提交
82
    *((size_t*)ptr) = size;
83
    increment_used_memory(size+PREFIX_SIZE);
84
    return (char*)ptr+PREFIX_SIZE;
85
#endif
A
antirez 已提交
86 87 88
}

void *zrealloc(void *ptr, size_t size) {
89
#ifndef HAVE_MALLOC_SIZE
A
antirez 已提交
90
    void *realptr;
91
#endif
A
antirez 已提交
92 93 94 95
    size_t oldsize;
    void *newptr;

    if (ptr == NULL) return zmalloc(size);
96 97 98
#ifdef HAVE_MALLOC_SIZE
    oldsize = redis_malloc_size(ptr);
    newptr = realloc(ptr,size);
99
    if (!newptr) zmalloc_oom(size);
100

101 102
    decrement_used_memory(oldsize);
    increment_used_memory(redis_malloc_size(newptr));
103 104
    return newptr;
#else
105
    realptr = (char*)ptr-PREFIX_SIZE;
A
antirez 已提交
106
    oldsize = *((size_t*)realptr);
107
    newptr = realloc(realptr,size+PREFIX_SIZE);
108
    if (!newptr) zmalloc_oom(size);
A
antirez 已提交
109 110

    *((size_t*)newptr) = size;
111 112
    decrement_used_memory(oldsize);
    increment_used_memory(size);
113
    return (char*)newptr+PREFIX_SIZE;
114
#endif
A
antirez 已提交
115 116 117
}

void zfree(void *ptr) {
118
#ifndef HAVE_MALLOC_SIZE
A
antirez 已提交
119 120
    void *realptr;
    size_t oldsize;
121
#endif
A
antirez 已提交
122 123

    if (ptr == NULL) return;
124
#ifdef HAVE_MALLOC_SIZE
125
    decrement_used_memory(redis_malloc_size(ptr));
126 127
    free(ptr);
#else
128
    realptr = (char*)ptr-PREFIX_SIZE;
A
antirez 已提交
129
    oldsize = *((size_t*)realptr);
130
    decrement_used_memory(oldsize+PREFIX_SIZE);
A
antirez 已提交
131
    free(realptr);
132
#endif
A
antirez 已提交
133 134 135 136 137 138 139 140 141 142 143
}

char *zstrdup(const char *s) {
    size_t l = strlen(s)+1;
    char *p = zmalloc(l);

    memcpy(p,s,l);
    return p;
}

size_t zmalloc_used_memory(void) {
144 145 146 147 148 149 150 151 152 153
    size_t um;

    if (zmalloc_thread_safe) pthread_mutex_lock(&used_memory_mutex);
    um = used_memory;
    if (zmalloc_thread_safe) pthread_mutex_unlock(&used_memory_mutex);
    return um;
}

void zmalloc_enable_thread_safeness(void) {
    zmalloc_thread_safe = 1;
A
antirez 已提交
154
}